diff options
Diffstat (limited to 'xsd')
114 files changed, 54142 insertions, 0 deletions
diff --git a/xsd/buildfile b/xsd/buildfile new file mode 100644 index 0000000..d4e7af5 --- /dev/null +++ b/xsd/buildfile @@ -0,0 +1,121 @@ +# file      : xsd/buildfile +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +import libs  = libxsd-frontend%lib{xsd-frontend} +import libs += libcutl%lib{cutl} +import libs += libxerces-c%lib{xerces-c} + +ops = options cxx/options cxx/parser/options cxx/tree/options + +./: exe{xsd}: {hxx ixx txx cxx}{** -version -{$ops} -pregenerated/**} \ +              {hxx}{version}                                          \ +              $libs + +# Target metadata, see also --build2-metadata in xsd.cxx. +# +# Note that xsd does not query any environment variables. +# +exe{xsd}: +{ +  export.metadata = 1 xsd +  xsd.name = [string] xsd +  xsd.version  = [string] $version +  xsd.checksum = [string] $version +} + +hxx{version}: in{version} $src_root/manifest + +## Consumption build ($develop == false). +# + +# Use pregenerated versions in the consumption build. +# +exe{xsd}: pregenerated/{hxx ixx cxx}{**}: include = (!$develop) + +if! $develop +  cxx.poptions =+ "-I($src_base/pregenerated)" # Note: must come first. + +# Distribute pregenerated versions only in the consumption build. +# +pregenerated/{hxx ixx cxx}{*}: dist = (!$develop) + +# +## + +## Development build ($develop == true). +# + +exe{xsd}: {hxx ixx cxx}{$ops}: include = $develop + +if $develop +  import! [metadata] cli = cli%exe{cli} + +# In the development build distribute regenerated {hxx ixx cxx}{options}, +# remapping their locations to the paths of the pregenerated versions (which +# are only distributed in the consumption build; see above). This way we make +# sure that the distributed files are always up-to-date. +# +for f: $ops +{ +  d = $directory($f) # empty, cxx/, etc. + +  <{hxx ixx cxx}{$f}>: cli{$f} +  { +    dist = ($develop ? $relative([dir_path] "pregenerated/xsd/$d", $d) : false) + +    # Symlink the generated code in src for convenience of development. +    # +    backlink = true +  } +} + +<hxx{~'/(.*)/'} ixx{~'/\1/'} cxx{~'/\1/'}>: cli{~'/\1/'} $cli +% +if $develop +{{ +  t = $path($>[0]).t + +  depdb dyndep --byproduct --file $t + +  h = $path($>[0]) +  i = $path($>[1]) +  c = $path($>[2]) + +  d = $directory($h) +  p = $string($leaf($d, $out_root)) # xsd, xsd/cxx, etc + +  options = --std c++11 -I $src_root --include-prefix $p              \ +            --guard-prefix $regex.replace($ucase($p), '[/\\]', '_')   \ +            --generate-specifier --generate-file-scanner              \ +            --suppress-undocumented --ostream-type ::std::wostream    \ +            --exclude-base --include-with-brackets --option-length 28 \ +            --cxx-prologue '#include <xsd/options-parser.hxx>' + +  $cli $options --generate-dep --dep-file $t -o $d $path($<[0]) + +  # If the result differs from the pregenerated version, copy it over. +  # +  d = [dir_path] $src_base/pregenerated/$p + +  dh = $d/$leaf($h) +  di = $d/$leaf($i) +  dc = $d/$leaf($c) + +  if diff $dh $h >- && \ +     diff $di $i >- && \ +     diff $dc $c >- +    exit +  end + +  cp $h $dh +  cp $i $di +  cp $c $dc +}} + +# +## + +# Pass the copyright notice extracted from the LICENSE file. +# +obj{xsd cxx/parser/generator cxx/tree/generator}: \ +  cxx.poptions += -DXSD_COPYRIGHT=\"$copyright\" diff --git a/xsd/cxx/elements.cxx b/xsd/cxx/elements.cxx new file mode 100644 index 0000000..02a768e --- /dev/null +++ b/xsd/cxx/elements.cxx @@ -0,0 +1,1365 @@ +// file      : xsd/cxx/elements.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/elements.hxx> + +#include <cctype>    // std::toupper +#include <memory> +#include <sstream> +#include <fstream> +#include <cassert> +#include <iostream> + +using std::wcerr; +using std::endl; + +namespace CXX +{ +  // +  // +  wchar_t +  upcase (wchar_t c) +  { +    return std::toupper (c); +  } + +  namespace +  { +    wchar_t const* keywords[] = { +      L"NULL", +      L"and", +      L"asm", +      L"auto", +      L"bitand", +      L"bitor", +      L"bool", +      L"break", +      L"case", +      L"catch", +      L"char", +      L"class", +      L"compl", +      L"const", +      L"const_cast", +      L"continue", +      L"default", +      L"delete", +      L"do", +      L"double", +      L"dynamic_cast", +      L"else", +      L"end_eq", +      L"enum", +      L"explicit", +      L"export", +      L"extern", +      L"false", +      L"float", +      L"for", +      L"friend", +      L"goto", +      L"if", +      L"inline", +      L"int", +      L"long", +      L"mutable", +      L"namespace", +      L"new", +      L"not", +      L"not_eq", +      L"operator", +      L"or", +      L"or_eq", +      L"private", +      L"protected", +      L"public", +      L"register", +      L"reinterpret_cast", +      L"return", +      L"short", +      L"signed", +      L"sizeof", +      L"static", +      L"static_cast", +      L"struct", +      L"switch", +      L"template", +      L"this", +      L"throw", +      L"true", +      L"try", +      L"typedef", +      L"typeid", +      L"typename", +      L"union", +      L"unsigned", +      L"using", +      L"virtual", +      L"void", +      L"volatile", +      L"wchar_t", +      L"while", +      L"xor", +      L"xor_eq" +    }; + +    // Note: excluding "identifiers with special meaning" in certain contexts +    // ("final", "override") since they shouldn't cause any issues. +    // +    wchar_t const* keywords_cxx11[] = { +      L"alignas", +      L"alignof", +      L"char16_t", +      L"char32_t", +      L"constexpr", +      L"decltype", +      L"noexcept", +      L"nullptr", +      L"static_assert", +      L"thread_local" +    }; + +    // Note: excluding "identifiers with special meaning" in certain contexts +    // ("import", "module") since they shouldn't cause any issues. +    // +    wchar_t const* keywords_cxx20[] = { +      L"char8_t", +      L"concept", +      L"consteval", +      L"constinit", +      L"co_await", +      L"co_return", +      L"co_yield", +      L"requires" +    }; +  } + +  // Context +  // + +  Context:: +  Context (std::wostream& o, +           SemanticGraph::Schema& root, +           SemanticGraph::Path const& path, +           options_type const& ops, +           StringLiteralMap const* string_literal_map_) +      : os (o), +        schema_root (root), +        schema_path (schema_path_), +        options (ops), +        std (ops.std ()), +        char_type (char_type_), +        char_encoding (char_encoding_), +        L (L_), +        string_type (string_type_), +        auto_ptr (auto_ptr_), +        string_literal_map (string_literal_map_), +        type_exp (type_exp_), +        inst_exp (inst_exp_), +        inl (inl_), +        ns_mapping_cache (ns_mapping_cache_), +        schema_path_ (path), +        xs_ns_ (0), +        char_type_ (ops.char_type ()), +        char_encoding_ (ops.char_encoding ()), +        L_ (char_type == L"wchar_t" ? L"L" : L""), +        inl_ (ops.generate_inline () ? L"inline\n" : L""), +        cxx_id_expr_ (L"^(::)?([a-zA-Z_]\\w*)(::[a-zA-Z_]\\w*)*$"), +        cxx_id_expr (cxx_id_expr_), +        urn_mapping_ (L"#^urn.*:([a-zA-Z_].*)$#$1#"), +        urn_mapping (urn_mapping_), +        nsr_mapping (nsr_mapping_), +        nsm_mapping (nsm_mapping_), +        include_mapping (include_mapping_), +        reserved_name_map (reserved_name_map_), +        keyword_set (keyword_set_) +  { +    // Export symbol. +    // +    { +      String es (ops.export_symbol ()); +      type_exp_ = es ? es + L" " : es; +      inst_exp_ = es ? es + L"\n" : es; +    } + +    // Resolve and cache XML Schema namespace. +    // +    { +      SemanticGraph::Nameable* n; + +      if (schema_root.names_begin ()->name () == +          L"http://www.w3.org/2001/XMLSchema") +      { +        // schema_root is the XML Schema itself. +        // +        n = &schema_root.names_begin ()->named (); +      } +      else +      { +        // Otherwise, the first used schema is implied XML Schema. +        // +        SemanticGraph::Uses& u = *schema_root.uses_begin (); +        assert (u.is_a<SemanticGraph::Implies> ()); +        n = &u.schema ().names_begin ()->named (); +      } + +      xs_ns_ = dynamic_cast<SemanticGraph::Namespace*> (n); +    } + +    // String type. +    // +    if (char_type == L"char") +      string_type_ = L"::std::string"; +    else if (char_type == L"wchar_t") +      string_type_ = L"::std::wstring"; +    else +      string_type_ = L"::std::basic_string< " + char_type + L" >"; + +    // Automatic pointer type. +    // +    auto_ptr_ = std >= cxx_version::cxx11 +      ? "::std::unique_ptr" +      : "::std::auto_ptr"; + +    // Default encoding. +    // +    if (!char_encoding) +    { +      if (char_type == L"char") +        char_encoding = L"utf8"; +      else +        char_encoding = L"auto"; +    } + +    // Default mapping. +    // +    nsr_mapping_.push_back ( +      Regex (L"#^.* (.*?/)??" L"(([a-zA-Z_]\\w*)(/[a-zA-Z_]\\w*)*)/?$#$2#")); +    nsr_mapping_.push_back ( +      Regex (L"#^.* http://www\\.w3\\.org/2001/XMLSchema$#xml_schema#")); + +    // Custom regex mapping. +    // +    for (NarrowStrings::const_iterator i (ops.namespace_regex ().begin ()), +           e (ops.namespace_regex ().end ()); i != e; ++i) +    { +      nsr_mapping_.push_back (Regex (String (*i))); +    } + +    // Custom direct mapping. +    // +    for (NarrowStrings::const_iterator i (ops.namespace_map ().begin ()), +           e (ops.namespace_map ().end ()); i != e; ++i) +    { +      String s (*i); + +      // Split the string in two parts at the last '='. +      // +      size_t pos (s.rfind ('=')); + +      if (pos == String::npos) +        throw InvalidNamespaceMapping (s, "delimiter ('=') not found"); + +      // Empty xml_ns designates the no-namespace case. +      // +      String xml_ns (s, 0, pos); +      String cxx_ns (s, pos + 1); + +      if (!cxx_ns.empty () && !cxx_id_expr.match (cxx_ns)) +        throw InvalidNamespaceMapping (s, "invalid C++ identifier"); + +      nsm_mapping_[xml_ns] = cxx_ns; +    } + +    // Include path regex +    // +    for (NarrowStrings::const_iterator i (ops.include_regex ().begin ()), +           e (ops.include_regex ().end ()); i != e; ++i) +    { +      include_mapping_.push_back (Regex (String (*i))); +    } + +    // Reserved names. +    // +    for (NarrowStrings::const_iterator i (ops.reserved_name ().begin ()), +           e (ops.reserved_name ().end ()); i != e; ++i) +    { +      String s (*i); + +      // Split the string in two parts at '='. +      // +      size_t pos (s.find ('=')); + +      if (pos == String::npos) +        reserved_name_map_[s] = L""; +      else +        reserved_name_map_[String (s, 0, pos)] = String (s, pos + 1); +    } + +    // Populate the keyword set. +    // +    for (size_t i (0); i < sizeof (keywords) / sizeof (wchar_t*); ++i) +      keyword_set_.insert (keywords[i]); + +    if (std >= cxx_version::cxx11) +    { +      for (size_t i (0); i < sizeof (keywords_cxx11) / sizeof (wchar_t*); ++i) +        keyword_set_.insert (keywords_cxx11[i]); +    } + +    if (std >= cxx_version::cxx20) +    { +      for (size_t i (0); i < sizeof (keywords_cxx20) / sizeof (wchar_t*); ++i) +        keyword_set_.insert (keywords_cxx20[i]); +    } + +  } + +  String Context:: +  ns_name (SemanticGraph::Namespace& ns) +  { +    using SemanticGraph::Schema; +    using SemanticGraph::Includes; +    using SemanticGraph::Imports; +    using SemanticGraph::Implies; +    using SemanticGraph::Sources; + +    String tmp; +    MapMapping::const_iterator i (nsm_mapping.find (ns.name ())); + +    if (i != nsm_mapping.end ()) +    { +      tmp = i->second; +    } +    else +    { +      SemanticGraph::Path path; +      Schema& schema (dynamic_cast<Schema&> (ns.scope ())); + +      if (schema.used_p ()) +      { +        // Here we need to detect a special multi-schema compilation +        // case where the root schemas are imported into a special +        // schema that doesn't have a namespace. +        // +        SemanticGraph::Uses& u (*schema.used_begin ()); +        SemanticGraph::Schema& s (u.user ()); + +        if (s.names_begin () != s.names_end ()) +          path = u.path (); +      } +      else +        path = schema_path; + +      String pair; + +      if (!path.empty ()) +      { +        path.normalize (); + +        // Try to use the portable representation of the path. If that +        // fails, fall back to the native representation. +        // +        try +        { +          pair = path.posix_string (); +        } +        catch (SemanticGraph::InvalidPath const&) +        { +          pair = path.string (); +        } +      } + +      pair += L' ' + ns.name (); + +      // Check cache first +      // +      MappingCache::const_iterator i (ns_mapping_cache.find (pair)); + +      if (i != ns_mapping_cache.end ()) +      { +        tmp = i->second; +      } +      else +      { +        bool trace (options.namespace_regex_trace ()); + +        if (trace) +          wcerr << "namespace: '" << pair << "'" << endl; + +        bool found (false); +        Regex colon (L"#/#::#"); + +        for (RegexMapping::const_reverse_iterator e (nsr_mapping.rbegin ()); +             e != nsr_mapping.rend (); ++e) +        { +          if (trace) +            wcerr << "try: '" << e->regex () << "' : "; + +          if (e->match (pair)) +          { +            tmp = e->replace (pair); +            tmp = colon.replace (tmp); // replace `/' with `::' + +            // Check the result. +            // +            found = cxx_id_expr.match (tmp); + +            if (trace) +              wcerr << "'" << tmp << "' : "; +          } + +          if (trace) +            wcerr << (found ? '+' : '-') << endl; + +          if (found) +            break; +        } + +        if (!found) +        { +          String const& n (ns.name ()); + +          // Check if the name is valid by itself. +          // +          if (n.empty ()) +          { +            // Empty name denotes a no-namespace case. +            // +            tmp = n; +          } +          else +          { +            tmp = colon.replace (n); // replace `/' with `::' + +            if (!cxx_id_expr.match (tmp)) +            { +              // See if this is a urn-style namespace. +              // +              if (urn_mapping.match (n)) +              { +                Regex filter (L"#[.:-]#_#"); +                tmp = urn_mapping.replace (n); +                tmp = filter.replace (tmp); + +                if (!cxx_id_expr.match (tmp)) +                  throw NoNamespaceMapping ( +                    ns.file (), ns.line (), ns.column (), ns.name ()); +              } +              else +                throw NoNamespaceMapping ( +                  ns.file (), ns.line (), ns.column (), ns.name ()); +            } +          } +        } + +        // Add the mapping to the cache. +        // +        ns_mapping_cache[pair] = tmp; +      } +    } + + +    // Parse resulting namespace string and id() each name. +    // +    String r; +    String::size_type b (0), e; + +    do +    { +      e = tmp.find (L"::", b); + +      String name (tmp, b, e == tmp.npos ? e : e - b); + +      if (!name.empty ()) +        r += L"::" + escape (name); + +      b = e; + +      if (b == tmp.npos) +        break; + +      b += 2; + +    } while (true); + +    return r; +  } + +  SemanticGraph::Namespace& Context:: +  xs_ns () +  { +    return *xs_ns_; +  } + +  String Context:: +  xs_ns_name () +  { +    return ns_name (*xs_ns_); +  } + +  SemanticGraph::Namespace& Context:: +  namespace_ (SemanticGraph::Nameable& n) +  { +    // The basic idea goes like this: go up Names edges until you +    // reach Namespace. There are, however, anonymous types which +    // need special handling. In the case of an anonymous type we +    // will go up the first Belongs edge (because the first edge +    // is where the type was defined. +    // + +    if (n.named_p ()) +    { +      SemanticGraph::Scope& s (n.scope ()); + +      SemanticGraph::Namespace* ns ( +        dynamic_cast<SemanticGraph::Namespace*> (&n)); + +      return ns ? *ns : namespace_ (s); +    } +    else +    { +      SemanticGraph::Type& t (dynamic_cast<SemanticGraph::Type&> (n)); + +      SemanticGraph::Belongs& b (*t.classifies_begin ()); + +      return namespace_ (b.instance ()); +    } +  } + +  String Context:: +  xml_ns_name (SemanticGraph::Nameable& n) +  { +    return namespace_ (n).name (); +  } + +  String Context:: +  fq_name (SemanticGraph::Nameable& n, char const* name_key) +  { +    using namespace SemanticGraph; + +    String r; + +    if (dynamic_cast<Schema*> (&n)) +    { +      return L""; // Map to global namespace. +    } +    else if (SemanticGraph::Namespace* ns = +             dynamic_cast<SemanticGraph::Namespace*> (&n)) +    { +      r = ns_name (*ns); +    } +    else +    { +      r = fq_name (n.scope ()); +      r += L"::"; +      r += n.context ().get<String> (name_key); +    } + +    return r; +  } + +  SemanticGraph::Type& Context:: +  ultimate_base (SemanticGraph::Complex& c) +  { +    using namespace SemanticGraph; + +    Type* b (&c.inherits ().base ()); + +    while (true) +    { +      Complex* cb (dynamic_cast<Complex*> (b)); + +      if (cb != 0 && cb->inherits_p ()) +      { +        b = &cb->inherits ().base (); +        continue; +      } + +      break; +    } + +    return *b; +  } + +  String Context:: +  escape (String const& name) +  { +    String r; +    size_t n (name.size ()); + +    // In most common cases we will have that many chars. +    // +    r.reserve (n); + +    for (size_t i (0); i < n; ++i) +    { +      bool first (i == 0); + +      unsigned int u (unicode_char (name, i)); // May advance i. + +      if (first) +      { +        if (!((u >= 'a' && u <= 'z') || +              (u >= 'A' && u <= 'Z') || +              u == '_')) +          r = (u >= '0' && u <= '9') ? L"cxx_" : L"cxx"; +      } + +      if (!((u >= 'a' && u <= 'z') || +            (u >= 'A' && u <= 'Z') || +            (u >= '0' && u <= '9') || +            u == '_')) +        r.push_back ('_'); +      else +        r.push_back (static_cast<wchar_t> (u)); +    } + +    if (r.empty ()) +      r = L"cxx"; + +    // Custom reserved words. +    // +    ReservedNameMap::const_iterator i (reserved_name_map.find (r)); + +    if (i != reserved_name_map.end ()) +    { +      if (i->second) +        return i->second; +      else +        r += L'_'; +    } + +    // Keywords +    // +    if (keyword_set.find (r) != keyword_set.end ()) +    { +      r += L'_'; + +      // Re-run custom words. +      // +      i = reserved_name_map.find (r); + +      if (i != reserved_name_map.end ()) +      { +        if (i->second) +          return i->second; +        else +          r += L'_'; +      } +    } + +    return r; +  } + +  // String escaping. +  // + +  String +  charlit (unsigned int u) +  { +    String r ("\\x"); +    bool lead (true); + +    for (int i (7); i >= 0; --i) +    { +      unsigned int x ((u >> (i * 4)) & 0x0F); + +      if (lead) +      { +        if (x == 0) +          continue; + +        lead = false; +      } + +      r += x < 10 ? ('0' + x) : ('A' + x - 10); +    } + +    return r; +  } + +  String +  strlit_ascii (String const& str) +  { +    String r; +    size_t n (str.size ()); + +    // In most common cases we will have that many chars. +    // +    r.reserve (n + 2); + +    r += '"'; + +    bool escape (false); + +    for (size_t i (0); i < n; ++i) +    { +      unsigned int u (Context::unicode_char (str, i)); // May advance i. + +      // [128 - ]     - unrepresentable +      // 127          - \x7F +      // [32  - 126]  - as is +      // [0   - 31]   - \X or \xXX +      // + +      if (u < 32 || u == 127) +      { +        switch (u) +        { +        case L'\n': +          { +            r += L"\\n"; +            break; +          } +        case L'\t': +          { +            r += L"\\t"; +            break; +          } +        case L'\v': +          { +            r += L"\\v"; +            break; +          } +        case L'\b': +          { +            r += L"\\b"; +            break; +          } +        case L'\r': +          { +            r += L"\\r"; +            break; +          } +        case L'\f': +          { +            r += L"\\f"; +            break; +          } +        case L'\a': +          { +            r += L"\\a"; +            break; +          } +        default: +          { +            r += charlit (u); +            escape = true; +            break; +          } +        } +      } +      else if (u < 127) +      { +        if (escape) +        { +          // Close and open the string so there are no clashes. +          // +          r += '"'; +          r += '"'; + +          escape = false; +        } + +        switch (u) +        { +        case L'"': +          { +            r += L"\\\""; +            break; +          } +        case L'\\': +          { +            r += L"\\\\"; +            break; +          } +        default: +          { +            r += static_cast<wchar_t> (u); +            break; +          } +        } +      } +      else +      { +        // Unrepresentable character. +        // +        throw UnrepresentableCharacter (str, i + 1); +      } +    } + +    r += '"'; + +    return r; +  } + +  const unsigned int utf8_first_char_mask[5] = +  { +    0x00, 0x00, 0xC0, 0xE0, 0xF0 +  }; + +  String +  strlit_utf8 (String const& str) +  { +    String r; +    size_t n (str.size ()); + +    // In most common cases we will have that many chars. +    // +    r.reserve (n + 2); + +    r += '"'; + +    bool escape (false); + +    for (size_t i (0); i < n; ++i) +    { +      unsigned int u (Context::unicode_char (str, i)); // May advance i. + +      // [128 - ]     - UTF-8 +      // 127          - \x7F +      // [32  - 126]  - as is +      // [0   - 31]   - \X or \xXX +      // + +      if (u < 32 || u == 127) +      { +        switch (u) +        { +        case L'\n': +          { +            r += L"\\n"; +            break; +          } +        case L'\t': +          { +            r += L"\\t"; +            break; +          } +        case L'\v': +          { +            r += L"\\v"; +            break; +          } +        case L'\b': +          { +            r += L"\\b"; +            break; +          } +        case L'\r': +          { +            r += L"\\r"; +            break; +          } +        case L'\f': +          { +            r += L"\\f"; +            break; +          } +        case L'\a': +          { +            r += L"\\a"; +            break; +          } +        default: +          { +            r += charlit (u); +            escape = true; +            break; +          } +        } +      } +      else if (u < 127) +      { +        if (escape) +        { +          // Close and open the string so there are no clashes. +          // +          r += '"'; +          r += '"'; + +          escape = false; +        } + +        switch (u) +        { +        case L'"': +          { +            r += L"\\\""; +            break; +          } +        case L'\\': +          { +            r += L"\\\\"; +            break; +          } +        default: +          { +            r += static_cast<wchar_t> (u); +            break; +          } +        } +      } +      else +      { +        unsigned int count (0); +        unsigned int tmp[4]; + +        if (u < 0x800) +          count = 2; +        else if (u < 0x10000) +          count = 3; +        else if (u < 0x110000) +          count = 4; + +        switch (count) +        { +        case 4: +          { +            tmp[3] = (u | 0x80UL) & 0xBFUL; +            u >>= 6; +          } +          // Fall through. +        case 3: +          { +            tmp[2] = (u | 0x80UL) & 0xBFUL; +            u >>= 6; +          } +          // Fall through. +        case 2: +          { +            tmp[1] = (u | 0x80UL) & 0xBFUL; +            u >>= 6; +          } +          // Fall through. +        case 1: +          { +            tmp[0] = u | utf8_first_char_mask[count]; +            break; +          } +        default: +          assert (false); +        } + +        for (unsigned int j (0); j < count; ++j) +          r += charlit (tmp[j]); + +        escape = true; +      } +    } + +    r += '"'; + +    return r; +  } + +  String +  strlit_iso8859_1 (String const& str) +  { +    String r; +    size_t n (str.size ()); + +    // In most common cases we will have that many chars. +    // +    r.reserve (n + 2); + +    r += '"'; + +    bool escape (false); + +    for (size_t i (0); i < n; ++i) +    { +      unsigned int u (Context::unicode_char (str, i)); // May advance i. + +      // [256 -    ]  - unrepresentable +      // [127 - 255]  - \xXX +      // [32  - 126]  - as is +      // [0   - 31]   - \X or \xXX +      // + +      if (u < 32) +      { +        switch (u) +        { +        case L'\n': +          { +            r += L"\\n"; +            break; +          } +        case L'\t': +          { +            r += L"\\t"; +            break; +          } +        case L'\v': +          { +            r += L"\\v"; +            break; +          } +        case L'\b': +          { +            r += L"\\b"; +            break; +          } +        case L'\r': +          { +            r += L"\\r"; +            break; +          } +        case L'\f': +          { +            r += L"\\f"; +            break; +          } +        case L'\a': +          { +            r += L"\\a"; +            break; +          } +        default: +          { +            r += charlit (u); +            escape = true; +            break; +          } +        } +      } +      else if (u < 127) +      { +        if (escape) +        { +          // Close and open the string so there are no clashes. +          // +          r += '"'; +          r += '"'; + +          escape = false; +        } + +        switch (u) +        { +        case L'"': +          { +            r += L"\\\""; +            break; +          } +        case L'\\': +          { +            r += L"\\\\"; +            break; +          } +        default: +          { +            r += static_cast<wchar_t> (u); +            break; +          } +        } +      } +      else if (u < 256) +      { +        r += charlit (u); +        escape = true; +      } +      else +      { +        // Unrepresentable character. +        // +        throw UnrepresentableCharacter (str, i + 1); +      } +    } + +    r += '"'; + +    return r; +  } + +  String +  strlit_utf32 (String const& str) +  { +    String r; +    size_t n (str.size ()); + +    // In most common cases we will have that many chars. +    // +    r.reserve (n + 3); + +    r += L"L\""; + +    bool escape (false); + +    for (size_t i (0); i < n; ++i) +    { +      unsigned int u (Context::unicode_char (str, i)); // May advance i. + +      // [128 - ]     - \xUUUUUUUU +      // 127          - \x7F +      // [32  - 126]  - as is +      // [0   - 31]   - \X or \xXX +      // + +      if (u < 32 || u == 127) +      { +        switch (u) +        { +        case L'\n': +          { +            r += L"\\n"; +            break; +          } +        case L'\t': +          { +            r += L"\\t"; +            break; +          } +        case L'\v': +          { +            r += L"\\v"; +            break; +          } +        case L'\b': +          { +            r += L"\\b"; +            break; +          } +        case L'\r': +          { +            r += L"\\r"; +            break; +          } +        case L'\f': +          { +            r += L"\\f"; +            break; +          } +        case L'\a': +          { +            r += L"\\a"; +            break; +          } +        default: +          { +            r += charlit (u); +            escape = true; +            break; +          } +        } +      } +      else if (u < 127) +      { +        if (escape) +        { +          // Close and open the string so there are no clashes. C++11 +          // requires a space between " and L. +          // +          r += L"\" L\""; +          escape = false; +        } + +        switch (u) +        { +        case L'"': +          { +            r += L"\\\""; +            break; +          } +        case L'\\': +          { +            r += L"\\\\"; +            break; +          } +        default: +          { +            r += static_cast<wchar_t> (u); +            break; +          } +        } +      } +      else +      { +        r += charlit (u); +        escape = true; +      } +    } + +    r += '"'; + +    return r; +  } + +  String Context:: +  strlit (String const& str) +  { +    // First see if we have a custom mapping. +    // +    assert (string_literal_map != 0); +    StringLiteralMap::const_iterator i (string_literal_map->find (str)); + +    if (i != string_literal_map->end ()) +      return i->second; + +    if (char_type == L"char") +    { +      if (char_encoding == L"utf8") +        return strlit_utf8 (str); +      else if (char_encoding == L"iso8859-1") +        return strlit_iso8859_1 (str); +      else +      { +        // For LCP, custom, and other unknown encodings, use ASCII. +        // +        return strlit_ascii (str); +      } +    } +    else +      return strlit_utf32 (str); +  } + +  String Context:: +  comment (String const& str) +  { +    String r; + +    wchar_t const* s (str.c_str ()); +    size_t size (str.size ()); + +    // In most common cases we will have that many chars. +    // +    r.reserve (size); + +    for (wchar_t const* p (s); p < s + size; ++p) +    { +      unsigned int u (unicode_char (p)); // May advance p. + +      // We are going to treat \v, \f and \n as unrepresentable +      // here even though they can be present in C++ source code. +      // +      if (u > 127 || (u < 32 && u != '\t')) +        r += L'?'; +      else +        r += static_cast<wchar_t> (u); +    } + +    return r; +  } + +  String Context:: +  process_include_path (String const& name) const +  { +    String path (String (options.include_prefix ()) + name); +    bool trace (options.include_regex_trace ()); + +    if (trace) +      wcerr << "include: '" << path << "'" << endl; + +    String r; +    bool found (false); + +    for (RegexMapping::const_reverse_iterator e (include_mapping.rbegin ()); +         e != include_mapping.rend (); ++e) +    { +      if (trace) +        wcerr << "try: '" << e->regex () << "' : "; + +      if (e->match (path)) +      { +        r = e->replace (path); +        found = true; + +        if (trace) +          wcerr << "'" << r << "' : "; +      } + +      if (trace) +        wcerr << (found ? '+' : '-') << endl; + +      if (found) +        break; +    } + +    if (!found) +      r = path; + +    if (!r.empty () && r[0] != L'"' && r[0] != L'<') +    { +      wchar_t op (options.include_with_brackets () ? L'<' : L'"'); +      wchar_t cl (options.include_with_brackets () ? L'>' : L'"'); +      r = op + r + cl; +    } + +    return r; +  } + +  // Namespace +  // + +  void Namespace:: +  pre (Type& n) +  { +    String ns (ctx_.ns_name (n)); + +    String::size_type b (0), e; + +    if (st_) +      st_->enter (n, L"", ns ? false : true); + +    do +    { +      e = ns.find (L"::", b); + +      String name (ns, b, e == ns.npos ? e : e - b); + +      if (!name.empty ()) +      { +        if (st_) +          st_->enter (n, name, e == ns.npos); + +        ctx_.os << "namespace " << name << "{"; +      } + +      b = e; + +      if (b == ns.npos) +        break; + +      b += 2; + +    } while (true); +  } + +  void Namespace:: +  post (Type& n) +  { +    String ns (ctx_.ns_name (n)); + +    String::size_type b (0), e; + +    do +    { +      e = ns.find (L"::", b); + +      String name (ns, b, e == ns.npos ? e : e - b); + +      if (!name.empty ()) +      { +        ctx_.os << "}"; + +        if (st_) +          st_->leave (); +      } + + +      b = e; + +      if (b == ns.npos) +        break; + +      b += 2; + +    } +    while (true); + +    if (st_) +      st_->leave (); +  } +} diff --git a/xsd/cxx/elements.hxx b/xsd/cxx/elements.hxx new file mode 100644 index 0000000..62ba97c --- /dev/null +++ b/xsd/cxx/elements.hxx @@ -0,0 +1,626 @@ +// file      : xsd/cxx/elements.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_ELEMENTS_HXX +#define XSD_CXX_ELEMENTS_HXX + +#include <set> +#include <map> +#include <vector> +#include <ostream> + +#include <libcutl/re.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/types.hxx> +#include <xsd/elements.hxx> + +#include <xsd/cxx/options.hxx> +#include <xsd/cxx/literal-map.hxx> + +namespace CXX +{ +  using std::endl; + +  // On some platforms std::toupper can be something other than a +  // function with C++ linkage. +  // +  wchar_t +  upcase (wchar_t c); + + +  // Exceptions. +  // + +  struct UnrepresentableCharacter +  { +    UnrepresentableCharacter (String const& str, size_t pos) +        : str_ (str), pos_ (pos) +    { +    } + +    String const& +    string () const +    { +      return str_; +    } + +    size_t +    position () const +    { +      return pos_; +    } + +  private: +    String str_; +    size_t pos_; +  }; + +  struct NoNamespaceMapping +  { +    NoNamespaceMapping (SemanticGraph::Path const& file, +                        size_t line, +                        size_t column, +                        String const& ns) +        : file_ (file), +          line_ (line), +          column_ (column), +          ns_ (ns) +    { +    } + + +    SemanticGraph::Path const& +    file () const +    { +      return file_; +    } + +    size_t +    line () const +    { +      return line_; +    } + +    size_t +    column () const +    { +      return column_; +    } + +    String const& +    ns () const +    { +      return ns_; +    } + +  private: +    SemanticGraph::Path file_; +    size_t line_; +    size_t column_; +    String ns_; +  }; + +  struct InvalidNamespaceMapping +  { +    InvalidNamespaceMapping (String const& mapping, +                             String const& reason) +        : mapping_ (mapping), reason_ (reason) +    { +    } + +    String const& +    mapping () const +    { +      return mapping_; +    } + +    String const& +    reason () const +    { +      return reason_; +    } + +  private: +    String mapping_; +    String reason_; +  }; + +  // +  // +  class Context +  { +  public: +    typedef cutl::re::wregex RegexPat; +    typedef cutl::re::wregexsub Regex; +    typedef std::vector<Regex> RegexMapping; +    typedef std::map<String, String> MapMapping; +    typedef std::map<String, String> MappingCache; + +    typedef std::map<String, String> ReservedNameMap; +    typedef std::set<String> KeywordSet; + +    typedef CXX::options options_type; + +  public: +    Context (std::wostream& o, +             SemanticGraph::Schema& root, +             SemanticGraph::Path const& path, +             options_type const& ops, +             StringLiteralMap const* custom_literals_map); + +  protected: +    Context (Context& c) +        : os (c.os), +          schema_root (c.schema_root), +          schema_path (c.schema_path), +          options (c.options), +          std (c.std), +          char_type (c.char_type), +          char_encoding (c.char_encoding), +          L (c.L), +          string_type (c.string_type), +          auto_ptr (c.auto_ptr), +          string_literal_map (c.string_literal_map), +          type_exp (c.type_exp), +          inst_exp (c.inst_exp), +          inl (c.inl), +          ns_mapping_cache (c.ns_mapping_cache), +          xs_ns_ (c.xs_ns_), +          cxx_id_expr (c.cxx_id_expr), +          urn_mapping (c.urn_mapping), +          nsr_mapping (c.nsr_mapping), +          nsm_mapping (c.nsm_mapping), +          include_mapping (c.include_mapping), +          reserved_name_map (c.reserved_name_map), +          keyword_set (c.keyword_set) +    { +    } + +    Context (Context& c, std::wostream& o) +        : os (o), +          schema_root (c.schema_root), +          schema_path (c.schema_path), +          options (c.options), +          std (c.std), +          char_type (c.char_type), +          char_encoding (c.char_encoding), +          L (c.L), +          string_type (c.string_type), +          auto_ptr (c.auto_ptr), +          string_literal_map (c.string_literal_map), +          type_exp (c.type_exp), +          inst_exp (c.inst_exp), +          inl (c.inl), +          ns_mapping_cache (c.ns_mapping_cache), +          xs_ns_ (c.xs_ns_), +          cxx_id_expr (c.cxx_id_expr), +          urn_mapping (c.urn_mapping), +          nsr_mapping (c.nsr_mapping), +          nsm_mapping (c.nsm_mapping), +          include_mapping (c.include_mapping), +          reserved_name_map (c.reserved_name_map), +          keyword_set (c.keyword_set) +    { +    } + +  public: +    static String +    unclash (String const& name, String const& new_name) +    { +      return name == new_name ? (new_name + L'_') : new_name; +    } + +  public: +    // Return UTF-32 character starting at this position. Position is +    // advanced by 1 if this Unicode character takes more than one +    // underlying character. +    // +    static unsigned int +    unicode_char (String const& str, size_t& pos); + +    static unsigned int +    unicode_char (wchar_t const*& p); + +    // Escape C++ keywords and illegal characters. +    // +    String +    escape (String const&); + +    // Create a string literal so that it can be used in C++ source +    // code. It includes "". +    // +    String +    strlit (String const&); + +    // Escape the string so that it can be used in C++ comment. +    // +    String +    comment (String const&); + +    // Translate XML namespace name to a C++ identifier. +    // +    String +    ns_name (SemanticGraph::Namespace&); + +    // XML Schema namespace. +    // +    SemanticGraph::Namespace& +    xs_ns (); + +    // C++ namespace for XML Schema. +    // +    String +    xs_ns_name (); + +    // +    // +    SemanticGraph::Namespace& +    namespace_ (SemanticGraph::Nameable& n); + +    // Original XML namespace name. +    // +    String +    xml_ns_name (SemanticGraph::Nameable& ns); + + +    // Fully-qualified C++ name. +    // +    String +    fq_name (SemanticGraph::Nameable& n, char const* name_key = "name"); + +  public: +    static SemanticGraph::Type& +    ultimate_base (SemanticGraph::Complex&); + +  public: +    String +    process_include_path (String const&) const; + +  public: +    static bool +    skip (SemanticGraph::Member& m) +    { +      // "Subsequent" local element. +      // +      return !m.scope ().is_a<SemanticGraph::Namespace> () && +        m.context ().count ("min") == 0; +    } + +    static size_t +    min (SemanticGraph::Member const& m) +    { +      return m.context ().get<size_t> ("min"); +    } + +    static size_t +    min (SemanticGraph::Any const& a) +    { +      return a.context ().get<size_t> ("min"); +    } + +    static size_t +    max (SemanticGraph::Member const& m) +    { +      return m.context ().get<size_t> ("max"); +    } + +    static size_t +    max (SemanticGraph::Any const& a) +    { +      return a.context ().get<size_t> ("max"); +    } + +  public: +    // Get escaped name. +    // +    static String const& +    ename (SemanticGraph::Nameable const& n) +    { +      return n.context ().get<String> ("name"); +    } + +  public: +    std::wostream& os; + +    SemanticGraph::Schema& schema_root; +    SemanticGraph::Path const& schema_path; + +    options_type const& options; + +    cxx_version std; + +    String& char_type; +    String& char_encoding; +    String& L;                  // string literal prefix +    String& string_type; +    String& auto_ptr; + +    StringLiteralMap const* string_literal_map; + +    String& type_exp; +    String& inst_exp; +    String& inl; + +  public: +    MappingCache& ns_mapping_cache; + +  private: +    SemanticGraph::Path const schema_path_; + +    SemanticGraph::Namespace* xs_ns_; + +    String char_type_; +    String char_encoding_; +    String L_; +    String string_type_; +    String auto_ptr_; + +    String type_exp_; +    String inst_exp_; +    String inl_; + +  private: +    RegexPat const cxx_id_expr_; +    RegexPat const& cxx_id_expr; +    Regex urn_mapping_; +    RegexMapping nsr_mapping_; +    MapMapping nsm_mapping_; +    Regex const& urn_mapping; +    RegexMapping const& nsr_mapping; +    MapMapping const& nsm_mapping; +    MappingCache ns_mapping_cache_; + +    RegexMapping include_mapping_; +    RegexMapping const& include_mapping; + +    ReservedNameMap const& reserved_name_map; +    ReservedNameMap reserved_name_map_; + +    KeywordSet const& keyword_set; +    KeywordSet keyword_set_; +  }; + +  inline unsigned int Context:: +  unicode_char (String const& str, size_t& pos) +  { +    if (sizeof (wchar_t) == 4) +    { +      return str[pos]; +    } +    else if (sizeof (wchar_t) == 2) +    { +      wchar_t x (str[pos]); + +      if (x < 0xD800 || x > 0xDBFF) +        return x; +      else +        return ((x - 0xD800) << 10) + (str[++pos] - 0xDC00) + 0x10000; +    } +    else +      return 0; +  } + +  inline unsigned int Context:: +  unicode_char (wchar_t const*& p) +  { +    if (sizeof (wchar_t) == 4) +    { +      return *p; +    } +    else if (sizeof (wchar_t) == 2) +    { +      wchar_t x (*p); + +      if (x < 0xD800 || x > 0xDBFF) +        return x; +      else +        return ((x - 0xD800) << 10) + (*(++p) - 0xDC00) + 0x10000; +    } +    else +      return 0; +  } + +  // Sources traverser that goes into each schema only once. +  // +  struct Sources: Traversal::Sources +  { +    virtual void +    traverse (SemanticGraph::Sources& s) +    { +      if (schemas_.insert (&s.schema ()).second) +        Traversal::Sources::traverse (s); +    } + +  private: +    std::set<SemanticGraph::Schema*> schemas_; +  }; + +  // Usual namespace mapping. +  // +  struct Namespace: Traversal::Namespace +  { +    struct ScopeTracker +    { +      // First scope name if always empty (global scope). The last flag +      // signals the last scope. +      // +      virtual void +      enter (Type&, String const& name, bool last) = 0; + +      virtual void +      leave () = 0; +    }; + + +    Namespace (Context& c) +        : ctx_ (c), st_ (0) +    { +    } + +    Namespace (Context& c, ScopeTracker& st) +        : ctx_ (c), st_ (&st) +    { +    } + +    virtual void +    pre (Type&); + +    virtual void +    post (Type&); + +  private: +    Context& ctx_; +    ScopeTracker* st_; +  }; + +  // +  // +  template <typename X> +  struct Has : X +  { +    Has (bool& result) +        : result_ (result) +    { +    } + +    virtual void +    traverse (typename X::Type&) +    { +      result_ = true; +    } + +  private: +    bool& result_; +  }; + +  // Checks if scope 'Y' names any of 'X' +  // +  template <typename X, typename Y> +  bool +  has (Y& y) +  { +    using SemanticGraph::Scope; + +    bool result (false); +    Has<X> t (result); + +    for (Scope::NamesIterator i (y.names_begin ()), e (y.names_end ()); +         !result && i != e; ++i) +      t.dispatch (i->named ()); + +    return result; +  } + +  // Checks if the compositor has any particle of 'X' +  // +  template <typename X> +  bool +  has_particle (SemanticGraph::Compositor& y) +  { +    using SemanticGraph::Compositor; + +    bool result (false); +    Has<X> t (result); + +    for (Compositor::ContainsIterator i (y.contains_begin ()), +           e (y.contains_end ()); !result && i != e; ++i) +    { +      SemanticGraph::Particle& p (i->particle ()); + +      t.dispatch (p); + +      if (!result && p.is_a<Compositor> ()) +        result = has_particle<X> (dynamic_cast<Compositor&> (p)); +    } + +    return result; +  } + +  // Specialization for Complex +  // +  template <typename X> +  bool +  has_particle (SemanticGraph::Complex& c) +  { +    return c.contains_compositor_p () && +      has_particle<X> (c.contains_compositor ().compositor ()); +  } + +  // Fundamental type mapping helper. +  // +  struct Fundamental: Traversal::Fundamental::Type, +                      Traversal::Fundamental::String, +                      Traversal::Fundamental::NormalizedString, +                      Traversal::Fundamental::Token, +                      Traversal::Fundamental::Name, +                      Traversal::Fundamental::NameToken, +                      Traversal::Fundamental::NCName, +                      Traversal::Fundamental::Id, +                      Traversal::Fundamental::IdRef +  { +    virtual void +    fundamental_type (SemanticGraph::Fundamental::Type& t) = 0; + +    virtual void +    fundamental_template (SemanticGraph::Fundamental::Type& t) = 0; + +    virtual void +    traverse (SemanticGraph::Fundamental::Type& t) +    { +      fundamental_type (t); +    } + +    virtual void +    traverse (SemanticGraph::Fundamental::String& t) +    { +      fundamental_template (t); +    } + +    virtual void +    traverse (SemanticGraph::Fundamental::NormalizedString& t) +    { +      fundamental_template (t); +    } + +    virtual void +    traverse (SemanticGraph::Fundamental::Token& t) +    { +      fundamental_template (t); +    } + +    virtual void +    traverse (SemanticGraph::Fundamental::Name& t) +    { +      fundamental_template (t); +    } + +    virtual void +    traverse (SemanticGraph::Fundamental::NameToken& t) +    { +      fundamental_template (t); +    } + +    virtual void +    traverse (SemanticGraph::Fundamental::NCName& t) +    { +      fundamental_template (t); +    } + +    virtual void +    traverse (SemanticGraph::Fundamental::Id& t) +    { +      fundamental_template (t); +    } + +    virtual void +    traverse (SemanticGraph::Fundamental::IdRef& t) +    { +      fundamental_template (t); +    } +  }; +} + +#endif  // XSD_CXX_TREE_ELEMENTS_HXX diff --git a/xsd/cxx/literal-map.cxx b/xsd/cxx/literal-map.cxx new file mode 100644 index 0000000..b81f249 --- /dev/null +++ b/xsd/cxx/literal-map.cxx @@ -0,0 +1,261 @@ +// file      : xsd/cxx/literal-map.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <memory>  // std::unique_ptr +#include <cstddef> // std::size_t +#include <fstream> +#include <iostream> + +#include <xercesc/util/XMLUni.hpp> + +#include <xercesc/framework/LocalFileInputSource.hpp> + +#include <xercesc/sax/Locator.hpp> +#include <xercesc/sax/SAXParseException.hpp> +#include <xercesc/sax2/DefaultHandler.hpp> +#include <xercesc/sax2/SAX2XMLReader.hpp> +#include <xercesc/sax2/XMLReaderFactory.hpp> + +#include <libxsd-frontend/xml.hxx> + +#include <xsd/cxx/literal-map.hxx> + +using namespace std; +using namespace xercesc; +namespace XML = XSDFrontend::XML; + +namespace CXX +{ +  class Handler: public DefaultHandler +  { +  public: +    struct Failed {}; + +    Handler (String const& file, StringLiteralMap& map) +        : state_ (s_init), file_ (file), map_ (map) +    { +    } + +    virtual void +    setDocumentLocator (const Locator* const l) +    { +      locator_ = l; +    } + +    virtual void +    startElement (const XMLCh* const, +                  const XMLCh* const lname, +                  const XMLCh* const, +                  const xercesc::Attributes&) +    { +      String n (XML::transcode (lname)); + +      if (n == L"string-literal-map" && state_ == s_init) +        state_ = s_map; +      else if (n == L"entry" && state_ == s_map) +      { +        str_seen_ = false; +        lit_seen_ = false; +        state_ = s_entry; +      } +      else if (n == L"string" && state_ == s_entry) +      { +        str_seen_ = true; +        str_.clear (); +        state_ = s_string; +      } +      else if (n == L"literal" && state_ == s_entry) +      { +        lit_seen_ = true; +        lit_.clear (); +        state_ = s_literal; +      } +      else +      { +        wcerr << file_ << ":" << line () << ":" << col () << ": error: " +              << "unexpected element '" << n << "'" << endl; +        throw Failed (); +      } +    } + +    virtual void +    endElement (const XMLCh* const, +                const XMLCh* const lname, +                const XMLCh* const) +    { +      String n (XML::transcode (lname)); + +      if (n == L"string-literal-map") +        state_ = s_init; +      else if (n == L"entry") +      { +        if (!str_seen_) +        { +          wcerr << file_ << ":" << line () << ":" << col () << ": error: " +                << "expected 'string' element" << endl; +          throw Failed (); +        } + +        if (!lit_seen_) +        { +          wcerr << file_ << ":" << line () << ":" << col () << ": error: " +                << "expected 'literal' element" << endl; +          throw Failed (); +        } + +        map_[str_] = lit_; +        state_ = s_map; +      } +      else if (n == L"string") +        state_ = s_entry; +      else if (n == L"literal") +        state_ = s_entry; +    } + +    virtual void +    characters (const XMLCh* const s, const XMLSize_t length) +    { +      String str (XML::transcode (s, length)); + +      if (state_ == s_string) +        str_ += str; +      else if (state_ == s_literal) +        lit_ += str; +      else +      { +        for (size_t i (0); i < str.size (); ++i) +        { +          wchar_t c (str[i]); + +          if (c != 0x20 && c != 0x0A && c != 0x0D && c != 0x09) +          { +            wcerr << file_ << ":" << line () << ":" << col () << ": error: " +                  << "unexpected character data" << endl; +            throw Failed (); +          } +        } +      } +    } + +    // Error hanlding. +    // +    enum Severity {s_warning, s_error, s_fatal}; + +    virtual void +    warning (const SAXParseException& e) +    { +      handle (e, s_warning); +    } + +    virtual void +    error (const SAXParseException& e) +    { +      handle (e, s_error); +    } + +    virtual void +    fatalError (const SAXParseException& e) +    { +      handle (e, s_fatal); +    } + +    virtual void +    resetErrors () +    { +    } + +    void +    handle (const SAXParseException& e, Severity s) +    { +      String msg (XML::transcode (e.getMessage ())); + +      wcerr << file_ << ":" +            << e.getLineNumber () << ":" << e.getColumnNumber () << ": " +            << (s == s_warning ? "warning: " : "error: ") << msg << endl; + +      if (s != s_warning) +        throw Failed (); +    } + +    size_t +    line () const +    { +      return locator_ != 0 +        ? static_cast<size_t> (locator_->getLineNumber ()) +        : 0; +    } + +    size_t +    col () const +    { +      return locator_ != 0 +        ? static_cast<size_t> (locator_->getColumnNumber ()) +        : 0; +    } + +  private: +    const Locator* locator_; + +    enum +    { +      s_init, +      s_map, +      s_entry, +      s_string, +      s_literal +    } state_; + +    String file_; +    StringLiteralMap& map_; + +    bool str_seen_; +    bool lit_seen_; + +    String str_; +    String lit_; +  }; + +  bool +  read_literal_map (NarrowString const& file, StringLiteralMap& map) +  { +    try +    { +      // Try to open the file with fstream. This way we get to +      // report the error in a consistent manner. +      // +      { +        ifstream ifs (file.c_str ()); +        if (!ifs.is_open ()) +        { +          wcerr << file.c_str () << ": unable to open in read mode" << endl; +          return false; +        } +      } + +      String wfile (file); + +      LocalFileInputSource is (XML::XMLChString (wfile).c_str ()); +      Handler h (wfile, map); + +      unique_ptr<SAX2XMLReader> parser ( +        XMLReaderFactory::createXMLReader ()); + +      parser->setFeature (XMLUni::fgSAX2CoreNameSpaces, true); +      parser->setFeature (XMLUni::fgSAX2CoreNameSpacePrefixes, true); +      parser->setFeature (XMLUni::fgSAX2CoreValidation, false); +      parser->setFeature (XMLUni::fgXercesSchema, false); +      parser->setFeature (XMLUni::fgXercesSchemaFullChecking, false); + +      parser->setErrorHandler (&h); +      parser->setContentHandler (&h); + +      parser->parse (is); +    } +    catch (Handler::Failed const&) +    { +      return false; +    } + +    return true; +  } +} diff --git a/xsd/cxx/literal-map.hxx b/xsd/cxx/literal-map.hxx new file mode 100644 index 0000000..bc8fabb --- /dev/null +++ b/xsd/cxx/literal-map.hxx @@ -0,0 +1,19 @@ +// file      : xsd/cxx/literal-map.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_LITERAL_MAP_HXX +#define XSD_CXX_LITERAL_MAP_HXX + +#include <map> + +#include <xsd/types.hxx> + +namespace CXX +{ +  typedef std::map<String, String> StringLiteralMap; + +  bool +  read_literal_map (NarrowString const& file, StringLiteralMap& map); +} + +#endif // XSD_CXX_LITERAL_MAP_HXX diff --git a/xsd/cxx/option-types.cxx b/xsd/cxx/option-types.cxx new file mode 100644 index 0000000..8744d7f --- /dev/null +++ b/xsd/cxx/option-types.cxx @@ -0,0 +1,59 @@ +// file      : xsd/cxx/option-types.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <istream> +#include <ostream> + +#include <xsd/cxx/option-types.hxx> + +using namespace std; + +namespace CXX +{ +  // +  // cxx_version +  // + +  static const char* cxx_version_[] = +  { +    "c++98", +    "c++11", +    "c++14", +    "c++17", +    "c++20", +    "c++23", +  }; + +  string cxx_version:: +  string () const +  { +    return cxx_version_[v_]; +  } + +  istream& +  operator>> (istream& is, cxx_version& v) +  { +    string s; +    is >> s; + +    if (!is.fail ()) +    { +      if (s == "c++98") +        v = cxx_version::cxx98; +      else if (s == "c++11") +        v = cxx_version::cxx11; +      else if (s == "c++14") +        v = cxx_version::cxx14; +      else if (s == "c++17") +        v = cxx_version::cxx17; +      else if (s == "c++20") +        v = cxx_version::cxx20; +      else if (s == "c++23") +        v = cxx_version::cxx23; +      else +        is.setstate (istream::failbit); +    } + +    return is; +  } +} diff --git a/xsd/cxx/option-types.hxx b/xsd/cxx/option-types.hxx new file mode 100644 index 0000000..98a493a --- /dev/null +++ b/xsd/cxx/option-types.hxx @@ -0,0 +1,38 @@ +// file      : xsd/cxx/option-types.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_XSD_OPTION_TYPES_HXX +#define XSD_XSD_OPTION_TYPES_HXX + +#include <iosfwd> +#include <string> + +namespace CXX +{ +  struct cxx_version +  { +    enum value +    { +      cxx98, +      cxx11, +      cxx14, +      cxx17, +      cxx20, +      cxx23 +    }; + +    cxx_version (value v) : v_ (v) {} +    operator value () const {return v_;} + +    std::string +    string () const; + +  private: +    value v_; +  }; + +  std::istream& +  operator>> (std::istream&, cxx_version&); +} + +#endif // XSD_XSD_OPTION_TYPES_HXX diff --git a/xsd/cxx/options.cli b/xsd/cxx/options.cli new file mode 100644 index 0000000..1be7607 --- /dev/null +++ b/xsd/cxx/options.cli @@ -0,0 +1,560 @@ +// file      : xsd/cxx/options.cli +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include <cstddef>; // std::size_t + +include <xsd/types.hxx>; // NarrowString, NarrowStrings + +include <xsd/cxx/option-types.hxx>; + +include <xsd/options.cli>; + +namespace CXX +{ +  class options: ::options = 0 +  { +    // Language. +    // +    cxx_version --std = cxx_version::cxx11 +    { +      "<version>", +      "Specify the C++ standard that the generated code should conform to. +       Valid values are \cb{c++98}, \cb{c++11} (default), \cb{c++14}, +       \cb{c++17}, \cb{c++20}, and \cb{c++23}. + +       The C++ standard affects various aspects of the generated code that +       are discussed in more detail in various mapping-specific +       documentation. Overall, when C++11 is selected, the generated +       code relies on the move semantics and uses \cb{std::unique_ptr} +       instead of deprecated \cb{std::auto_ptr}. Currently, there is no +       difference between the C++11 and the later standards modes. + +       When the C++11 mode is selected, you normally don't need to +       perform any extra steps other than enable C++11 in your C++ +       compiler, if required. The XSD compiler will automatically +       add the necessary macro defines to the generated header files +       that will switch the header-only XSD runtime library (\cb{libxsd}) +       to the C++11 mode. However, if you include any of the XSD runtime +       headers directly in your application (normally you just include +       the generated headers), then you will need to define the +       \cb{XSD_CXX11} macro for your entire project." +    }; + +    // Character type and encoding. +    // +    NarrowString --char-type = "char" +    { +      "<type>", +      "Generate code using the provided character <type> instead of the +       default \cb{char}. Valid values are \cb{char} and \cb{wchar_t}." +    }; + +    NarrowString --char-encoding +    { +      "<enc>", +      "Specify the character encoding that should be used in the generated +       code. Valid values for the \cb{char} character type are \cb{utf8} +       (default), \cb{iso8859-1}, \cb{lcp} (Xerces-C++ local code page), +       and \cb{custom}. If you pass \cb{custom} as the value then you will +       need to include the transcoder implementation header for your +       encoding at the beginning of the generated header files (see the +       \cb{--hxx-prologue} option). + +       For the \cb{wchar_t} character type the only valid value is \cb{auto} +       and the encoding is automatically selected between UTF-16 and +       UTF-32/UCS-4, depending on the \cb{wchar_t} type size." +    }; + +    // Output options. +    // +    NarrowString --output-dir +    { +      "<dir>", +      "Write generated files to <dir> instead of the current directory." +    }; + +    bool --generate-inline +    { +      "Generate simple functions inline. This option triggers creation of +       the inline file." +    }; + +    // Extern XML Schema. +    // +    bool --generate-xml-schema +    { +      "Generate a C++ header file as if the schema being compiled defines the +       XML Schema namespace. For the C++/Tree mapping, the resulting file will +       contain definitions for all XML Schema built-in types. For the +       C++/Parser mapping, the resulting file will contain definitions for +       all the parser skeletons and implementations corresponding to the +       XML Schema built-in types. + +       The schema file provided to the compiler need not exist and is only +       used to derive the name of the resulting header file. Use the +       \cb{--extern-xml-schema} option to include this file in the +       generated files for other schemas." +     }; + +    NarrowString --extern-xml-schema +    { +      "<file>", +      "Include a header file derived from <file> instead of generating the +       XML Schema namespace mapping inline. The provided file need not +       exist and is only used to derive the name of the included header +       file. Use the \cb{--generate-xml-schema} option to generate this +       header file." +     }; + +    // Namespace mapping. +    // +    NarrowStrings --namespace-map +    { +      "<xns>=<cns>", +      "Map XML Schema namespace <xns> to C++ namespace <cns>. Repeat +       this option to specify mapping for more than one XML Schema namespace. +       For example, the following option: + +       \cb{--namespace-map http://example.com/foo/bar=foo::bar} + +       Will map the \cb{http://example.com/foo/bar} XML Schema namespace to +       the \cb{foo::bar} C++ namespace." +    }; + +    NarrowStrings --namespace-regex +    { +      "<regex>", +      "Add <regex> to the list of regular expressions used to translate XML +       Schema namespace names to C++ namespace names. <regex> is a Perl-like +       regular expression in the form +       \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. Any character can be +       used as a delimiter instead of '\cb{/}'. Escaping of the delimiter +       character in \ci{pattern} or \ci{replacement} is not supported. + +       All the regular expressions are pushed into a stack with the last +       specified expression considered first. The first match that +       succeeds is used. Regular expressions are applied to a string in +       the form + +       \c{\i{filename} \i{namespace}} + +       For example, if you have file \cb{hello.xsd} with namespace +       \cb{http://example.com/hello} and you run \cb{xsd} on this file, +       then the string in question will be: + +       \cb{hello.xsd. http://example.com/hello} + +       For the built-in XML Schema namespace the string is: + +       \cb{XMLSchema.xsd http://www.w3.org/2001/XMLSchema} + +       The following three steps are performed for each regular expression +       until the match is found: + +       1. The expression is applied and if the result is empty the next +       expression is considered. + +       2. All '\cb{/}' are replaced with '\cb{::}'. + +       3. The result is verified to be a valid C++ scope name (e.g., +       \cb{foo::bar}). If this test succeeds, the result is used as a +       C++ namespace name. + +       As an example, the following expression maps XML  Schema namespaces +       in the form \cb{http://example.com/foo/bar} to C++ namespaces in the +       form \cb{foo::bar}: + +       \cb{%.* http://example.com/(.+)%$1%} + +       See also the REGEX AND SHELL QUOTING section below." +    }; + +    bool --namespace-regex-trace +    { +      "Trace the process of applying regular expressions specified with the +       \cb{--namespace-regex} option. Use this option to find out why your +       regular expressions don't do what you expected them to do." +    }; + +    // Reserved names. +    // +    NarrowStrings --reserved-name +    { +      "<n>[=<r>]", +      "Add name <n> to the list of names that should not be used as +       identifiers. The name can optionally be followed by \cb{=} and the +       replacement name <r> that should be used instead. All the C++ keywords +       are already in this list." +    }; + +    // Include options. +    // +    bool --include-with-brackets +    { +      "Use angle brackets (<>) instead of quotes (\"\") in generated +       \cb{#include} directives." +    }; + +    NarrowString --include-prefix +    { +      "<prefix>", +      "Add <prefix> to generated \cb{#include} directive paths. + +       For example, if you had the following import element in your schema + +       \cb{<import namespace=\"...\" schemaLocation=\"base.xsd\"/>} + +       and compiled this fragment with \cb{--include-prefix schemas/}, then +       the include directive in the generated code would be: + +       \cb{#include \"schemas/base.hxx\"}" +    }; + +    NarrowStrings --include-regex +    { +      "<regex>", +      "Add <regex> to the list of regular expressions used to transform +       \cb{#include} directive paths. <regex> is a Perl-like regular +       expression in the form \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. +       Any character can be used as a delimiter instead of '\cb{/}'. Escaping +       of the delimiter character in \ci{pattern} or \ci{replacement} is not +       supported. + +       All the regular expressions are pushed into a stack with the last +       specified expression considered first. The first match that succeeds +       is used. + +       As an example, the following expression transforms paths in the form +       \cb{schemas/foo/bar} to paths in the form \cb{generated/foo/bar}: + +       \cb{%schemas/(.+)%generated/$1%} + +       See also the REGEX AND SHELL QUOTING section below." +    }; + +    bool --include-regex-trace +    { +      "Trace the process of applying regular expressions specified with the +       \cb{--include-regex} option. Use this option to find out why your +       regular expressions don't do what you expected them to do." +    }; + +    NarrowString --guard-prefix +    { +      "<prefix>", +      "Add <prefix> to generated header inclusion guards. The prefix is +       transformed to upper case and characters that are illegal in a +       preprocessor macro name are replaced with underscores. If this +       option is not specified then the directory part of the input schema +       file is used as a prefix." +    }; + +    // File suffixes. +    // +    NarrowString --hxx-suffix = ".hxx" +    { +      "<suffix>", +      "Use the provided <suffix> instead of the default \cb{.hxx} to +       construct the name of the header file. Note that this suffix is also +       used to construct names of header files corresponding to +       included/imported schemas." +    }; + +    NarrowString --ixx-suffix = ".ixx" +    { +      "<suffix>", +      "Use the provided <suffix> instead of the default \cb{.ixx} to +       construct the name of the inline file." +    }; + +    NarrowString --cxx-suffix = ".cxx" +    { +      "<suffix>", +      "Use the provided <suffix> instead of the default \cb{.cxx} to +       construct the name of the source file." +    }; + +    NarrowString --fwd-suffix = "-fwd.hxx" +    { +      "<suffix>", +      "Use the provided <suffix> instead of the default \cb{-fwd.hxx} to +       construct the name of the forward declaration file." +    }; + +    NarrowString --hxx-regex +    { +      "<regex>", +      "Use the provided expression to construct the name of the header file. +       <regex> is a Perl-like regular expression in the form +       \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. +       Note that this expression is also used to construct names of header +       files corresponding to included/imported schemas. See also the REGEX +       AND SHELL QUOTING section below." +    }; + +    NarrowString --ixx-regex +    { +      "<regex>", +      "Use the provided expression to construct the name of the inline file. +       <regex> is a Perl-like regular expression in the form +       \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. See also the REGEX AND +       SHELL QUOTING section below." +    }; + +    NarrowString --cxx-regex +    { +      "<regex>", +      "Use the provided expression to construct the name of the source file. +       <regex> is a Perl-like regular expression in the form +       \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. See also the REGEX AND +       SHELL QUOTING section below." +    }; + +    NarrowString --fwd-regex +    { +      "<regex>", +      "Use the provided expression to construct the name of the forward +       declaration file. <regex> is a Perl-like regular expression in the +       form \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. See also the REGEX +       AND SHELL QUOTING section below." +    }; + +    // Prologues/epilogues. +    // +    NarrowStrings --hxx-prologue +    { +      "<text>", +      "Insert <text> at the beginning of the header file." +    }; + +    NarrowStrings --ixx-prologue +    { +      "<text>", +      "Insert <text> at the beginning of the inline file." +    }; + +    NarrowStrings --cxx-prologue +    { +      "<text>", +      "Insert <text> at the beginning of the source file." +    }; + +    NarrowStrings --fwd-prologue +    { +      "<text>", +      "Insert <text> at the beginning of the forward declaration file." +    }; + +    NarrowStrings --prologue +    { +      "<text>", +      "Insert <text> at the beginning of each generated file for which +       there is no file-specific prologue." +    }; + +    NarrowStrings --hxx-epilogue +    { +      "<text>", +      "Insert <text> at the end of the header file." +    }; + +    NarrowStrings --ixx-epilogue +    { +      "<text>", +      "Insert <text> at the end of the inline file." +    }; + +    NarrowStrings --cxx-epilogue +    { +      "<text>", +      "Insert <text> at the end of the source file." +    }; + +    NarrowStrings --fwd-epilogue +    { +      "<text>", +      "Insert <text> at the end of the forward declaration file." +    }; + +    NarrowStrings --epilogue +    { +      "<text>", +      "Insert <text> at the end of each generated file for which there +       is no file-specific epilogue." +    }; + +    NarrowString --hxx-prologue-file +    { +      "<file>", +      "Insert the content of the <file> at the beginning of the header file." +    }; + +    NarrowString --ixx-prologue-file +    { +      "<file>", +      "Insert the content of the <file> at the beginning of the inline file." +    }; + +    NarrowString --cxx-prologue-file +    { +      "<file>", +      "Insert the content of the <file> at the beginning of the source file." +    }; + +    NarrowString --fwd-prologue-file +    { +      "<file>", +      "Insert the content of the <file> at the beginning of the forward +       declaration file." +    }; + +    NarrowString --prologue-file +    { +      "<file>", +      "Insert the content of the <file> at the beginning of each generated +       file for which there is no file-specific prologue file." +    }; + +    NarrowString --hxx-epilogue-file +    { +      "<file>", +      "Insert the content of the <file> at the end of the header file." +    }; + +    NarrowString --ixx-epilogue-file +    { +      "<file>", +      "Insert the content of the <file> at the end of the inline file." +    }; + +    NarrowString --cxx-epilogue-file +    { +      "<file>", +      "Insert the content of the <file> at the end of the source file." +    }; + +    NarrowString --fwd-epilogue-file +    { +      "<file>", +      "Insert the content of the <file> at the end of the forward declaration +       file." +    }; + +    NarrowString --epilogue-file +    { +      "<file>", +      "Insert the content of the <file> at the end of each generated file +       for which there is no file-specific epilogue file." +    }; + +    // Export options. +    // +    NarrowString --export-symbol +    { +      "<symbol>", +      "Insert <symbol> in places where DLL export/import control statements +       (\cb{__declspec(dllexport/dllimport)}) are necessary." +    }; + +    bool --export-xml-schema +    { +      "Export/import types in the XML Schema namespace using the export +       symbol provided with the \cb{--export-symbol} option. The +       \cb{XSD_NO_EXPORT} macro can be used to omit this code during C++ +       compilation, which may be useful if you would like to use the same +       generated code across multiple platforms." +    }; + +    bool --export-maps +    { +      "Export polymorphism support maps from a Win32 DLL into which this +       generated code is placed. This is necessary when your type hierarchy +       is split across several DLLs since otherwise each DLL will have its +       own set of maps. In this situation the generated code for the DLL +       which contains base types and/or substitution group heads should be +       compiled with this option and the generated code for all other DLLs +       should be compiled with \cb{--import-maps}. This option is only valid +       together with \cb{--generate-polymorphic}. The \cb{XSD_NO_EXPORT} +       macro can be used to omit this code during C++ compilation, which may +       be useful if you would like to use the same generated code across +       multiple platforms." +    }; + +    bool --import-maps +    { +      "Import polymorphism support maps to a Win32 DLL or executable into +       which this generated code is linked. See the \cb{--export-maps} +       option documentation for details. This options is only valid together +       with \cb{--generate-polymorphic}. The \cb{XSD_NO_EXPORT} macro can be +       used to omit this code during C++ compilation, which may be useful if +       you would like to use the same generated code across multiple +       platforms." +    }; + +    // Make dependency generation. +    // +    bool --generate-dep +    { +      "Generate \cb{make} dependency information. This option triggers the +       creation of the \cb{.d} file containing the dependencies of the +       generated files on the main schema file as well as all the schema +       files that it includes/imports, transitively. This dependency file +       is then normally included into the main \cb{makefile} to implement +       automatic dependency tracking. See also the \cb{--dep-*} options. + +       Note also that automatic dependency generation is not supported in +       the file-per-type mode (\cb{--file-per-type}). In this case, all +       the generated files are produced with a single compiler invocation +       and depend on all the schemas. As a result, it is easier to establish +       such a dependency manually, perhaps with the help of the +       \cb{--file-list*} options." +    }; + +    bool --generate-dep-only +    { +      "Generate \cb{make} dependency information only." +    }; + +    bool --dep-phony +    { +      "Generate phony targets for included/imported schema files, causing +       each to depend on nothing. Such dummy rules work around \cb{make} +       errors caused by the removal of schema files without also updating +       the dependency file to match." +    }; + +    NarrowStrings --dep-target +    { +      "<target>", +      "Change the target of the dependency rule. By default it contains +       all the generated C++ files as well as the dependency file itself, +       without any directory prefixes. If you require multiple targets, +       then you can specify them as a single, space-separated argument or +       you can repeat this option multiple times." +    }; + +    NarrowString --dep-suffix = ".d" +    { +      "<suffix>", +      "Use <suffix> instead of the default \cb{.d} to construct the name of +       the dependency file. See also \cb{--dep-file}." +    }; + +    NarrowString --dep-file +    { +      "<path>", +      "Use <path> as the generated dependency file path instead of deriving +       it from the input file name. Write the dependency information to +       \cb{stdout} if <path> is \cb{-}. See also \cb{--dep-regex}." +    }; + +    NarrowString --dep-regex +    { +      "<regex>", +      "Use the provided expression to construct the name of the dependency +       file. <regex> is a Perl-like regular expression in the form +       \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. See also the REGEX +       AND SHELL QUOTING section below." +    }; +  }; +} diff --git a/xsd/cxx/parser/attribute-validation-source.cxx b/xsd/cxx/parser/attribute-validation-source.cxx new file mode 100644 index 0000000..1c873fd --- /dev/null +++ b/xsd/cxx/parser/attribute-validation-source.cxx @@ -0,0 +1,412 @@ +// file      : xsd/cxx/parser/attribute-validation-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/parser/attribute-validation-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      struct Test: Traversal::Attribute, +                   Traversal::AnyAttribute, +                   Context +      { +        Test (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Attribute& a) +        { +          String const& name (a.name ()); + +          if (a.qualified_p () && a.namespace_ ().name ()) +          { +            String const& ns (a.namespace_ ().name ()); + +            os << "n == " << strlit (name) << " &&" << endl +               << "ns == " << strlit (ns); +          } +          else +            os << "n == " << strlit (name) << " && ns.empty ()"; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& ns (a.definition_namespace ().name ()); + +          for (SemanticGraph::AnyAttribute::NamespaceIterator +                 i (a.namespace_begin ()), e (a.namespace_end ()); i != e;) +          { +            if (*i == L"##any") +            { +              os << "!n.empty ()"; +            } +            else if (*i == L"##other") +            { +              if (ns) +              { +                // Note that here I assume that ##other does not include +                // unqualified names in a schema with target namespace. +                // This is not what the spec says but that seems to be +                // the consensus. +                // +                os << "(!ns.empty () && ns != " << strlit (ns) << ")"; +              } +              else +                os << "!ns.empty ()"; +            } +            else if (*i == L"##local") +            { +              os << "(ns.empty () && !n.empty ())"; +            } +            else if (*i == L"##targetNamespace") +            { +              os << "ns == " << strlit (ns); +            } +            else +            { +              os << "ns == " << strlit (*i); +            } + +            if (++i != e) +              os << " ||" << endl; +          } +        } +      }; + +      // +      // +      struct PhaseOne: Traversal::Attribute, Context +      { +        PhaseOne (Context& c) +            : Context (c), test_ (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& name (ename (a)); +          String const& inst (emember (a)); + +          SemanticGraph::Type& type (a.type ()); +          String const& post (post_name (type)); +          String const& ret (ret_type (type)); + +          os << "if ("; + +          test_.traverse (a); + +          os << ")" +             << "{" +             << "if (this->" << inst << ")" +             << "{" +             << "this->" << inst << "->pre ();" +             << "this->" << inst << "->_pre_impl ();" +             << "this->" << inst << "->_characters (s);" +             << "this->" << inst << "->_post_impl ();"; + +          if (ret == L"void") +            os << "this->" << inst << "->" << post << " ();" +               << "this->" << name << " ();"; +          else +          { +            // Don't create an lvalue in C++11 (think std::unique_ptr). +            // In C++98 we do it for compatibility with older/broken +            // compilers (e.g., IBM xlC that needs an lvalue to pass +            // std::auto_ptr). +            // +            if (std == cxx_version::cxx98) +              os << arg_type (type) << " tmp (this->" << inst << "->" << +                post << " ());" +                 << "this->" << name << " (tmp);"; +            else +              os << "this->" << name << " (this->" << inst << "->" << +                post << " ());"; +          } + +          os << "}"; + +          if (!a.optional_p ()) +            os << "static_cast< v_state_attr_* > (" << +              "this->v_state_attr_stack_.top ())->" << name << " = true;"; + +          os << "return true;" +             << "}"; +        } + +      private: +        Test test_; +      }; + + +      // +      // +      struct PhaseTwo: Traversal::AnyAttribute, Context +      { +        PhaseTwo (Context& c) +            : Context (c), test_ (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          os << "if ("; + +          test_.traverse (a); + +          os << ")" << endl +             << "{" +             << "this->_any_attribute (ns, n, s);" +             << "return true;" +             << "}"; +        } + +      private: +        Test test_; +      }; + + +      // +      // +      struct AttributeStateInit: Traversal::Attribute, Context +      { +        AttributeStateInit (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          if (!a.optional_p ()) +            os << "as." << ename (a) << " = false;"; +        } +      }; + + +      // +      // +      struct AttributeStateCheck: Traversal::Attribute, Context +      { +        AttributeStateCheck (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          if (!a.optional_p ()) +          { +            String ns (a.qualified_p () ? a.namespace_ ().name () : String ()); + +            os << "if (!as." << ename (a) << ")" << endl +               << "this->_expected_attribute (" << endl +               << strlit (ns) << ", " << strlit (a.name ()) << ");"; +          } +        } +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), +              phase_one_ (c), +              phase_two_ (c), +              attribute_state_init_ (c), +              attribute_state_check_ (c) +        { +          names_phase_one_ >> phase_one_; +          names_phase_two_ >> phase_two_; + +          names_attribute_state_init_ >> attribute_state_init_; +          names_attribute_state_check_ >> attribute_state_check_; +        } + +        virtual void +        traverse (Type& c) +        { +          bool has_att (has<Traversal::Attribute> (c)); +          bool has_any (has<Traversal::AnyAttribute> (c)); + +          if (!has_att && !has_any) +            return; + +          bool has_req_att (false); +          if (has_att) +          { +            RequiredAttributeTest test (has_req_att); +            Traversal::Names names_test (test); +            names (c, names_test); +          } + +          String const& name (ename (c)); + +          os <<"// Attribute validation and dispatch functions for " << +            name << "." << endl +             <<"//" << endl; + +          if (has_att) +          { +            // _attribute_impl_phase_one +            // +            os << "bool " << name << "::" << endl +               << "_attribute_impl_phase_one (const " << string_type << +              "& ns," << endl +               << "const " << string_type << "& n," << endl +               << "const " << string_type << "& s)" << endl +               << "{"; + +            names (c, names_phase_one_); + +            // Nothing matched - call our base (extension) or return false +            // if there is no base (or restriction (even from anyType)). +            // +            os << "return "; + +            if (c.inherits_p () && +                !c.inherits ().is_a<SemanticGraph::Restricts> ()) +            { +              os << "this->" << fq_name (c.inherits ().base ()) << +                "::_attribute_impl_phase_one (ns, n, s);"; +            } +            else +              os << "false;"; + +            os << "}"; +          } + + +          if (has_any) +          { +            // _attribute_impl_phase_two +            // +            os << "bool " << name << "::" << endl +               << "_attribute_impl_phase_two (const " << string_type << +              "& ns," << endl +               << "const " << string_type << "& n," << endl +               << "const " << string_type << "& s)" +               << "{"; + +            names (c, names_phase_two_); + +            // Nothing matched - call our base (extension) or return false +            // if there is no base (or restriction (even from anyType)). +            // +            os << "return "; + +            if (c.inherits_p () && +                !c.inherits ().is_a<SemanticGraph::Restricts> ()) +            { +              os << "this->" << fq_name (c.inherits ().base ()) << +                "::_attribute_impl_phase_two (ns, n, s);"; +            } +            else +              os << "false;"; + +            os << "}"; +          } + +          if (has_req_att) +          { +            // _pre_a_validate +            // +            os << "void " << name << "::" << endl +               << "_pre_a_validate ()" +               << "{" +               << "this->v_state_attr_stack_.push ();" +               << "v_state_attr_& as = *static_cast< v_state_attr_* > (" << +              "this->v_state_attr_stack_.top ());" +               << endl; + +            names (c, names_attribute_state_init_); + +            // Call our base (extension) last. +            // +            if (c.inherits_p () && +                !c.inherits ().is_a<SemanticGraph::Restricts> ()) +            { +              os << "this->" << fq_name (c.inherits ().base ()) << +                "::_pre_a_validate ();"; +            } + +            os << "}"; + + +            // _post_a_validate +            // +            os << "void " << name << "::" << endl +               << "_post_a_validate ()" +               << "{"; + +            // Call our base (extension) first. +            // +            if (c.inherits_p () && +                !c.inherits ().is_a<SemanticGraph::Restricts> ()) +            { +              os << "this->" << fq_name (c.inherits ().base ()) << +                "::_post_a_validate ();" +                 << endl; +            } + +            os << "v_state_attr_& as = *static_cast< v_state_attr_* > (" << +              "this->v_state_attr_stack_.top ());" +               << endl; + +            names (c, names_attribute_state_check_); + +            os << endl +               << "this->v_state_attr_stack_.pop ();" +               << "}"; +          } +        } + +      private: +        PhaseOne phase_one_; +        Traversal::Names names_phase_one_; + +        PhaseTwo phase_two_; +        Traversal::Names names_phase_two_; + +        AttributeStateInit attribute_state_init_; +        Traversal::Names names_attribute_state_init_; + +        AttributeStateCheck attribute_state_check_; +        Traversal::Names names_attribute_state_check_; +      }; +    } + +    void +    generate_attribute_validation_source (Context& ctx) +    { +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names schema_names; + +      Namespace ns (ctx); +      Traversal::Names names; + +      schema >> sources >> schema; +      schema >> schema_names >> ns >> names; + +      Complex complex (ctx); + +      names >> complex; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/parser/attribute-validation-source.hxx b/xsd/cxx/parser/attribute-validation-source.hxx new file mode 100644 index 0000000..1f19bed --- /dev/null +++ b/xsd/cxx/parser/attribute-validation-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/attribute-validation-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX +#define XSD_CXX_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_attribute_validation_source (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX diff --git a/xsd/cxx/parser/characters-validation-source.cxx b/xsd/cxx/parser/characters-validation-source.cxx new file mode 100644 index 0000000..749a4cc --- /dev/null +++ b/xsd/cxx/parser/characters-validation-source.cxx @@ -0,0 +1,73 @@ +// file      : xsd/cxx/parser/characters-validation-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/parser/characters-validation-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          if (!c.mixed_p ()) +            return; + +          String const& name (ename (c)); + +          os <<"// Character validation functions for " << name << "." << endl +             <<"//" << endl; + +            // _characters_impl +            // +          os << "bool " << name << "::" << endl +             << "_characters_impl (const " << string_type << "& s)" +             << "{" +             << "this->_any_characters (s);" +             << "return true;" +             << "}"; +        } +      }; +    } + +    void +    generate_characters_validation_source (Context& ctx) +    { +      //@@ Most of the time there is no mixed content type so +      //   we generate an empty namespace which looks ugly. Will +      //   need to implement smart namespace to handle this at +      //   some point. +      // +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names schema_names; + +      Namespace ns (ctx); +      Traversal::Names names; + +      schema >> sources >> schema; +      schema >> schema_names >> ns >> names; + +      Complex complex (ctx); + +      names >> complex; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/parser/characters-validation-source.hxx b/xsd/cxx/parser/characters-validation-source.hxx new file mode 100644 index 0000000..909901b --- /dev/null +++ b/xsd/cxx/parser/characters-validation-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/characters-validation-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX +#define XSD_CXX_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_characters_validation_source (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX diff --git a/xsd/cxx/parser/driver-source.cxx b/xsd/cxx/parser/driver-source.cxx new file mode 100644 index 0000000..d1e6b7f --- /dev/null +++ b/xsd/cxx/parser/driver-source.cxx @@ -0,0 +1,775 @@ +// file      : xsd/cxx/parser/driver-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <map> +#include <sstream> + +#include <xsd/cxx/parser/driver-source.hxx> +#include <xsd/cxx/parser/print-impl-common.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      typedef map<SemanticGraph::Type*, String> TypeInstanceMap; +      typedef set<String> InstanceSet; + +      // For base types we only want member's types, but not the +      // base itself. +      // +      struct BaseType: Traversal::Complex, +                       Traversal::List, +                       Context +      { +        BaseType (Context& c, Traversal::NodeBase& def) +            : Context (c), def_ (def) +        { +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          inherits (c); + +          if (!restriction_p (c)) +            names (c); +        } + +        virtual void +        traverse (SemanticGraph::List& l) +        { +          def_.dispatch (l.argumented ().type ()); +        } + +      private: +        Traversal::NodeBase& def_; +      }; + +      struct ParserDef: Traversal::Type, +                        Traversal::List, +                        Traversal::Complex, + +                        Traversal::AnyType, +                        Traversal::AnySimpleType, + +                        Traversal::Fundamental::Byte, +                        Traversal::Fundamental::UnsignedByte, +                        Traversal::Fundamental::Short, +                        Traversal::Fundamental::UnsignedShort, +                        Traversal::Fundamental::Int, +                        Traversal::Fundamental::UnsignedInt, +                        Traversal::Fundamental::Long, +                        Traversal::Fundamental::UnsignedLong, +                        Traversal::Fundamental::Integer, +                        Traversal::Fundamental::NonPositiveInteger, +                        Traversal::Fundamental::NonNegativeInteger, +                        Traversal::Fundamental::PositiveInteger, +                        Traversal::Fundamental::NegativeInteger, + +                        Traversal::Fundamental::Boolean, + +                        Traversal::Fundamental::Float, +                        Traversal::Fundamental::Double, +                        Traversal::Fundamental::Decimal, + +                        Traversal::Fundamental::String, +                        Traversal::Fundamental::NormalizedString, +                        Traversal::Fundamental::Token, +                        Traversal::Fundamental::Name, +                        Traversal::Fundamental::NameToken, +                        Traversal::Fundamental::NameTokens, +                        Traversal::Fundamental::NCName, +                        Traversal::Fundamental::Language, + +                        Traversal::Fundamental::QName, + +                        Traversal::Fundamental::Id, +                        Traversal::Fundamental::IdRef, +                        Traversal::Fundamental::IdRefs, + +                        Traversal::Fundamental::AnyURI, + +                        Traversal::Fundamental::Base64Binary, +                        Traversal::Fundamental::HexBinary, + +                        Traversal::Fundamental::Date, +                        Traversal::Fundamental::DateTime, +                        Traversal::Fundamental::Duration, +                        Traversal::Fundamental::Day, +                        Traversal::Fundamental::Month, +                        Traversal::Fundamental::MonthDay, +                        Traversal::Fundamental::Year, +                        Traversal::Fundamental::YearMonth, +                        Traversal::Fundamental::Time, + +                        Traversal::Fundamental::Entity, +                        Traversal::Fundamental::Entities, + +                        Context +      { +        ParserDef (Context& c, TypeInstanceMap& map, InstanceSet& set) +            : Context (c), map_ (map), set_ (set), base_ (c, *this) +        { +          *this >> inherits_ >> base_ >> inherits_; + +          *this >> names_; +          base_ >> names_; + +          names_ >> member_ >> belongs_ >> *this; +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          if (map_.find (&t) == map_.end ()) +          { +            String inst (find_instance_name (t)); +            map_[&t] = inst; + +            os << fq_name (t, "impl") << " " << inst << ";"; +          } +        } + +        virtual void +        traverse (SemanticGraph::List& l) +        { +          if (map_.find (&l) == map_.end ()) +          { +            String inst (find_instance_name (l)); +            map_[&l] = inst; + +            os << fq_name (l, "impl") << " " << inst << ";"; + +            dispatch (l.argumented ().type ()); +          } +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          if (map_.find (&c) == map_.end ()) +          { +            String inst (find_instance_name (c)); +            map_[&c] = inst; + +            os << fq_name (c, "impl") << " " << inst << ";"; + +            inherits (c); + +            if (!restriction_p (c)) +              names (c); +          } +        } + +        // anyType & anySimpleType. +        // +        virtual void +        traverse (SemanticGraph::AnyType& t) +        { +          fund_type (t, "any_type"); +        } + +        virtual void +        traverse (SemanticGraph::AnySimpleType& t) +        { +          fund_type (t, "any_simple_type"); +        } + +        // Boolean. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Boolean& t) +        { +          fund_type (t, "boolean"); +        } + +        // Integral types. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Byte& t) +        { +          fund_type (t, "byte"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedByte& t) +        { +          fund_type (t, "unsigned_byte"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Short& t) +        { +          fund_type (t, "short"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedShort& t) +        { +          fund_type (t, "unsigned_short"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Int& t) +        { +          fund_type (t, "int"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedInt& t) +        { +          fund_type (t, "unsigned_int"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Long& t) +        { +          fund_type (t, "long"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedLong& t) +        { +          fund_type (t, "unsigned_long"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Integer& t) +        { +          fund_type (t, "integer"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +        { +          fund_type (t, "non_positive_integer"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +        { +          fund_type (t, "non_negative_integer"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::PositiveInteger& t) +        { +          fund_type (t, "positive_integer"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NegativeInteger& t) +        { +          fund_type (t, "negative_integer"); +        } + +        // Floats. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Float& t) +        { +          fund_type (t, "float"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Double& t) +        { +          fund_type (t, "double"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Decimal& t) +        { +          fund_type (t, "decimal"); +        } + +        // Strings. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::String& t) +        { +          fund_type (t, "string"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NormalizedString& t) +        { +          fund_type (t, "normalized_string"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Token& t) +        { +          fund_type (t, "token"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameToken& t) +        { +          fund_type (t, "nmtoken"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameTokens& t) +        { +          fund_type (t, "nmtokens"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Name& t) +        { +          fund_type (t, "name"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NCName& t) +        { +          fund_type (t, "ncname"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Language& t) +        { +          fund_type (t, "language"); +        } + + +        // Qualified name. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::QName& t) +        { +          fund_type (t, "qname"); +        } + + +        // ID/IDREF. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Id& t) +        { +          fund_type (t, "id"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRef& t) +        { +          fund_type (t, "idref"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRefs& t) +        { +          fund_type (t, "idrefs"); +        } + +        // URI. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::AnyURI& t) +        { +          fund_type (t, "uri"); +        } + +        // Binary. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Base64Binary& t) +        { +          fund_type (t, "base64_binary"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::HexBinary& t) +        { +          fund_type (t, "hex_binary"); +        } + + +        // Date/time. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Date& t) +        { +          fund_type (t, "date"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::DateTime& t) +        { +          fund_type (t, "date_time"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Duration& t) +        { +          fund_type (t, "duration"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Day& t) +        { +          fund_type (t, "day"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Month& t) +        { +          fund_type (t, "month"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::MonthDay& t) +        { +          fund_type (t, "month_day"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Year& t) +        { +          fund_type (t, "year"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::YearMonth& t) +        { +          fund_type (t, "year_month"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Time& t) +        { +          fund_type (t, "time"); +        } + +        // Entity. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Entity& t) +        { +          fund_type (t, "entity"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Entities& t) +        { +          fund_type (t, "entities"); +        } + +      private: +        virtual void +        fund_type (SemanticGraph::Type& t, String const& name) +        { +          if (map_.find (&t) == map_.end ()) +          { +            String inst (find_instance_name (name)); +            map_[&t] = inst; + +            os << fq_name (t, "impl") << " " << inst << ";"; +          } +        } + +        String +        find_instance_name (String const& raw_name) +        { +          String base_name (escape (raw_name + L"_p")); +          String name (base_name); + +          for (size_t i (1); set_.find (name) != set_.end (); ++i) +          { +            std::wostringstream os; +            os << i; +            name = base_name + os.str (); +          } + +          set_.insert (name); +          return name; +        } + +        String +        find_instance_name (SemanticGraph::Type& t) +        { +          return find_instance_name (t.name ()); +        } + +        TypeInstanceMap& map_; +        InstanceSet& set_; + +        BaseType base_; +        Traversal::Inherits inherits_; + +        Traversal::Names names_; +        Traversal::Member member_; +        Traversal::Belongs belongs_; +      }; + +      struct ArgList: Traversal::Complex, +                      Traversal::List, +                      Traversal::Member, +                      Context +      { +        ArgList (Context& c, TypeInstanceMap& map) +            : Context (c), map_ (map), first_ (true) +        { +          inherits_ >> *this; +          names_ >> *this; +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          inherits (c, inherits_); + +          if (!restriction_p (c)) +            names (c, names_); +        } + +        virtual void +        traverse (SemanticGraph::List& l) +        { +          if (!first_) +            os << "," << endl; +          else +            first_ = false; + +          os << map_[&l.argumented ().type ()]; +        } + +        virtual void +        traverse (SemanticGraph::Member& m) +        { +          if (skip (m)) +            return; + +          if (!first_) +            os << "," << endl; +          else +            first_ = false; + +          os << map_[&m.type ()]; +        } + +      private: +        TypeInstanceMap& map_; + +        Traversal::Inherits inherits_; +        Traversal::Names names_; + +        bool first_; +      }; + +      struct ParserConnect: Traversal::List, +                            Traversal::Complex, +                            Context +      { +        ParserConnect (Context& c, TypeInstanceMap& map) +            : Context (c), map_ (map), base_ (c, *this) +        { +          *this >> inherits_ >> base_ >> inherits_; + +          *this >> names_; +          base_ >> names_; + +          names_ >> member_ >> belongs_ >> *this; +        } + +        virtual void +        traverse (SemanticGraph::List& l) +        { +          if (type_set_.find (&l) == type_set_.end ()) +          { +            os << map_[&l] << ".parsers (" << +              map_[&l.argumented ().type ()] << ");" +               << endl; + +            type_set_.insert (&l); +          } +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          if (type_set_.find (&c) == type_set_.end ()) +          { +            if (has_members (c)) +            { +              os << map_[&c] << ".parsers ("; + +              ArgList args (*this, map_); +              args.dispatch (c); + +              os << ");" +                 << endl; +            } + +            type_set_.insert (&c); + +            inherits (c); + +            if (!restriction_p (c)) +              names (c); +          } +        } + +      private: +        bool +        has_members (SemanticGraph::Complex& c) +        { +          using SemanticGraph::Complex; + +          if (has<Traversal::Member> (c)) +            return true; + +          if (c.inherits_p ()) +          { +            SemanticGraph::Type& b (c.inherits ().base ()); + +            if (Complex* cb = dynamic_cast<Complex*> (&b)) +              return has_members (*cb); + +            return b.is_a<SemanticGraph::List> (); +          } + +          return false; +        } + +      private: +        TypeInstanceMap& map_; +        set<SemanticGraph::Type*> type_set_; + +        BaseType base_; +        Traversal::Inherits inherits_; + +        Traversal::Names names_; +        Traversal::Member member_; +        Traversal::Belongs belongs_; +      }; +    } + +    void +    generate_driver_source (Context& ctx) +    { +      // Figure out the root element. Validator should have made sure +      // it is unique. +      // +      SemanticGraph::Element* root (0); +      { +        Traversal::Schema schema; +        Sources sources; + +        schema >> sources >> schema; + +        Traversal::Names schema_names; +        Traversal::Namespace ns; +        Traversal::Names ns_names; +        RootElement root_element (ctx.options, root); + +        schema >> schema_names >> ns >> ns_names >> root_element; + +        schema.dispatch (ctx.schema_root); +      } + +      std::wostream& os (ctx.os); +      String const& L (ctx.L); +      String const& cerr (ctx.cerr_inst); + +      InstanceSet set; +      TypeInstanceMap map; +      SemanticGraph::Type& root_type (root->type ()); + +      set.insert ("doc_p"); + +      os << "#include <iostream>" << endl +         << endl +         << "int" << endl +         << "main (int argc, char* argv[])" +         << "{" +         << "if (argc != 2)" +         << "{" +         << cerr << " << " << L << "\"usage: \" << argv[0] << " << +        L << "\" file.xml\" << std::endl;" +         << "return 1;" +         << "}" +         << "try" +         << "{" +         << "// Instantiate individual parsers." << endl +         << "//" << endl; + +      { +        ParserDef def (ctx, map, set); +        def.dispatch (root_type); +      } + +      os << endl +         << "// Connect the parsers together." << endl +         << "//" << endl; + +      { +        ParserConnect connect (ctx, map); +        connect.dispatch (root_type); +      } + +      String const& root_p (map[&root_type]); + +      os << "// Parse the XML document." << endl +         << "//" << endl; + +      if (root->namespace_().name ()) +        os << ctx.xs_ns_name () << "::document doc_p (" << endl +           << root_p << "," << endl +           << ctx.strlit (root->namespace_().name ()) << "," << endl +           << ctx.strlit (root->name ()) << ");" +           << endl; +      else +        os << ctx.xs_ns_name () << "::document doc_p (" << root_p << ", " << +          ctx.strlit (root->name ()) << ");" +           << endl; + +      os << root_p << ".pre ();" +         << "doc_p.parse (argv[1]);"; + +      String const& ret (Context::ret_type (root_type)); +      String const& post (Context::post_name (root_type)); + +      if (ret == L"void") +        os << root_p << "." << post << " ();"; +      else +      { +        os << Context::arg_type (root_type) << " v (" << +          root_p << "." << post << " ());" +           << endl; + +        if (ctx.options.generate_print_impl ()) +        { +          PrintCall t (ctx, root->name (), "v"); +          t.dispatch (root_type); +        } +        else +          os << "// TODO" << endl +             << "//" << endl; +      } + +      os << "}" // try +         << "catch (const " << ctx.xs_ns_name () << "::exception& e)" +         << "{" +         << cerr << " << e << std::endl;" +         << "return 1;" +         << "}" +         << "catch (const std::ios_base::failure&)" +         << "{" +         << cerr << " << argv[1] << " << +        L << "\": error: io failure\" << std::endl;" +         << "return 1;" +         << "}" +         << "}"; +    } +  } +} diff --git a/xsd/cxx/parser/driver-source.hxx b/xsd/cxx/parser/driver-source.hxx new file mode 100644 index 0000000..154091f --- /dev/null +++ b/xsd/cxx/parser/driver-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/driver-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_DRIVER_SOURCE_HXX +#define XSD_CXX_PARSER_DRIVER_SOURCE_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_driver_source (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_DRIVER_SOURCE_HXX diff --git a/xsd/cxx/parser/element-validation-source.cxx b/xsd/cxx/parser/element-validation-source.cxx new file mode 100644 index 0000000..b5e1e9d --- /dev/null +++ b/xsd/cxx/parser/element-validation-source.cxx @@ -0,0 +1,1600 @@ +// file      : xsd/cxx/parser/element-validation-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <vector> + +#include <xsd/cxx/parser/element-validation-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      typedef vector<SemanticGraph::Particle*> Particles; + +      // +      // +      struct ParticleTest: Traversal::Compositor, +                           Traversal::Element, +                           Traversal::Any, +                           Context +      { +        ParticleTest (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          String const& name (e.name ()); + +          if (polymorphic && e.global_p ()) +            os << "("; + +          if (e.qualified_p () && e.namespace_ ().name ()) +          { +            String const& ns (e.namespace_ ().name ()); + +            os << "n == " << strlit (name) << " &&" << endl +               << "ns == " << strlit (ns); +          } +          else +            os << "n == " << strlit (name) << " && ns.empty ()"; + + +          // Only a globally-defined element can be a subst-group root. +          // +          if (polymorphic && e.global_p ()) +          { +            os << ") ||" << endl +               << "::xsd::cxx::parser::substitution_map_instance< " << +              char_type << " > ().check (" << endl +               << "ns, n, " << strlit (e.namespace_ ().name ()) << +              ", " << strlit (name) << ", t)"; +          } +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& ns (a.definition_namespace ().name ()); + +          // Note that we need to make sure the "flush" element (both name +          // and namespace are empty) does not match any compositor. +          // +          for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), +                 e (a.namespace_end ()); i != e;) +          { +            if (*i == L"##any") +            { +              os << "!n.empty ()"; +            } +            else if (*i == L"##other") +            { +              if (ns) +              { +                // Note that here I assume that ##other does not include +                // unqualified names in a schema with target namespace. +                // This is not what the spec says but that seems to be +                // the consensus. +                // +                os << "(!ns.empty () && ns != " << strlit (ns) << ")"; +              } +              else +                os << "!ns.empty ()"; +            } +            else if (*i == L"##local") +            { +              os << "(ns.empty () && !n.empty ())"; +            } +            else if (*i == L"##targetNamespace") +            { +              os << "ns == " << strlit (ns); +            } +            else +            { +              os << "ns == " << strlit (*i); +            } + +            if (++i != e) +              os << " ||" << endl; +          } +        } + +        virtual void +        traverse (SemanticGraph::Compositor& c) +        { +          // This compositor should already have been tested for +          // triviality (empty). +          // +          Particles const& p (c.context ().get<Particles> ("prefixes")); + +          bool paren (p.size () != 1); + +          for (Particles::const_iterator i (p.begin ()), e (p.end ()); +               i != e;) +          { +            if (paren) +              os << "("; + +            dispatch (**i); + +            if (paren) +              os << ")"; + +            if (++i != e) +              os << " ||" << endl; +          } +        } +      }; + + +      // Generates particle namespace-name pair. Used to generate +      // the _expected_element call. +      // +      struct ParticleName: Traversal::Compositor, +                           Traversal::Element, +                           Traversal::Any, +                           Context +      { +        ParticleName (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          String ns (e.qualified_p () ? e.namespace_ ().name () : String ()); +          os << strlit (ns) << ", " << strlit (e.name ()); +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& ns (*a.namespace_begin ()); +          os << strlit (ns) << ", " << L << "\"*\""; +        } + +        virtual void +        traverse (SemanticGraph::Compositor& c) +        { +          Particles const& p (c.context ().get<Particles> ("prefixes")); + +          dispatch (**p.begin ()); +        } +      }; + + +      // Common base for the ParticleIn{All, Choice, Sequence} treversers. +      // +      struct ParticleInCompositor: Context +      { +      protected: +        ParticleInCompositor (Context& c, SemanticGraph::Complex& type) +            : Context (c), type_ (type), particle_test_ (c) +        { +        } + + +        // Generate sub-parser setup code as well as the pre/post calls. +        // +        void +        pre_post_calls (SemanticGraph::Particle& p) +        { +          using SemanticGraph::Element; +          using SemanticGraph::Complex; + +          if (Element* e = dynamic_cast<Element*> (&p)) +          { +            SemanticGraph::Type& type (e->type ()); +            String const& fq_type (fq_name (type)); +            bool poly (polymorphic && !anonymous (type)); + +            String name, inst, def_parser, map; + +            if (e->context ().count("name")) +            { +              name = ename (*e); + +              if (poly) +              { +                def_parser = emember (*e); +                map = emember_map (*e); +                inst = "p"; +              } +              else +                inst = L"this->" + emember (*e); +            } +            else +            { +              // This is the subsequent mentioning of this element in the +              // content. We need to find the first one in order to get +              // to the escaped names. +              // +              Complex::NamesIteratorPair ip (type_.find (e->name ())); +              assert (ip.first != ip.second); +              Element& fe (dynamic_cast<Element&>(ip.first->named ())); + +              name = ename (fe); + +              if (poly) +              { +                def_parser = emember (fe); +                map = emember_map (fe); +                inst = "p"; +              } +              else +                inst = L"this->" + emember (fe); +            } + +            if (poly) +            { +              // For pre-computing length. +              // +              String type_id (type.name ()); + +              if (String type_ns = xml_ns_name (type)) +              { +                type_id += L' '; +                type_id += type_ns; +              } + +              os << fq_type << "* p = 0;" +                 << endl +                 << "if (t == 0 && this->" << def_parser << " != 0)" << endl +                 << inst << " = this->" << def_parser << ";" +                 << "else" +                 << "{" +                 << string_type << " ts (" << fq_name (type) << +                "::_static_type (), " << type_id.size () << "UL);" +                 << endl +                 << "if (t == 0)" << endl +                 << "t = &ts;" +                 << endl +                 << "if (this->" << def_parser << " != 0 && *t == ts)" << endl +                 << inst << " = this->" << def_parser << ";" +                 << "else" +                 << "{"; + +              // Check that the types are related by inheritance. +              // +              os << "if (t != &ts &&" << endl +                 << "!::xsd::cxx::parser::validating::" << +                "inheritance_map_instance< " << char_type << +                " > ().check (" << endl +                 << "t->data (), ts))" << endl +                 << "throw ::xsd::cxx::parser::dynamic_type< " << char_type << +                " > (*t);" +                 << endl +                 << "if (this->" << map << " != 0)" << endl +                 << inst << " = dynamic_cast< " << fq_type << "* > (" << endl +                 << "this->" << map << "->find (*t));" +                 << "}" +                 << "}"; +            } + +            os << "this->" << complex_base << "::context_.top ()." << +              "parser_ = " << inst << ";" +               << endl +               << "if (" << inst << ")" << endl +               << inst << "->pre ();" +               << "}" +               << "else" // start +               << "{"; + +            if (poly) +              os << fq_type << "* p =" << endl +                 << "dynamic_cast< " << fq_type << "* > (" << endl +                 << "this->" << complex_base << "::context_.top ().parser_);" +                 << endl; + +            os << "if (" << inst << ")" +               << "{"; + +            String const& ret (ret_type (type)); +            String const& post (post_name (type)); + +            if (ret == L"void") +              os << inst << "->" << post << " ();" +                 << "this->" << name << " ();"; +            else +            { +              // Don't create an lvalue in C++11 (think std::unique_ptr). +              // In C++98 we do it for compatibility with older/broken +              // compilers (e.g., IBM xlC that needs an lvalue to pass +              // std::auto_ptr). +              // +              if (std == cxx_version::cxx98) +                os << arg_type (type) << " tmp (" << inst << "->" << +                  post << " ());" +                   << "this->" << name << " (tmp);"; +              else +                os << "this->" << name << " (" << inst << "->" << +                  post << " ());"; +            } + +            os << "}"; +          } +          else +          { +            os << "this->_start_any_element (ns, n, t);" +               << "this->" << complex_base << "::context_.top ().any_ = true;" +               << "}" +               << "else" // start +               << "{" +               << "this->" << complex_base << "::context_.top ().any_ = false;" +               << "this->_end_any_element (ns, n);"; +          } +        } + +      protected: +        SemanticGraph::Complex& type_; +        ParticleTest particle_test_; +      }; + + + +      // The 'all' compositor can only contain elements with min={0,1}, max=1. +      // +      struct ParticleInAll: Traversal::Element, +                            ParticleInCompositor +      { +        ParticleInAll (Context& c, SemanticGraph::Complex& type) +            : ParticleInCompositor (c, type) +        { +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          size_t state (e.context ().get<size_t> ("state")); + +          if (state != 0) +            os << "else "; + +          os << "if ("; + +          particle_test_.traverse (e); + +          os << ")" +             << "{" +             << "if (count[" << state << "UL] == 0)" +             << "{" +             << "if (start)" +             << "{"; + +          pre_post_calls (e); + +          os << "count[" << state << "UL] = 1;" +             << "}" +             << "}" +             << "else" // count != 0 +             << "{" +             << "assert (start);" // Assuming well-formed XML. + +            // Since there is never more content after 'all', we could have +            // as well thrown here. But instead we will let the code in +            // start_element handle this along with other unexpected +            // elements. +            // +             << "state = ~0UL;" +             << "}" +             << "}"; +        } +      }; + + +      // +      // +      struct ParticleInChoice: Traversal::Particle, +                               Traversal::Compositor, +                               ParticleInCompositor +      { +        ParticleInChoice (Context& c, SemanticGraph::Complex& type) +            : ParticleInCompositor (c, type), particle_name_ (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Particle& p) +        { +          using SemanticGraph::Element; + +          size_t state (p.context ().get<size_t> ("state")); + +          size_t min (p.min ()), max (p.max ()); + +          os << "case " << state << "UL:" << endl +             << "{"; + +          if (max != 1) // We don't need the test if max == 1. +          { +            os << "if ("; + +            particle_test_.dispatch (p); + +            os << ")" +               << "{"; +          } + +          os << "if (start)" +             << "{"; + +          pre_post_calls (p); + +          switch (max) +          { +          case 0: +            { +              os << "count++;"; +              break; +            } +          case 1: +            { +              // We do not need to increment count because min <= max and +              // we do not generate min check for min <= 1 (see below). +              // +              os << "state = ~0UL;"; +              break; +            } +          default: +            { +              os << "if (++count == " << max << "UL)" << endl +                 << "state = ~0UL;"; +            } +          }; + +          os << "}"; // start + +          // We've already moved to the final state if max == 1. +          // +          if (max != 1) +          { +            os << "}" +               << "else" +               << "{" +               << "assert (start);"; // Assuming well-formed XML + +            // Check if min cardinality requirements have been met. Since +            // count is always >= 1, don't generate dead code if min <= 1. +            // +            if (min > 1) +            { +              os << "if (count < " << min << "UL)" << endl +                 << "this->_expected_element (" << endl; + +              particle_name_.dispatch (p); + +              os << "," << endl +                 << "ns, n);"; +            } + + +            os << "state = ~0UL;" +               << "}"; +          } + +          os << "break;" +             << "}"; // case +        } + +        virtual void +        traverse (SemanticGraph::Compositor& c) +        { +          using SemanticGraph::Compositor; + +          size_t max (c.max ()); +          size_t min (c.context ().get<size_t> ("effective-min")); +          size_t n (c.context ().get<size_t> ("comp-number")); +          size_t state (c.context ().get<size_t> ("state")); + +          String func (c.is_a<SemanticGraph::Choice> () ? +                       "choice_" : "sequence_"); + +          os << "case " << state << "UL:" << endl +             << "{" +             << "unsigned long s (~0UL);" +             << endl; + +          bool first (true); + +          for (Compositor::ContainsIterator ci (c.contains_begin ()); +               ci != c.contains_end (); ++ci) +          { +            SemanticGraph::Particle& p (ci->particle ()); + +            if (p.is_a<Compositor> () && !c.context ().count ("comp-number")) +              continue; // Empty compositor. + +            if (!p.context ().count ("prefix")) +              break; + +            size_t state (p.context ().get<size_t> ("state")); + +            if (first) +              first = false; +            else +              os << "else "; + +            os << "if ("; + +            particle_test_.dispatch (p); + +            os << ")" << endl +               << "s = " << state << "UL;"; +          } + +          // This compositor. +          // +          os << endl +             << "if (s != ~0UL)" +             << "{" +             << "assert (start);"; // End is handled by the sub-machine. + +          switch (max) +          { +          case 0: +            { +              os << "count++;"; +              break; +            } +          case 1: +            { +              // We do not need to increment count because min <= max and +              // we do not generate min check for min <= 1 (see below). +              // +              os << "state = ~0UL;"; +              break; +            } +          default: +            { +              os << "if (++count == " << max << "UL)" << endl +                 << "state = ~0UL;"; +            } +          }; + +          // Delegate to the sub-machine. +          // + +          os << endl +             << "v_state_& vs = *static_cast< v_state_* > (" << +            "this->v_state_stack_.top ());" +             << "v_state_descr_& vd = vs.data[vs.size++];" // push +             << endl +             << "vd.func = &" << ename (type_) << "::" << func << n << ";" +             << "vd.state = s;" +             << "vd.count = 0;" +             << endl +             << "this->" << func << n << " (vd.state, vd.count, ns, n, t, true);" +             << "}"; + + +          // Not this compositor. We've elready moved to the final state +          // if max == 1. +          // +          if (max != 1) +          { +            os << "else" +               << "{" +               << "assert (start);"; // Assuming well-formed XML + +            // Check if min cardinality requirements have been met. Since +            // count is always >= 1, don't generate dead code if min <= 1. +            // +            if (min > 1) +            { +              os << "if (count < " << min << "UL)" << endl +                 << "this->_expected_element (" << endl; + +              particle_name_.dispatch (c); + +              os << "," << endl +                 << "ns, n);"; +            } + +            os << "state = ~0UL;" +               << "}"; +          } + +          os << "break;" +             << "}"; // case +        } + +      private: +        ParticleName particle_name_; +      }; + + +      // +      // +      struct ParticleInSequence: Traversal::Particle, +                                 Traversal::Compositor, +                                 ParticleInCompositor +      { +        ParticleInSequence (Context& c, +                            size_t state, +                            size_t next_state, +                            SemanticGraph::Complex& type) +            : ParticleInCompositor (c, type), +              state_ (state), particle_name_ (c) +        { +          // next_state == 0 indicates the terminal state (~0UL). +          // +          if (next_state != 0) +          { +            std::wostringstream ostr; +            ostr << next_state; +            next_state_ = ostr.str (); +          } +          else +            next_state_ = L"~0"; +        } + +        virtual void +        traverse (SemanticGraph::Particle& p) +        { +          size_t min (p.min ()), max (p.max ()); + +          os << "case " << state_ << "UL:" << endl +             << "{" +             << "if ("; + +          particle_test_.dispatch (p); + +          os << ")" +             << "{"; + +          // This element. +          // + +          os << "if (start)" +             << "{"; + +          pre_post_calls (p); + +          switch (max) +          { +          case 0: +            { +              os << "count++;"; +              break; +            } +          case 1: +            { +              os << "count = 0;" +                 << "state = " << next_state_ << "UL;"; +              break; +            } +          default: +            { +              os << "if (++count == " << max << "UL)" +                 << "{" +                 << "count = 0;" +                 << "state = " << next_state_ << "UL;" +                 << "}"; +            } +          }; + +          os << "}" // start +             << "break;" +             << "}"; + +          // Not this element. +          // + +          os << "else" +             << "{" +             << "assert (start);"; // Assuming well-formed XML. + +          // Check if min cardinality requirements have been met. Since +          // count is always >= 0, don't generate dead code if min == 0. +          // +          if (min != 0) +          { +            os << "if (count < " << min << "UL)" << endl +               << "this->_expected_element (" << endl; + +            particle_name_.dispatch (p); + +            os << "," << endl +               << "ns, n);"; +          } + +          os << "count = 0;" +             << "state = " << next_state_ << "UL;" +             << "}" // else +             << "}" // case +             << "// Fall through." << endl; +        } + +        virtual void +        traverse (SemanticGraph::Compositor& c) +        { +          using SemanticGraph::Compositor; + +          size_t max (c.max ()); +          size_t min (c.context ().get<size_t> ("effective-min")); +          size_t n (c.context ().get<size_t> ("comp-number")); + +          String func (c.is_a<SemanticGraph::Choice> () ? +                       "choice_" : "sequence_"); + +          os << "case " << state_ << "UL:" << endl +             << "{" +             << "unsigned long s (~0UL);" +             << endl; + +          bool first (true); + +          for (Compositor::ContainsIterator ci (c.contains_begin ()); +               ci != c.contains_end (); ++ci) +          { +            SemanticGraph::Particle& p (ci->particle ()); + +            if (p.is_a<Compositor> () && !c.context ().count ("comp-number")) +              continue; // Empty compositor. + +            if (!p.context ().count ("prefix")) +              break; + +            size_t state (p.context ().get<size_t> ("state")); + +            if (first) +              first = false; +            else +              os << "else "; + +            os << "if ("; + +            particle_test_.dispatch (p); + +            os << ")" << endl +               << "s = " << state << "UL;"; +          } + +          // This element. +          // + +          os << endl +             << "if (s != ~0UL)" +             << "{" +             << "assert (start);"; // End is handled by the sub-machine. + +          switch (max) +          { +          case 0: +            { +              os << "count++;" +                 << endl; +              break; +            } +          case 1: +            { +              os << "count = 0;" +                 << "state = " << next_state_ << "UL;" +                 << endl; +              break; +            } +          default: +            { +              os << "if (++count == " << max << "UL)" +                 << "{" +                 << "count = 0;" +                 << "state = " << next_state_ << "UL;" +                 << "}"; +            } +          }; + +          // Delegate to the sub-machine. +          // + +          os << "v_state_& vs = *static_cast< v_state_* > (" << +            "this->v_state_stack_.top ());" +             << "v_state_descr_& vd = vs.data[vs.size++];" // push +             << endl +             << "vd.func = &" << ename (type_) << "::" << func << n << ";" +             << "vd.state = s;" +             << "vd.count = 0;" +             << endl +             << "this->" << func << n << " (vd.state, vd.count, ns, n, t, true);" +             << "break;" +             << "}"; + +          // Not this compositor. +          // + +          os << "else" +             << "{" +             << "assert (start);"; // Assuming well-formed XML + +          // Check if min cardinality requirements have been met. Since +          // count is always >= 0, don't generate dead code if min == 0. +          // +          if (min != 0) +          { +            os << "if (count < " << min << "UL)" << endl +               << "this->_expected_element (" << endl; + +            particle_name_.dispatch (c); + +            os << "," << endl +               << "ns, n);"; +          } + +          os << "count = 0;" +             << "state = " << next_state_ << "UL;" +             << "}" // else +             << "}" // case +             << "// Fall through." << endl; +        } + +      private: +        size_t state_; +        String next_state_; + +        ParticleName particle_name_; +      }; + + +      // +      // +      struct ParticleFunction: Traversal::All, +                               Traversal::Choice, +                               Traversal::Sequence, +                               Context +      { +        ParticleFunction (Context& c, SemanticGraph::Complex& type) +            : Context (c), type_ (type) +        { +          *this >> contains_particle_ >> *this; +        } + + +        virtual void +        traverse (SemanticGraph::All& a) +        { +          if (!a.context().count ("comp-number")) // Empty compositor. +            return; + +          using SemanticGraph::Element; +          using SemanticGraph::Compositor; + + +          os << "void " << ename (type_) << "::" << endl +             << "all_0 (unsigned long& state," << endl +             << "unsigned char* count," << endl +             << "const " << string_type << "& ns," << endl +             << "const " << string_type << "& n," << endl +             << "const " << string_type << "* t," << endl +             << "bool start)" +             << "{" +             << "XSD_UNUSED (t);" +             << endl; + +          for (Compositor::ContainsIterator ci (a.contains_begin ()), +                 ce (a.contains_end ()); ci != ce; ++ci) +          { +            ParticleInAll t (*this, type_); +            t.dispatch (ci->particle ()); +          } + +          // Handle the flush. +          // +          os << "else if (n.empty () && ns.empty ())" +             << "{"; + +          for (Compositor::ContainsIterator ci (a.contains_begin ()), +                 ce (a.contains_end ()); ci != ce; ++ci) +          { +            if (ci->min () == 0) +              continue; + +            Element& e (dynamic_cast<Element&> (ci->particle ())); +            String ns (e.qualified_p () ? e.namespace_ ().name () : String ()); +            size_t state (e.context ().get<size_t> ("state")); + +            os << "if (count[" << state << "UL] == 0)" << endl +               << "this->_expected_element (" << endl +               << strlit (ns) << ", " << +              strlit (e.name ()) << ");" +               << endl; +          } + +          os << "state = ~0UL;" +             << "}" +             << "else" << endl +             << "state = ~0UL;" +             << "}"; +        } + +        virtual void +        traverse (SemanticGraph::Choice& c) +        { +          if (!c.context().count ("comp-number")) // Empty compositor. +            return; + +          using SemanticGraph::Compositor; + +          size_t n (c.context ().get<size_t> ("comp-number")); + +          os << "void " << ename (type_) << "::" << endl +             << "choice_" << n << " (unsigned long& state," << endl +             << "unsigned long& count," << endl +             << "const " << string_type << "& ns," << endl +             << "const " << string_type << "& n," << endl +             << "const " << string_type << "* t," << endl +             << "bool start)" +             << "{" +             << "XSD_UNUSED (count);" +             << "XSD_UNUSED (ns);" +             << "XSD_UNUSED (n);" +             << "XSD_UNUSED (t);" +             << endl +             << "switch (state)" +             << "{"; + +          for (Compositor::ContainsIterator ci (c.contains_begin ()), +                 ce (c.contains_end ()); ci != ce; ++ci) +          { +            SemanticGraph::Particle& p (ci->particle ()); + +            if (p.is_a<Compositor> () && !p.context().count ("comp-number")) +              continue; // Empty compositor. + +            ParticleInChoice t (*this, type_); +            t.dispatch (p); +          } + +          os << "}" // switch +             << "}"; + +          // Generate nested compositor functions. +          // +          Traversal::Choice::traverse (c); +        } + +        virtual void +        traverse (SemanticGraph::Sequence& s) +        { +          if (!s.context().count ("comp-number")) // Empty compositor. +            return; + +          using SemanticGraph::Compositor; + +          size_t n (s.context ().get<size_t> ("comp-number")); + +          os << "void " << ename (type_) << "::" << endl +             << "sequence_" << n << " (unsigned long& state," << endl +             << "unsigned long& count," << endl +             << "const " << string_type << "& ns," << endl +             << "const " << string_type << "& n," << endl +             << "const " << string_type << "* t," << endl +             << "bool start)" +             << "{" +             << "XSD_UNUSED (t);" +             << endl +             << "switch (state)" +             << "{"; + +          size_t state (0); + +          for (Compositor::ContainsIterator ci (s.contains_begin ()), +                 ce (s.contains_end ()); ci != ce;) +          { +            SemanticGraph::Particle& p (ci->particle ()); + +            if (p.is_a<Compositor> () && !p.context().count ("comp-number")) +            { +              // Empty compositor. +              // +              ++ci; +              continue; +            } + +            // Find the next state. +            // +            do +              ++ci; +            while (ci != ce && +                   ci->particle ().is_a<Compositor> () && +                   !ci->particle ().context().count ("comp-number")); + +            size_t next (ci == ce ? 0 : state + 1); + +            ParticleInSequence t (*this, state++, next, type_); +            t.dispatch (p); +          } + +          os << "case ~0UL:" << endl +             << "break;" +             << "}" // switch +             << "}"; + +          // Generate nested compositor functions. +          // +          Traversal::Sequence::traverse (s); +        } + +      private: +        SemanticGraph::Complex& type_; +        Traversal::ContainsParticle contains_particle_; +      }; + + +      // +      // +      struct CompositorPre: Traversal::All, +                            Traversal::Compositor, +                            Context +      { +        CompositorPre (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::All& a) +        { +          // Clear the counts and push the initial state. +          // +          os << "v_all_count_.push ();" +             << endl; + +          SemanticGraph::Compositor& c (a); +          traverse (c); +        } + +        virtual void +        traverse (SemanticGraph::Compositor&) // Choice and sequence. +        { +          os << "v_state_& vs = *static_cast< v_state_* > (" << +            "this->v_state_stack_.top ());" +             << "v_state_descr_& vd = vs.data[vs.size++];" // push +             << endl +             << "vd.func = 0;" +             << "vd.state = 0;" +             << "vd.count = 0;"; +        } +      }; + + +      // +      // +      struct CompositorStartElement: Traversal::All, +                                     Traversal::Compositor, +                                     Context +      { +        CompositorStartElement (Context& c, SemanticGraph::Complex& type) +            : Context (c), type_ (type), +              particle_test_ (c), particle_name_ (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::All&) +        { +          // The 'all' state machine reaches the final state only +          // on an unknown element, in which case we won't get here +          // again (it would be a validation error). Note that 'all' +          // compositor cannot contain nested compositors so we don't +          // need to re-set vd. +          // +          os << "all_0 (vd->state, v_all_count_.top (), ns, n, t, true);" +             << endl +             << "if (vd->state != ~0UL)" << endl +             << "vd->count++;" +             << "else" << endl +             << "return false;" // Let our parent handle this. +             << endl; +        } + +        virtual void +        traverse (SemanticGraph::Compositor& c) // Choice and sequence. +        { +          using SemanticGraph::Compositor; + +          size_t max (c.max ()); +          size_t min (c.context ().get<size_t> ("effective-min")); +          size_t n (c.context ().get<size_t> ("comp-number")); + +          String func (c.is_a<SemanticGraph::Choice> () ? +                       "choice_" : "sequence_"); + +          // Invoke the current state machine. If it reaches its +          // terminal state, pop it and invoke the next one until +          // we reach the top, which requires special handling. +          // +          os << "while (vd->func != 0)" +             << "{" +             << "(this->*vd->func) (vd->state, vd->count, ns, n, t, true);" +             << endl +             << "vd = vs.data + (vs.size - 1);" // re-acquire +             << endl +             << "if (vd->state == ~0UL)" << endl +             << "vd = vs.data + (--vs.size - 1);" // pop +             << "else" << endl +             << "break;" +             << "}"; + + +          // Check if we got to the top. This code is pretty much the +          // same as the one found in ParticleInSequence. +          // +          os << "if (vd->func == 0)" +             << "{" +             << "if (vd->state != ~0UL)" +             << "{" +             << "unsigned long s = ~0UL;" +             << endl; + +          bool first (true); + +          // Note that we don't need to worry about the compositor +          // being empty - this case is handled by our caller. +          // +          for (Compositor::ContainsIterator ci (c.contains_begin ()); +               ci != c.contains_end (); ++ci) +          { +            SemanticGraph::Particle& p (ci->particle ()); + +            if (p.is_a<Compositor> () && !c.context ().count ("comp-number")) +              continue; // Empty compositor. + +            if (!p.context ().count ("prefix")) +              break; + +            size_t state (p.context ().get<size_t> ("state")); + +            if (first) +              first = false; +            else +              os << "else "; + +            os << "if ("; + +            particle_test_.dispatch (p); + +            os << ")" << endl +               << "s = " << state << "UL;"; +          } + +          os << endl +             << "if (s != ~0UL)" +             << "{"; + +          // This element is a prefix of the root compositor. +          // + +          switch (max) +          { +          case 0: +            { +              os << "vd->count++;"; +              break; +            } +          case 1: +            { +              os << "vd->count++;" +                 << "vd->state = ~0UL;"; +              break; +            } +          default: +            { +              os << "if (++vd->count == " << max << "UL)" << endl +                 << "vd->state = ~0UL;"; +            } +          }; + +          // Delegate to the sub-machine. +          // + +          os << endl +             << "vd = vs.data + vs.size++;" // push +             << "vd->func = &" << ename (type_) << "::" << func << n << ";" +             << "vd->state = s;" +             << "vd->count = 0;" +             << endl +             << "this->" << func << n << " (vd->state, vd->count, ns, n, t, true);" +             << "}"; + +          // This element is not our prefix. +          // + +          os << "else" +             << "{"; + +          // Check if min cardinality requirements have been met. Since +          // count is always >= 0, don't generate dead code if min == 0. +          // +          if (min != 0) +          { +            os << "if (vd->count < " << min << "UL)" << endl +               << "this->_expected_element (" << endl; + +            particle_name_.dispatch (c); + +            os << "," << endl +               << "ns, n);"; +          } + +          // Return false to indicate that we are not handling this element. +          // +          os << "return false;" +             << "}" +             << "}" // if (state != ~0) +             << "else" << endl +             << "return false;" +             << "}"; // if (function == 0) +        } + +      private: +        SemanticGraph::Complex& type_; +        ParticleTest particle_test_; +        ParticleName particle_name_; +      }; + + +      // +      // +      struct CompositorEndElement: Traversal::All, +                                   Traversal::Compositor, +                                   Context +      { +        CompositorEndElement (Context& c) +          : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::All&) +        { +          os << "all_0 (vd.state, v_all_count_.top (), " << +            "ns, n, 0, false);" +             << endl; +        } + +        virtual void +        traverse (SemanticGraph::Compositor&) // Choice and sequence. +        { +          os << "assert (vd.func != 0);" +             << "(this->*vd.func) (vd.state, vd.count, ns, n, 0, false);" +             << endl +             << "if (vd.state == ~0UL)" << endl +             << "vs.size--;" // pop +             << endl; +        } +      }; + + +      // +      // +      struct CompositorPost: Traversal::All, +                             Traversal::Compositor, +                             Context +      { +        CompositorPost (Context& c) +            : Context (c), particle_name_ (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::All& a) +        { +          using SemanticGraph::Element; + +          os << "v_state_& vs = *static_cast< v_state_* > (" << +            "this->v_state_stack_.top ());" +             << "v_state_descr_& vd = vs.data[vs.size - 1];" +             << endl; + +          // Flush the state machine with the empty element name. This +          // allows us to detect missing content. +          // +          os << "if (vd.count != 0)" +             << "{" +             << string_type << " empty;" +             << "all_0 (vd.state, v_all_count_.top (), empty, empty, 0, true);" +             << "}"; + +          if (a.context ().get<size_t> ("effective-min") != 0) +          { +            os << "else" << endl +               << "this->_expected_element (" << endl; + +            particle_name_.dispatch (a); + +            os << ");"; +          } + +          os << endl +             << "vs.size--;" // pop +             << "v_all_count_.pop ();"; +        } + +        virtual void +        traverse (SemanticGraph::Compositor& c) // Choice and sequence. +        { +          size_t min (c.context ().get<size_t> ("effective-min")); + +          os << "v_state_& vs = *static_cast< v_state_* > (" << +            "this->v_state_stack_.top ());" +             << "v_state_descr_* vd = vs.data + (vs.size - 1);" +             << endl; + + +          // Flush unfinished state machines with the empty element name. +          // This allows us to detect missing content. Note that I am +          // not re-setting vd since no new compositors are pushed on +          // flush. +          // +          os << string_type << " empty;" +             << "while (vd->func != 0)" +             << "{" +             << "(this->*vd->func) (vd->state, vd->count, empty, empty, 0, true);" +             << "assert (vd->state == ~0UL);" +             << "vd = vs.data + (--vs.size - 1);" // pop +             << "}"; + +          // Check if min cardinality requirements have been met. Since +          // count is always >= 0, don't generate dead code if min == 0. +          // +          if (min != 0) +          { +            os << "if (vd->count < " << min << "UL)" << endl +               << "this->_expected_element (" << endl; + +            particle_name_.dispatch (c); + +            os << ");"; +          } +        } + +      private: +        ParticleName particle_name_; +      }; + + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          // Nothing to generate if we don't have any elements and wildcards. +          // +          if (!has<Traversal::Element> (c) && +              !has_particle<Traversal::Any> (c)) +            return; + +          using SemanticGraph::Compositor; + +          String const& name (ename (c)); +          Compositor& comp (c.contains_compositor ().compositor ()); + +          // Don't use restriction_p here since we don't want special +          // treatment of anyType. +          // +          bool restriction ( +            c.inherits_p () && +            c.inherits ().is_a<SemanticGraph::Restricts> ()); + +          os <<"// Element validation and dispatch functions for " << +            name << "." << endl +             <<"//" << endl; + +          // _start_element_impl +          // + +          os << "bool " << name << "::" << endl +             << "_start_element_impl (const " << string_type << "& ns," << endl +             << "const " << string_type << "& n," << endl +             << "const " << string_type << "* t)" +             << "{" +             << "XSD_UNUSED (t);" +             << endl; + +          os << "v_state_& vs = *static_cast< v_state_* > (" << +            "this->v_state_stack_.top ());" +             << "v_state_descr_* vd = vs.data + (vs.size - 1);" +             << endl; + +          //@@ OPT: I don't really need to call parser_base since it always +          // returns false. +          // +          // In case of an inheritance-by-extension, call our base first. +          // We don't need to generate this code for the 'all' compositor +          // because it can only inherit from the empty content model. +          // States of the root machine for sequence and choice: +          // +          //  0 - calling base +          //  1 - base returned false +          // ~0 - terminal state +          // +          if (!restriction && !comp.is_a<SemanticGraph::All> ()) +          { +            os << "if (vd->func == 0 && vd->state == 0)" +               << "{" +               << "if (this->"; + +            if (c.inherits_p ()) +              os << fq_name (c.inherits ().base ()); +            else +              os << complex_base; + + +            os << "::_start_element_impl (ns, n, t))" << endl +               << "return true;" +               << "else" << endl +               << "vd->state = 1;" +               << "}"; +          } + +          { +            CompositorStartElement t (*this, c); +            t.dispatch (comp); +          } + +          os << "return true;" +             << "}"; + + +          // _end_element_impl +          // + +          os << "bool " << name << "::" << endl +             << "_end_element_impl (const " << string_type << "& ns," << endl +             << "const " << string_type << "& n)" +             << "{"; + +          os << "v_state_& vs = *static_cast< v_state_* > (" << +            "this->v_state_stack_.top ());" +             << "v_state_descr_& vd = vs.data[vs.size - 1];" +             << endl; + +          //@@ OPT: I don't really need to call parser_base since it always +          // returns false. +          // +          // In case of an inheritance-by-extension, call our base first. +          // We don't need to generate this code for the 'all' compositor +          // because it can only inherit from the empty content model. +          // +          if (!restriction && !comp.is_a<SemanticGraph::All> ()) +          { +            os << "if (vd.func == 0 && vd.state == 0)" +               << "{" +               << "if (!"; + +            if (c.inherits_p ()) +              os << fq_name (c.inherits ().base ()); +            else +              os << complex_base; + +            os << "::_end_element_impl (ns, n))" << endl +               << "assert (false);" // Start and end should match. +               << "return true;" +               << "}"; +          } + +          { +            CompositorEndElement t (*this); +            t.dispatch (comp); +          } + +          os << "return true;" +             << "}"; + + +          // _pre_e_validate +          // +          os << "void " << name << "::" << endl +             << "_pre_e_validate ()" +             << "{" +             << "this->v_state_stack_.push ();" +             << "static_cast< v_state_* > (this->v_state_stack_.top ())->" << +            "size = 0;" +             << endl; + +          { +            CompositorPre t (*this); +            t.dispatch (comp); +          } + +          // In case of an inheritance-by-extension, call our base +	  // _pre_e_validate. We don't need to generate this code for the +	  // 'all' compositor because it can only inherit from the empty +	  // content model. +          // +          if (!restriction && !comp.is_a<SemanticGraph::All> ()) +          { +            // We don't need to call parser_base's implementation +            // since it does nothing. +            // +            if (c.inherits_p ()) +            { +              os << endl +                 << fq_name (c.inherits ().base ()) << "::_pre_e_validate ();"; +            } +          } + +          os << "}"; + + +          // _post_e_validate +          // +          os << "void " << name << "::" << endl +             << "_post_e_validate ()" +             << "{"; + +          // In case of an inheritance-by-extension, call our base +	  // _post_e_validate. We don't need to generate this code for +	  // the 'all' compositor because it can only inherit from +	  // the empty content model. +          // +          if (!restriction && !comp.is_a<SemanticGraph::All> ()) +          { +            // We don't need to call parser_base's implementation +            // since it does nothing. +            // +            if (c.inherits_p ()) +            { +              os << fq_name (c.inherits ().base ()) << "::_post_e_validate ();" +                 << endl; +            } +          } + +          { +            CompositorPost t (*this); +            t.dispatch (c.contains_compositor ().compositor ()); +          } + +          os << endl +             << "this->v_state_stack_.pop ();" +             << "}"; + +          // +          // +          ParticleFunction t (*this, c); +          t.dispatch (c.contains_compositor ().compositor ()); +        } +      }; +    } + +    void +    generate_element_validation_source (Context& ctx) +    { +      ctx.os << "#include <cassert>" << endl +             << endl; + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names schema_names; + +      Namespace ns (ctx); +      Traversal::Names names; + +      schema >> sources >> schema; +      schema >> schema_names >> ns >> names; + +      Complex complex (ctx); + +      names >> complex; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/parser/element-validation-source.hxx b/xsd/cxx/parser/element-validation-source.hxx new file mode 100644 index 0000000..b358aee --- /dev/null +++ b/xsd/cxx/parser/element-validation-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/element-validation-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_ELEMENT_VALIDATION_SOURCE_HXX +#define XSD_CXX_PARSER_ELEMENT_VALIDATION_SOURCE_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_element_validation_source (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_ELEMENT_VALIDATION_SOURCE_HXX diff --git a/xsd/cxx/parser/elements.cxx b/xsd/cxx/parser/elements.cxx new file mode 100644 index 0000000..63fb3d5 --- /dev/null +++ b/xsd/cxx/parser/elements.cxx @@ -0,0 +1,247 @@ +// file      : xsd/cxx/parser/elements.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    Context:: +    Context (std::wostream& o, +             SemanticGraph::Schema& root, +             SemanticGraph::Path const& path, +             options_type const& ops, +             StringLiteralMap const* map, +             Regex const* he, +             Regex const* ie, +             Regex const* hie) +        : CXX::Context (o, root, path, ops, map), +          options (ops), +          xml_parser (xml_parser_), +          simple_base (simple_base_), +          complex_base (complex_base_), +          list_base (list_base_), +          cout_inst (cout_inst_), +          cerr_inst (cerr_inst_), +          parser_map (parser_map_), +          std_string_type (std_string_type_), +          validation (validation_), +          polymorphic (polymorphic_), +          hxx_expr (he), +          ixx_expr (ie), +          hxx_impl_expr (hie), +          xml_parser_ (ops.xml_parser ()), +          validation_ ((ops.xml_parser () == "expat" || +                        ops.generate_validation ()) && +                       !ops.suppress_validation ()), +          polymorphic_ (ops.generate_polymorphic ()) +    { +      if (char_type == L"char") +        std_string_type = L"::std::string"; +      else if (char_type == L"wchar_t") +        std_string_type = L"::std::wstring"; +      else +        std_string_type = L"::std::basic_string< " + char_type + L" >"; + +      String xs_ns (xs_ns_name ()); + +      string_type = xs_ns + L"::ro_string"; +      simple_base = xs_ns + L"::simple_content"; +      complex_base = xs_ns + L"::complex_content"; +      list_base = xs_ns + L"::list_base"; + +      cout_inst = (char_type == L"char" ? L"std::cout" : L"std::wcout"); +      cerr_inst = (char_type == L"char" ? L"std::cerr" : L"std::wcerr"); + +      if (polymorphic) +        parser_map_ = xs_ns + L"::parser_map"; +    } + +    Context:: +    Context (Context& c) +        : CXX::Context (c), +          options (c.options), +          xml_parser (c.xml_parser), +          simple_base (c.simple_base), +          complex_base (c.complex_base), +          list_base (c.list_base), +          cout_inst (c.cout_inst), +          cerr_inst (c.cerr_inst), +          parser_map (c.parser_map), +          std_string_type (c.std_string_type), +          validation (c.validation), +          polymorphic (c.polymorphic), +          hxx_expr (c.hxx_expr), +          ixx_expr (c.ixx_expr), +          hxx_impl_expr (c.hxx_impl_expr) +    { +    } + +    Context:: +    Context (Context& c, std::wostream& o) +        : CXX::Context (c, o), +          options (c.options), +          xml_parser (c.xml_parser), +          simple_base (c.simple_base), +          complex_base (c.complex_base), +          list_base (c.list_base), +          cout_inst (c.cout_inst), +          cerr_inst (c.cerr_inst), +          parser_map (c.parser_map), +          std_string_type (c.std_string_type), +          validation (c.validation), +          polymorphic (c.polymorphic), +          hxx_expr (c.hxx_expr), +          ixx_expr (c.ixx_expr), +          hxx_impl_expr (c.hxx_impl_expr) +    { +    } + +    Content::Value Context:: +    content (SemanticGraph::Complex& c) +    { +      using namespace SemanticGraph; + +      if (c.mixed_p ()) +        return Content::mixed; + +      if (c.inherits_p ()) +      { +        Type& base (c.inherits ().base ()); + +        if (Complex* cb = dynamic_cast<Complex*> (&base)) +          return content (*cb); + +        if (base.is_a<AnyType> ()) +          return Content::complex; + +        // Everyhting else (built-in type and AnySimpleType) is simple +        // content. +        // +        return Content::simple; +      } +      else +        return Content::complex; +    } + +    bool Context:: +    anonymous (SemanticGraph::Type& t) +    { +      return t.context ().count ("anonymous"); +    } + +    String const& Context:: +    ret_type (SemanticGraph::Type& t) +    { +      return t.context ().get<String> ("ret-type"); +    } + +    String const& Context:: +    arg_type (SemanticGraph::Type& t) +    { +      return t.context ().get<String> ("arg-type"); +    } + +    String const& Context:: +    post_name (SemanticGraph::Type& t) +    { +      return t.context ().get<String> ("post"); +    } + +    String const& Context:: +    eparser (SemanticGraph::Member& m) +    { +      return m.context ().get<String> ("parser"); +    } + +    String const& Context:: +    emember (SemanticGraph::Member& m) +    { +      return m.context ().get<String> ("member"); +    } + +    String const& Context:: +    emember_map (SemanticGraph::Member& m) +    { +      return m.context ().get<String> ("member-map"); +    } + +    String const& Context:: +    eimpl (SemanticGraph::Type& t) +    { +      return t.context ().get<String> ("impl"); +    } + +    // Includes +    // +    void TypeForward:: +    traverse (SemanticGraph::Type& t) +    { +      os << "class " << t.context ().get<String> (name_key_) << ";"; +    } + +    void Includes:: +    traverse_ (SemanticGraph::Uses& u) +    { +      // Support for weak (forward) inclusion used in the file-per-type +      // compilation model. +      // +      SemanticGraph::Schema& s (u.schema ()); +      bool weak (u.context ().count ("weak")); + +      if (weak && (type_ == header || type_ == impl_header)) +      { +        // Generate forward declarations. We don't really need them +        // in the impl files. +        // +        if (type_ == header) +          schema_.dispatch (s); + +        return; +      } + +      if (type_ == source && !weak) +        return; + +      SemanticGraph::Path path ( +        s.context ().count ("renamed") +        ? s.context ().get<SemanticGraph::Path> ("renamed") +        : u.path ()); +      path.normalize (); + +      // Try to use the portable representation of the path. If that +      // fails, fall back to the native representation. +      // +      NarrowString path_str; +      try +      { +        path_str = path.posix_string (); +      } +      catch (SemanticGraph::InvalidPath const&) +      { +        path_str = path.string (); +      } + +      String inc_path; + +      switch (type_) +      { +      case header: +      case source: +        { +          inc_path = ctx_.hxx_expr->replace (path_str); +          break; +        } +      case impl_header: +        { +          inc_path = ctx_.hxx_impl_expr->replace (path_str); +          break; +        } +      } + +      ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl +              << endl; +    } +  } +} diff --git a/xsd/cxx/parser/elements.hxx b/xsd/cxx/parser/elements.hxx new file mode 100644 index 0000000..0015923 --- /dev/null +++ b/xsd/cxx/parser/elements.hxx @@ -0,0 +1,315 @@ +// file      : xsd/cxx/parser/elements.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_ELEMENTS_HXX +#define XSD_CXX_PARSER_ELEMENTS_HXX + +#include <sstream> + +#include <libcutl/re.hxx> + +#include <xsd/types.hxx> + +#include <xsd/cxx/elements.hxx> + +#include <xsd/cxx/parser/options.hxx> + +namespace CXX +{ +  namespace Parser +  { +    struct Content +    { +      enum Value +      { +        simple, +        complex, +        mixed +      }; +    }; + +    // +    // +    class Context: public CXX::Context +    { +    public: +      typedef cutl::re::regexsub Regex; + +      typedef Parser::options options_type; + +    public: +      Context (std::wostream&, +               SemanticGraph::Schema&, +               SemanticGraph::Path const& path, +               options_type const&, +               StringLiteralMap const*, +               Regex const* hxx_expr, +               Regex const* ixx_expr, +               Regex const* hxx_impl_expr); + +    protected: +      Context (Context& c); +      Context (Context& c, std::wostream& o); + +    public: +      bool +      restriction_p (SemanticGraph::Complex& c) const +      { +        if (c.inherits_p () && +            c.inherits ().is_a<SemanticGraph::Restricts> ()) +        { +          // Restriction of anyType is a special case. +          // +          return !c.inherits ().base ().is_a<SemanticGraph::AnyType> (); +        } + +        return false; +      } + +    public: +      static Content::Value +      content (SemanticGraph::Complex&); + +    public: +      static bool +      anonymous (SemanticGraph::Type&); + +    public: +      static String const& +      ret_type (SemanticGraph::Type&); + +      static String const& +      arg_type (SemanticGraph::Type&); + +      static String const& +      post_name (SemanticGraph::Type&); + +    public: +      static String const& +      eparser (SemanticGraph::Member&); + +      static String const& +      emember (SemanticGraph::Member&); + +      static String const& +      emember_map (SemanticGraph::Member&); + +    public: +      static String const& +      eimpl (SemanticGraph::Type&); + +    public: +      options_type const& options; +      String& xml_parser; +      String& simple_base; +      String& complex_base; +      String& list_base; +      String& cout_inst; +      String& cerr_inst; +      String& parser_map; +      String& std_string_type; +      bool& validation; +      bool& polymorphic; + +      Regex const* hxx_expr; +      Regex const* ixx_expr; +      Regex const* hxx_impl_expr; + +    private: +      String xml_parser_; +      String simple_base_; +      String complex_base_; +      String list_base_; +      String cout_inst_; +      String cerr_inst_; +      String parser_map_; +      String std_string_type_; +      bool validation_; +      bool polymorphic_; +    }; + +    // +    // +    struct RequiredAttributeTest: Traversal::Attribute +    { +      RequiredAttributeTest (bool& result) +          : result_ (result) +      { +      } + +      virtual void +      traverse (Type& a) +      { +        if (!result_ && !a.optional_p ()) +          result_ = true; +      } + +    private: +      bool& result_; +    }; + +    // +    // +    struct ParserParamDecl: Traversal::Complex, +                            Traversal::List, +                            Traversal::Member, +                            Context +    { +      ParserParamDecl (Context& c, bool name_arg) +          : Context (c), first_ (true), name_arg_ (name_arg) +      { +        inherits_ >> *this; +        names_ >> *this; +      } + +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        inherits (c, inherits_); + +        if (!restriction_p (c)) +          names (c, names_); +      } + +      virtual void +      traverse (SemanticGraph::List& l) +      { +        if (!first_) +          os << "," << endl; +        else +          first_ = false; + +        os << fq_name (l.argumented ().type ()) << "&"; + +        if (name_arg_) +          os << " " << ename (l) << "_item"; +        else +          os << " /* " << comment (l.name ()) << " item */"; +      } + +      virtual void +      traverse (SemanticGraph::Member& m) +      { +        if (skip (m)) return; + +        if (!first_) +          os << "," << endl; +        else +          first_ = false; + +        os << fq_name (m.type ()) << "&"; + +        if (name_arg_) +          os << " " << ename (m); +        else +          os << " /* " << comment (m.name ()) << " */"; +      } + +    private: +      Traversal::Inherits inherits_; +      Traversal::Names names_; + +      bool first_; +      bool name_arg_; +    }; + + +    // +    // +    struct TypeForward: Traversal::Type, Context +    { +      TypeForward (Context& c, char const* name_key) +          : Context (c), name_key_ (name_key) +      { +      } + +      virtual void +      traverse (SemanticGraph::Type& t); + +    private: +      char const* name_key_; +    }; + +    struct Includes: Traversal::Imports, +                     Traversal::Includes +    { +      enum Type +      { +        header, +        source, +        impl_header +      }; + +      Includes (Context& c, Type t) +          : ctx_ (c), +            type_ (t), +            namespace_ (c), +            type_forward_ (c, t == header ? "name" : "impl") +      { +        schema_ >> schema_names_ >> namespace_ >> names_ >> type_forward_; +      } + +      virtual void +      traverse (SemanticGraph::Imports& i) +      { +        traverse_ (i); +      } + +      virtual void +      traverse (SemanticGraph::Includes& i) +      { +        traverse_ (i); +      } + +    private: +      void +      traverse_ (SemanticGraph::Uses&); + +    private: +      Context& ctx_; +      Type type_; + +      Traversal::Schema schema_; +      Traversal::Names schema_names_; +      Namespace namespace_; +      Traversal::Names names_; +      TypeForward type_forward_; +    }; + +    // Find root element for the test driver. +    // +    struct RootElement: Traversal::Element +    { +      typedef Parser::options options_type; + +      RootElement (options_type const& options, +                   SemanticGraph::Element*& element) +          : options_ (options), element_ (element) +      { +      } + +      virtual void +      traverse (Type& e) +      { +        if (options_.root_element_first ()) +        { +          if (element_ == 0) +            element_ = &e; +        } +        else if (String name = options_.root_element ()) +        { +          if (e.name () == name) +            element_ = &e; +        } +        else +          element_ = &e; // Cover root-element-last and no option. +      } + +    private: +      options_type const& options_; +      SemanticGraph::Element*& element_; +    }; +  } +} + +#endif  // XSD_CXX_PARSER_ELEMENTS_HXX diff --git a/xsd/cxx/parser/generator.cxx b/xsd/cxx/parser/generator.cxx new file mode 100644 index 0000000..b1acdbb --- /dev/null +++ b/xsd/cxx/parser/generator.cxx @@ -0,0 +1,1133 @@ +// file      : xsd/cxx/parser/generator.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <algorithm> +#include <iostream> +#include <fstream> + +#include <libcutl/re.hxx> + +#include <libcutl/compiler/code-stream.hxx> +#include <libcutl/compiler/cxx-indenter.hxx> +#include <libcutl/compiler/sloc-counter.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> + +#include <xsd/version.hxx> + +#include <xsd/type-map/lexer.hxx> +#include <xsd/type-map/parser.hxx> +#include <xsd/type-map/type-map.hxx> + +#include <xsd/cxx/parser/elements.hxx> +#include <xsd/cxx/parser/generator.hxx> + +#include <xsd/cxx/parser/validator.hxx> +#include <xsd/cxx/parser/name-processor.hxx> +#include <xsd/cxx/parser/state-processor.hxx> +#include <xsd/cxx/parser/type-processor.hxx> + +#include <xsd/cxx/parser/parser-header.hxx> +#include <xsd/cxx/parser/parser-inline.hxx> +#include <xsd/cxx/parser/parser-source.hxx> +#include <xsd/cxx/parser/parser-forward.hxx> + +#include <xsd/cxx/parser/impl-header.hxx> +#include <xsd/cxx/parser/impl-source.hxx> +#include <xsd/cxx/parser/driver-source.hxx> + +#include <xsd/cxx/parser/element-validation-source.hxx> +#include <xsd/cxx/parser/attribute-validation-source.hxx> +#include <xsd/cxx/parser/characters-validation-source.hxx> + +#include <xsd/cxx/parser/options.hxx> + +using std::endl; +using std::wcerr; +using std::wcout; + +using namespace XSDFrontend::SemanticGraph; + +// +// +typedef std::wifstream WideInputFileStream; +typedef std::wofstream WideOutputFileStream; +typedef std::ifstream NarrowInputFileStream; + +namespace CXX +{ +  namespace +  { +    char const copyright_gpl[] = +    "// Copyright (c) " XSD_COPYRIGHT ".\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 gives permission\n" +    "// to link this program with the Xerces-C++ library (or with modified\n" +    "// versions of Xerces-C++ that use the same license as Xerces-C++), and\n" +    "// distribute linked combinations including the two. You must obey the GNU\n" +    "// General Public License version 2 in all respects for all of the code\n" +    "// used other than Xerces-C++. If you modify this copy of the program, you\n" +    "// may extend this exception to your version of the program, but you are\n" +    "// not obligated to do so. If you do not wish to do so, delete this\n" +    "// exception statement from your version.\n" +    "//\n" +    "// Furthermore, Code Synthesis makes a special exception for the Free/Libre\n" +    "// and Open Source Software (FLOSS) which is described in the accompanying\n" +    "// FLOSSE file.\n" +    "//\n\n"; + +    char const copyright_proprietary[] = +    "// Copyright (c) " XSD_COPYRIGHT ".\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" +    "// prior to generating this code. See the license text for conditions.\n" +    "//\n\n"; + +    char const copyright_impl[] = +    "// Not copyrighted - public domain.\n" +    "//\n" +    "// This sample parser implementation was generated by CodeSynthesis XSD,\n" +    "// an XML Schema to C++ data binding compiler. You may use it in your\n" +    "// programs without any restrictions.\n" +    "//\n\n"; +  } + +  void Parser::Generator:: +  usage () +  { +    CXX::Parser::options::print_usage (wcout); +    CXX::options::print_usage (wcout); +  } + +  namespace +  { +    template <typename S> +    void +    open (S& ifs, NarrowString const& path) +    { +      try +      { +        Path fs_path (path); +        ifs.open (fs_path.string ().c_str (), +                  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 Parser::Generator::Failed (); +        } +      } +      catch (InvalidPath const&) +      { +        wcerr << "error: '" << path.c_str () << "' is not a valid " +              << "filesystem path" << endl; + +        throw Parser::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, +            NarrowStrings const& primary, +            NarrowStrings const& def) +    { +      NarrowStrings const& v (primary.empty () ? def : primary); + +      for (NarrowStrings::const_iterator i (v.begin ()), e (v.end ()); +           i != e; ++i) +      { +        os << i->c_str () << endl; +      } +    } +  } + + +  size_t Parser::Generator:: +  generate (Parser::options const& ops, +            Schema& schema, +            Path const& file_path, +            bool fpt, +            StringLiteralMap const& string_literal_map, +            bool gen_driver, +            const WarningSet& disabled_warnings, +            FileList& file_list, +            AutoUnlinks& unlinks) +  { +    using std::ios_base; + +    typedef cutl::re::regexsub Regex; + +    try +    { +      bool generate_xml_schema (ops.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.extern_xml_schema ()) +        { +          if (file_path.string () != name) +            generate_xml_schema = false; +        } +      } + +      bool impl (!generate_xml_schema && +                    (ops.generate_noop_impl () || +                     ops.generate_print_impl ())); + +      bool driver (gen_driver && !generate_xml_schema && +                      ops.generate_test_driver ()); + +      // Evaluate the graph for possibility of generating something useful. +      // +      { +        Validator validator; +        if (!validator.validate ( +              ops, schema, file_path, driver, disabled_warnings)) +          throw Failed (); +      } + +      bool gen_cxx (!ops.file_list_only ()); + +      // Process names. +      // +      if (gen_cxx) +      { +        NameProcessor proc; +        proc.process (ops, schema, file_path, string_literal_map); +      } + +      bool validation ((ops.xml_parser () == "expat" || +                           ops.generate_validation ()) && +                          !ops.suppress_validation ()); + +      // Compute state machine info. +      // +      if (gen_cxx && validation) +      { +        StateProcessor proc; +        proc.process (schema, file_path); +      } + +      // Read-in type maps. +      // +      TypeMap::Namespaces type_map; +      if (gen_cxx) +      { +        using namespace TypeMap; + +        NarrowStrings const& files (ops.type_map ()); + +        for (NarrowStrings::const_iterator f (files.begin ()); +             f != files.end (); ++f ) +        { +          NarrowInputFileStream ifs; +          open (ifs, *f); + +          Lexer l (ifs, *f); +          TypeMap::Parser p (l, *f); + +          if (!p.parse (type_map)) +            throw Failed (); +        } + +        // Add the built-in mappings at the end. +        // + +        // String-based types. +        // +        String char_type (ops.char_type ()); +        String string_type; + +        if (char_type == L"char") +          string_type = L"::std::string"; +        else if (char_type == L"wchar_t") +          string_type = L"::std::wstring"; +        else +          string_type = L"::std::basic_string< " + char_type + L" >"; + +        String xns; +        String auto_ptr; +        { +          Context ctx (std::wcerr, schema, file_path, ops, 0, 0, 0, 0); +          xns = ctx.xs_ns_name (); +          auto_ptr = ctx.auto_ptr; +        } + +        String buffer (auto_ptr + L"< " + xns + L"::buffer >"); +        TypeMap::Namespace xsd ("http://www\\.w3\\.org/2001/XMLSchema"); + +        xsd.types_push_back ("string", string_type); +        xsd.types_push_back ("normalizedString", string_type); +        xsd.types_push_back ("token", string_type); +        xsd.types_push_back ("Name", string_type); +        xsd.types_push_back ("NMTOKEN", string_type); +        xsd.types_push_back ("NMTOKENS", xns + L"::string_sequence"); +        xsd.types_push_back ("NCName", string_type); + +        xsd.types_push_back ("ID", string_type); +        xsd.types_push_back ("IDREF", string_type); +        xsd.types_push_back ("IDREFS", xns + L"::string_sequence"); + +        xsd.types_push_back ("language", string_type); +        xsd.types_push_back ("anyURI", string_type); +        xsd.types_push_back ("QName", xns + L"::qname"); + +        xsd.types_push_back ("base64Binary", buffer, buffer); +        xsd.types_push_back ("hexBinary", buffer, buffer); + +        xsd.types_push_back ("gDay", xns + L"::gday"); +        xsd.types_push_back ("gMonth", xns + L"::gmonth"); +        xsd.types_push_back ("gYear", xns + L"::gyear"); +        xsd.types_push_back ("gMonthDay", xns + L"::gmonth_day"); +        xsd.types_push_back ("gYearMonth", xns + L"::gyear_month"); +        xsd.types_push_back ("date", xns + L"::date"); +        xsd.types_push_back ("time", xns + L"::time"); +        xsd.types_push_back ("dateTime", xns + L"::date_time"); +        xsd.types_push_back ("duration", xns + L"::duration"); + +        // Fundamental C++ types. +        // +        xsd.types_push_back ("boolean", "bool", "bool"); + +        xsd.types_push_back ("byte", "signed char", "signed char"); +        xsd.types_push_back ("unsignedByte", +                             "unsigned char", +                             "unsigned char"); + +        xsd.types_push_back ("short", "short", "short"); +        xsd.types_push_back ("unsignedShort", +                             "unsigned short", +                             "unsigned short"); + +        xsd.types_push_back ("int", "int", "int"); +        xsd.types_push_back ("unsignedInt", "unsigned int", "unsigned int"); + +        xsd.types_push_back ("long", "long long", "long long"); +        xsd.types_push_back ("unsignedLong", +                             "unsigned long long", +                             "unsigned long long"); + +        xsd.types_push_back ("integer", "long long", "long long"); + +        xsd.types_push_back ("negativeInteger", "long long", "long long"); +        xsd.types_push_back ("nonPositiveInteger", "long long", "long long"); + +        xsd.types_push_back ("positiveInteger", +                             "unsigned long long", +                             "unsigned long long"); +        xsd.types_push_back ("nonNegativeInteger", +                             "unsigned long long", +                             "unsigned long long"); + +        xsd.types_push_back ("float", "float", "float"); +        xsd.types_push_back ("double", "double", "double"); +        xsd.types_push_back ("decimal", "double", "double"); + +        type_map.push_back (xsd); + +        // Everything else maps to void. +        // +        TypeMap::Namespace rest (".*"); +        rest.types_push_back (".*", "void", "void"); +        type_map.push_back (rest); +      } + +      // Process types. +      // +      if (gen_cxx) +      { +        TypeProcessor proc; +        proc.process (ops, schema, gen_driver, type_map); +      } + +      // +      // +      bool inline_ (ops.generate_inline () && !generate_xml_schema); +      bool source (!generate_xml_schema); + +      // Generate code. +      // +      NarrowString name (file_path.leaf ().string ()); +      NarrowString skel_suffix (ops.skel_file_suffix ()); +      NarrowString impl_suffix (ops.impl_file_suffix ()); + +      NarrowString hxx_suffix (ops.hxx_suffix ()); +      NarrowString ixx_suffix (ops.ixx_suffix ()); +      NarrowString cxx_suffix (ops.cxx_suffix ()); + +      Regex hxx_expr ( +        ops.hxx_regex ().empty () +        ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#" +        : ops.hxx_regex ()); + +      Regex ixx_expr ( +        ops.ixx_regex ().empty () +        ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + ixx_suffix + "#" +        : ops.ixx_regex ()); + +      Regex cxx_expr ( +        ops.cxx_regex ().empty () +        ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + cxx_suffix + "#" +        : ops.cxx_regex ()); + + +      Regex hxx_impl_expr; +      Regex cxx_impl_expr; +      Regex cxx_driver_expr; + +      if (impl || driver) +      { +        hxx_impl_expr = +          "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#"; + +        cxx_impl_expr = +          "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#"; + +        cxx_driver_expr = +          "#^(.+?)(\\.[^./\\\\]+)?$#$1-driver" + cxx_suffix + "#"; +      } + +      if (!hxx_expr.match (name)) +      { +        wcerr << "error: header expression '" << +          hxx_expr.regex ().str ().c_str () << "' does not match '" << +          name.c_str () << "'" << endl; +        throw Failed (); +      } + +      if (inline_ && !ixx_expr.match (name)) +      { +        wcerr << "error: inline expression '" << +          ixx_expr.regex ().str ().c_str () << "' does not match '" << +          name.c_str () << "'" << endl; +        throw Failed (); +      } + +      if (source && !cxx_expr.match (name)) +      { +        wcerr << "error: source expression '" << +          cxx_expr.regex ().str ().c_str () << "' does not match '" << +          name.c_str () << "'" << endl; +        throw Failed (); +      } + +      if (impl || driver) +      { +        if (!hxx_impl_expr.match (name)) +        { +          wcerr << "error: implementation header expression '" << +            hxx_impl_expr.regex ().str ().c_str () << "' does not match '" << +            name.c_str () << "'" << endl; +          throw Failed (); +        } + +        if (!cxx_impl_expr.match (name)) +        { +          wcerr << "error: implementation source expression '" << +            cxx_impl_expr.regex ().str ().c_str () << "' does not match '" << +            name.c_str () << "'" << endl; +          throw Failed (); +        } + +        if (!cxx_driver_expr.match (name)) +        { +          wcerr << "error: driver source expression '" << +            cxx_driver_expr.regex ().str ().c_str () << "' does not match '" << +            name.c_str () << "'" << endl; +          throw Failed (); +        } +      } + +      NarrowString hxx_name (hxx_expr.replace (name)); +      NarrowString ixx_name (inline_ ? ixx_expr.replace (name) : NarrowString ()); +      NarrowString cxx_name (source ? cxx_expr.replace (name) : NarrowString ()); + +      NarrowString hxx_impl_name; +      NarrowString cxx_impl_name; +      NarrowString cxx_driver_name; + +      if (impl || driver) +      { +        hxx_impl_name = hxx_impl_expr.replace (name); +        cxx_impl_name = cxx_impl_expr.replace (name); +        cxx_driver_name = cxx_driver_expr.replace (name); +      } + +      Path hxx_path (hxx_name); +      Path ixx_path (ixx_name); +      Path cxx_path (cxx_name); + +      Path hxx_impl_path; +      Path cxx_impl_path; +      Path cxx_driver_path; + +      if (impl || driver) +      { +        hxx_impl_path = Path (hxx_impl_name); +        cxx_impl_path = Path (cxx_impl_name); +        cxx_driver_path = Path (cxx_driver_name); +      } + +      Path out_dir; + +      if (NarrowString dir = ops.output_dir ()) +      { +        try +        { +          out_dir = Path (dir); +        } +        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.directory ()); + +        if (!fpt_dir.empty ()) +          out_dir /= fpt_dir; +      } + +      if (!out_dir.empty ()) +      { +        hxx_path = out_dir / hxx_path; +        ixx_path = out_dir / ixx_path; +        cxx_path = out_dir / cxx_path; + +        if (impl || driver) +        { +          hxx_impl_path = out_dir / hxx_impl_path; +          cxx_impl_path = out_dir / cxx_impl_path; +          cxx_driver_path = out_dir /cxx_driver_path; +        } +      } + +      // Open the impl files first so that if open fails, the skel files +      // are not deleted. +      // +      WideOutputFileStream hxx_impl; +      WideOutputFileStream cxx_impl; +      WideOutputFileStream cxx_driver; + +      if (impl) +      { +        if (gen_cxx) +        { +          if (!ops.force_overwrite ()) +          { +            WideInputFileStream tmp ( +              hxx_impl_path.string ().c_str (), ios_base::in); + +            if (tmp.is_open ()) +            { +              wcerr << hxx_impl_path << ": error: cowardly refusing to " << +                "overwrite an existing file" << endl; +              throw Failed (); +            } + +            tmp.close (); +          } + +          hxx_impl.open (hxx_impl_path.string ().c_str (), ios_base::out); + +          if (!hxx_impl.is_open ()) +          { +            wcerr << hxx_impl_path << ": error: unable to open in write mode" +                  << endl; +            throw Failed (); +          } + +          unlinks.add (hxx_impl_path); +        } + +        file_list.push_back (hxx_impl_path.string ()); + +        if (gen_cxx) +        { +          if (!ops.force_overwrite ()) +          { +            WideInputFileStream tmp ( +              cxx_impl_path.string ().c_str (), ios_base::in); + +            if (tmp.is_open ()) +            { +              wcerr << cxx_impl_path << ": error: cowardly refusing to " << +                "overwrite an existing file" << endl; +              throw Failed (); +            } + +            tmp.close (); +          } + +          cxx_impl.open (cxx_impl_path.string ().c_str (), ios_base::out); + +          if (!cxx_impl.is_open ()) +          { +            wcerr << cxx_impl_path << ": error: unable to open in write mode" +                  << endl; +            throw Failed (); +          } + +          unlinks.add (cxx_impl_path); +        } + +        file_list.push_back (cxx_impl_path.string ()); +      } + +      if (driver) +      { +        if (gen_cxx) +        { +          if (!ops.force_overwrite ()) +          { +            WideInputFileStream tmp ( +              cxx_driver_path.string ().c_str (), ios_base::in); + +            if (tmp.is_open ()) +            { +              wcerr << cxx_driver_path << ": error: cowardly refusing to " << +                "overwrite an existing file" << endl; +              throw Failed (); +            } + +            tmp.close (); +          } + +          cxx_driver.open (cxx_driver_path.string ().c_str (), ios_base::out); + +          if (!cxx_driver.is_open ()) +          { +            wcerr << cxx_driver_path << ": error: unable to open in write " << +              "mode" << endl; +            throw Failed (); +          } + +          unlinks.add (cxx_driver_path); +        } + +        file_list.push_back (cxx_driver_path.string ()); +      } + +      // Open the skel files. +      // +      WideOutputFileStream hxx; +      WideOutputFileStream ixx; +      WideOutputFileStream cxx; + +      if (gen_cxx) +      { +        hxx.open (hxx_path.string ().c_str (), 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.string ()); + +      if (inline_) +      { +        if (gen_cxx) +        { +          ixx.open (ixx_path.string ().c_str (), 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.string ()); +      } + +      if (source) +      { +        if (gen_cxx) +        { +          cxx.open (cxx_path.string ().c_str (), 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.string ()); +      } + +      if (!gen_cxx) +        return 0; + +      // Print copyright and license. +      // +      char const* copyright ( +        ops.proprietary_license () ? copyright_proprietary : copyright_gpl); + +      hxx << copyright; + +      if (inline_) +        ixx << copyright; + +      if (source) +        cxx << copyright; + +      if (impl) +      { +        hxx_impl << copyright_impl; +        cxx_impl << copyright_impl; +      } + +      if (driver) +        cxx_driver << copyright_impl; + +      // Prologue. +      // +      WideInputFileStream prologue; +      { +        NarrowString name (ops.prologue_file ()); + +        if (name) +          open (prologue, name); +      } + +      // Epilogue. +      // +      WideInputFileStream epilogue; +      { +        NarrowString name (ops.epilogue_file ()); + +        if (name) +          open (epilogue, name); +      } + +      // SLOC counter. +      // +      size_t sloc_total (0); +      bool show_sloc (ops.show_sloc ()); + +      typedef +      compiler::ostream_filter<compiler::cxx_indenter, wchar_t> +      ind_filter; + +      typedef +      compiler::ostream_filter<compiler::sloc_counter, wchar_t> +      sloc_filter; + +      // +      // +      Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. + +      NarrowString guard_prefix (ops.guard_prefix ()); + +      if (!guard_prefix) +        guard_prefix = file_path.directory ().string (); + +      if (guard_prefix) +        guard_prefix += '_'; + +      // HXX +      // +      { +        Context ctx (hxx, +                     schema, +                     file_path, +                     ops, +                     &string_literal_map, +                     &hxx_expr, +                     &ixx_expr, +                     &hxx_impl_expr); + +        sloc_filter sloc (hxx); + +        String guard (guard_expr.replace (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; + +        if (ctx.std >= cxx_version::cxx11) +        { +          hxx << "#ifndef XSD_CXX11" << endl +              << "#define XSD_CXX11" << endl +              << "#endif" << endl +              << endl; +        } + +        // Copy prologue. +        // +        hxx << "// Begin prologue." << endl +            << "//" << endl; + +        append (hxx, ops.hxx_prologue (), ops.prologue ()); +        append (hxx, ops.hxx_prologue_file (), prologue); + +        hxx << "//" << endl +            << "// End prologue." << endl +            << endl; + +        // Version check. +        // +        hxx << "#include <xsd/cxx/config.hxx>" << endl +            << endl +            << "#if (LIBXSD_VERSION != " << XSD_VERSION << "L)" << endl +            << "#error XSD runtime version mismatch" << endl +            << "#endif" << endl +            << endl; + +        hxx << "#include <xsd/cxx/pre.hxx>" << endl +            << endl; + +        // Generate. +        // +        { +          ind_filter ind (hxx); // We don't want to indent prologues/epilogues. + +          if (!generate_xml_schema) +            generate_parser_forward (ctx); + +          generate_parser_header (ctx, generate_xml_schema); +        } + +        if (inline_) +          hxx << "#include " << ctx.process_include_path (ixx_name) << endl; + +        hxx << "#include <xsd/cxx/post.hxx>" << endl +            << endl; + +        // Copy epilogue. +        // +        hxx << "// Begin epilogue." << endl +            << "//" << endl; + +        append (hxx, ops.hxx_epilogue_file (), epilogue); +        append (hxx, ops.hxx_epilogue (), ops.epilogue ()); + +        hxx << "//" << endl +            << "// End epilogue." << endl +            << endl; + +        hxx << "#endif // " << guard << endl; + +        if (show_sloc) +          wcerr << hxx_path << ": " << sloc.stream ().count () << endl; + +        sloc_total += sloc.stream ().count (); +      } + + +      // IXX +      // +      if (inline_) +      { +        Context ctx (ixx, +                     schema, +                     file_path, +                     ops, +                     &string_literal_map, +                     &hxx_expr, +                     &ixx_expr, +                     &hxx_impl_expr); + +        sloc_filter sloc (ixx); + +        // Copy prologue. +        // +        ixx << "// Begin prologue." << endl +            << "//" << endl; + +        append (ixx, ops.ixx_prologue (), ops.prologue ()); +        append (ixx, ops.ixx_prologue_file (), prologue); + +        ixx << "//" << endl +            << "// End prologue." << endl +            << endl; + +        // Generate. +        // +        { +          ind_filter ind (ixx); // We don't want to indent prologues/epilogues. +          generate_parser_inline (ctx); +        } + +        // Copy epilogue. +        // +        ixx << "// Begin epilogue." << endl +            << "//" << endl; + +        append (ixx, ops.ixx_epilogue_file (), epilogue); +        append (ixx, ops.ixx_epilogue (), ops.epilogue ()); + +        ixx << "//" << endl +            << "// End epilogue." << endl +            << endl; + +        if (show_sloc) +          wcerr << ixx_path << ": " << sloc.stream ().count () << endl; + +        sloc_total += sloc.stream ().count (); +      } + + +      // CXX +      // +      if (source) +      { +        Context ctx (cxx, +                     schema, +                     file_path, +                     ops, +                     &string_literal_map, +                     &hxx_expr, +                     &ixx_expr, +                     &hxx_impl_expr); + +        sloc_filter sloc (cxx); + +        // Copy prologue. +        // +        cxx << "// Begin prologue." << endl +            << "//" << endl; + +        append (cxx, ops.cxx_prologue (), ops.prologue ()); +        append (cxx, ops.cxx_prologue_file (), prologue); + +        cxx << "//" << endl +            << "// End prologue." << endl +            << endl; + +        cxx << "#include <xsd/cxx/pre.hxx>" << endl +             << endl; + +        cxx << "#include " << ctx.process_include_path (hxx_name) << endl +            << endl; + +        // Generate. +        // +        { +          ind_filter ind (cxx); // We don't want to indent prologues/epilogues. + +          if (!inline_) +            generate_parser_inline (ctx); + +          generate_parser_source (ctx); + +          if (validation) +          { +            generate_element_validation_source (ctx); +            generate_attribute_validation_source (ctx); +            generate_characters_validation_source (ctx); +          } +        } + +        cxx << "#include <xsd/cxx/post.hxx>" << endl +            << endl; + +        // Copy epilogue. +        // +        cxx << "// Begin epilogue." << endl +            << "//" << endl; + +        append (cxx, ops.cxx_epilogue_file (), epilogue); +        append (cxx, ops.cxx_epilogue (), ops.epilogue ()); + +        cxx << "//" << endl +            << "// End epilogue." << endl +            << endl; + +        if (show_sloc) +          wcerr << cxx_path << ": " << sloc.stream ().count () << endl; + +        sloc_total += sloc.stream ().count (); +      } + +      // HXX impl +      // +      if (impl) +      { +        Context ctx (hxx_impl, +                     schema, +                     file_path, +                     ops, +                     &string_literal_map, +                     &hxx_expr, +                     &ixx_expr, +                     &hxx_impl_expr); + +        String guard (guard_expr.replace (guard_prefix + hxx_impl_name)); +        guard = ctx.escape (guard); // Make it a C++ id. +        std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + +        hxx_impl << "#ifndef " << guard << endl +                 << "#define " << guard << endl +                 << endl; + +        hxx_impl << "#include " << ctx.process_include_path (hxx_name) +                 << endl << endl; + +        { +          ind_filter ind (hxx_impl); +          generate_impl_header (ctx); +        } + +        hxx_impl << "#endif // " << guard << endl; +      } + +      // CXX impl +      // +      if (impl) +      { +        Context ctx (cxx_impl, +                     schema, +                     file_path, +                     ops, +                     &string_literal_map, +                     &hxx_expr, +                     &ixx_expr, +                     &hxx_impl_expr); + +        cxx_impl << "#include " << ctx.process_include_path (hxx_impl_name) +                 << endl << endl; + +        { +          ind_filter ind (cxx_impl); +          generate_impl_source (ctx); +        } +      } + +      // CXX driver +      // +      if (driver) +      { +        Context ctx (cxx_driver, +                     schema, +                     file_path, +                     ops, +                     &string_literal_map, +                     &hxx_expr, +                     &ixx_expr, +                     &hxx_impl_expr); + +        cxx_driver << "#include " << ctx.process_include_path (hxx_impl_name) +                   << endl << endl; + +        { +          ind_filter ind (cxx_driver); +          generate_driver_source (ctx); +        } +      } + +      return sloc_total; +    } +    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 (cutl::re::format const& e) +    { +      wcerr << "error: invalid regex: '" << +        e.regex ().c_str () << "': " << +        e.description ().c_str () << endl; + +      throw Failed (); +    } +    catch (cutl::re::wformat const& e) +    { +      wcerr << "error: invalid regex: '" << +        e.regex () << "': " << e.description ().c_str () << endl; + +      throw Failed (); +    } +  } +} diff --git a/xsd/cxx/parser/generator.hxx b/xsd/cxx/parser/generator.hxx new file mode 100644 index 0000000..150cd74 --- /dev/null +++ b/xsd/cxx/parser/generator.hxx @@ -0,0 +1,45 @@ +// file      : xsd/cxx/parser/generator.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_GENERATOR_HXX +#define XSD_CXX_PARSER_GENERATOR_HXX + +#include <libxsd-frontend/semantic-graph/elements.hxx> // Path +#include <libxsd-frontend/semantic-graph/schema.hxx> + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> + +#include <xsd/cxx/literal-map.hxx> +#include <xsd/cxx/parser/options.hxx> + +namespace CXX +{ +  namespace Parser +  { +    class Generator +    { +    public: +      static void +      usage (); + +      struct Failed {}; + +      static size_t +      generate (options const&, +                XSDFrontend::SemanticGraph::Schema&, +                XSDFrontend::SemanticGraph::Path const& file, +                bool file_per_type, +                StringLiteralMap const&, +                bool gen_driver, +                const WarningSet& disabled_warnings, +                FileList& file_list, +                AutoUnlinks& unlinks); + +    private: +      Generator (); +    }; +  } +} + +#endif // XSD_CXX_PARSER_GENERATOR_HXX diff --git a/xsd/cxx/parser/impl-header.cxx b/xsd/cxx/parser/impl-header.cxx new file mode 100644 index 0000000..be14dfa --- /dev/null +++ b/xsd/cxx/parser/impl-header.cxx @@ -0,0 +1,232 @@ +// file      : xsd/cxx/parser/impl-header.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/parser/impl-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          String const& name (eimpl (e)); +          String const& ret (ret_type (e)); +          SemanticGraph::Type& base (e.inherits ().base ()); + +          os << "class " << type_exp << name << ": " << +            "public virtual " << ename (e) << "," << endl +             << "  public " << fq_name (base, "impl") +             << "{" +             << "public:" << endl +             << "virtual void" << endl +             << "pre ();" +             << endl +             << "virtual " << ret << endl +             << post_name (e) << " ();" +             << "};"; +        } +      }; + +      // +      // +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String const& name (eimpl (l)); +          SemanticGraph::Type& t (l.argumented ().type ()); + +          String item (unclash (ename (l), "item")); + +          os << "class " << type_exp << name << ": public virtual " << +            ename (l) +             << "{" +             << "public:" << endl +             << "virtual void" << endl +             << "pre ();" +             << endl; + +          // item +          // +          String const& arg (arg_type (t)); + +          os << "virtual void" << endl +             << item; + +          if (arg == L"void") +            os << " ();"; +          else +            os << " (" << arg << ");"; + +          os << endl; + +          // post +          // +          String const& ret (ret_type (l)); + +          os << "virtual " << ret << endl +             << post_name (l) << " ();" +             << "};"; +        } +      }; + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String const& name (eimpl (u)); +          String const& ret (ret_type (u)); + +          os << "class " << type_exp << name << ": public virtual " << +            ename (u) +             << "{" +             << "public:" << endl +             << "virtual void" << endl +             << "pre ();" +             << endl +             << "virtual void" << endl +             << "_characters (const " << string_type << "&);" +             << endl +             << "virtual " << ret << endl +             << post_name (u) << " ();" +             << "};"; +        } +      }; + + +      // +      // +      struct ParserCallback: Traversal::Member, Context +      { +        ParserCallback (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) +            return; + +          String const& arg (arg_type (m.type ())); + +          os << "virtual void" << endl +             << ename (m); + +          if (arg == L"void") +            os << " ();"; +          else +            os << " (" << arg << ");"; + +          os << endl; +        } +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), +              parser_callback_ (c) +        { +          names_parser_callback_ >> parser_callback_; +        } + +        virtual void +        traverse (Type& c) +        { +          String const& name (eimpl (c)); +          String const& ret (ret_type (c)); + +          os << "class " << type_exp << name << ": public virtual " << +            ename (c); + +          if (c.inherits_p ()) +            os << "," << endl +               << "  public " << fq_name (c.inherits ().base (), "impl"); + +          os << "{" +             << "public:" << endl +             << "virtual void" << endl +             << "pre ();" +             << endl; + +          // In case of an inheritance-by-restriction, we don't need to +          // generate parser callbacks, etc. since they are the same as in +          // the base. +          // +          if (!restriction_p (c)) +          { +            names (c, names_parser_callback_); +          } + +          os << "virtual " << ret << endl +             << post_name (c) << " ();" +             << "};"; +        } + +      private: +        // +        // +        ParserCallback parser_callback_; +        Traversal::Names names_parser_callback_; +      }; +    } + +    void +    generate_impl_header (Context& ctx) +    { +      Traversal::Schema schema; + +      Sources sources; +      Includes includes (ctx, Includes::impl_header); +      Traversal::Names schema_names; + +      Namespace ns (ctx); +      Traversal::Names names; + +      schema >> includes; +      schema >> sources >> schema; +      schema >> schema_names >> ns >> names; + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/parser/impl-header.hxx b/xsd/cxx/parser/impl-header.hxx new file mode 100644 index 0000000..1939e05 --- /dev/null +++ b/xsd/cxx/parser/impl-header.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/impl-header.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_IMPL_HEADER_HXX +#define XSD_CXX_PARSER_IMPL_HEADER_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_impl_header (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_IMPL_HEADER_HXX diff --git a/xsd/cxx/parser/impl-source.cxx b/xsd/cxx/parser/impl-source.cxx new file mode 100644 index 0000000..80a9644 --- /dev/null +++ b/xsd/cxx/parser/impl-source.cxx @@ -0,0 +1,384 @@ +// file      : xsd/cxx/parser/impl-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/parser/impl-source.hxx> +#include <xsd/cxx/parser/print-impl-common.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          String const& name (eimpl (e)); +          String const& ret (ret_type (e)); +          SemanticGraph::Type& base (e.inherits ().base ()); +          String const& base_ret (ret_type (base)); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // pre +          // +          os << "void " << name << "::" << endl +             << "pre ()" +             << "{" +             << "}"; + +          // post +          // +          os << ret << " " << name << "::" << endl +             << post_name (e) << " ()" +             << "{"; + +          if (ret == base_ret) +          { +            os << (ret != L"void" ? "return " : "") << +              post_name (base) << " ();"; +          } +          else if (ret == L"void") +          { +            os << arg_type (base) << " v (" << post_name (base) << " ());" +               << endl; + +            if (options.generate_print_impl ()) +            { +              PrintCall t (*this, e.name (), "v"); +              t.dispatch (base); +            } +            else +              os << "// TODO" << endl +                 << "//" << endl; +          } +          else +          { +            if (base_ret == L"void") +              os << post_name (base) << " ();"; +            else +              os << arg_type (base) << " v (" << post_name (base) << " ());" +                 << endl +                 << "// TODO" << endl +                 << "//" << endl +                 << "// return ... ;" << endl; +          } + +          os << "}"; +        } +      }; + +      // +      // +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String const& name (eimpl (l)); +          SemanticGraph::Type& type (l.argumented ().type ()); + +          String item (unclash (ename (l), "item")); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // pre +          // +          os << "void " << name << "::" << endl +             << "pre ()" +             << "{" +             << "}"; + +          // item +          // +          String const& arg (arg_type (type)); + +          os << "void " << name << "::" << endl +             << item; + +          if (arg == L"void") +            os << " ()"; +          else +            os << " (" << arg << " " << item << ")"; + +          os << "{"; + +          if (arg != L"void") +          { +            if (options.generate_print_impl ()) +            { +              PrintCall t (*this, type.name (), item); +              t.dispatch (type); +            } +            else +              os << "// TODO" << endl +                 << "//" << endl; +          } + +          os << "}"; + +          // post +          // +          String const& ret (ret_type (l)); + +          os << ret << " " << name << "::" << endl +             << post_name (l) << " ()" +             << "{"; + +          if (ret != L"void") +            os << "// TODO" << endl +               << "//" << endl +               << "// return ... ;" << endl; + +          os << "}"; +        } +      }; + +      // +      // +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String const& name (eimpl (u)); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // pre +          // +          os << "void " << name << "::" << endl +             << "pre ()" +             << "{" +             << "}"; + +          // _characters +          // +          os << "void " << name << "::" << endl +             << "_characters (const " << string_type << "& s)" +             << "{"; + +          if (options.generate_print_impl ()) +            os << cout_inst << " << " << strlit (u.name () + L": ") << +              " << s << std::endl;"; +          else +            os << "// TODO" << endl +               << "//" << endl; + +          os << "}"; + +          // post +          // +          String const& ret (ret_type (u)); + +          os << ret << " " << name << "::" << endl +             << post_name (u) << " ()" +             << "{"; + +          if (ret != L"void") +            os << "// TODO" << endl +               << "//" << endl +               << "// return ... ;" << endl; + +          os << "}"; +        } +      }; + +      // +      // +      struct ParserCallback: Traversal::Member, Context +      { +        ParserCallback (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) +            return; + +          String const& name (ename (m)); +          String const& arg (arg_type (m.type ())); + +          os << "void " << +            eimpl (dynamic_cast<SemanticGraph::Complex&> (m.scope ())) << +            "::" << endl +             << name; + +          if (arg == L"void") +            os << " ()"; +          else +            os << " (" << arg << " " << name << ")"; + +          os << "{"; + +          if (arg != L"void") +          { +            if (options.generate_print_impl ()) +            { +              PrintCall t (*this, m.name (), name); +              t.dispatch (m.type ()); +            } +            else +              os << "// TODO" << endl +                 << "//" << endl; +          } + +          os << "}"; +        } +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), parser_callback_ (c) +        { +          names_parser_callback_ >> parser_callback_; +        } + +        virtual void +        traverse (Type& c) +        { +          String const& name (eimpl (c)); + +          bool restriction (restriction_p (c)); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // pre +          // +          os << "void " << name << "::" << endl +             << "pre ()" +             << "{" +             << "}"; + +          // Parser callbacks. +          // +          if (!restriction) +            names (c, names_parser_callback_); + +          // post +          // +          String const& ret (ret_type (c)); + +          os << ret << " " << name << "::" << endl +             << post_name (c) << " ()" +             << "{"; + +          if (c.inherits_p ()) +          { +            SemanticGraph::Type& base (c.inherits ().base ()); +            String const& base_ret (ret_type (base)); + +            if (ret == base_ret) +            { +              os << (ret != L"void" ? "return " : "") << +                post_name (base) << " ();"; +            } +            else if (ret == L"void") +            { +              os << arg_type (base) << " v (" << post_name (base) << " ());" +                 << endl; + +              if (options.generate_print_impl ()) +              { +                PrintCall t (*this, c.name (), "v"); +                t.dispatch (base); +              } +              else +                os << "// TODO" << endl +                   << "//" << endl; +            } +            else +            { +              if (base_ret == L"void") +                os << post_name (base) << " ();"; +              else +                os << arg_type (base) << " v (" << post_name (base) << " ());" +                   << endl +                   << "// TODO" << endl +                   << "//" << endl +                   << "// return ... ;" << endl; +            } +          } +          else +          { +            if (ret != L"void") +              os << "// TODO" << endl +                 << "//" << endl +                 << "// return ... ;" << endl; +          } + +          os << "}"; +        } + +      private: +        // +        // +        ParserCallback parser_callback_; +        Traversal::Names names_parser_callback_; +      }; +    } + +    void +    generate_impl_source (Context& ctx) +    { +      if (ctx.options.generate_print_impl ()) +        ctx.os << "#include <iostream>" << endl +               << endl; + +      Traversal::Schema schema; +      Sources sources; +      Traversal::Names schema_names; +      Namespace ns (ctx); +      Traversal::Names names; + +      schema >> sources >> schema; +      schema >> schema_names >> ns >> names; + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/parser/impl-source.hxx b/xsd/cxx/parser/impl-source.hxx new file mode 100644 index 0000000..0fc8060 --- /dev/null +++ b/xsd/cxx/parser/impl-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/impl-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_IMPL_SOURCE_HXX +#define XSD_CXX_PARSER_IMPL_SOURCE_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_impl_source (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_IMPL_SOURCE_HXX diff --git a/xsd/cxx/parser/name-processor.cxx b/xsd/cxx/parser/name-processor.cxx new file mode 100644 index 0000000..73710ba --- /dev/null +++ b/xsd/cxx/parser/name-processor.cxx @@ -0,0 +1,1175 @@ +// file      : xsd/cxx/parser/name-processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <map> +#include <sstream> +#include <iostream> + +#include <xsd/cxx/parser/name-processor.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + + +using namespace std; + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      // +      // +      typedef set<String> NameSet; + +      class Context: public CXX::Context +      { +      public: +        Context (Parser::options const& ops, +                 SemanticGraph::Schema& root, +                 SemanticGraph::Path const& path, +                 StringLiteralMap const* map) +            : CXX::Context (std::wcerr, root, path, ops, map), +              skel_suffix_ (ops.skel_type_suffix ()), +              impl_suffix_ (ops.impl_type_suffix ()), +              impl (ops.generate_noop_impl () || +                    ops.generate_print_impl () || +                    ops.generate_test_driver ()), +              skel_suffix (skel_suffix_), +              impl_suffix (impl_suffix_), +              global_type_names (global_type_names_), +              polymorphic (ops.generate_polymorphic ()) +        { +        } + +      protected: +        Context (Context& c) +            : CXX::Context (c), +              impl (c.impl), +              skel_suffix (c.skel_suffix), +              impl_suffix (c.impl_suffix), +              global_type_names (c.global_type_names), +              polymorphic (c.polymorphic) +        { +        } + +      public: +        String +        find_name (String const& n, NameSet& set) +        { +          String base_name (escape (n)); +          String name (base_name); + +          for (size_t i (1); set.find (name) != set.end (); ++i) +          { +            std::wostringstream os; +            os << i; +            name = base_name + os.str (); +          } + +          set.insert (name); +          return name; +        } + +      private: +        String const skel_suffix_; +        String const impl_suffix_; + +        map<String, NameSet> global_type_names_; + +      public: +        bool const impl; +        String const& skel_suffix; +        String const& impl_suffix; + +        map<String, NameSet>& global_type_names; + +        bool polymorphic; +      }; + + +      // +      // +      struct PrimaryMember: Traversal::Member, Context +      { +        PrimaryMember (Context& c, NameSet& set) +            : Context (c), set_ (set) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (Parser::Context::skip (m)) +            return; + +          m.context ().set ("name", find_name (m.name (), set_)); +        } + +      private: +        NameSet& set_; +      }; + +      struct DerivedMember: Traversal::Member, Context +      { +        DerivedMember (Context& c, NameSet& set) +            : Context (c), set_ (set) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (Parser::Context::skip (m)) +            return; + +          m.context ().set ("parser", +                            find_name (m.name () + L"_parser", set_)); + +          String const& base (m.context ().get<String> ("name")); +          m.context ().set ("member", find_name (base + L"_parser_", set_)); + +          if (polymorphic && +              m.is_a<SemanticGraph::Element> () && +              !m.type ().context ().count ("anonymous")) +          { +            m.context ().set ( +              "member-map", find_name (base + L"_parser_map_", set_)); + +            m.context ().set ( +              "member-map-impl", +              find_name (base + L"_parser_map_impl_", set_)); +          } +        } + +      private: +        NameSet& set_; +      }; + + +      // +      // +      struct MemberInRestrictionBase: Traversal::Member +      { +      protected: +        MemberInRestrictionBase (NameSet& set, SemanticGraph::Complex& base) +            : set_ (set), base_ (base) +        { +        } + +        struct NotFound {}; + +        Type& +        find_member (SemanticGraph::Complex& c, Type& m) +        { +          using SemanticGraph::Complex; + +          Complex::NamesIteratorPair r (c.find (m.name ())); + +          for (; r.first != r.second; ++r.first) +          { +            if (r.first->named ().is_a<Type> ()) +            { +              Type& bm (dynamic_cast<Type&> (r.first->named ())); + +              if (typeid (bm) != typeid (m)) +                continue; + +              if (m.qualified_p ()) +              { +                if (bm.qualified_p () && +                    m.name () == bm.name () && +                    m.namespace_ ().name () == bm.namespace_ ().name ()) +                  return bm; +              } +              else +              { +                if (!bm.qualified_p () && m.name () == bm.name ()) +                  return bm; +              } +            } +          } + +          // If we didn't find anything, try our base. +          // +          if (c.inherits_p ()) +          { +            SemanticGraph::Type& base (c.inherits ().base ()); + +            if (base.is_a<Complex> ()) +              return find_member (dynamic_cast<Complex&> (base), m); +          } + +          //std::wcerr << "unable to find member " << m.name () << " in " +          //           << c.name () << std::endl; + +          throw NotFound (); +        } + +      protected: +        NameSet& set_; +        SemanticGraph::Complex& base_; +      }; + +      struct PrimaryMemberInRestriction: MemberInRestrictionBase, Context +      { +        PrimaryMemberInRestriction (Context& c, +                                    NameSet& set, +                                    SemanticGraph::Complex& base) +            : MemberInRestrictionBase (set, base), Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (Parser::Context::skip (m)) +            return; + +          String name; + +          try +          { +            // Try to find corresponding member in one of our bases. +            // This may fail if we use an element that substitutes +            // one in our base. +            // +            Type& bm (find_member (base_, m)); +            name = bm.context ().get<String> ("name"); +          } +          catch (NotFound const&) +          { +            // Fall back to the standard name assignment. +            // +            name = find_name (m.name (), set_); +          } + +          m.context ().set ("name", name); +        } +      }; + +      struct DerivedMemberInRestriction: MemberInRestrictionBase, Context +      { +        DerivedMemberInRestriction (Context& c, +                                    NameSet& set, +                                    SemanticGraph::Complex& base) +            : MemberInRestrictionBase (set, base), Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (Parser::Context::skip (m)) +            return; + +          bool poly (polymorphic && +                        m.is_a<SemanticGraph::Element> () && +                        !m.type ().context ().count ("anonymous")); + +          String parser, member, member_map, member_map_impl; + +          try +          { +            // Try to find corresponding member in one of our bases. +            // This may fail if we use an element that substitutes +            // one in our base. +            // +            Type& bm (find_member (base_, m)); +            parser = bm.context ().get<String> ("parser"); +            member = bm.context ().get<String> ("member"); + +            if (poly) +            { +              member_map = bm.context ().get<String> ("member-map"); +              member_map_impl = bm.context ().get<String> ("member-map-impl"); +            } +          } +          catch (NotFound const&) +          { +            // Fall back to the standard name assignment. +            // +            String const& base (m.context ().get<String> ("name")); + +            parser = find_name (m.name () + L"_parser", set_); +            member = find_name (base + L"_parser_", set_); + +            if (poly) +            { +              member_map = find_name (base + L"_parser_map_", set_); +              member_map_impl = find_name (base + L"_parser_map_impl_", set_); +            } +          } + +          m.context ().set ("parser", parser); +          m.context ().set ("member", member); + +          if (poly) +          { +            m.context ().set ("member-map", member_map); +            m.context ().set ("member-map-impl", member_map_impl); +          } +        } +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          SemanticGraph::Context& cc (c.context ()); + +          // Use processed name. +          // +          String const& name (cc.get<String> ("name")); + +          // We leave this set around to allow other mappings to use +          // this information. +          // +          cc.set ("cxx-parser-name-processor-member-set", NameSet ()); +          NameSet& member_set ( +            cc.get<NameSet> ("cxx-parser-name-processor-member-set")); + +          member_set.insert (name); + +          // Add our base's members to the initial list unless we are +          // inheriting by restriction in which case we need to have +          // the same names as our base. +          // +          bool restriction (false); + +          if (c.inherits_p ()) +          { +            // @@ What if this types name is the same as one of base's +            //    members? +            // +            SemanticGraph::Type& base (c.inherits ().base ()); + +            if (base.is_a<SemanticGraph::Complex> ()) +            { +              if (!base.context ().count ( +                    "cxx-parser-name-processor-member-set")) +              { +                dispatch (base); +              } + +              NameSet const& base_set ( +                base.context ().get<NameSet> ( +                  "cxx-parser-name-processor-member-set")); + +              member_set.insert (base_set.begin (), base_set.end ()); + +              // Inheritance by restriction from anyType is a special case. +	      // +              restriction = c.inherits ().is_a<SemanticGraph::Restricts> () && +	        !c.inherits ().base ().is_a<SemanticGraph::AnyType> (); +            } +          } + +          if (restriction) +          { +            // First assign the "primary" names. +            // +            { +              PrimaryMemberInRestriction member ( +                *this, +                member_set, +                dynamic_cast<SemanticGraph::Complex&> ( +                  c.inherits ().base ())); + +              Traversal::Names names (member); + +              Complex::names (c, names); +            } + +            // Assign "derived" names. +            // +            { +              DerivedMemberInRestriction member ( +                *this, +                member_set, +                dynamic_cast<SemanticGraph::Complex&> ( +                  c.inherits ().base ())); + +              Traversal::Names names (member); + +              Complex::names (c, names); +            } +          } +          else +          { +            // First assign the "primary" names. +            // +            { +              PrimaryMember member (*this, member_set); +              Traversal::Names names (member); + +              Complex::names (c, names); +            } + +            // Assign "derived" names. +            // +            { +              DerivedMember member (*this, member_set); +              Traversal::Names names (member); + +              Complex::names (c, names); +            } +          } +        } +      }; + + +      // +      // +      struct GlobalType: Traversal::Type, Context +      { +        GlobalType (Context& c, NameSet& set) +            : Context (c), set_ (set) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          SemanticGraph::Context& c (t.context ()); +          String const& n (t.name ()); + +          String name (find_name (n + skel_suffix, set_)); +          c.set ("name", name); + +          // Assign the post_* name. +          // +          c.set ("post", find_post_name (t)); + +          // Note that we do not add this name to the set so that it +          // does not influence other names. +          // +          if (impl) +            c.set ("impl", escape (n + impl_suffix)); +        } + +      private: +        String +        find_post_name (SemanticGraph::Type& t) +        { +          String const& n (t.name ()); + +          // It is possible that our base has the same type name (just +          // in a different namespaces). Avoid name clash in this case. +          // +          using SemanticGraph::Complex; + +          Complex* c = dynamic_cast<Complex*> (&t); + +          if (c == 0 || !c->inherits_p ()) +          { +            return escape (L"post_" + n); +          } +          else +          { +            NameSet set; + +            // Collect all base's post_*. In some mutual inclusion cases it +            // is possible that our base won't have the post name assigned +            // yet. In this situation will will have to figure it out +            // ourselves (we can do it since we use the "raw" type name). +            // +            SemanticGraph::Type* b (&c->inherits ().base ()); + +            while (true) +            { +              if (b->context ().count ("post")) +                set.insert (b->context ().get<String> ("post")); +              else +                set.insert (find_post_name (*b)); + +              Complex* cb (dynamic_cast<Complex*> (b)); + +              if (cb != 0 && cb->inherits_p ()) +              { +                b = &cb->inherits ().base (); +                continue; +              } + +              break; +            } + +            String base_name (escape (L"post_" + n)); +            String post (base_name); + +            for (size_t i (1); set.find (post) != set.end (); ++i) +            { +              std::wostringstream os; +              os << i; +              post = base_name + os.str (); +            } + +            return post; +          } +        } + +      private: +        NameSet& set_; +      }; + + +      struct Namespace: Traversal::Namespace, Context +      { +        Namespace (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& ns) +        { +          NameSet& type_set (global_type_names[ns.name ()]); + +          GlobalType type (*this, type_set); +          Traversal::Names names (type); + +          Traversal::Namespace::names (ns, names); +        } +      }; + + +      struct FundType: Traversal::AnyType, +                       Traversal::AnySimpleType, + +                       Traversal::Fundamental::Byte, +                       Traversal::Fundamental::UnsignedByte, +                       Traversal::Fundamental::Short, +                       Traversal::Fundamental::UnsignedShort, +                       Traversal::Fundamental::Int, +                       Traversal::Fundamental::UnsignedInt, +                       Traversal::Fundamental::Long, +                       Traversal::Fundamental::UnsignedLong, +                       Traversal::Fundamental::Integer, +                       Traversal::Fundamental::NonPositiveInteger, +                       Traversal::Fundamental::NonNegativeInteger, +                       Traversal::Fundamental::PositiveInteger, +                       Traversal::Fundamental::NegativeInteger, + +                       Traversal::Fundamental::Boolean, + +                       Traversal::Fundamental::Float, +                       Traversal::Fundamental::Double, +                       Traversal::Fundamental::Decimal, + +                       Traversal::Fundamental::String, +                       Traversal::Fundamental::NormalizedString, +                       Traversal::Fundamental::Token, +                       Traversal::Fundamental::Name, +                       Traversal::Fundamental::NameToken, +                       Traversal::Fundamental::NameTokens, +                       Traversal::Fundamental::NCName, +                       Traversal::Fundamental::Language, + +                       Traversal::Fundamental::QName, + +                       Traversal::Fundamental::Id, +                       Traversal::Fundamental::IdRef, +                       Traversal::Fundamental::IdRefs, + +                       Traversal::Fundamental::AnyURI, + +                       Traversal::Fundamental::Base64Binary, +                       Traversal::Fundamental::HexBinary, + +                       Traversal::Fundamental::Date, +                       Traversal::Fundamental::DateTime, +                       Traversal::Fundamental::Duration, +                       Traversal::Fundamental::Day, +                       Traversal::Fundamental::Month, +                       Traversal::Fundamental::MonthDay, +                       Traversal::Fundamental::Year, +                       Traversal::Fundamental::YearMonth, +                       Traversal::Fundamental::Time, + +                       Traversal::Fundamental::Entity, +                       Traversal::Fundamental::Entities, + +                       Context +      { +        FundType (Context& c) +            : Context (c) +        { +        } + +        // anyType & anySimpleType. +        // +        virtual void +        traverse (SemanticGraph::AnyType& t) +        { +          t.context ().set ("name", make_skel_name ("any_type")); +          t.context ().set ("impl", make_impl_name ("any_type")); +          t.context ().set ("post", String ("post_any_type")); +        } + +        virtual void +        traverse (SemanticGraph::AnySimpleType& t) +        { +          t.context ().set ("name", make_skel_name ("any_simple_type")); +          t.context ().set ("impl", make_impl_name ("any_simple_type")); +          t.context ().set ("post", String ("post_any_simple_type")); +        } + +        // Boolean. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Boolean& t) +        { +          t.context ().set ("name", make_skel_name ("boolean")); +          t.context ().set ("impl", make_impl_name ("boolean")); +          t.context ().set ("post", String ("post_boolean")); +        } + +        // Integral types. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Byte& t) +        { +          t.context ().set ("name", make_skel_name ("byte")); +          t.context ().set ("impl", make_impl_name ("byte")); +          t.context ().set ("post", String ("post_byte")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedByte& t) +        { +          t.context ().set ("name", make_skel_name ("unsigned_byte")); +          t.context ().set ("impl", make_impl_name ("unsigned_byte")); +          t.context ().set ("post", String ("post_unsigned_byte")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Short& t) +        { +          t.context ().set ("name", make_skel_name ("short")); +          t.context ().set ("impl", make_impl_name ("short")); +          t.context ().set ("post", String ("post_short")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedShort& t) +        { +          t.context ().set ("name", make_skel_name ("unsigned_short")); +          t.context ().set ("impl", make_impl_name ("unsigned_short")); +          t.context ().set ("post", String ("post_unsigned_short")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Int& t) +        { +          t.context ().set ("name", make_skel_name ("int")); +          t.context ().set ("impl", make_impl_name ("int")); +          t.context ().set ("post", String ("post_int")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedInt& t) +        { +          t.context ().set ("name", make_skel_name ("unsigned_int")); +          t.context ().set ("impl", make_impl_name ("unsigned_int")); +          t.context ().set ("post", String ("post_unsigned_int")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Long& t) +        { +          t.context ().set ("name", make_skel_name ("long")); +          t.context ().set ("impl", make_impl_name ("long")); +          t.context ().set ("post", String ("post_long")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedLong& t) +        { +          t.context ().set ("name", make_skel_name ("unsigned_long")); +          t.context ().set ("impl", make_impl_name ("unsigned_long")); +          t.context ().set ("post", String ("post_unsigned_long")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Integer& t) +        { +          t.context ().set ("name", make_skel_name ("integer")); +          t.context ().set ("impl", make_impl_name ("integer")); +          t.context ().set ("post", String ("post_integer")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +        { +          t.context ().set ("name", make_skel_name ("non_positive_integer")); +          t.context ().set ("impl", make_impl_name ("non_positive_integer")); +          t.context ().set ("post", String ("post_non_positive_integer")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +        { +          t.context ().set ("name", make_skel_name ("non_negative_integer")); +          t.context ().set ("impl", make_impl_name ("non_negative_integer")); +          t.context ().set ("post", String ("post_non_negative_integer")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::PositiveInteger& t) +        { +          t.context ().set ("name", make_skel_name ("positive_integer")); +          t.context ().set ("impl", make_impl_name ("positive_integer")); +          t.context ().set ("post", String ("post_positive_integer")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NegativeInteger& t) +        { +          t.context ().set ("name", make_skel_name ("negative_integer")); +          t.context ().set ("impl", make_impl_name ("negative_integer")); +          t.context ().set ("post", String ("post_negative_integer")); +        } + +        // Floats. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Float& t) +        { +          t.context ().set ("name", make_skel_name ("float")); +          t.context ().set ("impl", make_impl_name ("float")); +          t.context ().set ("post", String ("post_float")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Double& t) +        { +          t.context ().set ("name", make_skel_name ("double")); +          t.context ().set ("impl", make_impl_name ("double")); +          t.context ().set ("post", String ("post_double")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Decimal& t) +        { +          t.context ().set ("name", make_skel_name ("decimal")); +          t.context ().set ("impl", make_impl_name ("decimal")); +          t.context ().set ("post", String ("post_decimal")); +        } + +        // Strings. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::String& t) +        { +          t.context ().set ("name", make_skel_name ("string")); +          t.context ().set ("impl", make_impl_name ("string")); +          t.context ().set ("post", String ("post_string")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NormalizedString& t) +        { +          t.context ().set ("name", make_skel_name ("normalized_string")); +          t.context ().set ("impl", make_impl_name ("normalized_string")); +          t.context ().set ("post", String ("post_normalized_string")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Token& t) +        { +          t.context ().set ("name", make_skel_name ("token")); +          t.context ().set ("impl", make_impl_name ("token")); +          t.context ().set ("post", String ("post_token")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameToken& t) +        { +          t.context ().set ("name", make_skel_name ("nmtoken")); +          t.context ().set ("impl", make_impl_name ("nmtoken")); +          t.context ().set ("post", String ("post_nmtoken")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameTokens& t) +        { +          t.context ().set ("name", make_skel_name ("nmtokens")); +          t.context ().set ("impl", make_impl_name ("nmtokens")); +          t.context ().set ("post", String ("post_nmtokens")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Name& t) +        { +          t.context ().set ("name", make_skel_name ("name")); +          t.context ().set ("impl", make_impl_name ("name")); +          t.context ().set ("post", String ("post_name")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NCName& t) +        { +          t.context ().set ("name", make_skel_name ("ncname")); +          t.context ().set ("impl", make_impl_name ("ncname")); +          t.context ().set ("post", String ("post_ncname")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Language& t) +        { +          t.context ().set ("name", make_skel_name ("language")); +          t.context ().set ("impl", make_impl_name ("language")); +          t.context ().set ("post", String ("post_language")); +        } + + +        // Qualified name. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::QName& t) +        { +          t.context ().set ("name", make_skel_name ("qname")); +          t.context ().set ("impl", make_impl_name ("qname")); +          t.context ().set ("post", String ("post_qname")); +        } + + +        // ID/IDREF. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Id& t) +        { +          t.context ().set ("name", make_skel_name ("id")); +          t.context ().set ("impl", make_impl_name ("id")); +          t.context ().set ("post", String ("post_id")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRef& t) +        { +          t.context ().set ("name", make_skel_name ("idref")); +          t.context ().set ("impl", make_impl_name ("idref")); +          t.context ().set ("post", String ("post_idref")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRefs& t) +        { +          t.context ().set ("name", make_skel_name ("idrefs")); +          t.context ().set ("impl", make_impl_name ("idrefs")); +          t.context ().set ("post", String ("post_idrefs")); +        } + +        // URI. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::AnyURI& t) +        { +          t.context ().set ("name", make_skel_name ("uri")); +          t.context ().set ("impl", make_impl_name ("uri")); +          t.context ().set ("post", String ("post_uri")); +        } + +        // Binary. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Base64Binary& t) +        { +          t.context ().set ("name", make_skel_name ("base64_binary")); +          t.context ().set ("impl", make_impl_name ("base64_binary")); +          t.context ().set ("post", String ("post_base64_binary")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::HexBinary& t) +        { +          t.context ().set ("name", make_skel_name ("hex_binary")); +          t.context ().set ("impl", make_impl_name ("hex_binary")); +          t.context ().set ("post", String ("post_hex_binary")); +        } + + +        // Date/time. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Date& t) +        { +          t.context ().set ("name", make_skel_name ("date")); +          t.context ().set ("impl", make_impl_name ("date")); +          t.context ().set ("post", String ("post_date")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::DateTime& t) +        { +          t.context ().set ("name", make_skel_name ("date_time")); +          t.context ().set ("impl", make_impl_name ("date_time")); +          t.context ().set ("post", String ("post_date_time")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Duration& t) +        { +          t.context ().set ("name", make_skel_name ("duration")); +          t.context ().set ("impl", make_impl_name ("duration")); +          t.context ().set ("post", String ("post_duration")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Day& t) +        { +          t.context ().set ("name", make_skel_name ("gday")); +          t.context ().set ("impl", make_impl_name ("gday")); +          t.context ().set ("post", String ("post_gday")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Month& t) +        { +          t.context ().set ("name", make_skel_name ("gmonth")); +          t.context ().set ("impl", make_impl_name ("gmonth")); +          t.context ().set ("post", String ("post_gmonth")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::MonthDay& t) +        { +          t.context ().set ("name", make_skel_name ("gmonth_day")); +          t.context ().set ("impl", make_impl_name ("gmonth_day")); +          t.context ().set ("post", String ("post_gmonth_day")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Year& t) +        { +          t.context ().set ("name", make_skel_name ("gyear")); +          t.context ().set ("impl", make_impl_name ("gyear")); +          t.context ().set ("post", String ("post_gyear")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::YearMonth& t) +        { +          t.context ().set ("name", make_skel_name ("gyear_month")); +          t.context ().set ("impl", make_impl_name ("gyear_month")); +          t.context ().set ("post", String ("post_gyear_month")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Time& t) +        { +          t.context ().set ("name", make_skel_name ("time")); +          t.context ().set ("impl", make_impl_name ("time")); +          t.context ().set ("post", String ("post_time")); +        } + +        // Entity. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Entity& t) +        { +          t.context ().set ("name", make_skel_name ("entity")); +          t.context ().set ("impl", make_impl_name ("entity")); +          t.context ().set ("post", String ("post_entity")); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Entities& t) +        { +          t.context ().set ("name", make_skel_name ("entities")); +          t.context ().set ("impl", make_impl_name ("entities")); +          t.context ().set ("post", String ("post_entities")); +        } + +      private: +        String +        make_skel_name (String const& base) +        { +          return escape (base + skel_suffix); +        } + +        String +        make_impl_name (String const& base) +        { +          return escape (base + impl_suffix); +        } +      }; + +      // Go into sourced/included/imported schemas while making sure +      // we don't process the same stuff more than once. +      // +      struct Uses: Traversal::Sources, +                   Traversal::Includes, +                   Traversal::Imports +      { +        virtual void +        traverse (SemanticGraph::Sources& sr) +        { +          SemanticGraph::Schema& s (sr.schema ()); + +          if (!s.context ().count ("cxx-parser-name-processor-seen")) +          { +            s.context ().set ("cxx-parser-name-processor-seen", true); +            Traversal::Sources::traverse (sr); +          } +        } + +        virtual void +        traverse (SemanticGraph::Includes& i) +        { +          SemanticGraph::Schema& s (i.schema ()); + +          if (!s.context ().count ("cxx-parser-name-processor-seen")) +          { +            s.context ().set ("cxx-parser-name-processor-seen", true); +            Traversal::Includes::traverse (i); +          } +        } + +        virtual void +        traverse (SemanticGraph::Imports& i) +        { +          SemanticGraph::Schema& s (i.schema ()); + +          if (!s.context ().count ("cxx-parser-name-processor-seen")) +          { +            s.context ().set ("cxx-parser-name-processor-seen", true); +            Traversal::Imports::traverse (i); +          } +        } +      }; + +      // Go into implied schemas while making sure we don't process +      // the same stuff more than once. +      // +      struct Implies: Traversal::Implies +      { +        virtual void +        traverse (SemanticGraph::Implies& i) +        { +          SemanticGraph::Schema& s (i.schema ()); + +          if (!s.context ().count ("cxx-parser-name-processor-seen")) +          { +            s.context ().set ("cxx-parser-name-processor-seen", true); +            Traversal::Implies::traverse (i); +          } +        } +      }; + +      void +      process_impl (options const& ops, +                    SemanticGraph::Schema& tu, +                    SemanticGraph::Path const& file, +                    StringLiteralMap const& map) +      { +        Context ctx (ops, tu, file, &map); + +        if (tu.names_begin ()->named ().name () == +            L"http://www.w3.org/2001/XMLSchema") +        { +          // XML Schema namespace. +          // +          Traversal::Schema schema; + +          Traversal::Names schema_names; +          Traversal::Namespace ns; +          Traversal::Names ns_names; +          FundType fund_type (ctx); + +          schema >> schema_names >> ns >> ns_names >> fund_type; + +          schema.dispatch (tu); +        } +        else +        { + +          // Pass one - assign names to fundamental types. +          // +          { +            Traversal::Schema schema; +            Implies implies; +            Traversal::Schema xs_schema; + +            schema >> implies >> xs_schema; + +            Traversal::Names xs_schema_names; +            Traversal::Namespace ns; +            Traversal::Names ns_names; +            FundType fund_type (ctx); + +            xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + +            schema.dispatch (tu); +          } + +          // Pass two - assign names to global types. This pass cannot +          // be combined with pass three because of possible recursive +          // schema inclusions. Also note that we check first if this +          // schema has already been processed which may happen in the +          // file-per-type compilation mode. +          // +          if (!tu.context ().count ("cxx-parser-name-processor-seen")) +          { +            Traversal::Schema schema; +            Uses uses; + +            schema >> uses >> schema; + +            Traversal::Names schema_names; +            Namespace ns (ctx); + +            schema >> schema_names >> ns; + +            // Some twisted schemas do recusive self-inclusion. +            // +            tu.context ().set ("cxx-parser-name-processor-seen", true); + +            schema.dispatch (tu); +          } + +          // Pass three - assign names inside complex types. Here we don't +          // need to go into included/imported schemas. +          // +          { +            Traversal::Schema schema; +            Sources sources; + +            schema >> sources >> schema; + +            Traversal::Names schema_names; +            Traversal::Namespace ns; +            Traversal::Names ns_names; + +            schema >> schema_names >> ns >> ns_names; + +            Complex complex (ctx); + +            ns_names >> complex; + +            schema.dispatch (tu); +          } +        } +      } +    } + +    void NameProcessor:: +    process (options const& ops, +             SemanticGraph::Schema& tu, +             SemanticGraph::Path const& file, +             StringLiteralMap const& map) +    { +      process_impl (ops, tu, file, map); +    } +  } +} diff --git a/xsd/cxx/parser/name-processor.hxx b/xsd/cxx/parser/name-processor.hxx new file mode 100644 index 0000000..f8ac28c --- /dev/null +++ b/xsd/cxx/parser/name-processor.hxx @@ -0,0 +1,30 @@ +// file      : xsd/cxx/parser/name-processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_NAME_PROCESSOR_HXX +#define XSD_CXX_PARSER_NAME_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph.hxx> + +#include <xsd/types.hxx> + +#include <xsd/cxx/elements.hxx> +#include <xsd/cxx/parser/options.hxx> + +namespace CXX +{ +  namespace Parser +  { +    class NameProcessor +    { +    public: +      void +      process (options const&, +               XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file, +               StringLiteralMap const& map); +    }; +  } +} + +#endif // XSD_CXX_PARSER_NAME_PROCESSOR_HXX diff --git a/xsd/cxx/parser/options.cli b/xsd/cxx/parser/options.cli new file mode 100644 index 0000000..e430333 --- /dev/null +++ b/xsd/cxx/parser/options.cli @@ -0,0 +1,147 @@ +// file      : xsd/cxx/parser/options.cli +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include <cstddef>; // std::size_t + +include <xsd/types.hxx>; // NarrowString, NarrowStrings + +include <xsd/cxx/options.cli>; + +namespace CXX +{ +  namespace Parser +  { +    class options: CXX::options +    { +      NarrowStrings --type-map +      { +        "<mapfile>", +        "Read XML Schema to C++ type mapping information from <mapfile>. +         Repeat this option to specify several type maps. Type maps are +         considered in order of appearance and the first match is used. By +         default all user-defined types are mapped to \cb{void}. See the +         TYPE MAP section below for more information." +      }; + +      NarrowString --xml-parser = "xerces" +      { +        "<parser>", +        "Use <parser> as the underlying XML parser. Valid values are +         \cb{xerces} for Xerces-C++ (default) and \cb{expat} for Expat." +      }; + +      // Features. +      // +      bool --generate-validation +      { +        "Generate validation code. The validation code (\"perfect parser\") +         ensures that instance documents conform to the schema. Validation +         code is generated by default when the selected underlying XML parser +         is non-validating (\cb{expat})." +      }; + +      bool --suppress-validation +      { +        "Suppress the generation of validation code. Validation is suppressed +         by default when the selected underlying XML parser is validating +         (\cb{xerces})." +      }; + +      bool --generate-polymorphic +      { +        "Generate polymorphism-aware code. Specify this option if you use +         substitution groups or \cb{xsi:type}." +      }; + +      bool --generate-noop-impl +      { +        "Generate a sample parser implementation that does nothing (no +         operation). The sample implementation can then be filled with +         the application-specific code. For an input file in the form +         \cb{name.xsd} this option triggers the generation of two +         additional C++ files in the form: \cb{name-pimpl.hxx} (parser +         implementation header file) and \cb{name-pimpl.cxx} (parser +         implementation source file)." +      }; + +      bool --generate-print-impl +      { +        "Generate a sample parser implementation that prints the XML data +         to \c{STDOUT}. For an input file in the form \cb{name.xsd} this +         option triggers the generation of two additional C++ files in the +         form: \cb{name-pimpl.hxx} (parser implementation header file) and +         \cb{name-pimpl.cxx} (parser implementation source file)." +      }; + +      bool --generate-test-driver +      { +        "Generate a test driver for the sample parser implementation. For an +         input file in the form \cb{name.xsd} this option triggers the +         generation of an additional C++ file in the form +         \cb{name-driver.cxx}." +      }; + +      bool --force-overwrite +      { +        "Force overwriting of the existing implementation and test driver +         files. Use this option only if you do not mind loosing the changes +         you have made in the sample implementation or test driver files." +      }; + +      // Root element. +      // +      bool --root-element-first +      { +        "Indicate that the first global element is the document root. This +         information is used to generate the test driver for the sample +         implementation." +      }; + +      bool --root-element-last +      { +        "Indicate that the last global element is the document root. This +         information is used to generate the test driver for the sample +         implementation." +      }; + +      NarrowString --root-element +      { +        "<element>", +        "Indicate that <element> is the document root. This information is +         used to generate the test driver for the sample implementation." +      }; + +      // Suffixes. +      // +      NarrowString --skel-type-suffix = "_pskel" +      { +        "<suffix>", +        "Use the provided <suffix> instead of the default \cb{_pskel} to +         construct the names of the generated parser skeletons." +      }; + +      NarrowString --skel-file-suffix = "-pskel" +      { +        "<suffix>", +        "Use the provided <suffix> instead of the default \cb{-pskel} to +         construct the names of the generated parser skeleton files." +      }; + +      NarrowString --impl-type-suffix = "_pimpl" +      { +        "<suffix>", +        "Use the provided <suffix> instead of the default \cb{_pimpl} to +         construct the names of the parser implementations for the built-in +         XML Schema types as well as sample parser implementations." +      }; + +      NarrowString --impl-file-suffix = "-pimpl" +      { +        "<suffix>", +        "Use the provided <suffix> instead of the default \cb{-pimpl} to +         construct the names of the generated sample parser implementation +         files." +      }; +    }; +  } +} diff --git a/xsd/cxx/parser/parser-forward.cxx b/xsd/cxx/parser/parser-forward.cxx new file mode 100644 index 0000000..65603fd --- /dev/null +++ b/xsd/cxx/parser/parser-forward.cxx @@ -0,0 +1,110 @@ +// file      : xsd/cxx/parser/parser-forward.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/parser/parser-forward.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          os << "class " << ename (e) << ";"; +        } +      }; + +      // +      // +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          os << "class " << ename (l) << ";"; +        } +      }; + +      // +      // +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          os << "class " << ename (u) << ";"; +        } +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          os << "class " << ename (c) << ";"; +        } +      }; +    } + +    void +    generate_parser_forward (Context& ctx) +    { +      ctx.os << "// Forward declarations" << endl +             << "//" << endl; + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names schema_names; + +      Namespace ns (ctx); +      Traversal::Names names; + +      schema >> sources >> schema; +      schema >> schema_names >> ns >> names; + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); + +      ctx.os << endl; +    } +  } +} diff --git a/xsd/cxx/parser/parser-forward.hxx b/xsd/cxx/parser/parser-forward.hxx new file mode 100644 index 0000000..b5345a5 --- /dev/null +++ b/xsd/cxx/parser/parser-forward.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/parser-forward.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_PARSER_FORWARD_HXX +#define XSD_CXX_PARSER_PARSER_FORWARD_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_parser_forward (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_PARSER_FORWARD_HXX diff --git a/xsd/cxx/parser/parser-header.cxx b/xsd/cxx/parser/parser-header.cxx new file mode 100644 index 0000000..327bb07 --- /dev/null +++ b/xsd/cxx/parser/parser-header.cxx @@ -0,0 +1,1440 @@ +// file      : xsd/cxx/parser/parser-header.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> + +#include <xsd/cxx/parser/parser-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          String const& name (ename (e)); +          SemanticGraph::Type& base (e.inherits ().base ()); + +          os << "class " << type_exp << name << ": public virtual " << +            fq_name (base) +             << "{" +             << "public:" << endl +             << "// Parser callbacks. Override them in your " << +            "implementation." << endl +             << "//" << endl; + +          os << "// virtual void" << endl +             << "// pre ();" << endl +             << endl; + +          String const& ret (ret_type (e)); + +          bool same (ret == ret_type (base)); + +          os << "virtual " << ret << endl +             << post_name (e) << " ()" << +            (same || ret == L"void" ? ";" : " = 0;"); + +          if (polymorphic) +          { +            os << endl +               << "public:" << endl +               << "static const " << char_type << "*" << endl +               << "_static_type ();" +               << endl +               << "virtual const " << char_type << "*" << endl +               << "_dynamic_type () const;"; +          } + +          os << "};"; +        } +      }; + +      // +      // +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String const& name (ename (l)); +          SemanticGraph::Type& t (l.argumented ().type ()); + +          String item (unclash (name, "item")); + +          os << "class " << type_exp << name << ": public " << list_base +             << "{" +             << "public:" << endl +             << "// Parser callbacks. Override them in your " << +            "implementation." << endl +             << "//" << endl; + +          // pre +          // +          os << "// virtual void" << endl +             << "// pre ();" << endl +             << endl; + +          // item +          // +          String const& arg (arg_type (t)); + +          os << "virtual void" << endl +             << item; + +          if (arg == L"void") +            os << " ();"; +          else +            os << " (" << arg << ");"; + +          os << endl; + +          // post +          // +          String const& ret (ret_type (l)); + +          os << "virtual " << ret << endl +             << post_name (l) << " ()" << (ret == L"void" ? ";" : " = 0;") +             << endl; + +          // +          // +          os << "// Parser construction API." << endl +             << "//" << endl; + +          // item_parser +          // +          os << "void" << endl +             << unclash (name, "item_parser") << " (" << fq_name (t) << "&);" +             << endl; + +          // parsers +          // +          os << "void" << endl +             << "parsers (" << fq_name (t) << "& /* item */);" +             << endl; + +          // c-tor +          // +          os << "// Constructor." << endl +             << "//" << endl +             << name << " ();" +             << endl; + + +          if (polymorphic) +          { +            os << "public:" << endl +               << "static const " << char_type << "*" << endl +               << "_static_type ();" +               << endl +               << "virtual const " << char_type << "*" << endl +               << "_dynamic_type () const;" +               << endl; +          } + +          // +          // +          os << "// Implementation." << endl +             << "//" << endl +             << "protected:" << endl; + +          os << "virtual void" << endl +             << "_xsd_parse_item (const " << string_type << "&);" +             << endl; + +          os << "protected:" << endl +             << fq_name (t) << "* _xsd_" << item << "_;" +             << "};"; +        } +      }; + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String const& name (ename (u)); + +          os << "class " << type_exp << name << ": public " << simple_base +             << "{" +             << "public:" << endl +             << "// Parser callbacks. Override them in your " << +            "implementation." << endl +             << "//" << endl; + +          os << "// virtual void" << endl +             << "// pre ();" << endl +             << "//" << endl +             << "// virtual void" << endl +             << "// _characters (const " << string_type << "&);" << endl +             << endl; + +          String const& ret (ret_type (u)); + +          os << "virtual " << ret << endl +             << post_name (u) << " ()" << (ret == L"void" ? ";" : " = 0;"); + +          if (polymorphic) +          { +            os << endl +               << "public:" << endl +               << "static const " << char_type << "*" << endl +               << "_static_type ();" +               << endl +               << "virtual const " << char_type << "*" << endl +               << "_dynamic_type () const;"; +          } + +          os << "};"; +        } +      }; + + +      // +      // +      struct ParserCallback: Traversal::Member, Context +      { +        ParserCallback (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) return; + +          String const& arg (arg_type (m.type ())); + +          os << "virtual void" << endl +             << ename (m); + +          if (arg == L"void") +            os << " ();"; +          else +            os << " (" << arg << ");"; + +          os << endl; +        } +      }; + + +      // +      // +      struct ParserModifier: Traversal::Member, Context +      { +        ParserModifier (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) +            return; + +          os << "void" << endl +             << eparser (m) << " (" << fq_name (m.type ()) << "&);" +             << endl; + +          if (polymorphic && +              m.is_a<SemanticGraph::Element> () && +              !anonymous (m.type ())) +          { +            os << "void" << endl +               << eparser (m) << " (const " << parser_map << "&);" +               << endl; +          } +        } +      }; + +      // +      // +      struct ParserMember: Traversal::Member, Context +      { +        ParserMember (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) +            return; + +          String type (fq_name (m.type ())); + +          os << type << "* " << emember (m) << ";"; + +          if (polymorphic && +              m.is_a<SemanticGraph::Element> () && +              !anonymous (m.type ())) +          { +            os << "const " << parser_map << "* " << emember_map (m) << ";" +               << endl; +          } +        } +      }; + +      // +      // +      struct Particle: Traversal::All, +                       Traversal::Choice, +                       Traversal::Sequence, +                       Context +      { +        Particle (Context& c) +            : Context (c) +        { +          *this >> contains_particle_ >> *this; +        } + + +        virtual void +        traverse (SemanticGraph::All& a) +        { +          if (!a.context().count ("comp-number")) +            return; + +          size_t state_count (a.context().get<size_t> ("state-count")); + +          os << "void" << endl +             << "all_0 (unsigned long& state," << endl +             << "unsigned char* count," << endl +             << "const " << string_type << "& ns," << endl +             << "const " << string_type << "& n," << endl +             << "const " << string_type << "* t," << endl +             << "bool start);" +             << endl +             << "unsigned char v_all_first_[" << state_count << "UL];" +             << "::xsd::cxx::parser::validating::all_stack v_all_count_;" +             << endl; +        } + +        virtual void +        traverse (SemanticGraph::Choice& c) +        { +          if (!c.context().count ("comp-number")) +            return; + +          size_t n (c.context ().get<size_t> ("comp-number")); + +          os << "void" << endl +             << "choice_" << n << " (unsigned long& state," << endl +             << "unsigned long& count," << endl +             << "const " << string_type << "& ns," << endl +             << "const " << string_type << "& n," << endl +             << "const " << string_type << "* t," << endl +             << "bool start);" +             << endl; + +          Traversal::Choice::traverse (c); +        } + +        virtual void +        traverse (SemanticGraph::Sequence& s) +        { +          if (!s.context().count ("comp-number")) +            return; + +          size_t n (s.context ().get<size_t> ("comp-number")); + +          os << "void" << endl +             << "sequence_" << n << " (unsigned long& state," << endl +             << "unsigned long& count," << endl +             << "const " << string_type << "& ns," << endl +             << "const " << string_type << "& n," << endl +             << "const " << string_type << "* t," << endl +             << "bool start);" +             << endl; + +          Traversal::Sequence::traverse (s); +        } + +      private: +        Traversal::ContainsParticle contains_particle_; +      }; + + +      // +      // +      struct AttributeValidationState: Traversal::Attribute, Context +      { +        AttributeValidationState (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          if (!a.optional_p ()) +          { +            os << "bool " << ename (a) << ";"; +          } +        } +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), +              parser_callback_ (c), +              parser_member_ (c), +              parser_modifier_ (c), +              attribute_validation_state_ (c) +        { +          names_parser_callback_ >> parser_callback_; +          names_parser_member_ >> parser_member_; +          names_parser_modifier_ >> parser_modifier_; +          names_attribute_validation_state_ >> attribute_validation_state_; +        } + +        virtual void +        traverse (Type& c) +        { +          String const& name (ename (c)); + +          // In case of an inheritance-by-restriction, we don't need to +          // generate parser callbacks, etc. since they are the same as in +          // the base. We only need the parsing/validation code. +          // +          bool restriction (restriction_p (c)); + +          bool he (has<Traversal::Element> (c)); +          bool ha (has<Traversal::Attribute> (c)); + +          bool hae (has_particle<Traversal::Any> (c)); +          bool haa (has<Traversal::AnyAttribute> (c)); + +          bool hra (false); // Has required attribute. +          if (ha) +          { +            RequiredAttributeTest test (hra); +            Traversal::Names names_test (test); +            names (c, names_test); +          } + + +          // +          // +          os << "class " << type_exp << name << ": public "; + +          if (c.inherits_p ()) +            os << "virtual " << fq_name (c.inherits ().base ()); +          else +            os << complex_base; + +          os << "{" +             << "public:" << endl +             << "// Parser callbacks. Override them in your " << +            "implementation." << endl +             << "//" << endl; + +          os << "// virtual void" << endl +             << "// pre ();" << endl +             << endl; + + +          if (!restriction && (ha || he)) +          { +            names (c, names_parser_callback_); +          } + +          String const& ret (ret_type (c)); + +          bool same (c.inherits_p () && +                        ret == ret_type (c.inherits ().base ())); + +          os << "virtual " << ret << endl +             << post_name (c) << " ()" << +            (same || ret == L"void" ? ";" : " = 0;") +             << endl; + +          // +          // +          if (!restriction && (he || ha)) +          { +            os << "// Parser construction API." << endl +               << "//" << endl; + +            names (c, names_parser_modifier_); + +            os << "void" << endl +               << "parsers ("; + +            { +              ParserParamDecl decl (*this, false); +              decl.traverse (c); +            } + +            os << ");" +               << endl; +          } + +          // Default c-tor. +          // +          if ((!restriction && (he || ha)) || +              (validation && (he || hae || hra))) +          { +            os << "// Constructor." << endl +               << "//" << endl +               << name << " ();" +               << endl; +          } + +          if (polymorphic) +          { +            os << "public:" << endl +               << "static const " << char_type << "*" << endl +               << "_static_type ();" +               << endl +               << "virtual const " << char_type << "*" << endl +               << "_dynamic_type () const;" +               << endl; +          } + +          // Implementation. +          // +          if (he || ha || (validation && (hae || haa))) +          { +            os << "// Implementation." << endl +               << "//" << endl +               << "protected:" << endl; +          } + +          // element +          // +          if (he || (validation && hae)) +          { +            // _start_element_impl +            // +            os << "virtual bool" << endl +               << "_start_element_impl (const " << string_type << "&," << endl +               << "const " << string_type << "&," << endl +               << "const " << string_type << "*);" +               << endl; + +            // end_element +            // +            os << "virtual bool" << endl +               << "_end_element_impl (const " << string_type << "&," << endl +               << "const " << string_type << "&);" +               << endl; +          } + +          // attribute +          // +          if (validation) +          { +            if (ha) +            { +              os << "virtual bool" << endl +                 << "_attribute_impl_phase_one (const " << string_type << +                "&," << endl +                 << "const " << string_type << "&," << endl +                 << "const " << string_type << "&);" << endl +                 << endl; +            } + +            if (haa) +            { +              os << "virtual bool" << endl +                 << "_attribute_impl_phase_two (const " << string_type << +                "&," << endl +                 << "const " << string_type << "&," << endl +                 << "const " << string_type << "&);" +                 << endl; +            } +          } +          else +          { +            if (ha) +            { +              os << "virtual bool" << endl +                 << "_attribute_impl (const " << string_type << "&," << endl +                 << "const " << string_type << "&," << endl +                 << "const " << string_type << "&);" +                 << endl; +            } +          } + +          // characters +          // +          if (validation && c.mixed_p ()) +          { +            os << "virtual bool" << endl +               << "_characters_impl (const " << string_type << "&);" +               << endl; +          } + +          if (!restriction && (he || ha)) +          { +            os << "protected:" << endl; +            names (c, names_parser_member_); +            os << endl; +          } + +          if (validation && (he || hae)) +          { +            size_t depth (c.context ().get<size_t> ("depth")); + +            os << "protected:" << endl; + +            os << "struct v_state_descr_" +               << "{" +               << "void (" << fq_name (c) << "::*func) (" << endl +               << "unsigned long&," << endl +               << "unsigned long&," << endl +               << "const " << string_type << "&," << endl +               << "const " << string_type << "&," << endl +               << "const " << string_type << "*," << endl +               << "bool);" +               << "unsigned long state;" +               << "unsigned long count;" +               << "};"; + +            // Allocate one extra slot for the special state. +            // +            os << "struct v_state_" +               << "{" +               << "v_state_descr_ data[" << depth + 1 << "UL];" +               << "unsigned long size;" +               << "};"; + +            os << "v_state_ v_state_first_;" +               << "::xsd::cxx::parser::pod_stack v_state_stack_;" +               << endl; + +            os << "virtual void" << endl +               << "_pre_e_validate ();" +               << endl; + +            os << "virtual void" << endl +               << "_post_e_validate ();" +               << endl; + +            Particle t (*this); +            t.dispatch (c.contains_compositor ().compositor ()); +          } + +          if (validation && hra) +          { +            os << "protected:" << endl; + +            os << "struct v_state_attr_" +               << "{"; + +            names (c, names_attribute_validation_state_); + +            os << "};"; + +            os << "v_state_attr_ v_state_attr_first_;" +               << "::xsd::cxx::parser::pod_stack v_state_attr_stack_;" +               << endl; + +            os << "virtual void" << endl +               << "_pre_a_validate ();" +               << endl; + +            os << "virtual void" << endl +               << "_post_a_validate ();" +               << endl; +          } + +          os << "};"; +        } + +      private: +        // +        // +        ParserCallback parser_callback_; +        Traversal::Names names_parser_callback_; + +        // +        // +        ParserMember parser_member_; +        Traversal::Names names_parser_member_; + +        // +        // +        ParserModifier parser_modifier_; +        Traversal::Names names_parser_modifier_; + +        // +        // +        AttributeValidationState attribute_validation_state_; +        Traversal::Names names_attribute_validation_state_; +      }; + +      struct FundType : Context, + +                        Traversal::AnyType, +                        Traversal::AnySimpleType, + +                        Traversal::Fundamental::Byte, +                        Traversal::Fundamental::UnsignedByte, +                        Traversal::Fundamental::Short, +                        Traversal::Fundamental::UnsignedShort, +                        Traversal::Fundamental::Int, +                        Traversal::Fundamental::UnsignedInt, +                        Traversal::Fundamental::Long, +                        Traversal::Fundamental::UnsignedLong, +                        Traversal::Fundamental::Integer, +                        Traversal::Fundamental::NonPositiveInteger, +                        Traversal::Fundamental::NonNegativeInteger, +                        Traversal::Fundamental::PositiveInteger, +                        Traversal::Fundamental::NegativeInteger, + +                        Traversal::Fundamental::Boolean, + +                        Traversal::Fundamental::Float, +                        Traversal::Fundamental::Double, +                        Traversal::Fundamental::Decimal, + +                        Traversal::Fundamental::String, +                        Traversal::Fundamental::NormalizedString, +                        Traversal::Fundamental::Token, +                        Traversal::Fundamental::Name, +                        Traversal::Fundamental::NameToken, +                        Traversal::Fundamental::NameTokens, +                        Traversal::Fundamental::NCName, +                        Traversal::Fundamental::Language, + +                        Traversal::Fundamental::QName, + +                        Traversal::Fundamental::Id, +                        Traversal::Fundamental::IdRef, +                        Traversal::Fundamental::IdRefs, + +                        Traversal::Fundamental::AnyURI, + +                        Traversal::Fundamental::Base64Binary, +                        Traversal::Fundamental::HexBinary, + +                        Traversal::Fundamental::Date, +                        Traversal::Fundamental::DateTime, +                        Traversal::Fundamental::Duration, +                        Traversal::Fundamental::Day, +                        Traversal::Fundamental::Month, +                        Traversal::Fundamental::MonthDay, +                        Traversal::Fundamental::Year, +                        Traversal::Fundamental::YearMonth, +                        Traversal::Fundamental::Time, + +                        Traversal::Fundamental::Entity, +                        Traversal::Fundamental::Entities +      { +        FundType (Context& c) +            : Context (c), xs_ns_ (xs_ns_name ()) +        { +          impl_ns_ = "::xsd::cxx::parser::"; +          impl_ns_ += (validation ? L"validating" : L"non_validating"); + +          if (char_type == L"char") +            string_type_ = L"::std::string"; +          else if (char_type == L"wchar_t") +            string_type_ = L"::std::wstring"; +          else +            string_type_ = L"::std::basic_string< " + char_type + L" >"; +        } + +        // anyType & anySimpleType. +        // +        virtual void +        traverse (SemanticGraph::AnyType& t) +        { +          gen_typedef (t, "void", "any_type_pskel", "any_type_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::AnySimpleType& t) +        { +          gen_typedef (t, "void", +                       "any_simple_type_pskel", "any_simple_type_pimpl"); +        } + +        // Boolean. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Boolean& t) +        { +          gen_typedef (t, "bool", "boolean_pskel", "boolean_pimpl"); +        } + +        // Integral types. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Byte& t) +        { +          gen_typedef (t, "signed char", "byte_pskel", "byte_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedByte& t) +        { +          gen_typedef (t, "unsigned char", +                       "unsigned_byte_pskel", "unsigned_byte_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Short& t) +        { +          gen_typedef (t, "short", "short_pskel", "short_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedShort& t) +        { +          gen_typedef (t, "unsigned short", +                       "unsigned_short_pskel", "unsigned_short_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Int& t) +        { +          gen_typedef (t, "int", "int_pskel", "int_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedInt& t) +        { +          gen_typedef (t, "unsigned int", +                       "unsigned_int_pskel", "unsigned_int_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Long& t) +        { +          gen_typedef (t, "long long", "long_pskel", "long_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedLong& t) +        { +          gen_typedef (t, "unsigned long long", +                       "unsigned_long_pskel", "unsigned_long_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Integer& t) +        { +          gen_typedef (t, "long long", "integer_pskel", "integer_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NegativeInteger& t) +        { +          gen_typedef (t, "long long", +                       "negative_integer_pskel", "negative_integer_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +        { +          gen_typedef (t, "long long", +                       "non_positive_integer_pskel", +                       "non_positive_integer_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::PositiveInteger& t) +        { +          gen_typedef (t, "unsigned long long", +                       "positive_integer_pskel", "positive_integer_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +        { +          gen_typedef (t, "unsigned long long", +                       "non_negative_integer_pskel", +                       "non_negative_integer_pimpl"); +        } + +        // Floats. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Float& t) +        { +          gen_typedef (t, "float", "float_pskel", "float_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Double& t) +        { +          gen_typedef (t, "double", "double_pskel", "double_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Decimal& t) +        { +          gen_typedef (t, "double", "decimal_pskel", "decimal_pimpl"); +        } + +        // Strings. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::String& t) +        { +          gen_typedef (t, string_type_, "string_pskel", "string_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NormalizedString& t) +        { +          gen_typedef (t, string_type_, +                       "normalized_string_pskel", "normalized_string_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Token& t) +        { +          gen_typedef (t, string_type_, "token_pskel", "token_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameToken& t) +        { +          nmtoken_ = gen_typedef (t, string_type_, +                                  "nmtoken_pskel", "nmtoken_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameTokens& t) +        { +          // NMTOKENS uses NMTOKEN implementation to parse individual items. +          // As a result, we don't generate NMTOKENS if we didn't generate +          // NMTOKEN. Here we assume NMTOKEN is handled before NMTOKENS. +          // +          if(nmtoken_) +            gen_typedef (t, xs_ns_ + L"::string_sequence", +                         "nmtokens_pskel", "nmtokens_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Name& t) +        { +          gen_typedef (t, string_type_, "name_pskel", "name_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NCName& t) +        { +          gen_typedef (t, string_type_, "ncname_pskel", "ncname_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Language& t) +        { +          gen_typedef (t, string_type_, "language_pskel", "language_pimpl"); +        } + +        // Qualified name. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::QName& t) +        { +          gen_typedef (t, xs_ns_ + L"::qname", "qname_pskel", "qname_pimpl"); +        } + +        // ID/IDREF. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Id& t) +        { +          gen_typedef (t, string_type_, "id_pskel", "id_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRef& t) +        { +          idref_ = gen_typedef (t, string_type_, "idref_pskel", "idref_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRefs& t) +        { +          // IDREFS uses IDREF implementation to parse individual items. +          // As a result, we don't generate IDREFS if we didn't generate +          // IDREF. Here we assume IDREF is handled before IDREFS. +          // +          if (idref_) +            gen_typedef (t, xs_ns_ + L"::string_sequence", +                         "idrefs_pskel", "idrefs_pimpl"); +        } + +        // URI. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::AnyURI& t) +        { +          gen_typedef (t, string_type_, "uri_pskel", "uri_pimpl"); +        } + +        // Binary. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Base64Binary& t) +        { +          String buffer (auto_ptr + L"< " + xs_ns_ + L"::buffer >"); +          gen_typedef (t, buffer, +                       "base64_binary_pskel", "base64_binary_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::HexBinary& t) +        { +          String buffer (auto_ptr + L"< " + xs_ns_ + L"::buffer >"); +          gen_typedef (t, buffer, "hex_binary_pskel", "hex_binary_pimpl"); +        } + + +        // Date/time. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Date& t) +        { +          gen_typedef (t, xs_ns_ + L"::date", "date_pskel", "date_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::DateTime& t) +        { +          gen_typedef (t, xs_ns_ + L"::date_time", +                       "date_time_pskel", "date_time_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Duration& t) +        { +          gen_typedef (t, xs_ns_ + L"::duration", +                       "duration_pskel", "duration_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Day& t) +        { +          gen_typedef (t, xs_ns_ + L"::gday", "gday_pskel", "gday_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Month& t) +        { +          gen_typedef (t, xs_ns_ + L"::gmonth", +                       "gmonth_pskel", "gmonth_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::MonthDay& t) +        { +          gen_typedef (t, xs_ns_ + L"::gmonth_day", +                       "gmonth_day_pskel", "gmonth_day_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Year& t) +        { +          gen_typedef (t, xs_ns_ + L"::gyear", "gyear_pskel", "gyear_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::YearMonth& t) +        { +          gen_typedef (t, xs_ns_ + L"::gyear_month", +                       "gyear_month_pskel", "gyear_month_pimpl"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Time& t) +        { +          gen_typedef (t, xs_ns_ + L"::time", "time_pskel", "time_pimpl"); +        } + +        // Entity. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Entity&) +        { +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Entities&) +        { +        } + +      private: +        bool +        gen_typedef (SemanticGraph::Type& t, +                     String const& type, +                     String const& pskel, +                     String const& pimpl) +        { +          if (ret_type (t) == type) +          { +            os << "typedef " << impl_ns_ << "::" << pskel << "< " << +              char_type << " > " << ename (t) << ";"; + +            String const& pimpl_name (t.context ().get<String> ("impl")); + +            os << "typedef " << impl_ns_ << "::" << pimpl << "< " << +              char_type << " > " << pimpl_name << ";" +               << endl; + +            return true; +          } + +          return false; +        } + +        String xs_ns_; +        String impl_ns_; +        String string_type_; + +        bool idref_; +        bool nmtoken_; +      }; + +      struct FundNamespace: Namespace, Context +      { +        FundNamespace (Context& c) +            : Namespace (c), Context (c) +        { +        } + +        void +        traverse (Type& ns) +        { +          pre (ns); + +          String impl ("::xsd::cxx::parser::"); +          impl += (validation ? L"validating" : L"non_validating"); + +          String const c (char_type); + +          os << "// Built-in XML Schema types mapping." << endl +             << "//" << endl +             << "typedef ::xsd::cxx::parser::string_sequence< " << c << +            " > string_sequence;" +             << "typedef ::xsd::cxx::parser::qname< " << c << " > qname;" +             << "typedef ::xsd::cxx::parser::buffer buffer;" +             << "typedef ::xsd::cxx::parser::time_zone time_zone;" +             << "typedef ::xsd::cxx::parser::gday gday;" +             << "typedef ::xsd::cxx::parser::gmonth gmonth;" +             << "typedef ::xsd::cxx::parser::gyear gyear;" +             << "typedef ::xsd::cxx::parser::gmonth_day gmonth_day;" +             << "typedef ::xsd::cxx::parser::gyear_month gyear_month;" +             << "typedef ::xsd::cxx::parser::date date;" +             << "typedef ::xsd::cxx::parser::time time;" +             << "typedef ::xsd::cxx::parser::date_time date_time;" +             << "typedef ::xsd::cxx::parser::duration duration;" +             << endl; + +          os << "// Base parser skeletons." << endl +             << "//" << endl +             << "typedef ::xsd::cxx::parser::parser_base< " << c << +            " > parser_base;" +             << "typedef " << impl << "::empty_content< " << c << +            " > empty_content;" +             << "typedef " << impl << "::simple_content< " << c << +            " > simple_content;" +             << "typedef " << impl << "::complex_content< " << c << +            " > complex_content;" +             << "typedef " << impl << "::list_base< " << c << " > list_base;" +             << endl; + +          if (polymorphic) +          { +            os << "// Parser map interface and default implementation." << endl +               << "//" << endl +               << "typedef ::xsd::cxx::parser::parser_map< " << c << +              " > parser_map;" +               << "typedef ::xsd::cxx::parser::parser_map_impl< " << c << +              " > parser_map_impl;" +               << endl; +          } + +          os << "// Parser skeletons and implementations for the XML Schema" << endl +             << "// built-in types." << endl +             << "//" << endl; + +          names (ns); + +          os << "// Exceptions. See xsd/cxx/parser/exceptions.hxx " << +            "for details." << endl +             << "//" << endl +             << "typedef ::xsd::cxx::parser::exception< " << +            char_type << " > exception;" +             << endl +             << "// Parsing diagnostics." << endl +             << "//" << endl +             << "typedef ::xsd::cxx::parser::severity severity;" +             << "typedef ::xsd::cxx::parser::error< " << c << " > error;" +             << "typedef ::xsd::cxx::parser::diagnostics< " << c << +            " > diagnostics;" +             << "typedef ::xsd::cxx::parser::parsing< " << c << " > parsing;" +             << endl; + +          os << "// Error handler. See " << +            "xsd/cxx/xml/error-handler.hxx for details." << endl +             << "//" << endl +             << "typedef ::xsd::cxx::xml::error_handler< " << c << +            " > error_handler;" +             << endl; + +          os << "// Read-only string." << endl +             << "//" << endl +             << "typedef ::xsd::cxx::ro_string< " << c << " > ro_string;" +             << endl; + +          if (xml_parser == L"xerces") +          { +            os << "// Parsing flags. See " << +              "xsd/cxx/parser/xerces/elements.hxx" << endl +               << "// for details." << endl +               << "//" << endl +               << "typedef ::xsd::cxx::parser::xerces::flags flags;" +               << endl; + +            os << "// Parsing properties. See " << +              "xsd/cxx/parser/xerces/elements.hxx" << endl +               << "// for details." << endl +               << "//" << endl +               << "typedef ::xsd::cxx::parser::xerces::properties< " << c << +              " > properties;" +               << endl; + +            os << "// Document type. See " << +              "xsd/cxx/parser/xerces/elements.hxx" << endl +               << "// for details." << endl +               << "//" << endl +               << "typedef ::xsd::cxx::parser::xerces::document< " << c << +              " > document;" +               << endl; + +          } +          else if (xml_parser == L"expat") +          { +            os << "// Document type. See " << +              "xsd/cxx/parser/expat/elements.hxx" << endl +               << "// for details." << endl +               << "//" << endl +               << "typedef ::xsd::cxx::parser::expat::document< " << c << +              " > document;" +               << endl; +          } + +          post (ns); +        } +      }; +    } + +    void +    generate_parser_header (Context& ctx, bool generate_xml_schema) +    { +      String c (ctx.char_type); + +      // +      // +      if (c == L"char") +      { +        ctx.os << "#ifndef XSD_USE_CHAR" << endl +               << "#define XSD_USE_CHAR" << endl +               << "#endif" << endl +               << endl; + +        ctx.os << "#ifndef XSD_CXX_PARSER_USE_CHAR" << endl +               << "#define XSD_CXX_PARSER_USE_CHAR" << endl +               << "#endif" << endl +               << endl; +      } +      else if (c == L"wchar_t") +      { +        ctx.os << "#ifndef XSD_USE_WCHAR" << endl +               << "#define XSD_USE_WCHAR" << endl +               << "#endif" << endl +               << endl; + +        ctx.os << "#ifndef XSD_CXX_PARSER_USE_WCHAR" << endl +               << "#define XSD_CXX_PARSER_USE_WCHAR" << endl +               << "#endif" << endl +               << endl; +      } + +      // +      // +      NarrowString extern_xml_schema; + +      if (!generate_xml_schema) +        extern_xml_schema = ctx.options.extern_xml_schema (); + +      if (extern_xml_schema) +      { +        String name (ctx.hxx_expr->replace (extern_xml_schema)); + +        ctx.os << "#include " << ctx.process_include_path (name) << endl +               << endl; + +        // Generate includes that came from the type map. +        // +        if (ctx.schema_root.context ().count ("includes")) +        { +          typedef set<String> Includes; + +          Includes const& is ( +            ctx.schema_root.context ().get<Includes> ("includes")); + +          for (Includes::const_reverse_iterator i (is.rbegin ()); +               i != is.rend (); ++i) +          { +            ctx.os << "#include " << *i << endl; +          } + +          ctx.os << endl; +        } +      } +      else +      { +        if (ctx.char_type == L"char" && +            ctx.xml_parser == L"xerces" && +            ctx.char_encoding != L"custom") +        { +          ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << ".hxx>" << endl; +        } + +        ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl +               << "#include <xsd/cxx/parser/exceptions.hxx>" << endl +               << "#include <xsd/cxx/parser/elements.hxx>" << endl +               << "#include <xsd/cxx/parser/xml-schema.hxx>" << endl; + +        if (ctx.polymorphic) +          ctx.os << "#include <xsd/cxx/parser/map.hxx>" << endl; + +        if (ctx.validation) +          ctx.os << "#include <xsd/cxx/parser/validating/parser.hxx>" << endl +                 << "#include <xsd/cxx/parser/validating/exceptions.hxx>" << endl +                 << "#include <xsd/cxx/parser/validating/xml-schema-pskel.hxx>" << endl +                 << "#include <xsd/cxx/parser/validating/xml-schema-pimpl.hxx>" << endl; +        else +          ctx.os << "#include <xsd/cxx/parser/non-validating/parser.hxx>" << endl +                 << "#include <xsd/cxx/parser/non-validating/xml-schema-pskel.hxx>" << endl +                 << "#include <xsd/cxx/parser/non-validating/xml-schema-pimpl.hxx>" << endl; + +        ctx.os << "#include <xsd/cxx/parser/" << ctx.xml_parser << +          "/elements.hxx>" << endl +               << endl; + +        // Generate includes that came from the type map. +        // +        if (ctx.schema_root.context ().count ("includes")) +        { +          typedef set<String> Includes; + +          Includes const& is ( +            ctx.schema_root.context ().get<Includes> ("includes")); + +          for (Includes::const_reverse_iterator i (is.rbegin ()); +               i != is.rend (); ++i) +          { +            ctx.os << "#include " << *i << endl; +          } + +          ctx.os << endl; +        } + +        // Generate fundamental types. +        // +        if (generate_xml_schema) +        { +          Traversal::Schema schema; +          Traversal::Names names; +          FundNamespace ns (ctx); + +          schema >> names >> ns; + +          Traversal::Names ns_names; +          FundType type (ctx); + +          ns >> ns_names >> type; + +          schema.dispatch (ctx.schema_root); +        } +        else +        { +          Traversal::Schema schema, xsd; +          Traversal::Implies implies; +          Traversal::Names names; +          FundNamespace ns (ctx); + +          schema >> implies >> xsd >> names >> ns; + +          Traversal::Names ns_names; +          FundType type (ctx); + +          ns >> ns_names >> type; + +          schema.dispatch (ctx.schema_root); +        } +      } + +      // Generate user type mapping. +      // +      if (!generate_xml_schema) +      { +        Traversal::Schema schema; + +        Sources sources; +        Includes includes (ctx, Includes::header); +        Traversal::Names schema_names; + +        Namespace ns (ctx); +        Traversal::Names names; + +        schema >> includes; +        schema >> sources >> schema; +        schema >> schema_names >> ns >> names; + +        List list (ctx); +        Union union_ (ctx); +        Complex complex (ctx); +        Enumeration enumeration (ctx); + +        names >> list; +        names >> union_; +        names >> complex; +        names >> enumeration; + +        schema.dispatch (ctx.schema_root); +      } +    } +  } +} diff --git a/xsd/cxx/parser/parser-header.hxx b/xsd/cxx/parser/parser-header.hxx new file mode 100644 index 0000000..642da40 --- /dev/null +++ b/xsd/cxx/parser/parser-header.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/parser-header.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_PARSER_HEADER_HXX +#define XSD_CXX_PARSER_PARSER_HEADER_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_parser_header (Context&, bool generate_xml_schema); +  } +} + +#endif  // XSD_CXX_PARSER_PARSER_HEADER_HXX diff --git a/xsd/cxx/parser/parser-inline.cxx b/xsd/cxx/parser/parser-inline.cxx new file mode 100644 index 0000000..6705d5b --- /dev/null +++ b/xsd/cxx/parser/parser-inline.cxx @@ -0,0 +1,399 @@ +// file      : xsd/cxx/parser/parser-inline.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/parser/parser-inline.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      // +      // +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String const& name (ename (l)); +          SemanticGraph::Type& t (l.argumented ().type ()); + +          String item (unclash (name, "item")); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // item_parser +          // +          os << inl +             << "void " << name << "::" << endl +             << unclash (name, "item_parser") << " (" << +            fq_name (t) << "& " << item << ")" +             << "{" +             << "this->_xsd_" << item << "_ = &" << item << ";" +             << "}"; + +          // parsers +          // +          os << inl +             << "void " << name << "::" << endl +             << "parsers (" << fq_name (t) << "& " << item << ")" +             << "{" +             << "this->_xsd_" << item << "_ = &" << item << ";" +             << "}"; + +          // c-tor +          // +          os << inl +             << name << "::" << endl +             << name << " ()" << endl +             << ": _xsd_" << item << "_ (0)" +             << "{" +             << "}"; +        } +      }; + + +      // +      // +      struct ParserModifier: Traversal::Member, Context +      { +        ParserModifier (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) +            return; + +          String const& scope (ename (m.scope ())); +          String const& parser (eparser (m)); + +          bool poly (polymorphic && +                        m.is_a<SemanticGraph::Element> () && +                        !anonymous (m.type ())); + +          os << inl +             << "void " << scope << "::" << endl +             << parser << " (" << fq_name (m.type ()) << "& p)" +             << "{" +             << "this->" << emember (m) << " = &p;" +             << "}"; + +          if (poly) +          { +            os << inl +               << "void " << scope << "::" << endl +               << parser << " (const " << parser_map << "& m)" +               << "{" +               << "this->" << emember_map (m) << " = &m;" +               << "}"; +          } +        } +      }; + + +      // +      // +      struct ParserMemberSet: Traversal::Member, Context +      { +        ParserMemberSet (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) return; + +          String const& name (ename (m)); + +          os << "this->" << emember (m) << " = &" << name << ";"; +        } +      }; + + +      // +      // +      struct ParserMemberInit: Traversal::Member, Context +      { +        ParserMemberInit (Context& c) +            : Context (c), first_ (true) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) return; + +          if (first_) +            first_ = false; +          else +            os << "," << endl << "  "; + +          os << emember (m) << " (0)"; + +          if (polymorphic && +              m.is_a<SemanticGraph::Element> () && +              !anonymous (m.type ())) +          { +            os << "," << endl +               << "  " << emember_map (m) << " (0)"; +          } +        } + +        bool +        comma () const +        { +          return !first_; +        } + +      private: +        bool first_; +      }; + +      struct ParserBaseSet: Traversal::Complex, +                            Traversal::List, +                            Context +      { +        ParserBaseSet (Context& c) +            : Context (c), member_ (c) +        { +          inherits_ >> *this; +          names_ >> member_; +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          inherits (c, inherits_); + +          if (!restriction_p (c)) +            names (c, names_); +        } + +        virtual void +        traverse (SemanticGraph::List& l) +        { +          String const& name (ename (l)); +          String item (unclash (name, "item")); + +          os << "this->_xsd_" << item << "_ = &" << name << "_item;"; +        } + +      private: +        Traversal::Inherits inherits_; + +        ParserMemberSet member_; +        Traversal::Names names_; +      }; + +      struct Particle: Traversal::All, Context +      { +        Particle (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::All& a) +        { +          if (!a.context().count ("comp-number")) +            return; + +          size_t state_count (a.context().get<size_t> ("state-count")); + +          os << "," << endl +             << "  v_all_count_ (" << state_count << "UL, v_all_first_)"; +        } +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), +              parser_modifier_ (c), +              parser_base_set_ (c), +              parser_member_set_ (c), +              particle_ (c) +        { +          names_parser_modifier_ >> parser_modifier_; +          inherits_parser_base_set_ >> parser_base_set_; +          names_parser_member_set_ >> parser_member_set_; +        } + +        virtual void +        traverse (Type& c) +        { +          bool he (has<Traversal::Element> (c)); +          bool ha (has<Traversal::Attribute> (c)); + +          bool hae (has_particle<Traversal::Any> (c)); + +          bool hra (false); // Has required attribute. +          if (ha) +          { +            RequiredAttributeTest test (hra); +            Traversal::Names names_test (test); +            names (c, names_test); +          } + +          bool restriction (restriction_p (c)); + +          if (!((!restriction && (he || ha)) || +                (validation && (he || hae || hra)))) +            return; + +          String const& name (ename (c)); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          if (!restriction && (he || ha)) +          { +            // <name>_parser () +            // +            names (c, names_parser_modifier_); + + +            // parsers () +            // + +            os << inl +               << "void " << name << "::" << endl +               << "parsers ("; + +            { +              ParserParamDecl decl (*this, true); +              decl.traverse (c); +            } + +            os << ")" +               << "{"; + +            inherits (c, inherits_parser_base_set_); +            names (c, names_parser_member_set_); + +            os << "}"; +          } + +          // Default c-tor. +          // +          os << inl +             << name << "::" << endl +             << name << " ()" << endl +             << ": "; + +          bool comma (false); + +          if (!restriction && (he || ha)) +          { +            ParserMemberInit member_init (*this); +            Traversal::Names names_member_init (member_init); + +            names (c, names_member_init); + +            comma = member_init.comma (); +          } + +          if (validation && (he || hae)) +          { +            if (comma) +              os << "," << endl << "  "; + +            os << "v_state_stack_ (sizeof (v_state_), &v_state_first_)"; + +            particle_.dispatch (c.contains_compositor ().compositor ()); + +            comma = true; +          } + +          if (validation && (hra)) +          { +            if (comma) +              os << "," << endl << "  "; + +            os << "v_state_attr_stack_ (sizeof (v_state_attr_), " << +              "&v_state_attr_first_)"; +          } + +          os << "{" +             << "}"; +        } + +      private: +        // +        // +        ParserModifier parser_modifier_; +        Traversal::Names names_parser_modifier_; + +        // +        // +        ParserBaseSet parser_base_set_; +        Traversal::Inherits inherits_parser_base_set_; + +        // +        // +        ParserMemberSet parser_member_set_; +        Traversal::Names names_parser_member_set_; + +        // +        // +        Particle particle_; +      }; +    } + +    void +    generate_parser_inline (Context& ctx) +    { +      // Emit "weak" header includes that are used in the file-per-type +      // compilation model. +      // +      if (!ctx.options.generate_inline ()) +      { +        Traversal::Schema schema; +        Includes includes (ctx, Includes::source); + +        schema >> includes; +        schema.dispatch (ctx.schema_root); +      } + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names schema_names; + +      Namespace ns (ctx); +      Traversal::Names names; + +      schema >> sources >> schema; +      schema >> schema_names >> ns >> names; + +      List list (ctx); +      Complex complex (ctx); + +      names >> list; +      names >> complex; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/parser/parser-inline.hxx b/xsd/cxx/parser/parser-inline.hxx new file mode 100644 index 0000000..aee0cdf --- /dev/null +++ b/xsd/cxx/parser/parser-inline.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/parser-inline.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_PARSER_INLINE_HXX +#define XSD_CXX_PARSER_PARSER_INLINE_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_parser_inline (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_PARSER_INLINE_HXX diff --git a/xsd/cxx/parser/parser-source.cxx b/xsd/cxx/parser/parser-source.cxx new file mode 100644 index 0000000..2887f96 --- /dev/null +++ b/xsd/cxx/parser/parser-source.cxx @@ -0,0 +1,957 @@ +// file      : xsd/cxx/parser/parser-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/parser/parser-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          String const& name (ename (e)); +          String const& ret (ret_type (e)); + +          SemanticGraph::Type& base (e.inherits ().base ()); + +          bool same (ret == ret_type (base)); + +          if (same || ret == L"void" || polymorphic) +          { +            os << "// " << name << endl +               << "//" << endl +               << endl; +          } + +          if (same || ret == L"void") +          { +            os << ret << " " << name << "::" << endl +               << post_name (e) << " ()" +               << "{"; + +            if (same) +            { +              if (ret == L"void") +                os << post_name (base) << " ();"; +              else +                os << "return " << post_name (base) << " ();"; +            } + +            os << "}"; +          } + +          if (polymorphic) +          { +            String id (e.name ()); + +            if (String ns = xml_ns_name (e)) +            { +              id += L' '; +              id += ns; +            } + +            os << "const " << char_type << "* " << name << "::" << endl +               << "_static_type ()" +               << "{" +               << "return " << strlit (id) << ";" +               << "}"; + +            os << "const " << char_type << "* " << name << "::" << endl +               << "_dynamic_type () const" +               << "{" +               << "return _static_type ();" +               << "}"; + +            if (validation) +            { +              bool gen (!anonymous (e)); + +              // We normally don't need to enter anonymous types into +              // the inheritance map. The only exception is when an +              // anonymous types is defined inside an element that +              // is a member of a substitution group. +              // +              if (!gen) +              { +                // The first instance that this anonymous type classifies +                // is the prototype for others if any. If this type does +                // not classify anything (e.g., it is a base), then we +                // don't need to do anything. +                // +                if (e.classifies_begin () != e.classifies_end ()) +                { +                  SemanticGraph::Instance& i ( +                    e.classifies_begin ()->instance ()); + +                  if (SemanticGraph::Element* e = +                      dynamic_cast<SemanticGraph::Element*> (&i)) +                  { +                    if (e->substitutes_p ()) +                      gen = true; +                  } +                } +              } + +              if (gen) +              { +                os << "static" << endl +                   << "const ::xsd::cxx::parser::validating::inheritance_map_entry< " << +                  char_type << " >" << endl +                   << "_xsd_" << name << "_inheritance_map_entry_ (" << endl +                   << name << "::_static_type ()," << endl +                   << fq_name (base) << "::_static_type ());" +                   << endl; +              } +            } +          } +        } +      }; + +      // +      // +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String const& name (ename (l)); +          SemanticGraph::Type& t (l.argumented ().type ()); + +          String item (unclash (name, "item")); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // item +          // +          String const& arg (arg_type (t)); + +          os << "void " << name << "::" << endl +             << item; + +          if (arg == L"void") +            os << " ()"; +          else +            os << " (" << arg << ")"; + +          os << "{" +             << "}"; + +          // post +          // +          if (ret_type (l) == L"void") +            os << "void " << name << "::" << endl +               << post_name (l) << " ()" +               << "{" +               << "}"; + +          // parse_item +          // +          String inst (L"_xsd_" + item + L"_"); +          String const& post (post_name (t)); + +          os << "void " << name << "::" << endl +             << "_xsd_parse_item (const " << string_type << "& v)" +             << "{" +             << "if (this->" << inst << ")" +             << "{" +             << "this->" << inst << "->pre ();" +             << "this->" << inst << "->_pre_impl ();" +             << "this->" << inst << "->_characters (v);" +             << "this->" << inst << "->_post_impl ();"; + +          if (ret_type (t) == L"void") +            os << "this->" << inst << "->" << post << " ();" +               << "this->" << item << " ();"; +          else +            os << "this->" << item << " (this->" << inst << "->" << +              post << " ());"; + +          os << "}" +             << "}"; + +          // +          // +          if (polymorphic) +          { +            String id (l.name ()); + +            if (String ns = xml_ns_name (l)) +            { +              id += L' '; +              id += ns; +            } + +            os << "const " << char_type << "* " << name << "::" << endl +               << "_static_type ()" +               << "{" +               << "return " << strlit (id) << ";" +               << "}"; + +            os << "const " << char_type << "* " << name << "::" << endl +               << "_dynamic_type () const" +               << "{" +               << "return _static_type ();" +               << "}"; +          } +        } +      }; + +      // +      // +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String const& name (ename (u)); +          String const& ret (ret_type (u)); + +          if (ret == L"void" || polymorphic) +          { +            os << "// " << name << endl +               << "//" << endl +               << endl; +          } + +          if (ret == L"void") +          { +            os << "void " << name << "::" << endl +               << post_name (u) << " ()" +               << "{" +               << "}"; +          } + +          if (polymorphic) +          { +            String id (u.name ()); + +            if (String ns = xml_ns_name (u)) +            { +              id += L' '; +              id += ns; +            } + +            os << "const " << char_type << "* " << name << "::" << endl +               << "_static_type ()" +               << "{" +               << "return " << strlit (id) << ";" +               << "}"; + +            os << "const " << char_type << "* " << name << "::" << endl +               << "_dynamic_type () const" +               << "{" +               << "return _static_type ();" +               << "}"; +          } +        } +      }; + +      // +      // +      struct StartElement: Traversal::Element, Context +      { +        StartElement (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +	  if (skip (e)) +            return; + +          bool poly (polymorphic && !anonymous (e.type ())); + +          os << "if ("; + +          if (poly && e.global_p ()) +            os << "("; + +          if (e.qualified_p () && e.namespace_ ().name ()) +          { +            os << "n == " << strlit (e.name ()) << " && " << +              "ns == " << strlit (e.namespace_ ().name ()); +          } +          else +          { +            os << "n == " << strlit (e.name ()) << " && ns.empty ()"; +          } + +          // Only a globally-defined element can be a subst-group root. +          // +          if (poly && e.global_p ()) +          { +            os << ") ||" << endl +               << "::xsd::cxx::parser::substitution_map_instance< " << +              char_type << " > ().check (" << endl +               << "ns, n, " << strlit (e.namespace_ ().name ()) << +              ", " << strlit (e.name ()) << ", t)"; +          } + +          os << ")" +             << "{"; + +          String inst; + +          if (poly) +          { +            SemanticGraph::Type& t (e.type ()); +            inst = "p"; + +            // For pre-computing length. +            // +            String type_id (t.name ()); + +            if (String type_ns = xml_ns_name (t)) +            { +              type_id += L' '; +              type_id += type_ns; +            } + +            String fq_type (fq_name (t)); +            String const& member (emember (e)); +            String const& member_map (emember_map (e)); + +            os << fq_type << "* p = 0;" +               << endl +               << "if (t == 0 && this->" << member << " != 0)" << endl +               << inst << " = this->" << member << ";" +               << "else" +               << "{" +               << string_type << " ts (" << fq_type << +              "::_static_type (), " << type_id.size () << "UL);" +               << endl +               << "if (t == 0)" << endl +               << "t = &ts;" +               << endl +               << "if (this->" << member << " != 0 && *t == ts)" << endl +               << inst << " = this->" << member << ";" +               << "else if (this->" << member_map << " != 0)" << endl +               << inst << " = dynamic_cast< " << fq_type << +              "* > (" << endl +               << "this->" << member_map << "->find (*t));" +               << "}"; +          } +          else +            inst = L"this->" + emember (e); + +          os << "this->" << complex_base << "::context_.top ().parser_ = " << +            inst << ";" +             << endl +             << "if (" << inst << ")" << endl +             << inst << "->pre ();" // _start_element calls _pre +             << endl +             << "return true;" +             << "}"; +        } +      }; + + +      // +      // +      struct EndElement: Traversal::Element, Context +      { +        EndElement (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +	  if (skip (e)) +            return; + +          bool poly (polymorphic && !anonymous (e.type ())); +          String const& name (ename (e)); + +          os << "if ("; + +          if (poly && e.global_p ()) +            os << "("; + +          if (e.qualified_p () && e.namespace_ ().name ()) +          { +            os << "n == " << strlit (e.name ()) << " && " << +              "ns == " << strlit (e.namespace_ ().name ()); +          } +          else +          { +            os << "n == " << strlit (e.name ()) << " && ns.empty ()"; +          } + +          // Only a globally-defined element can be a subst-group root. +          // +          if (poly && e.global_p ()) +          { +            os << ") ||" << endl +               << "::xsd::cxx::parser::substitution_map_instance< " << +              char_type << " > ().check (" << endl +               << "ns, n, " << strlit (e.namespace_ ().name ()) << +              ", " << strlit (e.name ()) << ")"; +          } + +          os << ")" +             << "{"; + +          // _end_element calls post +          // + +          SemanticGraph::Type& type (e.type ()); +          String const& post (post_name (type)); +          String inst; + +          if (poly) +          { +            String const& fq_type (fq_name (type)); +            inst = "p"; + +            os << fq_type << "* p =" << endl +               << "dynamic_cast< " << fq_type << "* > (" << endl +               << "this->" << complex_base << "::context_.top ().parser_);" +               << endl; +          } +          else +            inst = L"this->" + emember (e); + +          os << "if (" << inst << ")"; + +          if (ret_type (type) == L"void") +            os << "{" +               << inst << "->" << post << " ();" +               << "this->" << name << " ();" +               << "}"; +          else +            os << endl +               << "this->" << name << " (" << inst << "->" << post << " ());" +               << endl; + +          os << "return true;" +             << "}"; +        } +      }; + +      // +      // +      struct Attribute: Traversal::Attribute, Context +      { +        Attribute (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& name (ename (a)); +          String const& inst (emember (a)); + +          if (a.qualified_p () && a.namespace_ ().name ()) +          { +            os << "if (n == " << strlit (a.name ()) << " && " << +              "ns == " << strlit (a.namespace_ ().name ()) << ")" +               << "{"; +          } +          else +          { +            os << "if (n == " << strlit (a.name ()) << " && ns.empty ())" +               << "{"; +          } + +          SemanticGraph::Type& type (a.type ()); +          String const& post (post_name (type)); +          String const& ret (ret_type (type)); + +          os << "if (this->" << inst << ")" +             << "{" +             << "this->" << inst << "->pre ();" +             << "this->" << inst << "->_pre_impl ();" +             << "this->" << inst << "->_characters (v);" +             << "this->" << inst << "->_post_impl ();"; + +          if (ret == L"void") +            os << "this->" << inst << "->" << post << " ();" +               << "this->" << name << " ();"; +          else +            os << "this->" << name << " (this->" << inst << "->" << +              post << " ());"; + +          os << "}" +             << "return true;" +             << "}"; +        } +      }; + +      // +      // +      struct ParserCallback: Traversal::Member, Context +      { +        ParserCallback (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) +            return; + +          String const& arg (arg_type (m.type ())); + +          os << "void " << ename (m.scope ()) << "::" << endl +             << ename (m); + +          if (arg == L"void") +            os << " ()"; +          else +            os << " (" << arg << ")"; + +          os << "{" +             << "}"; +        } +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), +              parser_callback_ (c), +              start_element_ (c), +              end_element_ (c), +              attribute_ (c) +        { +          names_parser_callback_ >> parser_callback_; +          names_start_element_ >> start_element_; +          names_end_element_ >> end_element_; +          names_attribute_ >> attribute_; +        } + +        virtual void +        traverse (Type& c) +        { +          bool he (has<Traversal::Element> (c)); +          bool ha (has<Traversal::Attribute> (c)); + +          String const& ret (ret_type (c)); +          bool same (c.inherits_p () && +                        ret == ret_type (c.inherits ().base ())); + +          String const& name (ename (c)); + +          if ((he || ha || same || ret == L"void") || polymorphic) +          { +            os << "// " << name << endl +               << "//" << endl +               << endl; +          } + +          if (polymorphic) +          { +            String id (c.name ()); + +            if (String ns = xml_ns_name (c)) +            { +              id += L' '; +              id += ns; +            } + +            os << "const " << char_type << "* " << name << "::" << endl +               << "_static_type ()" +               << "{" +               << "return " << strlit (id) << ";" +               << "}"; + +            os << "const " << char_type << "* " << name << "::" << endl +               << "_dynamic_type () const" +               << "{" +               << "return _static_type ();" +               << "}"; + +            if (c.inherits_p () && validation) +            { +              bool gen (!anonymous (c)); + +              // We normally don't need to enter anonymous types into +              // the inheritance map. The only exception is when an +              // anonymous types is defined inside an element that +              // is a member of a substitution group. +              // +              if (!gen) +              { +                // The first instance that this anonymous type classifies +                // is the prototype for others if any. If this type does +                // not classify anything (e.g., it is a base), then we +                // don't need to do anything. +                // +                if (c.classifies_begin () != c.classifies_end ()) +                { +                  SemanticGraph::Instance& i ( +                    c.classifies_begin ()->instance ()); + +                  if (SemanticGraph::Element* e = +                      dynamic_cast<SemanticGraph::Element*> (&i)) +                  { +                    if (e->substitutes_p ()) +                      gen = true; +                  } +                } +              } + +              if (gen) +              { +                SemanticGraph::Type& base (c.inherits ().base ()); + +                os << "static" << endl +                   << "const ::xsd::cxx::parser::validating::inheritance_map_entry< " << +                  char_type << " >" << endl +                   << "_xsd_" << name << "_inheritance_map_entry_ (" << endl +                   << name << "::_static_type ()," << endl +                   << fq_name (base) << "::_static_type ());" +                   << endl; +              } +            } +          } + +          if (!(he || ha || same || ret == L"void")) +            return; + +          // Parser callbacks. +          // +          if (!restriction_p (c)) +            names (c, names_parser_callback_); + +          if (same || ret == L"void") +          { +            os << ret << " " << name << "::" << endl +               << post_name (c) << " ()" +               << "{"; + +            if (same) +            { +              SemanticGraph::Type& base (c.inherits ().base ()); + +              if (ret == L"void") +                os << post_name (base) << " ();"; +              else +                os << "return " << post_name (base) << " ();"; +            } + +            os << "}"; +          } + +          // The rest is parsing/validation code which is generated in +          // *-validation-source.cxx. +          // +          if (validation) +            return; + +          // Don't use restriction_p here since we don't want special +          // treatment of anyType. +          // +          bool restriction ( +            c.inherits_p () && +            c.inherits ().is_a<SemanticGraph::Restricts> ()); + +          // _start_element_impl & _end_element_impl +          // +          if (he) +          { +            os << "bool " << name << "::" << endl +               << "_start_element_impl (const " << string_type << "& ns," << endl +               << "const " << string_type << "& n," << endl +               << "const " << string_type << "* t)" +               << "{" +               << "XSD_UNUSED (t);" +               << endl; + +            if (!restriction) +            { +              os << "if (this->"; + +              if (c.inherits_p ()) +                os << fq_name (c.inherits ().base ()); +              else +                os << complex_base; + +              os << "::_start_element_impl (ns, n, t))" << endl +                 << "return true;" +                 << endl; +            } + +            names (c, names_start_element_); + +            os << "return false;" +               << "}"; + + +            // _end_element_impl +            // +            os << "bool " << name << "::" << endl +               << "_end_element_impl (const " << string_type << "& ns," << endl +               << "const " << string_type << "& n)" +               << "{"; + +            if (!restriction) +            { +              os << "if (this->"; + +              if (c.inherits_p () && !restriction) +                os << fq_name (c.inherits ().base ()); +              else +                os << complex_base; + +              os << "::_end_element_impl (ns, n))" << endl +                 << "return true;" +                 << endl; +            } + +            names (c, names_end_element_); + +            os << "return false;" +               << "}"; +          } + + +          if (ha) +          { +            // _attribute_impl +            // +            os << "bool " << name << "::" << endl +               << "_attribute_impl (const " << string_type << "& ns," << endl +               << "const " << string_type << "& n," << endl +               << "const " << string_type << "& v)" +               << "{"; + +            if (!restriction) +            { +              os << "if (this->"; + +              if (c.inherits_p ()) +                os << fq_name (c.inherits ().base ()); +              else +                os << complex_base; + +              os << "::_attribute_impl (ns, n, v))" << endl +                 << "return true;" +                 << endl; +            } + +            names (c, names_attribute_); + +            os << "return false;" +               << "}"; +          } +        } + +      private: +        // +        // +        ParserCallback parser_callback_; +        Traversal::Names names_parser_callback_; + +        // +        // +        StartElement start_element_; +        Traversal::Names names_start_element_; + +        // +        // +        EndElement end_element_; +        Traversal::Names names_end_element_; + +        // +        // +        Attribute attribute_; +        Traversal::Names names_attribute_; +      }; + + +      // Generate substitution group map entries. +      // +      struct GlobalElement: Traversal::Element, Context +      { +        GlobalElement (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (e.substitutes_p ()) +          { +            String name (escape (e.name ())); +            Type& r (e.substitutes ().root ()); + +            SemanticGraph::Type& type (e.type ()); + +            os << "// Substitution map entry for " << comment (e.name ()) << "." << endl +               << "//" << endl +               << "static" << endl +               << "const ::xsd::cxx::parser::substitution_map_entry< " << +              char_type << " >" << endl +               << "_xsd_" << name << "_substitution_map_entry_ (" << endl +               << strlit (e.namespace_ ().name ()) << "," << endl +               << strlit (e.name ()) << "," << endl +               << strlit (r.namespace_ ().name ()) << "," << endl +               << strlit (r.name ()) << "," << endl +               << fq_name (type) << "::_static_type ());" +               << endl; +          } +        } +      }; +    } + +    void +    generate_parser_source (Context& ctx) +    { +      if (ctx.polymorphic) +      { +        ctx.os << "#include <xsd/cxx/parser/substitution-map.hxx>" << endl; + +        if (ctx.validation) +          ctx.os << "#include <xsd/cxx/parser/validating/inheritance-map.hxx>" << endl +                 << endl; +        else +          ctx.os << endl; + +        bool import_maps (ctx.options.import_maps ()); +        bool export_maps (ctx.options.export_maps ()); + +        if (import_maps || export_maps) +        { +          ctx.os << "#ifndef XSD_NO_EXPORT" << endl +                 << endl +                 << "namespace xsd" +                 << "{" +                 << "namespace cxx" +                 << "{" +                 << "namespace parser" +                 << "{" +                 << "#ifdef _MSC_VER" << endl; + +          if (export_maps) +            ctx.os << "template struct __declspec (dllexport) " << +              "substitution_map_init< " << ctx.char_type << " >;"; + +          if (import_maps) +            ctx.os << "template struct __declspec (dllimport) " << +              "substitution_map_init< " << ctx.char_type << " >;"; + +          if (ctx.validation && export_maps) +            ctx.os << "template struct __declspec (dllexport) " << +              "inheritance_map_init< " << ctx.char_type << " >;"; + +          if (ctx.validation && import_maps) +            ctx.os << "template struct __declspec (dllimport) " << +              "inheritance_map_init< " << ctx.char_type << " >;"; + +          ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl +                 << "template struct __attribute__ ((visibility(\"default\"))) " << +            "substitution_map_init< " << ctx.char_type << " >;"; + +          if (ctx.validation) +            ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << +              "inheritance_map_init< " << ctx.char_type << " >;"; + +          ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl +                 << "template struct XSD_MAP_VISIBILITY " << +            "substitution_map_init< " << ctx.char_type << " >;"; + +          if (ctx.validation) +            ctx.os << "template struct XSD_MAP_VISIBILITY " << +              "inheritance_map_init< " << ctx.char_type << " >;"; + +          ctx.os << "#endif" << endl +                 << "}"  // parser +                 << "}"  // cxx +                 << "}"  // xsd +                 << "#endif // XSD_NO_EXPORT" << endl +                 << endl; +        } + +        ctx.os << "static" << endl +               << "const ::xsd::cxx::parser::substitution_map_init< " << +          ctx.char_type << " >" << endl +               << "_xsd_substitution_map_init_;" +               << endl; + +        if (ctx.validation) +        { +          ctx.os << "static" << endl +                 << "const ::xsd::cxx::parser::validating::inheritance_map_init< " << +            ctx.char_type << " >" << endl +                 << "_xsd_inheritance_map_init_;" +                 << endl; +        } +      } + +      // Emit "weak" header includes that are used in the file-per-type +      // compilation model. +      // +      if (ctx.options.generate_inline ()) +      { +        Traversal::Schema schema; +        Includes includes (ctx, Includes::source); + +        schema >> includes; +        schema.dispatch (ctx.schema_root); +      } + +      Traversal::Schema schema; +      Sources sources; +      Traversal::Names schema_names; + +      Namespace ns (ctx); +      Traversal::Names names; + +      schema >> sources >> schema; +      schema >> schema_names >> ns >> names; + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); +      GlobalElement global_element (ctx); + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      if (ctx.polymorphic) +        names >> global_element; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/parser/parser-source.hxx b/xsd/cxx/parser/parser-source.hxx new file mode 100644 index 0000000..3598a00 --- /dev/null +++ b/xsd/cxx/parser/parser-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/parser/parser-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_PARSER_SOURCE_HXX +#define XSD_CXX_PARSER_PARSER_SOURCE_HXX + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    void +    generate_parser_source (Context&); +  } +} + +#endif  // XSD_CXX_PARSER_PARSER_SOURCE_HXX diff --git a/xsd/cxx/parser/print-impl-common.hxx b/xsd/cxx/parser/print-impl-common.hxx new file mode 100644 index 0000000..14bfbc2 --- /dev/null +++ b/xsd/cxx/parser/print-impl-common.hxx @@ -0,0 +1,641 @@ +// file      : xsd/cxx/parser/print-impl-common.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_PRINT_IMPL_COMMON_HXX +#define XSD_CXX_PARSER_PRINT_IMPL_COMMON_HXX + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/parser/elements.hxx> + +namespace CXX +{ +  namespace Parser +  { +    struct PrintCall: Traversal::Type, + +                      Traversal::Fundamental::Boolean, + +                      Traversal::Fundamental::Byte, +                      Traversal::Fundamental::UnsignedByte, +                      Traversal::Fundamental::Short, +                      Traversal::Fundamental::UnsignedShort, +                      Traversal::Fundamental::Int, +                      Traversal::Fundamental::UnsignedInt, +                      Traversal::Fundamental::Long, +                      Traversal::Fundamental::UnsignedLong, +                      Traversal::Fundamental::Integer, +                      Traversal::Fundamental::NonPositiveInteger, +                      Traversal::Fundamental::NonNegativeInteger, +                      Traversal::Fundamental::PositiveInteger, +                      Traversal::Fundamental::NegativeInteger, + +                      Traversal::Fundamental::Float, +                      Traversal::Fundamental::Double, +                      Traversal::Fundamental::Decimal, + +                      Traversal::Fundamental::String, +                      Traversal::Fundamental::NormalizedString, +                      Traversal::Fundamental::Token, +                      Traversal::Fundamental::Name, +                      Traversal::Fundamental::NameToken, +                      Traversal::Fundamental::NameTokens, +                      Traversal::Fundamental::NCName, +                      Traversal::Fundamental::Language, + +                      Traversal::Fundamental::QName, + +                      Traversal::Fundamental::Id, +                      Traversal::Fundamental::IdRef, +                      Traversal::Fundamental::IdRefs, + +                      Traversal::Fundamental::AnyURI, + +                      Traversal::Fundamental::Base64Binary, +                      Traversal::Fundamental::HexBinary, + +                      Traversal::Fundamental::Date, +                      Traversal::Fundamental::DateTime, +                      Traversal::Fundamental::Duration, +                      Traversal::Fundamental::Day, +                      Traversal::Fundamental::Month, +                      Traversal::Fundamental::MonthDay, +                      Traversal::Fundamental::Year, +                      Traversal::Fundamental::YearMonth, +                      Traversal::Fundamental::Time, + +                      Context +    { +      PrintCall (Context& c, String const& tag, String const& arg) +          : Context (c), tag_ (tag), arg_ (arg) +      { +      } + +      virtual void +      traverse (SemanticGraph::Type&) +      { +        gen_user_type (); +      } + +      // Boolean. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Boolean& t) +      { +        if (default_type (t, "bool")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      // Integral types. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Byte& t) +      { +        if (default_type (t, "signed char")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << +            " << static_cast<short> (" << arg_ << ") << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedByte& t) +      { +        if (default_type (t, "unsigned char")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << +            " << static_cast<unsigned short> (" << arg_ << ") << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Short& t) +      { +        if (default_type (t, "short")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedShort& t) +      { +        if (default_type (t, "unsigned short")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Int& t) +      { +        if (default_type (t, "int")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedInt& t) +      { +        if (default_type (t, "unsigned int")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Long& t) +      { +        if (default_type (t, "long long")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedLong& t) +      { +        if (default_type (t, "unsigned long long")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Integer& t) +      { +        if (default_type (t, "long long")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NegativeInteger& t) +      { +        if (default_type (t, "long long")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +      { +        if (default_type (t, "long long")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::PositiveInteger& t) +      { +        if (default_type (t, "unsigned long long")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +      { +        if (default_type (t, "unsigned long long")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      // Floats. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Float& t) +      { +        if (default_type (t, "float")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Double& t) +      { +        if (default_type (t, "double")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Decimal& t) +      { +        if (default_type (t, "double")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      // Strings. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::String& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NormalizedString& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Token& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NameToken& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Name& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NCName& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Language& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Id& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRef& t) +      { +        gen_string (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::AnyURI& t) +      { +        gen_string (t); +      } + +      // String sequences. +      // + +      virtual void +      traverse (SemanticGraph::Fundamental::NameTokens& t) +      { +        gen_sequence (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRefs& t) +      { +        gen_sequence (t); +      } + +      // QName +      // + +      virtual void +      traverse (SemanticGraph::Fundamental::QName& t) +      { +        if (default_type (t, xs_ns_name () + L"::qname")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << ";" +             << endl +             << "if (" << arg_ << ".prefix ().empty ())" << endl +             << cout_inst << " << " << arg_ << ".name ();" +             << "else" << endl +             << cout_inst << " << " << arg_ << ".prefix () << " << L << +            "':' << " << arg_ << ".name ();" +             << endl +             << cout_inst << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      // Binary. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Base64Binary& t) +      { +        gen_buffer (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::HexBinary& t) +      { +        gen_buffer (t); +      } + +      // Date/time. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Date& t) +      { +        if (default_type (t, xs_ns_name () + L"::date")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << endl +             << " << " << arg_ << ".year () << '-'" << endl +             << " << " << arg_ << ".month () << '-'" << endl +             << " << " << arg_ << ".day ();"; + +          gen_time_zone (); +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::DateTime& t) +      { +        if (default_type (t, xs_ns_name () + L"::date_time")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << endl +             << " << " << arg_ << ".year () << '-'" << endl +             << " << " << arg_ << ".month () << '-'" << endl +             << " << " << arg_ << ".day () << 'T'" << endl +             << " << " << arg_ << ".hours () << ':'" << endl +             << " << " << arg_ << ".minutes () << ':'" << endl +             << " << " << arg_ << ".seconds ();"; + +          gen_time_zone (); +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Duration& t) +      { +        if (default_type (t, xs_ns_name () + L"::duration")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << ";" +             << endl +             << "if (" << arg_ << ".negative ())" << endl +             << cout_inst << " << '-';" +             << endl +             << cout_inst << " << 'P'" << endl +             << " << " << arg_ << ".years () << 'Y'" << endl +             << " << " << arg_ << ".months () << 'M'" << endl +             << " << " << arg_ << ".days () << " << L << "\"DT\"" << endl +             << " << " << arg_ << ".hours () << 'H'" << endl +             << " << " << arg_ << ".minutes () << 'M'" << endl +             << " << " << arg_ << ".seconds () << 'S'" +             << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Day& t) +      { +        if (default_type (t, xs_ns_name () + L"::gday")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ---") << +            " << " << arg_ << ".day ();"; + +          gen_time_zone (); +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Month& t) +      { +        if (default_type (t, xs_ns_name () + L"::gmonth")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": --") << +            " << " << arg_ << ".month ();"; + +          gen_time_zone (); +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::MonthDay& t) +      { +        if (default_type (t, xs_ns_name () + L"::gmonth_day")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": --") << endl +             << " << " << arg_ << ".month () << '-'" << endl +             << " << " << arg_ << ".day ();"; + +          gen_time_zone (); +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Year& t) +      { +        if (default_type (t, xs_ns_name () + L"::gyear")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << ".year ();"; + +          gen_time_zone (); +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::YearMonth& t) +      { +        if (default_type (t, xs_ns_name () + L"::gyear_month")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << endl +             << " << " << arg_ << ".year () << '-'" << endl +             << " << " << arg_ << ".month ();"; + +          gen_time_zone (); +        } +        else +          gen_user_type (); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Time& t) +      { +        if (default_type (t, xs_ns_name () + L"::time")) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << endl +             << " << " << arg_ << ".hours () << ':'" << endl +             << " << " << arg_ << ".minutes () << ':'" << endl +             << " << " << arg_ << ".seconds ();"; + +          gen_time_zone (); +        } +        else +          gen_user_type (); +      } + +    private: +      bool +      default_type (SemanticGraph::Type& t, String const& def_type) +      { +        return ret_type (t) == def_type; +      } + +      void +      gen_user_type () +      { +        os << "// TODO" << endl +           << "//" << endl; +      } + +      void +      gen_string (SemanticGraph::Type& t) +      { +        if ((char_type == L"char" && default_type (t, "::std::string")) || +            (char_type == L"wchar_t" && default_type (t, "::std::wstring"))) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " << +            arg_ << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      void +      gen_sequence (SemanticGraph::Type& t) +      { +        String type (xs_ns_name () + L"::string_sequence"); + +        if (default_type (t, type)) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << ";" +             << endl; + +          os << "for (" << type << "::const_iterator i (" << arg_ << +            ".begin ()), e (" << arg_ << ".end ());" << endl +             << "i != e;)" +             << "{" +             << cout_inst << " << *i++;" +             << "if (i != e)" << endl +             << cout_inst << " << ' ';" +             << "}" +             << cout_inst << " << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      void +      gen_buffer (SemanticGraph::Type& t) +      { +        String type (auto_ptr + L"< " + xs_ns_name () + L"::buffer >"); + +        if (default_type (t, type)) +        { +          os << cout_inst << " << " << strlit (tag_ + L": ") << " << " +             << arg_ << "->size () << " << L << "\" bytes\" << std::endl;"; +        } +        else +          gen_user_type (); +      } + +      void +      gen_time_zone () +      { +        os << endl +           << "if (" << arg_ << ".zone_present ())" +           << "{" +           << "if (" << arg_ << ".zone_hours () < 0)" << endl +           << cout_inst << " << " << arg_ << ".zone_hours () << ':' << -" << +          arg_ << ".zone_minutes ();" +           << "else" << endl +           << cout_inst << " << '+' << " << arg_ << ".zone_hours () << " << +          "':' << " << arg_ << ".zone_minutes ();"; + +        os << "}" +           << cout_inst << " << std::endl;"; +      } + +    private: +      String tag_; +      String arg_; +    }; +  } +} + +#endif // XSD_CXX_PARSER_PRINT_IMPL_COMMON_HXX diff --git a/xsd/cxx/parser/state-processor.cxx b/xsd/cxx/parser/state-processor.cxx new file mode 100644 index 0000000..a2b8fbf --- /dev/null +++ b/xsd/cxx/parser/state-processor.cxx @@ -0,0 +1,319 @@ +// file      : xsd/cxx/parser/state-processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <vector> +#include <iostream> + +#include <xsd/cxx/parser/state-processor.hxx> + +#include <xsd/cxx/parser/elements.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      typedef vector<SemanticGraph::Particle*> Particles; + +      /* +      void +      print (Particles const& p) +      { +        using std::wcerr; +        using std::endl; + +        wcerr << "prefixes: " << endl; + +        for (Particles::const_iterator i (p.begin ()); i != p.end (); ++i) +        { +          if (SemanticGraph::Element* e = +              dynamic_cast<SemanticGraph::Element*> (*i)) +          { +            wcerr << e->name () << endl; +          } +          else +          { +            wcerr << "<any>" << endl; +          } +        } + +        wcerr << endl; +      } +      */ + +      // +      // +      struct Particle: Traversal::All, +                       Traversal::Choice, +                       Traversal::Sequence +      { +        Particle (size_t& all, +                  size_t& choice, +                  size_t& sequence, +                  size_t& depth) +            : all_ (all), +              choice_ (choice), +              sequence_ (sequence), +              depth_ (depth) +        { +        } + +        virtual void +        traverse (SemanticGraph::All& a) +        { +          using SemanticGraph::Compositor; + +          // Go over particles, collecting "prefix" particles in prefixes_, +          // assigning state numbers and calculating effective minOccurs. +          // If all prefixes of this compositor have minOccurs = 0, then +          // the compositor itself effectively has minOccurs = 0 regardless +          // of the actual value specified in the schema. +          // +          // Note that we don't need to care about depth since the 'all' +          // compositor cannot contain any nested compositors. +          // + +          size_t state (0); +          size_t min (0); + +          for (Compositor::ContainsIterator ci (a.contains_begin ()); +               ci != a.contains_end (); ++ci) +          { +            SemanticGraph::Particle& p (ci->particle ()); + +            // The 'all' compositor can only include elements. +            // +            prefixes_.push_back (&p); + +            if (min == 0 && ci->min () != 0) +              min = 1; + +            p.context ().set ("prefix", true); +            p.context ().set ("state", state++); +          } + +          if (!prefixes_.empty ()) +          { +            a.context ().set ("comp-number", choice_++); +            a.context ().set ("prefixes", prefixes_); +            a.context ().set ("state-count", size_t (prefixes_.size ())); + +            // effective-min = min * actual-min +            // +            if (min == 1) +              min = a.min (); + +            a.context ().set ("effective-min", min); + +            // print (prefixes_); +          } +        } + +        virtual void +        traverse (SemanticGraph::Choice& c) +        { +          using SemanticGraph::Compositor; + +          // Go over particles, collecting "prefix" particles in prefixes_, +          // assigning state numbers and calculating effective minOccurs. +          // If any prefix of this compositor have minOccurs = 0, then the +          // compositor itself effectively has minOccurs = 0 regardless of +          // the actual value specified in the schema. +          // + +          size_t state (0); +          size_t min (1); + +          for (Compositor::ContainsIterator ci (c.contains_begin ()); +               ci != c.contains_end (); ++ci) +          { +            SemanticGraph::Particle& p (ci->particle ()); + +            if (p.is_a<SemanticGraph::Element> () || +                p.is_a<SemanticGraph::Any> ()) +            { +              prefixes_.push_back (&p); + +              if (min == 1 && ci->min () == 0) +                min = 0; +            } +            else +            { +              size_t depth (0); +              Particle t (all_, choice_, sequence_, depth); +              t.dispatch (p); + +              if (t.prefixes_.empty ()) +                continue; // Skip empty compositors. + +              if (++depth > depth_) // One for this compositor. +                depth_ = depth; + +              prefixes_.insert (prefixes_.end (), +                                t.prefixes_.begin (), +                                t.prefixes_.end ()); + +              if (min == 1 && +                  p.context ().get<size_t> ("effective-min") == 0) +                min = 0; +            } + +            p.context ().set ("prefix", true); +            p.context ().set ("state", state++); +          } + +          if (!prefixes_.empty ()) +          { +            c.context ().set ("comp-number", choice_++); +            c.context ().set ("prefixes", prefixes_); + +            // effective-min = min * actual-min +            // +            if (min == 1) +              min = c.min (); + +            c.context ().set ("effective-min", min); + +            // print (prefixes_); +          } +        } + +        virtual void +        traverse (SemanticGraph::Sequence& s) +        { +          using SemanticGraph::Compositor; + +          // Go over particles, collecting "prefix" particles in prefixes_, +          // assigning state numbers and calculating effective minOccurs. +          // If all prefixes of this compositor have minOccurs = 0, then +          // the compositor itself effectively has minOccurs = 0 regardless +          // of the actual value specified in the schema. +          // + +          bool prefix (true); +          size_t state (0); +          size_t min (0); + +          for (Compositor::ContainsIterator ci (s.contains_begin ()); +               ci != s.contains_end (); ++ci) +          { +            SemanticGraph::Particle& p (ci->particle ()); + +            if (p.is_a<SemanticGraph::Element> () || +                p.is_a<SemanticGraph::Any> ()) +            { +              if (prefix) +              { +                prefixes_.push_back (&p); + +                if (ci->min () != 0) +                  min = 1; +              } +            } +            else +            { +              size_t depth (0); +              Particle t (all_, choice_, sequence_, depth); +              t.dispatch (p); + +              if (t.prefixes_.empty ()) +                continue; // Skip empty compositors. + +              if (++depth > depth_) // One for this compositor. +                depth_ = depth; + +              if (prefix) +              { +                prefixes_.insert (prefixes_.end (), +                                  t.prefixes_.begin (), +                                  t.prefixes_.end ()); + +                if (p.context ().get<size_t> ("effective-min") != 0) +                  min = 1; +              } +            } + +            p.context ().set ("state", state++); + +            if (prefix) +              p.context ().set ("prefix", true); + +            if (prefix && min != 0) +              prefix = false; +          } + +          if (!prefixes_.empty ()) +          { +            s.context ().set ("comp-number", sequence_++); +            s.context ().set ("prefixes", prefixes_); + +            // effective-min = min * actual-min +            // +            if (min == 1) +              min = s.min (); + +            s.context ().set ("effective-min", min); + +            // print (prefixes_); +          } +        } + +      private: +        Particles prefixes_; + +        size_t& all_; +        size_t& choice_; +        size_t& sequence_; + +        size_t& depth_; +      }; + + +      // +      // +      struct Complex: Traversal::Complex +      { +        virtual void +        traverse (Type& c) +        { +          if (c.contains_compositor_p ()) +          { +            size_t all (0), choice (0), sequence (0), depth (0); +            Particle t (all, choice, sequence, depth); +            t.dispatch (c.contains_compositor ().compositor ()); + +            // Set the maximum stack depth for this type. Used to +            // allocate fixed-size state stack. +            // +            c.context ().set ("depth", depth + 1); +          } +        } +      }; +    } + +    void StateProcessor:: +    process (SemanticGraph::Schema& tu, SemanticGraph::Path const&) +    { +      Traversal::Schema schema; +      Sources sources; +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; + +      schema >> sources >> schema; +      schema >> schema_names >> ns >> ns_names; + +      Complex complex_type; + +      ns_names >> complex_type; + +      schema.dispatch (tu); +    } +  } +} diff --git a/xsd/cxx/parser/state-processor.hxx b/xsd/cxx/parser/state-processor.hxx new file mode 100644 index 0000000..eacc14a --- /dev/null +++ b/xsd/cxx/parser/state-processor.hxx @@ -0,0 +1,25 @@ +// file      : xsd/cxx/parser/state-processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_STATE_PROCESSOR_HXX +#define XSD_CXX_PARSER_STATE_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph.hxx> + +#include <xsd/types.hxx> + +namespace CXX +{ +  namespace Parser +  { +    class StateProcessor +    { +    public: +      void +      process (XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file); +    }; +  } +} + +#endif // XSD_CXX_PARSER_STATE_PROCESSOR_HXX diff --git a/xsd/cxx/parser/type-processor.cxx b/xsd/cxx/parser/type-processor.cxx new file mode 100644 index 0000000..6496b2a --- /dev/null +++ b/xsd/cxx/parser/type-processor.cxx @@ -0,0 +1,347 @@ +// file      : xsd/cxx/parser/type-processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> + +#include <xsd/cxx/parser/elements.hxx> +#include <xsd/cxx/parser/type-processor.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      // +      // +      struct Type: Traversal::Type +      { +        Type (SemanticGraph::Schema& schema, +              TypeMap::Namespaces& type_map, +              bool add_includes) +            : schema_ (schema), +              type_map_ (type_map), +              add_includes_ (add_includes) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& type) +        { +          using TypeMap::Namespace; +          using TypeMap::Namespaces; + +          SemanticGraph::Context& tc (type.context ()); + +          // There are two situations where we may try to process the +          // same type more than once. The first is when the type is +          // used in several element declarations in the same schema. +          // The second situation only occurs when we are in the file- +          // per-type mode. In this case the type was processed as part +          // of another root schema. In the second case, while the ret +          // and arg types are assumed to be the same, we need to re- +          // match the type in order to add include directives to the +          // new root schema. +          // +          bool set (true); + +          if (tc.count ("ret-type")) +          { +            SemanticGraph::Schema* s ( +              tc.get<SemanticGraph::Schema*> ("root-schema")); + +            if (&schema_ == s) +              return; + +            set = false; +          } + +          SemanticGraph::Namespace& ns ( +            dynamic_cast<SemanticGraph::Namespace&> (type.scope ())); + +          String ns_name (ns.name ()); +          String t_name (type.name ()); + +          //std::wcerr << "traversing: " << ns_name << "#" << t_name << endl; + +          for (Namespaces::const_iterator n (type_map_.begin ()); +               n != type_map_.end (); ++n) +          { +            // Check if the namespace matches. +            // +            bool ns_match; + +            if (!n->xsd_name ().empty ()) +            { +              ns_match = n->xsd_name ().match (ns_name); +            } +            else +              ns_match = ns_name.empty (); + +            //std::wcerr << "considering ns expr: " << n->xsd_name () +            //           << " for " << ns_name +            //           << ": " << (ns_match ? "+" : "-") << endl; + +            if (ns_match) +            { +              // Namespace matched. See if there is a type that matches. +              // +              for (Namespace::TypesIterator t (n->types_begin ()); +                   t != n->types_end (); ++t) +              { +                if (t->xsd_name ().match (t_name)) +                { +                  if (set) +                  { +                    // Got a match. See if the namespace has the C++ +                    // namespace mapping. +                    // +                    String cxx_ns; + +                    if (n->has_cxx_name ()) +                    { +                      if (!n->xsd_name ().empty ()) +                      { +                        cxx_ns = n->xsd_name ().replace ( +                          ns_name, n->cxx_name (), true); +                      } +                      else +                        cxx_ns = n->cxx_name (); + +                      cxx_ns += L"::"; +                    } + +                    // Figure out ret and arg type names. +                    // +                    String ret_type (cxx_ns); + +                    ret_type += t->xsd_name ().replace ( +                      t_name, t->cxx_ret_name (), true); + +                    String arg_type; + +                    if (t->cxx_arg_name ()) +                    { +                      arg_type = cxx_ns; +                      arg_type += t->xsd_name ().replace ( +                        t_name, t->cxx_arg_name (), true); +                    } +                    else +                    { +                      if (ret_type == L"void") +                        arg_type = ret_type; +                      else +                      { +                        wchar_t last (ret_type[ret_type.size () - 1]); + +                        // If it is already a pointer or reference then use +                        // it as is. +                        // +                        if (last == L'*' || last == L'&') +                          arg_type = ret_type; +                        else +                          arg_type = L"const " + ret_type + L"&"; +                      } +                    } + +                    tc.set ("ret-type", ret_type); +                    tc.set ("arg-type", arg_type); + +                    //std::wcerr << t_name << " -> " << ret_type << endl; +                  } + +                  tc.set ("root-schema", &schema_); + +                  // See of we need to add any includes to the translations +                  // unit. +                  // +                  if (add_includes_) +                  { +                    if (n->includes_begin () != n->includes_end ()) +                    { +                      typedef std::set<String> Includes; + +                      if (!schema_.context ().count ("includes")) +                        schema_.context ().set ("includes", Includes ()); + +                      Includes& is ( +                        schema_.context ().get<Includes> ("includes")); + +                      for (Namespace::IncludesIterator i (n->includes_begin ()); +                           i != n->includes_end (); ++i) +                      { +                        is.insert (*i); +                      } +                    } +                  } + +                  return; +                } +              } +            } +          } +        } + +      private: +        SemanticGraph::Schema& schema_; +        TypeMap::Namespaces& type_map_; +        bool add_includes_; +      }; + + +      // +      // +      struct GlobalType: Traversal::Type, +                         Traversal::List, +                         Traversal::Complex, +                         Traversal::Enumeration +      { +        GlobalType (SemanticGraph::Schema& schema, +                    TypeMap::Namespaces& type_map, +                    bool add_includes) +            : type_ (schema, type_map, add_includes) +        { +          inherits_ >> type_; +          names_ >> instance_ >> belongs_ >> type_; +          argumented_ >> type_; +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          type_.traverse (t); +        } + +        virtual void +        traverse (SemanticGraph::List& l) +        { +          type_.traverse (l); +          Traversal::List::argumented (l, argumented_); +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          type_.traverse (c); +          Complex::inherits (c, inherits_); +          Complex::names (c, names_); +        } + +        virtual void +        traverse (SemanticGraph::Enumeration& e) +        { +          type_.traverse (e); +          Complex::inherits (e, inherits_); +        } + +      private: +        Parser::Type type_; +        Traversal::Names names_; +        Traversal::Instance instance_; +        Traversal::Inherits inherits_; +        Traversal::Belongs belongs_; +        Traversal::Argumented argumented_; +      }; + +      void +      process_impl (options const& ops, +                    XSDFrontend::SemanticGraph::Schema& tu, +                    bool gen_driver, +                    TypeMap::Namespaces& type_map) +      { +        if (tu.names_begin ()->named ().name () == +            L"http://www.w3.org/2001/XMLSchema") +        { +          // XML Schema namespace. +          // +          Traversal::Schema schema; + +          Traversal::Names schema_names; +          Traversal::Namespace ns; +          Traversal::Names ns_names; +          GlobalType global_type (tu, type_map, true); + +          schema >> schema_names >> ns >> ns_names >> global_type; + +          schema.dispatch (tu); +        } +        else +        { +          // If --extern-xml-schema is specified, then we don't want +          // includes from the XML Schema type map. +          // +          bool extern_xml_schema (ops.extern_xml_schema ()); + +          // +          // +          Traversal::Schema schema; +          Traversal::Schema xs_schema; +          Sources sources; +          Traversal::Implies implies; + +          schema >> sources >> schema; +          schema >> implies >> xs_schema; + +          Traversal::Names schema_names; +          Traversal::Namespace ns; +          Traversal::Names ns_names; +          GlobalType global_type (tu, type_map, true); + +          schema >> schema_names >> ns >> ns_names >> global_type; + +          Traversal::Names xs_schema_names; +          Traversal::Namespace xs_ns; +          Traversal::Names xs_ns_names; +          GlobalType xs_global_type (tu, type_map, !extern_xml_schema); + +          xs_schema >> xs_schema_names >> xs_ns >> xs_ns_names >> +            xs_global_type; + +          schema.dispatch (tu); + +          // If we are generating the test driver, make sure the root +          // element type is processed. +          // +          if (gen_driver && ops.generate_test_driver ()) +          { +            // Figure out the root element. Validator should have made sure +            // it is unique. +            // +            SemanticGraph::Element* root (0); +            { +              Traversal::Schema schema; +              Sources sources; + +              schema >> sources >> schema; + +              Traversal::Names schema_names; +              Traversal::Namespace ns; +              Traversal::Names ns_names; +              RootElement root_element (ops, root); + +              schema >> schema_names >> ns >> ns_names >> root_element; + +              schema.dispatch (tu); +            } + +            global_type.dispatch (root->type ()); +          } +        } +      } +    } + +    void TypeProcessor:: +    process (options const& ops, +             XSDFrontend::SemanticGraph::Schema& s, +             bool gen_driver, +             TypeMap::Namespaces& tm) +    { +      process_impl (ops, s, gen_driver, tm); +    } +  } +} diff --git a/xsd/cxx/parser/type-processor.hxx b/xsd/cxx/parser/type-processor.hxx new file mode 100644 index 0000000..6800024 --- /dev/null +++ b/xsd/cxx/parser/type-processor.hxx @@ -0,0 +1,31 @@ +// file      : xsd/cxx/parser/type-processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_TYPE_PROCESSOR_HXX +#define XSD_CXX_PARSER_TYPE_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph.hxx> + +#include <xsd/types.hxx> + +#include <xsd/type-map/type-map.hxx> + +#include <xsd/cxx/parser/options.hxx> + +namespace CXX +{ +  namespace Parser +  { +    class TypeProcessor +    { +    public: +      void +      process (options const&, +               XSDFrontend::SemanticGraph::Schema&, +               bool gen_driver, +               TypeMap::Namespaces&); +    }; +  } +} + +#endif // XSD_CXX_PARSER_TYPE_PROCESSOR_HXX diff --git a/xsd/cxx/parser/validator.cxx b/xsd/cxx/parser/validator.cxx new file mode 100644 index 0000000..8e8161a --- /dev/null +++ b/xsd/cxx/parser/validator.cxx @@ -0,0 +1,723 @@ +// file      : xsd/cxx/parser/validator.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <iostream> + +#include <xsd/cxx/parser/validator.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/parser/elements.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Parser +  { +    namespace +    { +      class ValidationContext: public Context +      { +      public: +        ValidationContext (SemanticGraph::Schema& root, +                           SemanticGraph::Path const& path, +                           Parser::options const& ops, +                           const WarningSet& disabled_warnings, +                           bool& valid_) +            : Context (std::wcerr, root, path, ops, 0, 0, 0, 0), +              disabled_warnings_ (disabled_warnings), +              disabled_warnings_all_ (false), +              valid (valid_), +              subst_group_warning_issued (subst_group_warning_issued_), +              subst_group_warning_issued_ (false) +        { +        } + +      public: +        bool +        is_disabled (char const* w) +        { +          return disabled_warnings_all_ || +            disabled_warnings_.find (w) != disabled_warnings_.end (); +        } + +      public: +        String +        xpath (SemanticGraph::Nameable& n) +        { +          if (n.is_a<SemanticGraph::Namespace> ()) +            return L"<namespace-level>"; // There is a bug if you see this. + +          assert (n.named_p ()); + +          SemanticGraph::Scope& scope (n.scope ()); + +          if (scope.is_a<SemanticGraph::Namespace> ()) +            return n.name (); + +          return xpath (scope) + L"/" + n.name (); +        } + +      protected: +        ValidationContext (ValidationContext& c) +            :  Context (c), +               disabled_warnings_ (c.disabled_warnings_), +               disabled_warnings_all_ (c.disabled_warnings_all_), +               valid (c.valid), +               subst_group_warning_issued (c.subst_group_warning_issued) +        { +        } + +      protected: +        const WarningSet& disabled_warnings_; +        bool disabled_warnings_all_; +        bool& valid; +        bool& subst_group_warning_issued; +        bool subst_group_warning_issued_; +      }; + +      // +      // +      struct Any: Traversal::Any, ValidationContext +      { +        Any (ValidationContext& c) +            : ValidationContext (c) +        { +        } + +        struct Element: Traversal::Element, ValidationContext +        { +          Element (ValidationContext& c, SemanticGraph::Any& any) +              : ValidationContext (c), +                any_ (any), +                ns_ (any.definition_namespace ().name ()) +          { +          } + +          virtual void +          traverse (SemanticGraph::Element& e) +          { +	    if (skip (e)) return; + +            using SemanticGraph::Any; + +            bool q (e.qualified_p ()); +            String ns (q ? e.namespace_ ().name () : ""); + +            for (Any::NamespaceIterator i (any_.namespace_begin ()); +                 i != any_.namespace_end (); ++i) +            { +              bool failed (false); + +              if (*i == L"##any") +              { +                failed = true; +              } +              else if (*i == L"##other") +              { +                if (ns_) +                { +                  // Note that here I assume that ##other does not +                  // include names without target namespace. This +                  // is not what the spec says but that seems to be +                  // the consensus. +                  // +                  failed = q && ns != ns_; +                } +                else +                { +                  // No target namespace. +                  // +                  failed = q && ns != L""; +                } +              } +              else if (*i == L"##local") +              { +                failed = !q || ns == L""; +              } +              else if (*i == L"##targetNamespace") +              { +                failed = (q && ns_ == ns) || (!q && ns_ == L""); +              } +              else +              { +                failed = q && *i == ns; +              } + +              if (failed) +              { +                Any& a (any_); + +                os << a.file () << ":" << a.line () << ":" << a.column () +                   << ": warning P001: namespace '" << *i << "' allows for " +                   << "element '" << e.name () << "'" << endl; + +                os << a.file () << ":" << a.line () << ":" << a.column () +                   << ": warning P001: generated code may not associate element '" +                   << e.name () << "' correctly if it appears in place of " +                   << "this wildcard" << endl; + +                os << e.file () << ":" << e.line () << ":" << e.column () +                   << ": info: element '" << e.name () << "' is defined " +                   << "here" << endl; + +                os << a.file () << ":" << a.line () << ":" << a.column () +                   << ": info: turn on validation to ensure correct " +                   << "association" << endl; +              } +            } +          } + +        private: +          SemanticGraph::Any& any_; +          String ns_; +        }; + +        struct Complex: Traversal::Complex +        { +          Complex () +              : up_ (true), down_ (true) +          { +          } + +          virtual void +          post (Type& c) +          { +            // Go down the inheritance hierarchy. +            // +            if (down_) +            { +              bool up = up_; +              up_ = false; + +              if (c.inherits_p ()) +                dispatch (c.inherits ().base ()); + +              up_ = up; +            } + +            // Go up the inheritance hierarchy. +            // +            if (up_) +            { +              bool down = down_; +              down_ = false; + +              for (Type::BegetsIterator i (c.begets_begin ()); +                   i != c.begets_end (); ++i) +              { +                dispatch (i->derived ()); +              } + +              down_ = down; +            } +          } + +        private: +          bool up_, down_; +        }; + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          using SemanticGraph::Compositor; + +          // Find our complex type. +          // +          Compositor* c (&a.contained_particle ().compositor ()); + +          while(!c->contained_compositor_p ()) +            c = &c->contained_particle ().compositor (); + +          SemanticGraph::Complex& type ( +            dynamic_cast<SemanticGraph::Complex&> ( +              c->contained_compositor ().container ())); + +          Complex complex; +          Traversal::Names names; +          Element element (*this, a); + +          complex >> names >> element; + +          complex.dispatch (type); +        } +      }; + + +      // +      // +      struct Traverser: Traversal::Schema, +                        Traversal::Complex, +                        Traversal::Type, +                        Traversal::Element, +                        ValidationContext +      { +        using Schema::traverse; + +        Traverser (ValidationContext& c) +            : ValidationContext (c), +              any_ (c) +        { +          *this >> sources_ >> *this; +          *this >> schema_names_ >> ns_ >> names_ >> *this; + +          // Any +          // +          if (!validation && !is_disabled ("P001")) +          { +            *this >> contains_compositor_ >> compositor_ >> contains_particle_; +            contains_particle_ >> compositor_; +            contains_particle_ >> any_; +          } +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          using SemanticGraph::Schema; + +          traverse (static_cast<SemanticGraph::Type&> (c)); + +          if (c.inherits_p ()) +          { +            SemanticGraph::Type& t (c.inherits ().base ()); + +            if (t.named_p () && +                types_.find ( +                  t.scope ().name () + L"#" + t.name ()) == types_.end ()) +            { +              // Don't worry about types that are in included/imported +              // schemas. +              // +              Schema& s (dynamic_cast<Schema&> (t.scope ().scope ())); + +              if (&s == &schema_root || sources_p (schema_root, s)) +              { +                valid = false; + +                wcerr << c.file () << ":" << c.line () << ":" << c.column () +                      << ": error: type '" << xpath (c) << "' inherits from " +                      << "yet undefined type '" << xpath (t) << "'" << endl; + +                wcerr << t.file () << ":" << t.line () << ":" << t.column () +                      << ": info: '" << xpath (t) << "' is defined here" +                      << endl; + +                wcerr << c.file () << ":" << c.line () << ":" << c.column () +                      << ": info: inheritance from a yet-undefined type is " +                      << "not supported" << endl; + +                wcerr << c.file () << ":" << c.line () << ":" << c.column () +                      << ": info: re-arrange your schema and try again" +                      << endl; +              } +            } +          } + +          Complex::traverse (c); +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          if (t.named_p ()) +          { +            types_.insert (t.scope ().name () + L"#" + t.name ()); +          } +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          if (is_disabled ("P002")) +            return; + +          if (e.substitutes_p () && +              !options.generate_polymorphic () && +              !subst_group_warning_issued) +          { +            subst_group_warning_issued = true; + +            os << e.file () << ":" << e.line () << ":" << e.column () +               << ": warning P002: substitution groups are used but " +               << "--generate-polymorphic was not specified" << endl; + +            os << e.file () << ":" << e.line () << ":" << e.column () +               << ": info: generated code may not be able to parse " +               << "some conforming instances" << endl; +          } +        } + +        // Return true if root sources s. +        // +        bool +        sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) +        { +          using SemanticGraph::Schema; +          using SemanticGraph::Sources; + +          for (Schema::UsesIterator i (root.uses_begin ()); +               i != root.uses_end (); ++i) +          { +            if (i->is_a<Sources> ()) +            { +              if (&i->schema () == &s || sources_p (i->schema (), s)) +                return true; +            } +          } + +          return false; +        } + +      private: +        set<String> types_; + +        Sources sources_; + +        Traversal::Names schema_names_; +        Traversal::Namespace ns_; + +        Traversal::Names names_; + +        // Any. +        // +        Any any_; +        Traversal::Compositor compositor_; +        Traversal::ContainsParticle contains_particle_; +        Traversal::ContainsCompositor contains_compositor_; +      }; + + +      struct AnonymousType: Traversal::Schema, +                            Traversal::Complex, +                            Traversal::Element, +                            Traversal::Attribute, +                            ValidationContext +      { +        using Schema::traverse; +        using Complex::traverse; + +        AnonymousType (ValidationContext& c) +            : ValidationContext (c), +              anonymous_error_issued_ (false) +        { +          *this >> sources_ >> *this; +          *this >> schema_names_ >> ns_ >> names_ >> *this; +          *this >> names_; +        } + +        bool +        traverse_common (SemanticGraph::Member& m) +        { +          SemanticGraph::Type& t (m.type ()); + +          if (!t.named_p () +              && !t.is_a<SemanticGraph::Fundamental::IdRef> () +              && !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +          { +            if (!anonymous_error_issued_) +            { +              valid = false; +              anonymous_error_issued_ = true; + +              wcerr << t.file () +                    << ": error: anonymous types detected" +                    << endl; + +              wcerr << t.file () +                    << ": info: " +                    << "anonymous types are not supported in this mapping" +                    << endl; + +              wcerr << t.file () +                    << ": info: consider explicitly naming these types or " +                    << "remove the --preserve-anonymous option to " +                    << "automatically name them" +                    << endl; + +              if (!options.show_anonymous ()) +                wcerr << t.file () +                      << ": info: use --show-anonymous option to see these " +                      << "types" << endl; +            } + +            return true; +          } + +          return false; +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          if (skip (e)) return; + +          if (traverse_common (e)) +          { +            if (options.show_anonymous ()) +            { +              wcerr << e.file () << ":" << e.line () << ":" << e.column () +                    << ": error: element '" << xpath (e) << "' " +                    << "is of anonymous type" << endl; +            } +          } +          else +            Traversal::Element::traverse (e); +        } + +        virtual void +        traverse (SemanticGraph::Attribute& a) +        { +          if (traverse_common (a)) +          { +            if (options.show_anonymous ()) +            { +              wcerr << a.file () << ":" << a.line () << ":" << a.column () +                    << ": error: attribute '" << xpath (a) << "' " +                    << "is of anonymous type" << endl; +            } +          } +          else +            Traversal::Attribute::traverse (a); +        } + +      private: +        bool anonymous_error_issued_; + +        set<String> types_; + +        Sources sources_; + +        Traversal::Names schema_names_; +        Traversal::Namespace ns_; + +        Traversal::Names names_; +      }; + +      struct GlobalElement: Traversal::Element, ValidationContext +      { +        GlobalElement (ValidationContext& c, SemanticGraph::Element*& element) +            : ValidationContext (c), element_ (element) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (!valid) +            return; + +          if (options.root_element_first ()) +          { +            if (element_ == 0) +              element_ = &e; +          } +          else if (options.root_element_last ()) +          { +            element_ = &e; +          } +          else if (String name = options.root_element ()) +          { +            if (e.name () == name) +              element_ = &e; +          } +          else +          { +            if (element_ == 0) +              element_ = &e; +            else +            { +              wcerr << schema_root.file () << ": error: unable to generate " +                    << "the test driver without a unique document root" +                    << endl; + +              wcerr << schema_root.file () << ": info: use --root-element-* " +                    << "options to specify the document root" << endl; + +              valid = false; +            } +          } +        } + +      private: +        SemanticGraph::Element*& element_; +      }; + +    } + +    bool Validator:: +    validate (options const& ops, +              SemanticGraph::Schema& root, +              SemanticGraph::Path const& path, +              bool gen_driver, +              const WarningSet& disabled_warnings) +    { +      bool valid (true); +      ValidationContext ctx (root, path, ops, disabled_warnings, valid); + +      // +      // +      if (ops.char_type () != "char" && +          ops.char_type () != "wchar_t" && +          !ctx.is_disabled ("P003")) +      { +        wcerr << "warning P003: unknown base character type '" << +          ops.char_type ().c_str () << "'" << endl; +      } + +      // +      // +      if (ops.xml_parser () != "xerces" && +          ops.xml_parser () != "expat" && +          !ctx.is_disabled ("P004")) +      { +        wcerr << "warning P004: unknown underlying XML parser '" << +          ops.xml_parser ().c_str () << "'" << endl; +      } + +      // +      // +      if (ops.xml_parser () == "expat" && +          ops.char_type () == "wchar_t") +      { +        wcerr << "error: using expat with wchar_t is not supported" +              << endl; + +        return false; +      } + +      // +      // +      if (ops.xml_parser () == "expat" && +          !ops.char_encoding ().empty () && +          ops.char_encoding () != "utf8") +      { +        wcerr << "error: using expat with character encoding other than " +              << "utf8 is not supported" +              << endl; + +        return false; +      } + +      // +      // +      if (ops.generate_validation () && ops.suppress_validation ()) +      { +        wcerr << "error: mutually exclusive options specified: " +              << "--generate-validation and --suppress-validation" +              << endl; + +        return false; +      } + +      // +      // +      if (ops.generate_noop_impl () && ops.generate_print_impl ()) +      { +        wcerr << "error: mutually exclusive options specified: " +              << "--generate-noop-impl and --generate-print-impl" +              << endl; + +        return false; +      } + +      // +      // +      { +        bool ref (ops.root_element_first ()); +        bool rel (ops.root_element_last ()); +        bool re (ops.root_element ()); + +        if ((ref && rel) || (ref && re) || (rel && re)) +        { +          wcerr << "error: mutually exclusive options specified: " +                << "--root-element-last, --root-element-first, and " +                << "--root-element" +                << endl; + +          return false; +        } +      } + +      // +      // +      bool import_maps (ops.import_maps ()); +      bool export_maps (ops.export_maps ()); + +      if (import_maps && export_maps) +      { +        wcerr << "error: --import-maps and --export-maps are " +              << "mutually exclusive" << endl; + +        return false; +      } + +      if (import_maps && !ctx.polymorphic) +      { +        wcerr << "error: --import-maps can only be specified together with " +              << "--generate-polymorphic" << endl; + +        return false; +      } + +      if (export_maps && !ctx.polymorphic) +      { +        wcerr << "error: --export-maps can only be specified together with " +              << "--generate-polymorphic" << endl; + +        return false; +      } + +      // Test for anonymout types. +      // +      { +        AnonymousType traverser (ctx); +        traverser.dispatch (root); +      } + + +      // Test the rest. +      // +      if (valid) +      { +        Traverser traverser (ctx); +        traverser.dispatch (root); +      } + +      // Test that the document root is unique. +      // +      if (valid && gen_driver) +      { +        SemanticGraph::Element* element (0); + +        Traversal::Schema schema; +        Sources sources; + +        schema >> sources >> schema; + +        Traversal::Names schema_names; +        Traversal::Namespace ns; +        Traversal::Names ns_names; +        GlobalElement global_element (ctx, element); + +        schema >> schema_names >> ns >> ns_names >> global_element; + +        schema.dispatch (root); + +        if (valid && element == 0) +        { +          wcerr << root.file () << ": error: unable to generate the " +                << "test driver without a global element (document root)" +                << endl; + +          valid = false; +        } +      } + +      return valid; +    } +  } +} diff --git a/xsd/cxx/parser/validator.hxx b/xsd/cxx/parser/validator.hxx new file mode 100644 index 0000000..daffdc8 --- /dev/null +++ b/xsd/cxx/parser/validator.hxx @@ -0,0 +1,30 @@ +// file      : xsd/cxx/parser/validator.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_PARSER_VALIDATOR_HXX +#define XSD_CXX_PARSER_VALIDATOR_HXX + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> + +#include <xsd/cxx/parser/elements.hxx> +#include <xsd/cxx/parser/options.hxx> + +namespace CXX +{ +  namespace Parser +  { +    class Validator +    { +    public: +      bool +      validate (options const&, +                SemanticGraph::Schema&, +                SemanticGraph::Path const& tu, +                bool gen_driver, +                const WarningSet& disabled_warnings); +    }; +  } +} + +#endif  // XSD_CXX_PARSER_VALIDATOR_HXX diff --git a/xsd/cxx/tree/counter.cxx b/xsd/cxx/tree/counter.cxx new file mode 100644 index 0000000..3fee0b1 --- /dev/null +++ b/xsd/cxx/tree/counter.cxx @@ -0,0 +1,265 @@ +// file      : xsd/cxx/tree/counter.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/counter.hxx> + +#include <iostream> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct Member: Traversal::Member +      { +        Member (size_t& complexity) +            : complexity_ (complexity) +        { +        } + +        virtual void +        traverse (Type&) +        { +          complexity_++; +        } + +        size_t& complexity_; +      }; + +      struct Any: Traversal::Any, Traversal::AnyAttribute +      { +        Any (size_t& complexity) +            : complexity_ (complexity) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any&) +        { +          complexity_++; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute&) +        { +          complexity_++; +        } + +        size_t& complexity_; +      }; + +      struct TypeBase: Traversal::List, +                       Traversal::Union, +                       Traversal::Enumeration, +                       Traversal::Complex, +                       Context +      { +        TypeBase (Context& c, size_t& complexity) +            : Context (c), complexity_ (complexity) +        { +        } + +        virtual void +        traverse (SemanticGraph::List&) +        { +          complexity_++; +        } + +        virtual void +        traverse (SemanticGraph::Union&) +        { +          complexity_++; +        } + +        virtual void +        traverse (SemanticGraph::Enumeration& e) +        { +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (e); +          } + +          complexity_ += (string_based ? 1 : 2); +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          complexity_++; // One for the type itself. + +          // Plus some for each member. +          // +          Any any (complexity_); +          Member member (complexity_); +          Traversal::Names names; + +          names >> member; + +          if (options.generate_wildcard ()) +            names >> any; + +          Complex::names (c, names); +        } + +      private: +        size_t& complexity_; +      }; + + +      // +      // +      struct GlobalType: Traversal::Type, Context + +      { +        GlobalType (Context& c, Counts& counts) +            : Context (c), counts_ (counts) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          counts_.global_types++; + +          size_t complexity (0); +          TypeBase type (*this, complexity); +          type.dispatch (t); + +          counts_.complexity_total += complexity; +          counts_.complexity.push_back (complexity); +        } + +      private: +        Counts& counts_; +      }; + +      // +      // +      struct GlobalElement: Traversal::Element, +                            GlobalElementBase, +                            Context +      { +        GlobalElement (Context& c, Counts& counts) +            : GlobalElementBase (c), +              Context (c), +              counts_ (counts), +              last_ (0) +        { +        } + +        ~GlobalElement () +        { +          if (last_ != 0) +          { +            last_->context ().set ("last", true); +            count_last (); +          } +        } + +        virtual void +        traverse (Type& e) +        { +          // Check if the previous element we saw needs to be generated. +          // +          if (last_ != 0) +            count_last (); + +          last_ = &e; + +          if (counts_.global_elements == 0) +            e.context ().set ("first", true); + +          counts_.global_elements++; +        } + +      private: +        void +        count_last () +        { +          if (generate_p (*last_)) +          { +            counts_.generated_global_elements++; + +            size_t complexity (0); + +            if (doc_root_p (*last_)) +            { +              if (options.generate_element_type ()) +              { +                complexity += 1; // For c-tors and d-tor. + +                if (!options.suppress_parsing ()) +                  complexity += 1; + +                if (options.generate_serialization ()) +                  complexity += 1; +              } +              else +              { +                if (!options.suppress_parsing ()) +                  complexity += 6; // 13 parsing functions. + +                if (options.generate_serialization ()) +                  complexity += 4; // 8 serialization functions. +              } +            } + +            if (complexity == 0) +            { +              // This element must be a substitution group members. For +              // such elements we are only generating an entry in a map. +              // We will assign it a complexity of 1 so that we don't +              // end up with the total complexity that is less than the +              // number of elements and types. +              // +              complexity = 1; +            } + +            counts_.complexity_total += complexity; +            counts_.complexity.push_back (complexity); +          } +        } + +      private: +        Counts& counts_; +        SemanticGraph::Element* last_; +      }; +    } + +    Counts Counter:: +    count (options const& ops, +           SemanticGraph::Schema& tu, +           SemanticGraph::Path const& path) +    { +      Counts counts; +      Context ctx (std::wcerr, tu, path, ops, counts, false, 0, 0, 0, 0); + +      Traversal::Schema schema; +      Sources sources; + +      schema >> sources >> schema; + +      // The GlobalElement object destructor updates the counts, so make sure +      // that this object is destroyed before we return the counts. +      // +      { +        Traversal::Names schema_names; +        Traversal::Namespace ns; +        Traversal::Names ns_names; +        GlobalType global_type (ctx, counts); +        GlobalElement global_element (ctx, counts); + +        schema >> schema_names >> ns >> ns_names; + +        ns_names >> global_element; +        ns_names >> global_type; + +        schema.dispatch (tu); +      } + +      return counts; +    } +  } +} diff --git a/xsd/cxx/tree/counter.hxx b/xsd/cxx/tree/counter.hxx new file mode 100644 index 0000000..bc1dc79 --- /dev/null +++ b/xsd/cxx/tree/counter.hxx @@ -0,0 +1,25 @@ +// file      : xsd/cxx/tree/counter.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_COUNTER_HXX +#define XSD_CXX_TREE_COUNTER_HXX + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ +  namespace Tree +  { +    class Counter +    { +    public: +      Counts +      count (options const&, +             SemanticGraph::Schema&, +             SemanticGraph::Path const&); +    }; +  } +} + +#endif // XSD_CXX_TREE_COUNTER_HXX diff --git a/xsd/cxx/tree/default-value.cxx b/xsd/cxx/tree/default-value.cxx new file mode 100644 index 0000000..fd1c8c4 --- /dev/null +++ b/xsd/cxx/tree/default-value.cxx @@ -0,0 +1,1273 @@ +// file      : xsd/cxx/tree/default-value.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/default-value.hxx> + +using std::hex; +using std::dec; + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      void +      normalize (String& s) +      { +        size_t n (s.size ()); + +        for (size_t i (0); i < n; ++i) +        { +          wchar_t& c (s[i]); + +          if (c == 0x0D || // carriage return +              c == 0x09 || // tab +              c == 0x0A) +            c = 0x20; +        } +      } + +      void +      collapse (String& s) +      { +        size_t n (s.size ()), j (0); +        bool subs (false), trim (true); + +        for (size_t i (0); i < n; ++i) +        { +          wchar_t c (s[i]); + +          if (c == 0x20 || c == 0x09 || c == 0x0A) +            subs = true; +          else +          { +            if (subs) +            { +              subs = false; + +              if (!trim) +                s[j++] = 0x20; +            } + +            if (trim) +              trim = false; + +            s[j++] = c; +          } +        } + +        s.resize (j); +      } + +      void +      strip_zeros (String& s) +      { +        size_t n (s.size ()), i (0); + +        if (n > 0 && (s[i] == '-' || s[i] == '+')) +          i++; + +        size_t j (i); + +        bool strip (true); + +        for (; i < n; ++i) +        { +          wchar_t c (s[i]); + +          if (c == '0') +          { +            if (!strip) +              s[j++] = c; +          } +          else +          { +            s[j++] = c; + +            if (strip) +              strip = false; +          } +        } + +        if (strip && j < n) +          s[j++] = '0'; // There was nothing except zeros so add one back. + +        s.resize (j); +      } + +      void +      make_float (String& s) +      { +        if (s.find ('.') == String::npos && +            s.find ('e') == String::npos && +            s.find ('E') == String::npos) +          s += L".0"; +      } +    } + +    // +    // IsLiteralValue +    // + +    IsLiteralValue:: +    IsLiteralValue (bool& r) +        : IsFundamentalType (r) +    { +      *this >> inherits_ >> *this; +    } + +    void IsLiteralValue:: +    traverse (SemanticGraph::Complex& c) +    { +      inherits (c); +    } + +    // +    // LiteralValue +    // + +    LiteralValue:: +    LiteralValue (Context& c) +        : Context (c) +    { +      *this >> inherits_ >> *this; +    } + +    String LiteralValue:: +    dispatch (SemanticGraph::Node& type, String const& value) +    { +      literal_.clear (); +      value_ = value; +      Traversal::NodeBase::dispatch (type); +      return literal_; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Complex& c) +    { +      inherits (c); +    } + +    // Boolean. +    // +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Boolean&) +    { +      collapse (value_); +      literal_ = (value_ == L"true" || value_ == L"1") ? L"true" : L"false"; +    } + +    // Integral types. +    // +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Byte&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::UnsignedByte&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_ + L"U"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Short&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::UnsignedShort&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_ + L"U"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Int&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::UnsignedInt&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_ + L"U"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Long&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_; +      literal_ += L"LL"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::UnsignedLong&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_; +      literal_ += L"ULL"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Integer&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_ + L"LL"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::NonPositiveInteger&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_ + L"LL"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::NonNegativeInteger&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_ + L"ULL"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::PositiveInteger&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_ + L"ULL"; +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::NegativeInteger&) +    { +      collapse (value_); +      strip_zeros (value_); +      literal_ = value_ + L"LL"; +    } + +    // Floats. +    // +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Float& t) +    { +      collapse (value_); + +      if (value_ == L"NaN") +      { +        literal_ = L"::std::numeric_limits< " + fq_name (t) + +          L" >::quiet_NaN ()"; +      } +      else if (value_ == L"INF") +      { +        literal_ = L"::std::numeric_limits< " + fq_name (t) + +          L" >::infinity ()"; +      } +      else if (value_ == L"-INF") +      { +        literal_ = L"- ::std::numeric_limits< " + fq_name (t) + +          L" >::infinity ()"; +      } +      else +      { +        strip_zeros (value_); +        make_float (value_); +        literal_ = value_ + L"F"; +      } +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Double& t) +    { +      collapse (value_); + +      if (value_ == L"NaN") +      { +        literal_ = L"::std::numeric_limits< " + fq_name (t) + +          L" >::quiet_NaN ()"; +      } +      else if (value_ == L"INF") +      { +        literal_ = L"::std::numeric_limits< " + fq_name (t) + +          L" >::infinity ()"; +      } +      else if (value_ == L"-INF") +      { +        literal_ = L"- ::std::numeric_limits< " + fq_name (t) + +          L" >::infinity ()"; +      } +      else +      { +        strip_zeros (value_); +        make_float (value_); +        literal_ = value_; +      } +    } + +    void LiteralValue:: +    traverse (SemanticGraph::Fundamental::Decimal&) +    { +      collapse (value_); +      strip_zeros (value_); +      make_float (value_); +      literal_ = value_; +    } + +    // +    // InitKind +    // + +    InitKind:: +    InitKind (Kind& r) +        : r_ (r) +    { +      *this >> inherits_ >> *this; +    } + +    void InitKind:: +    traverse (SemanticGraph::List&) +    { +      r_ = function; +    } + +    void InitKind:: +    traverse (SemanticGraph::Complex& c) +    { +      inherits (c); +    } + +    void InitKind:: +    traverse (SemanticGraph::Fundamental::Base64Binary&) +    { +      r_ = data; +    } + +    void InitKind:: +    traverse (SemanticGraph::Fundamental::HexBinary&) +    { +      r_ = data; +    } + +    void InitKind:: +    traverse (SemanticGraph::Fundamental::NameTokens&) +    { +      r_ = function; +    } + +    void InitKind:: +    traverse (SemanticGraph::Fundamental::IdRefs&) +    { +      r_ = function; +    } + +    void InitKind:: +    traverse (SemanticGraph::Fundamental::Entities&) +    { +      r_ = function; +    } + +    // +    // InitValue +    // + +    InitValue:: +    InitValue (Context& c) +        : Context (c), type_name_ (c), literal_value_ (c) +    { +    } + +    void InitValue:: +    dispatch (SemanticGraph::Node& type, String const& value) +    { +      value_ = value; +      Traversal::NodeBase::dispatch (type); +    } + +    void InitValue:: +    traverse (SemanticGraph::List& l) +    { +      collapse (value_); + +      if (!value_) +        return; + +      SemanticGraph::Type& t (l.argumented ().type ()); + +      String ov (value_); +      size_t b (0); + +      for (size_t e (ov.find (' ')); ; e = ov.find (' ', b)) +      { +        String v (ov, b, e != String::npos ? e - b : e); + +        os << "{"; +        type_name_.dispatch (t); +        os << " tmp ("; + +        String lit (literal_value_.dispatch (t, v)); + +        if (lit) +          os << lit; +        else +        { +          value_ = v; +          Traversal::NodeBase::dispatch (t); +        } + +        os << ");" +           << "r.push_back (tmp);" +           << "}"; + +        if (e == String::npos) +          break; + +        b = e + 1; +      } + +      value_ = ov; +    } + +    void InitValue:: +    traverse (SemanticGraph::Union&) +    { +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Complex& c) +    { +      Traversal::NodeBase::dispatch (ultimate_base (c)); +    } + +    // anyType & anySimpleType. +    // +    void InitValue:: +    traverse (SemanticGraph::AnyType& t) +    { +      os << fq_name (t) << " (" << strlit (value_) << ")"; +    } + +    void InitValue:: +    traverse (SemanticGraph::AnySimpleType& t) +    { +      os << fq_name (t) << " (" << strlit (value_) << ")"; +    } + +    // Strings. +    // +    void InitValue:: +    traverse (SemanticGraph::Fundamental::String&) +    { +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::NormalizedString&) +    { +      normalize (value_); +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Token&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::NameToken&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::NameTokens&) +    { +      string_sequence_type ( +        dynamic_cast<SemanticGraph::Type&> ( +          xs_ns ().find ("NMTOKEN").first->named ())); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Name&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::NCName&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Language&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    // Qualified name. +    // +    void InitValue:: +    traverse (SemanticGraph::Fundamental::QName& t) +    { +      size_t p (value_.rfind ('#')); + +      if (p != String::npos) +      { +        String ns (value_, 0, p); +        String qname (value_, p + 1, String::npos); + +        collapse (ns); +        collapse (qname); + +        p = qname.find (':'); + +        String name; +        if (p != String::npos) +          name.assign (qname, p + 1, String::npos); +        else +          name = qname; + +        os << fq_name (t) << " (" << strlit (ns) << ", " << +          strlit (name) << ")"; +      } +      else +      { +        // Unqualified name. +        // +        collapse (value_); +        os << fq_name (t) << " (" << strlit (value_) << ")"; +      } +    } + +    // ID/IDREF. +    // +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Id&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::IdRef&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::IdRefs&) +    { +      string_sequence_type ( +        dynamic_cast<SemanticGraph::Type&> ( +          xs_ns ().find ("IDREF").first->named ())); +    } + +    // URI. +    // +    void InitValue:: +    traverse (SemanticGraph::Fundamental::AnyURI&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    // Binary. +    // +    static unsigned char +    base64_decode (wchar_t c) +    { +      unsigned char r = 0xFF; + +      if (c >= 'A' && c <= 'Z') +        r = static_cast<unsigned char> (c - 'A'); +      else if (c >= 'a' && c <= 'z') +        r = static_cast<unsigned char> (c - 'a' + 26); +      else if (c >= '0' && c <= '9') +        r = static_cast<unsigned char> (c - '0' + 52); +      else if (c == '+') +        r = 62; +      else if (c == '/') +        r = 63; + +      return r; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Base64Binary& t) +    { +      collapse (value_); + +      if (dispatch_count_++ == 0) +      { +        if (value_) +        { +          os << "unsigned char " << data_ << "[] = {"; + +          // Decode. +          // +          size_t size (value_.size ()); + +          // Remove all whitespaces. +          // +          { +            size_t j (0); +            bool subs (false); + +            for (size_t i (0); i < size; ++i) +            { +              wchar_t c (value_[i]); + +              if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) +                subs = true; +              else +              { +                if (subs) +                  subs = false; + +                value_[j++] = c; +              } +            } + +            size = j; +            value_.resize (size, '\0'); +          } + +          // Our length should be a multiple of four. +          // +          size_t quad_count (size / 4); + +          // Source and destination indexes. +          // +          size_t si (0), di (0); + +          // Process all quads except the last one. +          // +          unsigned short v; +          unsigned char b1, b2, b3, b4; + +          wchar_t prev_fill (os.fill ('0')); + +          for (size_t q (0); q < quad_count - 1; ++q) +          { +            b1 = base64_decode (value_[si++]); +            b2 = base64_decode (value_[si++]); +            b3 = base64_decode (value_[si++]); +            b4 = base64_decode (value_[si++]); + +            if (q != 0) +              os << ", "; + +            if (di % 9 == 0) +              os << endl; + +            os << hex; + +            v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); +            os.width (2); +            os << "0x" << v; + +            v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); +            os.width (2); +            os << ", 0x" << v; + +            v = static_cast<unsigned char> ((b3 << 6) | b4); +            os.width (2); +            os << ", 0x" << v; + +            os << dec; + +            di += 3; +          } + +          // Process the last quad. The first two octets are always there. +          // +          b1 = base64_decode (value_[si++]); +          b2 = base64_decode (value_[si++]); + +          wchar_t e3 (value_[si++]), e4 (value_[si++]); + +          if (quad_count != 1) +            os << ", "; + +          if (di % 9 == 0) +            os << endl; + +          if (e4 == '=') +          { +            if (e3 == '=') +            { +              // Two pads. Last 4 bits in b2 should be zero. +              // +              v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); +              os << "0x" << hex << v << dec; +              di++; +            } +            else +            { +              // One pad. Last 2 bits in b3 should be zero. +              // +              b3 = base64_decode (e3); + +              os << hex; + +              v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); +              os.width (2); +              os << "0x" << v; + +              v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); +              os.width (2); +              os << ", 0x" << v; + +              os << dec; + +              di += 2; +            } +          } +          else +          { +            // No pads. +            // +            b3 = base64_decode (e3); +            b4 = base64_decode (e4); + +            os << hex; + +            v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); +            os.width (2); +            os << "0x" << v; + +            v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); +            os.width (2); +            os << ", 0x" << v; + +            v = static_cast<unsigned char> ((b3 << 6) | b4); +            os.width (2); +            os << ", 0x" << v; + +            os << dec; + +            di += 3; +          } + +          os.fill (prev_fill); + +          os << "};"; +        } +      } +      else +      { +        os << fq_name (t) << " ("; + +        if (value_) +          os << data_ << "," << endl +             << "sizeof (" << data_ << ")," << endl +             << "sizeof (" << data_ << ")," << endl +             << "false"; +        else +          os << "0"; + + +        os << ")"; +      } +    } + +    static unsigned char +    hex_decode (wchar_t c) +    { +      unsigned char r = 0xFF; + +      if (c >= '0' && c <= '9') +        r = static_cast<unsigned char> (c - '0'); +      else if (c >= 'A' && c <= 'F') +        r = static_cast<unsigned char> (10 + (c - 'A')); +      else if (c >= 'a' && c <= 'f') +        r = static_cast<unsigned char> (10 + (c - 'a')); + +      return r; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::HexBinary& t) +    { +      collapse (value_); + +      if (dispatch_count_++ == 0) +      { +        if (value_) +        { +          os << "unsigned char " << data_ << "[] = {"; + +          // Decode. +          // +          size_t n (value_.size () / 2); +          wchar_t prev_fill (os.fill ('0')); + +          for (size_t i (0); i < n; ++i) +          { +            unsigned char h (hex_decode (value_[2 * i])); +            unsigned char l (hex_decode (value_[2 * i + 1])); + +            if (h == 0xFF || l == 0xFF) +              break; + +            if (i != 0) +              os << ", "; + +            if (i % 9 == 0) +              os << endl; + +            unsigned short v = static_cast<unsigned char> ((h << 4) | l); +            os.width (2); +            os << "0x" << hex << v << dec; +          } + +          os.fill (prev_fill); + +          os << "};"; +        } +      } +      else +      { +        os << fq_name (t) << " ("; + +        if (value_) +          os << data_ << "," << endl +             << "sizeof (" << data_ << ")," << endl +             << "sizeof (" << data_ << ")," << endl +             << "false"; +        else +          os << "0"; + + +        os << ")"; +      } +    } + +    // Date/time. +    // +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Date& t) +    { +      // date := [-]CCYY[N]*-MM-DD[Z|(+|-)HH:MM] +      // +      collapse (value_); + +      size_t b (0); +      size_t e (value_.find ('-', value_[0] == '-' ? 5 : 4)); +      String year (value_, 0, e); + +      b = e + 1; +      String month (value_, b, 2); + +      b += 3; +      String day (value_, b, 2); + +      strip_zeros (year); +      strip_zeros (month); +      strip_zeros (day); + +      os << fq_name (t) << " (" << year << ", " << month << ", " << day; +      time_zone (b + 2); +      os << ")"; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::DateTime& t) +    { +      // date_time := [-]CCYY[N]*-MM-DDTHH:MM:SS[.S+][Z|(+|-)HH:MM] +      // +      collapse (value_); + +      size_t b (0); +      size_t e (value_.find ('-', value_[0] == '-' ? 5 : 4)); +      String year (value_, 0, e); +      b = e + 1; + +      String month (value_, b, 2); +      b += 3; + +      String day (value_, b, 2); +      b += 3; + +      String hours (value_, b, 2); +      b += 3; + +      String minutes (value_, b, 2); +      b += 3; + +      e = b + 2; +      for (; e < value_.size (); ++e) +      { +        wchar_t c (value_[e]); + +        if (c == 'Z' || c == '+' || c == '-') +          break; +      } + +      String seconds (value_, b, e - b); + +      strip_zeros (year); +      strip_zeros (month); +      strip_zeros (day); +      strip_zeros (hours); +      strip_zeros (minutes); +      strip_zeros (seconds); +      make_float (seconds); + +      os << fq_name (t) << " (" +         << year << ", " << month << ", " << day << ", " +         << hours << ", " << minutes << ", " << seconds; +      time_zone (e); +      os << ")"; +    } + +    namespace +    { +      size_t +      find_delim (String const& s, size_t pos) +      { +        for (; pos < s.size (); ++pos) +        { +          wchar_t c (s[pos]); + +          if (c == 'Y' || c == 'D' || c == 'M' || c == 'H' || +              c == 'M' || c == 'S' || c == 'T') +            break; +        } + +        return pos; +      } +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Duration& t) +    { +      // duration := [-]P[nY][nM][nD][TnHnMn[.n+]S] +      // +      collapse (value_); + +      size_t b (1), e, n (value_.size ()); + +      os << fq_name (t) << " ("; + +      if (value_[0] == '-') +      { +        os << "true, "; +        b++; +      } +      else +        os << "false, "; + +      e = find_delim (value_, b); + +      if (e < n && value_[e] == 'Y') +      { +        String v (value_, b, e - b); +        strip_zeros (v); +        os << v << ", "; + +        b = e + 1; +        e = find_delim (value_, b); +      } +      else +        os << "0, "; + +      if (e < n && value_[e] == 'M') +      { +        String v (value_, b, e - b); +        strip_zeros (v); +        os << v << ", "; + +        b = e + 1; +        e = find_delim (value_, b); +      } +      else +        os << "0, "; + +      if (e < n && value_[e] == 'D') +      { +        String v (value_, b, e - b); +        strip_zeros (v); +        os << v << ", "; + +        b = e + 1; +        e = find_delim (value_, b); +      } +      else +        os << "0, "; + +      if (e < n && value_[e] == 'T') +      { +        b = e + 1; +        e = find_delim (value_, b); +      } + +      if (e < n && value_[e] == 'H') +      { +        String v (value_, b, e - b); +        strip_zeros (v); +        os << v << ", "; + +        b = e + 1; +        e = find_delim (value_, b); +      } +      else +        os << "0, "; + +      if (e < n && value_[e] == 'M') +      { +        String v (value_, b, e - b); +        strip_zeros (v); +        os << v << ", "; + +        b = e + 1; +        e = find_delim (value_, b); +      } +      else +        os << "0, "; + +      if (e < n && value_[e] == 'S') +      { +        String v (value_, b, e - b); +        strip_zeros (v); +        make_float (v); +        os << v; + +        b = e + 1; +        e = find_delim (value_, b); +      } +      else +        os << "0.0"; + +      os << ")"; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Day& t) +    { +      // gday := ---DD[Z|(+|-)HH:MM] +      // +      collapse (value_); + +      String day (value_, 3, 2); +      strip_zeros (day); + +      os << fq_name (t) << " (" << day; +      time_zone (5); +      os << ")"; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Month& t) +    { +      // gmonth := --MM[Z|(+|-)HH:MM] +      // +      collapse (value_); + +      String month (value_, 2, 2); +      strip_zeros (month); + +      os << fq_name (t) << " (" << month; +      time_zone (4); +      os << ")"; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::MonthDay& t) +    { +      // gmonth_day := --MM-DD[Z|(+|-)HH:MM] +      // +      collapse (value_); + +      String month (value_, 2, 2); +      String day (value_, 5, 2); + +      strip_zeros (month); +      strip_zeros (day); + +      os << fq_name (t) << " (" << month << ", " << day; +      time_zone (7); +      os << ")"; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Year& t) +    { +      // gyear := [-]CCYY[N]*[Z|(+|-)HH:MM] +      // +      collapse (value_); + +      size_t pos (value_[0] == '-' ? 5 : 4); +      for (; pos < value_.size (); ++pos) +      { +        wchar_t c (value_[pos]); + +        if (c == 'Z' || c == '+' || c == '-') +          break; +      } + +      String year (value_, 0, pos); +      strip_zeros (year); + +      os << fq_name (t) << " (" << year; +      time_zone (pos); +      os << ")"; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::YearMonth& t) +    { +      // gyear_month := [-]CCYY[N]*-MM[Z|(+|-)HH:MM] +      // +      collapse (value_); + +      size_t pos (value_.find ('-', value_[0] == '-' ? 5 : 4)); + +      String year (value_, 0, pos); +      String month (value_, pos + 1, 2); + +      strip_zeros (year); +      strip_zeros (month); + +      os << fq_name (t) << " (" << year << ", " << month; +      time_zone (pos + 3); +      os << ")"; +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Time& t) +    { +      // time := HH:MM:SS[.S+][Z|(+|-)HH:MM] +      // +      collapse (value_); + +      String hours (value_, 0, 2); +      String minutes (value_, 3, 2); + +      size_t e (8); +      for (; e < value_.size (); ++e) +      { +        wchar_t c (value_[e]); + +        if (c == 'Z' || c == '+' || c == '-') +          break; +      } + +      String seconds (value_, 6, e - 6); + +      strip_zeros (hours); +      strip_zeros (minutes); +      strip_zeros (seconds); +      make_float (seconds); + +      os << fq_name (t) << " (" << hours << ", " << minutes << ", " << seconds; +      time_zone (e); +      os << ")"; +    } + +    void InitValue:: +    time_zone (size_t pos) +    { +      // time_zone := Z|(+|-)HH:MM +      // +      if (pos < value_.size ()) +      { +        String h, m; + +        if (value_[pos] == 'Z') +        { +          h = "0"; +          m = "0"; +        } +        else +        { +          if (value_[pos] == '-') +          { +            h = "-"; +            m = "-"; +          } + +          h.append (value_, pos + 1, 2); +          m.append (value_, pos + 4, 2); + +          strip_zeros (h); +          strip_zeros (m); +        } + +        os << ", " << h << ", " << m; +      } +    } + +    // Entity. +    // +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Entity&) +    { +      collapse (value_); +      os << strlit (value_); +    } + +    void InitValue:: +    traverse (SemanticGraph::Fundamental::Entities&) +    { +      string_sequence_type ( +        dynamic_cast<SemanticGraph::Type&> ( +          xs_ns ().find ("ENTITY").first->named ())); +    } + +    void InitValue:: +    string_sequence_type (SemanticGraph::Type& t) +    { +      collapse (value_); + +      if (!value_) +        return; + +      size_t b (0); + +      for (size_t e (value_.find (' ')); ; e = value_.find (' ', b)) +      { +        String v (value_, b, e != String::npos ? e - b : e); + +        os << "{"; +        type_name_.dispatch (t); +        os << " tmp (" << strlit (v) << ");" +           << "r.push_back (tmp);" +           << "}"; + +        if (e == String::npos) +          break; + +        b = e + 1; +      } +    } +  } +} diff --git a/xsd/cxx/tree/default-value.hxx b/xsd/cxx/tree/default-value.hxx new file mode 100644 index 0000000..149982f --- /dev/null +++ b/xsd/cxx/tree/default-value.hxx @@ -0,0 +1,363 @@ +// file      : xsd/cxx/tree/default-value.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_DEFAULT_VALUE_HXX +#define XSD_CXX_TREE_DEFAULT_VALUE_HXX + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    struct IsLiteralValue: IsFundamentalType, Traversal::Complex +    { +      using IsFundamentalType::traverse; + +      IsLiteralValue (bool& r); + +      virtual void +      traverse (SemanticGraph::Complex&); + +    private: +      Traversal::Inherits inherits_; +    }; + +    struct LiteralValue: Traversal::Fundamental::Byte, +                         Traversal::Fundamental::UnsignedByte, +                         Traversal::Fundamental::Short, +                         Traversal::Fundamental::UnsignedShort, +                         Traversal::Fundamental::Int, +                         Traversal::Fundamental::UnsignedInt, +                         Traversal::Fundamental::Long, +                         Traversal::Fundamental::UnsignedLong, +                         Traversal::Fundamental::Integer, +                         Traversal::Fundamental::NonPositiveInteger, +                         Traversal::Fundamental::NonNegativeInteger, +                         Traversal::Fundamental::PositiveInteger, +                         Traversal::Fundamental::NegativeInteger, + +                         Traversal::Fundamental::Boolean, + +                         Traversal::Fundamental::Float, +                         Traversal::Fundamental::Double, +                         Traversal::Fundamental::Decimal, + +                         Traversal::Complex, + +                         Context +    { +      using Traversal::NodeDispatcher::dispatch; +      using Traversal::EdgeDispatcher::dispatch; + +      LiteralValue (Context&); + +      String +      dispatch (SemanticGraph::Node& type, String const& value); + +      // Handle inheritance. +      // +      virtual void +      traverse (SemanticGraph::Complex&); + +      // Boolean. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Boolean&); + +      // Integral types. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Byte&); + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedByte&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Short&); + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedShort&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Int&); + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedInt&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Long&); + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedLong&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Integer&); + +      virtual void +      traverse (SemanticGraph::Fundamental::NonPositiveInteger&); + +      virtual void +      traverse (SemanticGraph::Fundamental::NonNegativeInteger&); + +      virtual void +      traverse (SemanticGraph::Fundamental::PositiveInteger&); + +      virtual void +      traverse (SemanticGraph::Fundamental::NegativeInteger&); + +      // Floats. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Float&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Double&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Decimal&); + +    private: +      String value_; +      String literal_; + +      Traversal::Inherits inherits_; +    }; + +    // Some initialization (e.g., list) need a function body while others +    // (e.g., *binary) require extra data. +    // +    struct InitKind: Traversal::List, +                     Traversal::Complex, + +                     Traversal::Fundamental::Base64Binary, +                     Traversal::Fundamental::HexBinary, + +                     Traversal::Fundamental::NameTokens, +                     Traversal::Fundamental::IdRefs, +                     Traversal::Fundamental::Entities +    { +      enum Kind +      { +        simple, +        data, +        function +      }; + +      // Should be simple initially. +      // +      InitKind (Kind& r); + +      virtual void +      traverse (SemanticGraph::List&); + +      virtual void +      traverse (SemanticGraph::Complex&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Base64Binary&); + +      virtual void +      traverse (SemanticGraph::Fundamental::HexBinary&); + +      virtual void +      traverse (SemanticGraph::Fundamental::NameTokens&); + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRefs&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Entities&); + +    private: +      Kind& r_; +      Traversal::Inherits inherits_; +    }; + +    struct InitValue: Traversal::List, +                      Traversal::Union, +                      Traversal::Complex, + +                      Traversal::AnyType, +                      Traversal::AnySimpleType, + +                      Traversal::Fundamental::String, +                      Traversal::Fundamental::NormalizedString, +                      Traversal::Fundamental::Token, +                      Traversal::Fundamental::Name, +                      Traversal::Fundamental::NameToken, +                      Traversal::Fundamental::NameTokens, +                      Traversal::Fundamental::NCName, +                      Traversal::Fundamental::Language, + +                      Traversal::Fundamental::QName, + +                      Traversal::Fundamental::Id, +                      Traversal::Fundamental::IdRef, +                      Traversal::Fundamental::IdRefs, + +                      Traversal::Fundamental::AnyURI, + +                      Traversal::Fundamental::Base64Binary, +                      Traversal::Fundamental::HexBinary, + +                      Traversal::Fundamental::Date, +                      Traversal::Fundamental::DateTime, +                      Traversal::Fundamental::Duration, +                      Traversal::Fundamental::Day, +                      Traversal::Fundamental::Month, +                      Traversal::Fundamental::MonthDay, +                      Traversal::Fundamental::Year, +                      Traversal::Fundamental::YearMonth, +                      Traversal::Fundamental::Time, + +                      Traversal::Fundamental::Entity, +                      Traversal::Fundamental::Entities, + +                      Context +    { +      using Traversal::NodeDispatcher::dispatch; +      using Traversal::EdgeDispatcher::dispatch; + +      InitValue (Context&); + +      void +      data (String const& data) +      { +        data_ = data; +        dispatch_count_ = 0; +      } + +      void +      dispatch (SemanticGraph::Node& type, String const& value); + +      virtual void +      traverse (SemanticGraph::List&); + +      virtual void +      traverse (SemanticGraph::Union&); + +      virtual void +      traverse (SemanticGraph::Complex&); + +      // anyType & anySimpleType. +      // +      virtual void +      traverse (SemanticGraph::AnyType&); + +      virtual void +      traverse (SemanticGraph::AnySimpleType&); + +      // Strings. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::String&); + +      virtual void +      traverse (SemanticGraph::Fundamental::NormalizedString&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Token&); + +      virtual void +      traverse (SemanticGraph::Fundamental::NameToken&); + +      virtual void +      traverse (SemanticGraph::Fundamental::NameTokens&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Name&); + +      virtual void +      traverse (SemanticGraph::Fundamental::NCName&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Language&); + +      // Qualified name. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::QName&); + +      // ID/IDREF. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Id&); + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRef&); + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRefs&); + +      // URI. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::AnyURI&); + +      // Binary. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Base64Binary&); + +      virtual void +      traverse (SemanticGraph::Fundamental::HexBinary&); + +      // Date/time. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Date&); + +      virtual void +      traverse (SemanticGraph::Fundamental::DateTime&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Duration&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Day&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Month&); + +      virtual void +      traverse (SemanticGraph::Fundamental::MonthDay&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Year&); + +      virtual void +      traverse (SemanticGraph::Fundamental::YearMonth&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Time&); + +      // Entity. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Entity&); + +      virtual void +      traverse (SemanticGraph::Fundamental::Entities&); + +    private: +      void +      string_sequence_type (SemanticGraph::Type& element_type); + +      void +      time_zone (size_t pos); + +    private: +      String value_; +      String data_; +      size_t dispatch_count_; +      MemberTypeName type_name_; +      LiteralValue literal_value_; +    }; +  } +} + +#endif // XSD_CXX_TREE_DEFAULT_VALUE_HXX diff --git a/xsd/cxx/tree/elements.cxx b/xsd/cxx/tree/elements.cxx new file mode 100644 index 0000000..fc080c8 --- /dev/null +++ b/xsd/cxx/tree/elements.cxx @@ -0,0 +1,1409 @@ +// file      : xsd/cxx/tree/elements.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    // Context +    // +    Context:: +    Context (std::wostream& o, +             SemanticGraph::Schema& root, +             SemanticGraph::Path const& path, +             options_type const& ops, +             Counts const& counts_, +             bool generate_xml_schema__, +             StringLiteralMap const* map, +             Regex const* fe, +             Regex const* he, +             Regex const* ie) +        : CXX::Context (o, root, path, ops, map), +          options (ops), +          counts (counts_), +          any_type (any_type_), +          any_simple_type (any_simple_type_), +          element_type (element_type_), +          container (container_), +          flags_type (flags_type_), +          qname_type (qname_type_), +          xs_string_type (xs_string_type_), +          properties_type (properties_type_), +          error_handler_type (error_handler_type_), +          list_stream_type (list_stream_type_), +          namespace_infomap_type (namespace_infomap_type_), +          parser_type (parser_type_), +          std_ostream_type (std_ostream_type_), +          ostream_type (ostream_type_), +          istream_type (istream_type_), +          xerces_ns (xerces_ns_), +          dom_auto_ptr (dom_auto_ptr_), +          dom_node_key (dom_node_key_), +          as_double_type (as_double_type_), +          as_decimal_type (as_decimal_type_), +          generate_xml_schema (generate_xml_schema_), +          doxygen (doxygen_), +          polymorphic (ops.generate_polymorphic ()), +          polymorphic_all (ops.polymorphic_type_all ()), +          poly_plate (ops.polymorphic_plate ()), +          detach (ops.generate_detach ()), +          fwd_expr (fe), +          hxx_expr (he), +          ixx_expr (ie), +          ns_scope (ns_scope_), +          regex_custom_type_map (regex_custom_type_map_), +          direct_custom_type_map (direct_custom_type_map_), +          qname_type_ (L"::xsd::cxx::xml::qualified_name< " + char_type + L" >"), +          parser_type_ (L"::xsd::cxx::xml::dom::parser< " + char_type + L" >"), +          generate_xml_schema_ (generate_xml_schema__), +          doxygen_ (ops.generate_doxygen ()), +          ns_scope_stack (ns_scope_stack_), +          cxx_uq_id_expr_ (L"^[a-zA-Z_]\\w*$"), +          cxx_uq_id_expr (cxx_uq_id_expr_) +    { +      SemanticGraph::Namespace& xs (xs_ns ()); +      SemanticGraph::Context& xsc (xs.context ()); + +      // Cache some often-used names from the XML Schema namespace +      // if names have already been processed. +      // +      if (xsc.count ("container")) +      { +        String xs_name (ns_name (xs)); + +        any_type = fq_name (xs.find ("anyType").first->named ()); +        any_simple_type = fq_name (xs.find ("anySimpleType").first->named ()); +        xs_string_type = fq_name (xs.find ("string").first->named ()); + +        container = xs_name + L"::" + xsc.get<String> ("container"); +        flags_type = xs_name + L"::" + xsc.get<String> ("flags"); + +        if (ops.generate_element_type ()) +          element_type = xs_name + L"::" + xsc.get<String> ("element-type"); + +        properties_type = xs_name + L"::" + xsc.get<String> ("properties"); + +        if (!ops.suppress_parsing () || ops.generate_serialization ()) +        { +          error_handler_type = xs_name + L"::" + +            xsc.get<String> ("error-handler"); +        } + +        dom_auto_ptr_ = xs_name + (std >= cxx_version::cxx11 +                                   ? L"::dom::unique_ptr" +                                   : L"::dom::auto_ptr"); + +        dom_node_key_ = xs_name + L"::dom::" + +          xsc.get<String> ("tree-node-key"); + +        if (ops.generate_serialization ()) +        { +          as_double_type_ = xs_name + L"::" + +            xsc.get<String> ("as-double"); + +          as_decimal_type_ = xs_name + L"::" + +            xsc.get<String> ("as-decimal"); + +          list_stream_type  = xs_name + L"::" + +            xsc.get<String> ("list-stream"); + +          namespace_infomap_type  = xs_name + L"::" + +            xsc.get<String> ("namespace-infomap"); +        } + +        // istream and ostream are templates and for now use the same +        // names regardless of the naming convention. +        // +        if (!ops.generate_extraction ().empty ()) +          istream_type = xs_name + L"::istream"; + +        if (!ops.generate_insertion ().empty ()) +          ostream_type = xs_name + L"::ostream"; +      } + +      // Xerces-C++ namespace. IntelliSense for some reason does not like +      // it fully-qualified (maybe because it's a namespace alias). +      // +      if (ops.generate_intellisense ()) +        xerces_ns = "xercesc"; +      else +        xerces_ns = "::xercesc"; + +      // +      // +      if (char_type == L"char") +        std_ostream_type_ = L"::std::ostream"; +      else if (char_type == L"wchar_t") +        std_ostream_type_ = L"::std::wostream"; +      else +        std_ostream_type_ = L"::std::basic_ostream< " + char_type + L" >"; + +      // Custom type mapping. +      // + +      // Direct custom type mapping. +      // +      { +        NarrowStrings const& v (ops.custom_type ()); + +        for (NarrowStrings::const_iterator i (v.begin ()), +               e (v.end ()); i != e; ++i) +        { +          String s (*i); + +          if (s.empty ()) +            throw InvalidCustomTypeMapping (s, "mapping string is empty"); + +          // Split the string in two parts at the last '='. +          // +          size_t pos (s.rfind ('=')); + +          // If no delimiter found then both type and base are empty. +          // +          if (pos == String::npos) +          { +            direct_custom_type_map[s].type.clear (); +            direct_custom_type_map[s].base.clear (); +            continue; +          } + +          String name (s, 0, pos); +          String rest (s, pos + 1); + +          // See if we've got the base part after '/'. +          // +          pos = rest.rfind ('/'); + +          String type, base; + +          if (pos != String::npos) +          { +            type.assign (rest, 0, pos); +            base.assign (rest, pos + 1, String::npos); +          } +          else +            type = rest; + +          // type can be a potentially-qualified template-id. base is +          // an unqualified C++ name. +          // + +          if (!base.empty () && !cxx_uq_id_expr.match (base)) +            throw InvalidCustomTypeMapping (s, "invalid C++ identifier"); + +          direct_custom_type_map[name].type = type; +          direct_custom_type_map[name].base = base; +        } +      } + +      // Regex custom type mapping. +      // +      { +        NarrowStrings const& v (ops.custom_type_regex ()); + +        for (NarrowStrings::const_iterator i (v.begin ()), +               e (v.end ()); i != e; ++i) +        { +          String s (*i); + +          if (s.empty ()) +            throw InvalidCustomTypeMapping (s, "mapping string is empty"); + +          wchar_t delimiter (s[0]); + +          // First get pattern. +          // +          size_t pos (s.find (delimiter, 1)); + +          if (pos == String::npos) +            throw InvalidCustomTypeMapping ( +              s, "missing pattern-substitution separator"); + +          String pat (s, 1, pos - 1); +          String rest (s, pos + 1); + +          String type, base; + +          // See if we've got type and base. +          // +          if (!rest.empty ()) +          { +            pos = rest.find (delimiter); + +            if (pos == String::npos) +              throw InvalidCustomTypeMapping ( +                s, "missing pattern-substitution separator"); + +            type.assign (rest, 0, pos); +            rest = String (rest, pos + 1); + +            if (!rest.empty ()) +            { +              pos = rest.find (delimiter); + +              if (pos == String::npos) +                throw InvalidCustomTypeMapping ( +                  s, "missing pattern-substitution separator"); + +              base.assign (rest, 0, pos); +              rest = String (rest, pos + 1); + +              if (!rest.empty ()) +                throw InvalidCustomTypeMapping (s, "invalid format"); +            } +          } + +          regex_custom_type_map.push_back ( +            RegexCustomTypeMapInfo (WideRegexPat (pat), type, base)); +        } +      } +    } + +    Context:: +    Context (Context& c) +        : CXX::Context (c), +          options (c.options), +          counts (c.counts), +          any_type (c.any_type), +          any_simple_type (c.any_simple_type), +          element_type (c.element_type), +          container (c.container), +          flags_type (c.flags_type), +          qname_type (c.qname_type), +          xs_string_type (c.xs_string_type), +          properties_type (c.properties_type), +          error_handler_type (c.error_handler_type), +          list_stream_type (c.list_stream_type), +          namespace_infomap_type (c.namespace_infomap_type), +          parser_type (c.parser_type), +          std_ostream_type (c.std_ostream_type), +          ostream_type (c.ostream_type), +          istream_type (c.istream_type), +          xerces_ns (c.xerces_ns), +          dom_auto_ptr (c.dom_auto_ptr), +          dom_node_key (c.dom_node_key), +          as_double_type (c.as_double_type), +          as_decimal_type (c.as_decimal_type), +          generate_xml_schema (c.generate_xml_schema), +          doxygen (c.doxygen), +          polymorphic (c.polymorphic), +          polymorphic_all (c.polymorphic_all), +          poly_plate (c.poly_plate), +          detach (c.detach), +          fwd_expr (c.fwd_expr), +          hxx_expr (c.hxx_expr), +          ixx_expr (c.ixx_expr), +          ns_scope (c.ns_scope), +          regex_custom_type_map (c.regex_custom_type_map), +          direct_custom_type_map (c.direct_custom_type_map), +          ns_scope_stack (c.ns_scope_stack), +          cxx_uq_id_expr (c.cxx_uq_id_expr) +    { +    } + +    Context:: +    Context (Context& c, std::wostream& o) +        : CXX::Context (c, o), +          options (c.options), +          counts (c.counts), +          any_type (c.any_type), +          any_simple_type (c.any_simple_type), +          element_type (c.element_type), +          container (c.container), +          flags_type (c.flags_type), +          qname_type (c.qname_type), +          xs_string_type (c.xs_string_type), +          properties_type (c.properties_type), +          error_handler_type (c.error_handler_type), +          list_stream_type (c.list_stream_type), +          namespace_infomap_type (c.namespace_infomap_type), +          parser_type (c.parser_type), +          std_ostream_type (c.std_ostream_type), +          ostream_type (c.ostream_type), +          istream_type (c.istream_type), +          xerces_ns (c.xerces_ns), +          dom_auto_ptr (c.dom_auto_ptr), +          dom_node_key (c.dom_node_key), +          as_double_type (c.as_double_type), +          as_decimal_type (c.as_decimal_type), +          generate_xml_schema (c.generate_xml_schema), +          doxygen (c.doxygen), +          polymorphic (c.polymorphic), +          polymorphic_all (c.polymorphic_all), +          poly_plate (c.poly_plate), +          detach (c.detach), +          fwd_expr (c.fwd_expr), +          hxx_expr (c.hxx_expr), +          ixx_expr (c.ixx_expr), +          ns_scope (c.ns_scope), +          regex_custom_type_map (c.regex_custom_type_map), +          direct_custom_type_map (c.direct_custom_type_map), +          ns_scope_stack (c.ns_scope_stack), +          cxx_uq_id_expr (c.cxx_uq_id_expr) +    { +    } + +    void Context:: +    update_ns_scope () +    { +      ns_scope.clear (); + +      bool first (true); + +      for (NamespaceStack::iterator i (ns_scope_stack.begin ()); +           i != ns_scope_stack.end (); +           ++i) +      { +        // We only qualify names until the namespace level. +        // +        if (first) +          first = false; +        else +          ns_scope += L"::"; + +        ns_scope += *i; +      } +    } + +    bool Context:: +    custom_type (SemanticGraph::Type const& t, String& r) const +    { +      String const& name (t.name ()); + +      // First search the direct mapping. +      // +      { +        DirectCustomTypeMap::const_iterator i ( +          direct_custom_type_map.find (name)); + +        if (i != direct_custom_type_map.end ()) +        { +          r = i->second.type; +          return true; +        } +      } + + +      // Second search the regex mapping. +      // +      for (RegexCustomTypeMap::const_iterator +             i (regex_custom_type_map.begin ()), +             e (regex_custom_type_map.end ()); +           i != e; ++i) +      { +        if (i->pat.match (name)) +        { +          // Empty type sub tells us to use the original name. +          // +          if (i->type_sub.empty ()) +          { +            r.clear (); +            return true; +          } + +          r = i->pat.replace (name, i->type_sub); +          return true; +        } +      } + +      return false; +    } + +    String Context:: +    custom_type (SemanticGraph::Type const& t) const +    { +      String r; +      if (custom_type (t, r)) +      { +        // Empty type name tells us to use the original name. +        // +        if (r.empty ()) +          r = ename (t); +      } + +      return r; +    } + +    bool Context:: +    renamed_type (SemanticGraph::Type const& t, String& r) const +    { +      String const& name (t.name ()); + +      // First search the direct mapping. +      // +      { +        DirectCustomTypeMap::const_iterator i ( +          direct_custom_type_map.find (name)); + +        if (i != direct_custom_type_map.end ()) +        { +          r = i->second.base; +          return true; +        } +      } + + +      // Second search the regex mapping. +      // +      for (RegexCustomTypeMap::const_iterator +             i (regex_custom_type_map.begin ()), +             e (regex_custom_type_map.end ()); +           i != e; ++i) +      { +        if (i->pat.match (name)) +        { +          if (!i->base_sub.empty ()) +          { +            r = i->pat.replace (name, i->base_sub); +          } +          else +            r.clear (); + +          return true; +        } +      } + +      return false; +    } + +    void Context:: +    write_annotation (SemanticGraph::Annotation& a) +    { +      String const& doc (a.documentation ()); +      wchar_t const* s (doc.c_str ()); +      size_t size (doc.size ()); + +      // Remove leading and trailing whitespaces. +      // +      while (*s == wchar_t (0x20) || *s == wchar_t (0x0A) || +             *s == wchar_t (0x0D) || *s == wchar_t (0x09)) +      { +        s++; +        size--; +      } + +      if (size != 0) +      { +        wchar_t const* e (s + size - 1); + +        while (e > s && +               (*e == wchar_t (0x20) || *e == wchar_t (0x0A) || +                *e == wchar_t (0x0D) || *e == wchar_t (0x09))) +          --e; + +        size = s <= e ? e - s + 1 : 0; +      } + +      if (size != 0) +      { +        os << " * "; + +        // Go over the data, forcing newline after 80 chars and adding +        // ' * ' after each new line. +        // +        wchar_t const* last_space (0); +        wchar_t const* b (s); +        wchar_t const* e (s); +        bool after_newline (false); +        bool rogue (false); + +        for (; e < s + size; ++e) +        { +          unsigned int u (unicode_char (e)); // May advance e. + +          // We are going to treat \v and \f as rogue here even though +          // they can be present in C++ source code. +          // +          if (u > 127 || (u < 32 && u != '\t' && u != '\n')) +            rogue = true; + +          if (u == ' ' || u == '\t') +          { +            if (after_newline) +            { +              if (e == b) +                b++; // Skip leading spaces after newline. + +              continue; +            } +            else +              last_space = e; +          } +          else if (after_newline) +          { +            os << " * "; +            after_newline = false; +          } + +          if (u == '\n') +          { +            write_rogue_text (b, e - b + 1, rogue); + +            b = e + 1; +            last_space = 0; +            after_newline = true; +            rogue = false; +            continue; +          } + +          if (e - b >= 70 && last_space != 0) +          { +            write_rogue_text (b, last_space - b, rogue); +            os << endl; + +            b = last_space + 1; +            last_space = 0; +            after_newline = true; +            // Cannot reset rogue since we don't output the whole string. +          } +        } + +        if (e != b) +          write_rogue_text (b, e - b, rogue); + +        if (!after_newline) +          os << endl; +      } +    } + +    void Context:: +    write_rogue_text (wchar_t const* s, size_t size, bool rogue) +    { +      if (!rogue) +        os.write (s, size); +      else +      { +        for (wchar_t const* p (s); p < s + size; ++p) +        { +          unsigned int u (unicode_char (p)); // May advance p. + +          // We are going to treat \v and \f as rogue here even though +          // they can be present in C++ source code. +          // +          if (u > 127 || (u < 32 && u != '\t' && u != '\n')) +            os.put ('?'); +          else +            os.put (static_cast<wchar_t> (u)); +        } +      } +    } + +    bool Context:: +    polymorphic_p (SemanticGraph::Type& t) +    { +      // IDREF templates cannot be polymorphic. +      // +      if (!t.named_p () && +          (t.is_a<SemanticGraph::Fundamental::IdRef> () || +           t.is_a<SemanticGraph::Fundamental::IdRefs> ())) +        return false; + +      if (polymorphic_all) +      { +        bool fund (false); +        IsFundamentalType test (fund); +        test.dispatch (t); +        return !fund; +      } +      else +        return t.context ().get<bool> ("polymorphic"); +    } + +    bool Context:: +    anonymous_substitutes_p (SemanticGraph::Type& t) +    { +      // IDREF templates cannot match. +      // +      if (!t.named_p () && +          (t.is_a<SemanticGraph::Fundamental::IdRef> () || +           t.is_a<SemanticGraph::Fundamental::IdRefs> ())) +        return false; + +      // See which elements this type classifies. +      // +      for (SemanticGraph::Type::ClassifiesIterator i (t.classifies_begin ()), +             e (t.classifies_end ()); i != e; ++i) +      { +        if (SemanticGraph::Element* e = +            dynamic_cast<SemanticGraph::Element*> (&i->instance ())) +        { +          if (e->substitutes_p ()) +            return true; +        } +      } + +      return false; +    } + +    // GenerateDefautCtor +    // +    GenerateDefaultCtor:: +    GenerateDefaultCtor (Context& c, bool& generate, bool no_base) +        : Context (c), generate_ (generate), no_base_ (no_base) +    { +      *this >> inherits_ >> *this; +      *this >> names_ >> *this; +    } + +    void GenerateDefaultCtor:: +    traverse (SemanticGraph::Complex& c) +    { +      // Make sure we figure out if we have any required members before +      // we base our decision on the base type. +      // +      Complex::names (c, names_); + +      if (!generate_) +        Complex::inherits (c, inherits_); +    } + +    void GenerateDefaultCtor:: +    traverse (SemanticGraph::Type&) +    { +      if (!no_base_) +        generate_ = true; +    } + +    void GenerateDefaultCtor:: +    traverse (SemanticGraph::Enumeration&) +    { +      if (!no_base_) +        generate_ = true; +    } + +    void GenerateDefaultCtor:: +    traverse (SemanticGraph::Element& e) +    { +      if (!skip (e) && min (e) == 1 && max (e) == 1) +        generate_ = true; +    } + +    void GenerateDefaultCtor:: +    traverse (SemanticGraph::Attribute& a) +    { +      if (min (a) == 1 && !a.fixed_p ()) +        generate_ = true; +    } + +    void GenerateDefaultCtor:: +    traverse (SemanticGraph::Any& a) +    { +      if (options.generate_wildcard () && +          min (a) == 1 && max (a) == 1) +        generate_ = true; +    } + + +    // GenerateFromBaseCtor +    // +    GenerateFromBaseCtor:: +    GenerateFromBaseCtor (Context& c, bool& generate) +        : generate_ (generate), +          custom_ (false), +          traverser_ (c, generate, custom_) +    { +      inherits_ >> traverser_; +    } + +    void GenerateFromBaseCtor:: +    traverse (SemanticGraph::Complex& c) +    { +      inherits (c, inherits_); + +      if (!generate_ && custom_) +      { +        // We have a customized type in the hierarchy. In this case we +        // want to generate the c-tor unless base and ultimate-base are +        // the same (see CtorArgs). +        // +        SemanticGraph::Type& b (c.inherits ().base ()); +        generate_ = b.is_a<SemanticGraph::Complex> () && +          !b.is_a<SemanticGraph::Enumeration> (); +      } +    } + +    GenerateFromBaseCtor::Traverser:: +    Traverser (Context& c, bool& generate, bool& custom) +        : Context (c), generate_ (generate), custom_ (custom) +    { +      *this >> inherits_ >> *this; +      *this >> names_ >> *this; +    } + +    void GenerateFromBaseCtor::Traverser:: +    traverse (SemanticGraph::Type& t) +    { +      if (!custom_) +      { +        String tmp; +        custom_ = custom_type (t, tmp); +      } +    } + +    void GenerateFromBaseCtor::Traverser:: +    traverse (SemanticGraph::Complex& c) +    { +      names (c, names_); + +      if (!generate_) +        inherits (c, inherits_); + +      if (!generate_) +        traverse (static_cast<SemanticGraph::Type&> (c)); +    } + +    void GenerateFromBaseCtor::Traverser:: +    traverse (SemanticGraph::Element& e) +    { +      if (!skip (e) && min (e) == 1 && max (e) == 1) +        generate_ = true; +    } + +    void GenerateFromBaseCtor::Traverser:: +    traverse (SemanticGraph::Attribute& a) +    { +      if (min (a) == 1 && !a.fixed_p ()) +        generate_ = true; +    } + +    void GenerateFromBaseCtor::Traverser:: +    traverse (SemanticGraph::Any& a) +    { +      if (options.generate_wildcard () && +          min (a) == 1 && max (a) == 1) +        generate_ = true; +    } + +    // HasComplexNonOptArgs +    // +    HasComplexPolyNonOptArgs:: +    HasComplexPolyNonOptArgs (Context& c, +                              bool base, +                              bool& complex, +                              bool& poly, +                              bool& clash) +        : Context (c), +          complex_ (complex), +          poly_ (poly), +          clash_ (clash) +    { +      if (base) +        *this >> inherits_ >> *this; + +      *this >> names_ >> *this; +    } + +    void HasComplexPolyNonOptArgs:: +    traverse (SemanticGraph::Complex& c) +    { +      // No optimizations: need to check every arg for clashes. +      // +      inherits (c, inherits_); +      names (c, names_); +    } + +    void HasComplexPolyNonOptArgs:: +    traverse (SemanticGraph::Element& e) +    { +      if (!skip (e) && min (e) == 1 && max (e) == 1) +      { +        bool poly (polymorphic && polymorphic_p (e.type ())); + +        bool simple (true); +        IsSimpleType t (simple); +        t.dispatch (e.type ()); + +        if (poly) +          poly_ = true; + +        if (!simple) +          complex_ = true; + +        if (poly && simple) +          clash_ = false; +      } +    } + +    // FromBaseCtorArg +    // +    FromBaseCtorArg:: +    FromBaseCtorArg (Context& c, CtorArgType at, bool arg) +        : Context (c), arg_type_ (at), arg_ (arg) +    { +    } + +    void FromBaseCtorArg:: +    traverse (SemanticGraph::Any& a) +    { +      if (!options.generate_wildcard ()) +        return; + +      if (min (a) == 1 && max (a) == 1) +      { +        String const& name (ename (a)); + +        os << "," << endl +           << "const " << xerces_ns << "::DOMElement&"; + +        if (arg_) +          os << " " << name; +      } +    } + +    void FromBaseCtorArg:: +    traverse (SemanticGraph::Element& e) +    { +      if (skip (e)) +        return; + +      if (min (e) == 1 && max (e) == 1) +      { +        String const& name (ename (e)); + +        os << "," << endl; + +        bool ptr (false); + +        switch (arg_type_) +        { +        case CtorArgType::complex_auto_ptr: +          { +            bool simple (true); +            IsSimpleType t (simple); +            t.dispatch (e.type ()); +            ptr = !simple; +            break; +          } +        case CtorArgType::poly_auto_ptr: +          { +            ptr = polymorphic && polymorphic_p (e.type ()); +            break; +          } +        case CtorArgType::type: +          break; +        } + +        if (ptr) +          os << auto_ptr << "< " << etype (e) << " >"; +        else +          os << "const " << etype (e) << "&"; + +        if (arg_) +          os << " " << name; +      } +    } + +    void FromBaseCtorArg:: +    traverse (SemanticGraph::Attribute& a) +    { +      // Note that we are not going to include attributes with +      // default or required fixed values here. Instead we are +      // going to default-initialize them. +      // +      if (min (a) == 1 && !a.fixed_p ()) +      { +        String const& name (ename (a)); + +        os << "," << endl +           << "const " << etype (a) << "&"; + +        if (arg_) +          os << " " << name; +      } +    } + +    // CtorArgs +    // +    CtorArgs:: +    CtorArgs (Context& c, CtorArgType at) +        : Context (c), +          arg_type_ (at), +          base_arg_ (0), +          first_ (true), +          member_name_ (c) +    { +      *this >> inherits_ >> *this; +      *this >> names_ >> *this; +    } + +    CtorArgs:: +    CtorArgs (Context& c, CtorArgType at, String& base_arg) +        : Context (c), +          arg_type_ (at), +          base_arg_ (&base_arg), +          first_ (true), +          member_name_ (c) +    { +      *this >> inherits_ >> *this; +      *this >> names_ >> *this; +    } + +    void CtorArgs:: +    traverse (SemanticGraph::Type& t) +    { +      os << comma () << "const "; + +      member_name_.dispatch (t); + +      os << "&"; + +      if (base_arg_ != 0) +      { +        // IDREF templates don't have a name. +        // +        *base_arg_ = t.named_p () +          ? (L"_xsd_" + ename (t) + L"_base") +          : L"_xsd_base"; + +        os << " " << *base_arg_; +      } +    } + +    void CtorArgs:: +    traverse (SemanticGraph::Enumeration& e) +    { +      os << comma () << "const "; + +      member_name_.traverse (e); + +      os << "&"; + +      if (base_arg_ != 0) +      { +        *base_arg_ = L"_xsd_" + ename (e) + L"_base"; + +        os << " " << *base_arg_; +      } +    } + +    void CtorArgs:: +    traverse (SemanticGraph::Any& a) +    { +      if (!options.generate_wildcard ()) +        return; + +      if (min (a) == 1 && max (a) == 1) +      { +        os << comma () << "const " << xerces_ns << "::DOMElement&"; + +        if (base_arg_ != 0) +          os << " " << ename (a); +      } +    } + +    void CtorArgs:: +    traverse (SemanticGraph::Element& e) +    { +      if (skip (e)) +        return; + +      if (min (e) == 1 && max (e) == 1) +      { +        bool ptr (false); + +        switch (arg_type_) +        { +        case CtorArgType::complex_auto_ptr: +          { +            bool simple (true); +            IsSimpleType t (simple); +            t.dispatch (e.type ()); +            ptr = !simple; +            break; +          } +        case CtorArgType::poly_auto_ptr: +          { +            ptr = polymorphic && polymorphic_p (e.type ()); +            break; +          } +        case CtorArgType::type: +          break; +        } + +        if (ptr) +          os << comma () << auto_ptr << "< " << etype (e) << " >"; +        else +          os << comma () << "const " << etype (e) << "&"; + +        if (base_arg_ != 0) +          os << " " << ename (e); +      } +    } + +    void CtorArgs:: +    traverse (SemanticGraph::Attribute& a) +    { +      // Note that we are not going to include attributes with +      // default or required fixed values here. Instead we are +      // going to default-initialize them. +      // +      if (min (a) == 1 && !a.fixed_p ()) +      { +        os << comma () << "const " << etype (a) << "&"; + +        if (base_arg_ != 0) +          os << " " << ename (a); +      } +    } + +    String CtorArgs:: +    comma () +    { +      bool tmp (first_); +      first_ = false; +      return tmp ? "" : ",\n"; +    } + + +    // CtorArgsWithoutBase +    // +    CtorArgsWithoutBase:: +    CtorArgsWithoutBase (Context& c, CtorArgType at, bool arg, bool first) +        : Context (c), arg_type_ (at), arg_ (arg), first_ (first) +    { +      *this >> inherits_ >> *this; +      *this >> names_ >> *this; +    } + +    void CtorArgsWithoutBase:: +    traverse (SemanticGraph::Any& a) +    { +      if (!options.generate_wildcard ()) +        return; + +      if (min (a) == 1 && max (a) == 1) +      { +        os << comma () << "const " << xerces_ns << "::DOMElement&"; + +        if (arg_) +          os << " " << ename (a); +      } +    } + +    void CtorArgsWithoutBase:: +    traverse (SemanticGraph::Element& e) +    { +      if (skip (e)) +        return; + +      if (min (e) == 1 && max (e) == 1) +      { +        bool ptr (false); + +        switch (arg_type_) +        { +        case CtorArgType::complex_auto_ptr: +          { +            bool simple (true); +            IsSimpleType t (simple); +            t.dispatch (e.type ()); +            ptr = !simple; +            break; +          } +        case CtorArgType::poly_auto_ptr: +          { +            ptr = polymorphic && polymorphic_p (e.type ()); +            break; +          } +        case CtorArgType::type: +          break; +        } + +        if (ptr) +          os << comma () << auto_ptr << "< " << etype (e) << " >"; +        else +          os << comma () << "const " << etype (e) << "&"; + +        if (arg_) +          os << " " << ename (e); +      } +    } + +    void CtorArgsWithoutBase:: +    traverse (SemanticGraph::Attribute& a) +    { +      // Note that we are not going to include attributes with +      // default or required fixed values here. Instead we are +      // going to default-initialize them. +      // +      if (min (a) == 1 && !a.fixed_p ()) +      { +        os << comma () << "const " << etype (a) << "&"; + +        if (arg_) +          os << " " << ename (a); +      } +    } + +    String CtorArgsWithoutBase:: +    comma () +    { +      bool tmp (first_); +      first_ = false; +      return tmp ? "" : ",\n"; +    } + +    // GlobalElementBase +    // +    bool GlobalElementBase:: +    generate_p (SemanticGraph::Element& e) +    { +      if (e.substitutes_p () && ctx_.polymorphic) +        return true; + +      if (!doc_root_p (e)) +        return false; + +      // If we are not generating element types nor parsing/serialization +      // code then we won't generate anything from it. +      // +      if (!ctx_.options.generate_element_type () && +          ctx_.options.suppress_parsing () && +          !ctx_.options.generate_serialization ()) +        return false; + +      return true; +    } + +    bool GlobalElementBase:: +    doc_root_p (SemanticGraph::Element& e) +    { +      if (!ctx_.options.root_element_first () && +          !ctx_.options.root_element_last () && +          !ctx_.options.root_element_all () && +          !ctx_.options.root_element_none () && +          ctx_.options.root_element ().empty ()) +        return true; // By default treat them all. + +      if (ctx_.options.root_element_none ()) +        return false; + +      if (ctx_.options.root_element_all ()) +        return true; + +      if (ctx_.options.root_element_first () && +          e.context ().count ("first") != 0) +        return true; + +      if (ctx_.options.root_element_last () && +          e.context ().count ("last") != 0) +        return true; + +      NarrowStrings const& names (ctx_.options.root_element ()); + +      // Hopefully nobody will specify more than a handful of names ;-). +      // +      for (NarrowStrings::const_iterator i (names.begin ()); +           i != names.end (); ++i) +      { +        String name (*i); + +        if (e.name () == name) +          return true; +      } + +      return false; +    } + +    // Namespace +    // +    Namespace:: +    Namespace (Context& c, +               size_t first, +               size_t last) +        : CXX::Namespace (c, *this), +          GlobalElementBase (c), +          ctx_ (c), +          first_ (first), +          last_ (last), +          count_ (0) +    { +    } + +    void Namespace:: +    traverse (Type& ns) +    { +      using SemanticGraph::Element; + +      if (first_ > last_) +        CXX::Namespace::traverse (ns); +      else +      { +        bool opened (false); + +        for (Type::NamesIterator i (ns.names_begin ()); +             i != ns.names_end (); ++i) +        { +          SemanticGraph::Nameable& n (i->named ()); + +          if (n.is_a<SemanticGraph::Type> () || +              (n.is_a<Element> () && generate_p (dynamic_cast<Element&> (n)))) +          { +            if (count_ >= first_ && count_ <= last_) +            { +              if (!opened) +              { +                opened = true; +                pre (ns); +              } + +              edge_traverser ().dispatch (*i); +            } + +            ++count_; +          } +        } + +        if (opened) +          post (ns); +      } +    } + +    void Namespace:: +    enter (Type&, String const& name, bool) +    { +      ctx_.enter_ns_scope (name); +    } + +    void Namespace:: +    leave () +    { +      ctx_.leave_ns_scope (); +    } + +    // Includes +    // +    void TypeForward:: +    traverse (SemanticGraph::Type& t) +    { +      String const& name (ename (t)); + +      if (String custom = custom_type (t)) +      { +        String new_name; +        renamed_type (t, new_name); + +        if (new_name) +          os << "class " << new_name << ";"; + +        if (custom == name) +          os << "class " << name << ";"; +        else +          os << "typedef " << custom << " " << name << ";"; +      } +      else +        os << "class " << name << ";"; +    } + +    void Includes:: +    traverse_ (SemanticGraph::Uses& u) +    { +      // Support for weak (forward) inclusion used in the file-per-type +      // compilation model. +      // +      Type t (type_); +      bool weak (u.context ().count ("weak")); +      SemanticGraph::Schema& s (u.schema ()); + +      if (weak && t == header) +      { +        // Generate forward declarations. +        // +        if (forward_) +          t = forward; +        else +        { +          schema_.dispatch (s); +          return; +        } +      } + +      if (t == source && !weak) +      { +        if (u.user ().context ().count ("type-schema")) +        { +          // Strong include into a type schema -- this is a base class. +          // We have already included its header in our header so it +          // would seem we don't need to do anything here. There is one +          // subtle issue, however: Our constructors include arguments +          // for base members which we simply pass to the base. The base +          // header has only forward declarations for its members. This +          // is not a problem if we pass references to base members -- +          // forward declarations are sufficient for this case. The +          // problematic case is when we pass them as auto/unique_ptr. +          // Because we pass them by value (which is done to support +          // unique_ptr move semantics), the compiler needs to be able +          // to destroy the member, presumably if an exception is thrown. +          // And for that forward declarations are not enough. +          // +          // So what we are going to do here is include all the base +          // member headers (transitively), just like the base's source +          // file does. +          // +          // Note that we only do this for source since in the inline +          // case the necessary files are already pulled via the the +          // .ixx file includes. +          // +          Traversal::Schema schema; +          schema >> *this; +          schema.dispatch (s); +        } + +        return; +      } + +      SemanticGraph::Path path ( +        s.context ().count ("renamed") +        ? s.context ().get<SemanticGraph::Path> ("renamed") +        : u.path ()); +      path.normalize (); + +      // Try to use the portable representation of the path. If that +      // fails, fall back to the native representation. +      // +      NarrowString path_str; +      try +      { +        path_str = path.posix_string (); +      } +      catch (SemanticGraph::InvalidPath const&) +      { +        path_str = path.string (); +      } + +      String inc_path; + +      switch (t) +      { +      case forward: +        { +          inc_path = ctx_.fwd_expr->replace (path_str); +          break; +        } +      case header: +      case source: +        { +          inc_path = ctx_.hxx_expr->replace (path_str); +          break; +        } +      case inline_: +        { +          if (weak) +          { +            inc_path = ctx_.hxx_expr->replace (path_str); +            ctx_.os << "#include " << ctx_.process_include_path (inc_path) +                    << endl; +          } + +          inc_path = ctx_.ixx_expr->replace (path_str); +          break; +        } +      } + +      ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl +              << endl; +    } +  } +} diff --git a/xsd/cxx/tree/elements.hxx b/xsd/cxx/tree/elements.hxx new file mode 100644 index 0000000..4d10def --- /dev/null +++ b/xsd/cxx/tree/elements.hxx @@ -0,0 +1,2122 @@ +// file      : xsd/cxx/tree/elements.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_ELEMENTS_HXX +#define XSD_CXX_TREE_ELEMENTS_HXX + +#include <map> +#include <set> +#include <deque> +#include <vector> +#include <sstream> + +#include <libcutl/re.hxx> + +#include <xsd/types.hxx> + +#include <xsd/cxx/elements.hxx> + +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ +  namespace Tree +  { +    struct Counts +    { +      Counts () +          : global_types (0), +            global_elements (0), +            generated_global_elements (0), +            complexity_total (0) +      { +      } + +      size_t global_types; +      size_t global_elements; +      size_t generated_global_elements; + +      // Complexity value for each global type and generated global +      // element, in order. +      // +      std::vector<size_t> complexity; +      size_t complexity_total; +    }; + +    struct InvalidCustomTypeMapping +    { +      InvalidCustomTypeMapping (String const& mapping, +                                String const& reason) +          : mapping_ (mapping), reason_ (reason) +      { +      } + +      String const& +      mapping () const +      { +        return mapping_; +      } + +      String const& +      reason () const +      { +        return reason_; +      } + +    private: +      String mapping_; +      String reason_; +    }; + +    // A set of potentially qualified XML Schema type names. +    // +    struct TypeNameSet +    { +      template <typename I> +      TypeNameSet (I begin, I end) +      { +        for (; begin != end; ++begin) +          insert (*begin); +      } + +      void +      insert (String const& name) +      { +        size_t p (name.rfind ('#')); + +        if (p == String::npos) +          unames_.insert (name); +        else +          qnames_.insert (name); +      } + +      bool +      find (SemanticGraph::Type& t) +      { +        if (!unames_.empty ()) +        { +          if (unames_.find (t.name ()) != unames_.end ()) +            return true; +        } + +        if (!qnames_.empty ()) +        { +          if (qnames_.find (t.scope ().name () + L"#" + t.name ()) != +              qnames_.end ()) +            return true; +        } + +        return false; +      } + +    private: +      typedef std::set<String> StringSet; + +      StringSet unames_; +      StringSet qnames_; +    }; + +    // +    // +    class Context: public CXX::Context +    { +    public: +      typedef cutl::re::regexsub Regex; +      typedef cutl::re::wregex WideRegexPat; + +      typedef Tree::options options_type; + +      struct DirectCustomTypeMapInfo +      { +        DirectCustomTypeMapInfo (String const& t = L"", +                                 String const& b = L"") +            : type (t), base (b) +        { +        } + +        String type; +        String base; +      }; + +      struct RegexCustomTypeMapInfo +      { +        RegexCustomTypeMapInfo (WideRegexPat const& p, +                                String const& t, +                                String const& b) +            : pat (p), type_sub (t), base_sub (b) +        { +        } + +        WideRegexPat pat; +        String type_sub; +        String base_sub; +      }; + +      typedef std::vector<RegexCustomTypeMapInfo> RegexCustomTypeMap; +      typedef std::map<String, DirectCustomTypeMapInfo> DirectCustomTypeMap; + +    public: +      Context (std::wostream& o, +               SemanticGraph::Schema& root, +               SemanticGraph::Path const& path, +               options_type const& ops, +               Counts const& counts_, +               bool generate_xml_schema, +               StringLiteralMap const*, +               Regex const* fwd_expr, +               Regex const* hxx_expr, +               Regex const* ixx_expr); + +    protected: +      Context (Context& c); +      Context (Context& c, std::wostream& o); + +      // Custom type mapping. +      // +    public: +      // Returns empty string if custom mapping is not required. +      // +      String +      custom_type (SemanticGraph::Type const&) const; + +      // Returns true if custom mapping is required. name is +      // populated with the custom type name or empty if the +      // original name should be used. +      // +      bool +      custom_type (SemanticGraph::Type const&, String& name) const; + +      // Returns true if this type has been renamed as part of the +      // customization process. If the function returns true, the +      // name string is populated with the new name or empty if +      // the type should not be generated at all. +      // +      bool +      renamed_type (SemanticGraph::Type const&, String& name) const; + +    public: +      // Performs a number of processing steps, including forcing a new +      // line after 80 characters as well as "commentizing" the text by +      // adding '* ' after each newline. +      // +      void +      write_annotation (SemanticGraph::Annotation&); + +      // +      // +    public: +      static bool +      ordered_p (SemanticGraph::Type const& t) +      { +        return t.context ().count ("ordered") && +          t.context ().get<bool> ("ordered"); +      } + +      // Check if we are generating mixed support for this type. We only +      // do it for ordered types. +      // +      static bool +      mixed_p (SemanticGraph::Complex const& c) +      { +        return c.mixed_p () && ordered_p (c); +      } + +      bool +      polymorphic_p (SemanticGraph::Type&); + +      bool +      anonymous_p (SemanticGraph::Type const& t) +      { +        return t.context ().count ("anonymous"); +      } + +      // Return true if this anonymous type is defined in an element +      // that belongs to a substitution group. +      // +      bool +      anonymous_substitutes_p (SemanticGraph::Type&); + +      // Escaped names. +      // +    public: +      // Accessor name. +      // +      static String const& +      eaname (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("aname"); +      } + +      static String const& +      eaname (SemanticGraph::Any const& a) +      { +        return a.context ().get<String> ("aname"); +      } + +      static String const& +      eaname (SemanticGraph::AnyAttribute const& a) +      { +        return a.context ().get<String> ("aname"); +      } + +      // Modifier name. +      // +      static String const& +      emname (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("mname"); +      } + +      static String const& +      emname (SemanticGraph::Any const& a) +      { +        return a.context ().get<String> ("mname"); +      } + +      static String const& +      emname (SemanticGraph::AnyAttribute const& a) +      { +        return a.context ().get<String> ("mname"); +      } + +      // Detach name. +      // +      static String const& +      edname (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("dname"); +      } + +      // +      // +      static String const& +      etype (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("type"); +      } + +      static String const& +      etraits (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("traits"); +      } + +      static String const& +      econtainer (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("container"); +      } + +      static String const& +      econtainer (SemanticGraph::Any const& a) +      { +        return a.context ().get<String> ("container"); +      } + +      static String const& +      econtainer (SemanticGraph::AnyAttribute const& a) +      { +        return a.context ().get<String> ("container"); +      } + +      static String const& +      eiterator (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("iterator"); +      } + +      static String const& +      eiterator (SemanticGraph::Any const& a) +      { +        return a.context ().get<String> ("iterator"); +      } + +      static String const& +      eiterator (SemanticGraph::AnyAttribute const& a) +      { +        return a.context ().get<String> ("iterator"); +      } + +      static String const& +      econst_iterator (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("const-iterator"); +      } + +      static String const& +      econst_iterator (SemanticGraph::Any const& a) +      { +        return a.context ().get<String> ("const-iterator"); +      } + +      static String const& +      econst_iterator (SemanticGraph::AnyAttribute const& a) +      { +        return a.context ().get<String> ("const-iterator"); +      } + +      static String const& +      emember (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("member"); +      } + +      static String const& +      emember (SemanticGraph::Any const& a) +      { +        return a.context ().get<String> ("member"); +      } + +      static String const& +      emember (SemanticGraph::AnyAttribute const& a) +      { +        return a.context ().get<String> ("member"); +      } + +      static String const& +      edefault_value (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("default-value"); +      } + +      static String const& +      edefault_value_member (SemanticGraph::Member const& m) +      { +        return m.context ().get<String> ("default-value-member"); +      } + +      // Underlying enum value type. +      // +      static String const& +      evalue (SemanticGraph::Enumeration const& e) +      { +        return e.context ().get<String> ("value"); +      } + +      // dom_document +      // +      static bool +      edom_document_p (SemanticGraph::Complex const& c) +      { +        return c.context ().count ("dom-document"); +      } + +      static String const& +      edom_document (SemanticGraph::Complex const& c) +      { +        return c.context ().get<String> ("dom-document"); +      } + +      static bool +      edom_document_member_p (SemanticGraph::Complex const& c) +      { +        return c.context ().count ("dom-document-member"); +      } + +      static String const& +      edom_document_member (SemanticGraph::Complex const& c) +      { +        return c.context ().get<String> ("dom-document-member"); +      } + +      // Parsing and serialization function names. +      // +      static String const& +      eparser (SemanticGraph::Element const& e) +      { +        return e.context ().get<String> ("parser"); +      } + +      static String const& +      eserializer (SemanticGraph::Element const& e) +      { +        return e.context ().get<String> ("serializer"); +      } + +    public: +      void +      enter_ns_scope (String const& name) +      { +        ns_scope_stack.push_back (name); +        update_ns_scope (); +      } + +      void +      leave_ns_scope () +      { +        ns_scope_stack.pop_back (); +        update_ns_scope (); +      } + +    private: +      void +      update_ns_scope (); + +    private: +      // Write text that may contain characters that we will have +      // to escape (indicated by the rogue flag). +      // +      void +      write_rogue_text (wchar_t const* s, size_t size, bool rogue); + +    public: +      options_type const& options; +      Counts const& counts; +      String& any_type; +      String& any_simple_type; +      String& element_type; +      String& container; +      String& flags_type; +      String& qname_type; +      String& xs_string_type; +      String& properties_type; +      String& error_handler_type; +      String& list_stream_type; +      String& namespace_infomap_type; +      String& parser_type; +      String& std_ostream_type; +      String& ostream_type; +      String& istream_type; +      String& xerces_ns; +      String& dom_auto_ptr; +      String& dom_node_key; +      String& as_double_type; +      String& as_decimal_type; + +      bool& generate_xml_schema; +      bool& doxygen; +      bool polymorphic; +      bool polymorphic_all; +      unsigned long poly_plate; +      bool detach; + +      Regex const* fwd_expr; +      Regex const* hxx_expr; +      Regex const* ixx_expr; + +      String& ns_scope; + +      RegexCustomTypeMap& regex_custom_type_map; +      DirectCustomTypeMap& direct_custom_type_map; + +    private: +      String any_type_; +      String any_simple_type_; +      String element_type_; +      String container_; +      String flags_type_; +      String qname_type_; +      String xs_string_type_; +      String properties_type_; +      String error_handler_type_; +      String list_stream_type_; +      String namespace_infomap_type_; +      String parser_type_; +      String std_ostream_type_; +      String ostream_type_; +      String istream_type_; +      String xerces_ns_; +      String dom_auto_ptr_; +      String dom_node_key_; +      String as_double_type_; +      String as_decimal_type_; + +      bool generate_xml_schema_; +      bool doxygen_; + +      typedef std::deque<String> NamespaceStack; +      typedef std::deque<String> ScopeStack; + +      String ns_scope_; + +      NamespaceStack& ns_scope_stack; +      NamespaceStack ns_scope_stack_; + +      RegexCustomTypeMap regex_custom_type_map_; +      DirectCustomTypeMap direct_custom_type_map_; + +    private: +      WideRegexPat const cxx_uq_id_expr_; +      WideRegexPat const& cxx_uq_id_expr; +    }; + +    // Check whether this Schema type maps to a fundamental C++ type. +    // +    struct IsFundamentalType: Traversal::Fundamental::Byte, +                              Traversal::Fundamental::UnsignedByte, +                              Traversal::Fundamental::Short, +                              Traversal::Fundamental::UnsignedShort, +                              Traversal::Fundamental::Int, +                              Traversal::Fundamental::UnsignedInt, +                              Traversal::Fundamental::Long, +                              Traversal::Fundamental::UnsignedLong, +                              Traversal::Fundamental::Integer, +                              Traversal::Fundamental::NonPositiveInteger, +                              Traversal::Fundamental::NonNegativeInteger, +                              Traversal::Fundamental::PositiveInteger, +                              Traversal::Fundamental::NegativeInteger, + +                              Traversal::Fundamental::Boolean, + +                              Traversal::Fundamental::Float, +                              Traversal::Fundamental::Double, +                              Traversal::Fundamental::Decimal + +    { +      IsFundamentalType (bool& r) +          : r_ (r) +      { +      } + +      // Integral types. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Byte&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedByte&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Short&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedShort&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Int&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedInt&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Long&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedLong&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Integer&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonPositiveInteger&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonNegativeInteger&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::PositiveInteger&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NegativeInteger&) +      { +        r_ = true; +      } + +      // Boolean. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Boolean&) +      { +        r_ = true; +      } + +      // Floats. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Float&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Double&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Decimal&) +      { +        r_ = true; +      } + +    private: +      bool& r_; +    }; + +    // Check whether this is a string-based type. +    // +    struct IsStringBasedType: Traversal::Complex, +                              Traversal::Union, +                              Traversal::Fundamental::String, +                              Traversal::Fundamental::NormalizedString, +                              Traversal::Fundamental::Token, +                              Traversal::Fundamental::Name, +                              Traversal::Fundamental::NameToken, +                              Traversal::Fundamental::NCName, +                              Traversal::Fundamental::Language +    { +      IsStringBasedType (bool& r) +          : r_ (r) +      { +        *this >> inherits_ >> *this; +      } + +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        inherits (c, inherits_); +      } + +      virtual void +      traverse (SemanticGraph::Union&) +      { +        // Current mapping of union is string-based. +        // +        r_ = true; +      } + +      // Strings. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::String&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NormalizedString&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Token&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NameToken&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Name&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NCName&) +      { +        r_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Language&) +      { +        r_ = true; +      } + +    private: +      bool& r_; +      Traversal::Inherits inherits_; +    }; + + +    // Check whether this is a enumeration-based type. +    // +    struct IsEnumBasedType: Traversal::Complex +    { +      IsEnumBasedType (SemanticGraph::Enumeration*& e) +          : enum_ (e) +      { +        *this >> inherits_; + +        inherits_ >> *this; +        inherits_ >> enum_; +      } + +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        inherits (c, inherits_); +      } + +    private: +      struct Enumeration: Traversal::Enumeration +      { +        Enumeration (SemanticGraph::Enumeration*& e) +            : e_ (e) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (e_ == 0) +            e_ = &e; +        } + +      private: +        SemanticGraph::Enumeration*& e_; +      }; + + +    private: +      Enumeration enum_; +      Traversal::Inherits inherits_; +    }; + + +    // +    // +    struct MemberTypeName : Context, +                            Traversal::Type, +                            Traversal::List, +                            Traversal::Union, +                            Traversal::Complex, + +                            Traversal::AnyType, +                            Traversal::AnySimpleType, + +                            Traversal::Fundamental::Byte, +                            Traversal::Fundamental::UnsignedByte, +                            Traversal::Fundamental::Short, +                            Traversal::Fundamental::UnsignedShort, +                            Traversal::Fundamental::Int, +                            Traversal::Fundamental::UnsignedInt, +                            Traversal::Fundamental::Long, +                            Traversal::Fundamental::UnsignedLong, +                            Traversal::Fundamental::Integer, +                            Traversal::Fundamental::NonPositiveInteger, +                            Traversal::Fundamental::NonNegativeInteger, +                            Traversal::Fundamental::PositiveInteger, +                            Traversal::Fundamental::NegativeInteger, + +                            Traversal::Fundamental::Boolean, + +                            Traversal::Fundamental::Float, +                            Traversal::Fundamental::Double, +                            Traversal::Fundamental::Decimal, + +                            Traversal::Fundamental::String, +                            Traversal::Fundamental::NormalizedString, +                            Traversal::Fundamental::Token, +                            Traversal::Fundamental::Name, +                            Traversal::Fundamental::NameToken, +                            Traversal::Fundamental::NameTokens, +                            Traversal::Fundamental::NCName, +                            Traversal::Fundamental::Language, + +                            Traversal::Fundamental::QName, + +                            Traversal::Fundamental::Id, +                            Traversal::Fundamental::IdRef, +                            Traversal::Fundamental::IdRefs, + +                            Traversal::Fundamental::AnyURI, + +                            Traversal::Fundamental::Base64Binary, +                            Traversal::Fundamental::HexBinary, + +                            Traversal::Fundamental::Date, +                            Traversal::Fundamental::DateTime, +                            Traversal::Fundamental::Duration, +                            Traversal::Fundamental::Day, +                            Traversal::Fundamental::Month, +                            Traversal::Fundamental::MonthDay, +                            Traversal::Fundamental::Year, +                            Traversal::Fundamental::YearMonth, +                            Traversal::Fundamental::Time, + +                            Traversal::Fundamental::Entity, +                            Traversal::Fundamental::Entities + +    { +      MemberTypeName (Context& c) +          : Context (c) +      { +      } + +      MemberTypeName (Context& c, std::wostream& o) +          : Context (c, o) +      { +      } + +      virtual void +      traverse (SemanticGraph::Type&) +      { +        abort (); +      } + +      virtual void +      traverse (SemanticGraph::List& l) +      { +        os << fq_name (l); +      } + +      virtual void +      traverse (SemanticGraph::Union& u) +      { +        os << fq_name (u); +      } + +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        os << fq_name (c); +      } + +      // anyType & anySimpleType. +      // +      virtual void +      traverse (SemanticGraph::AnyType& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::AnySimpleType& t) +      { +        os << fq_name (t); +      } + +      // Integral types. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Byte& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedByte& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Short& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedShort& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Int& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedInt& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Long& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedLong& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Integer& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::PositiveInteger& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NegativeInteger& t) +      { +        os << fq_name (t); +      } + +      // Boolean. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Boolean& t) +      { +        os << fq_name (t); +      } + +      // Floats. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Float& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Double& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Decimal& t) +      { +        os << fq_name (t); +      } + +      // Strings. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::String& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NormalizedString& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Token& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NameToken& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NameTokens& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Name& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NCName& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Language& t) +      { +        os << fq_name (t); +      } + + +      // Qualified name. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::QName& t) +      { +        os << fq_name (t); +      } + + +      // ID/IDREF. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Id& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRef& t) +      { +        if (t.named_p ()) +        { +          // IDREF<anyType> +          // +          os << fq_name (t); +        } +        else +        { +          SemanticGraph::Nameable& ncname ( +            xs_ns ().find ("NCName").first->named ()); + +          os << "::xsd::cxx::tree::idref< " << char_type << ", " << +            fq_name (ncname) << ", "  << +            type_name (t.argumented ().type ()) << " >"; +        } +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRefs& t) +      { +        if (t.named_p ()) +        { +          // IDREFS<anyType> +          // +          os << fq_name (t); +        } +        else +        { +          SemanticGraph::Nameable& ncname ( +            xs_ns ().find ("NCName").first->named ()); + +          os << "::xsd::cxx::tree::idrefs< " << char_type << ", " << +            any_simple_type << ", ::xsd::cxx::tree::idref< " << +            char_type << ", " << fq_name (ncname) << ", " << +            type_name (t.argumented ().type ()) << " > >"; +        } +      } + +      // URI. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::AnyURI& t) +      { +        os << fq_name (t); +      } + +      // Binary. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Base64Binary& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::HexBinary& t) +      { +        os << fq_name (t); +      } + + +      // Date/time. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Date& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::DateTime& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Duration& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Day& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Month& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::MonthDay& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Year& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::YearMonth& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Time& t) +      { +        os << fq_name (t); +      } + +      // Entity. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Entity& t) +      { +        os << fq_name (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Entities& t) +      { +        os << fq_name (t); +      } + +    private: +      // For idref/idrefs +      // +      String +      type_name (SemanticGraph::Type& t) +      { +        // This type is always named. +        // +        std::wostringstream o; + +        MemberTypeName type (*this, o); +        type.dispatch (t); + +        return o.str (); +      } +    }; + + +    // +    // +    struct BaseTypeName : MemberTypeName +    { +      BaseTypeName (Context& c) +          : MemberTypeName (c) +      { +      } + +      BaseTypeName (Context& c, std::wostream& o) +          : MemberTypeName (c, o) +      { +      } + +      virtual void +      fundamental_base (SemanticGraph::Type& t) +      { +        os << "::xsd::cxx::tree::fundamental_base< " << +          fq_name (t) << ", " << char_type << ", " << +          any_simple_type << " >"; +      } + +      // Integrals. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Byte& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedByte& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Short& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedShort& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Int& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedInt& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Long& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedLong& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Integer& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::PositiveInteger& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NegativeInteger& t) +      { +        fundamental_base (t); +      } + +      // Boolean. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Boolean& t) +      { +        fundamental_base (t); +      } + +      // Floats. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Float& t) +      { +        fundamental_base (t); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Double& t) +      { +        os << "::xsd::cxx::tree::fundamental_base< " << +          fq_name (t) << ", " << char_type << ", " << +          any_simple_type << ", " << +          "::xsd::cxx::tree::schema_type::double_ >"; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Decimal& t) +      { +        os << "::xsd::cxx::tree::fundamental_base< " << +          fq_name (t) << ", " << char_type << ", " << +          any_simple_type << ", " << +          "::xsd::cxx::tree::schema_type::decimal >"; +      } +    }; + +    // Initial value should be true. +    // +    struct IsSimpleType: Traversal::Complex, +                         Traversal::Member, +                         Traversal::Any, +                         Traversal::AnyAttribute +    { +      IsSimpleType (bool& v) +          : v_ (v) +      { +        *this >> names_ >> *this; +        *this >> inherits_ >> *this; +      } + +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        if (c.mixed_p ()) +          v_ = false; + +        if (v_) +          names (c, names_); + +        if (v_) +          inherits (c, inherits_); +      } + +      virtual void +      traverse (SemanticGraph::Member&) +      { +        v_ = false; +      } + +      virtual void +      traverse (SemanticGraph::Any&) +      { +        v_ = false; +      } + +      virtual void +      traverse (SemanticGraph::AnyAttribute&) +      { +        v_ = false; +      } + +    private: +      bool& v_; +      Traversal::Names names_; +      Traversal::Inherits inherits_; +    }; + +    // Test whether we need to generate default c-tor. Note that we are not +    // interested in anyAttribute since it is always mapped to a sequence. +    // +    struct GenerateDefaultCtor: Traversal::Complex, +                                Traversal::Enumeration, +                                Traversal::Type, +                                Traversal::Element, +                                Traversal::Attribute, +                                Traversal::Any, +                                Context +    { +      // generate should initially be false. +      // +      GenerateDefaultCtor (Context&, bool& generate, bool no_base); + +      virtual void +      traverse (SemanticGraph::Complex&); + +      virtual void +      traverse (SemanticGraph::Type&); + +      virtual void +      traverse (SemanticGraph::Enumeration&); + +      virtual void +      traverse (SemanticGraph::Element&); + +      virtual void +      traverse (SemanticGraph::Attribute&); + +      virtual void +      traverse (SemanticGraph::Any&); + +    private: +      bool& generate_; +      bool no_base_; + +    private: +      Traversal::Inherits inherits_; +      Traversal::Names names_; +    }; + +    // Test whether we need to generate from-base c-tor. +    // +    struct GenerateFromBaseCtor: Traversal::Complex +    { +      // generate should initially be false. +      // +      GenerateFromBaseCtor (Context& c, bool& generate); + +      virtual void +      traverse (SemanticGraph::Complex& c); + +    private: +      bool& generate_; +      bool custom_; + +      // Note that we are not interested in anyAttribute since it is always +      // mapped to a sequence. +      // +      struct Traverser: Traversal::Type, +                        Traversal::Complex, +                        Traversal::Element, +                        Traversal::Attribute, +                        Traversal::Any, +                        Context +      { +        Traverser (Context& c, bool& generate, bool& custom); + +        virtual void +        traverse (SemanticGraph::Type&); + +        virtual void +        traverse (SemanticGraph::Complex&); + +        virtual void +        traverse (SemanticGraph::Attribute&); + +        virtual void +        traverse (SemanticGraph::Element&); + +        virtual void +        traverse (SemanticGraph::Any&); + +      private: +        bool& generate_; +        bool& custom_; + +      private: +        Traversal::Inherits inherits_; +        Traversal::Names names_; +      } traverser_; + +      Traversal::Inherits inherits_; +    }; + +    // Test whether the type has any non-optional element of complex +    // (has attributes/elements) and polymorpjic types. +    // +    struct HasComplexPolyNonOptArgs: Traversal::Complex, +                                     Traversal::Element, +                                     Context +    { +      // complex and poly should initially be false. clash +      // should initially be true. +      // +      HasComplexPolyNonOptArgs (Context& c, +                                bool including_base, +                                bool& complex, +                                bool& poly, +                                bool& clash); + +      virtual void +      traverse (SemanticGraph::Complex&); + +      virtual void +      traverse (SemanticGraph::Element&); + +    private: +      bool& complex_; +      bool& poly_; +      bool& clash_; + +      Traversal::Inherits inherits_; +      Traversal::Names names_; +    }; + +    // Contructor argument types. +    // +    struct CtorArgType +    { +      enum Value +      { +        type, +        complex_auto_ptr, +        poly_auto_ptr +      }; + +      CtorArgType (Value v = Value (0)) : v_ (v) {} +      operator Value () const {return v_;} + +    private: +      Value v_; +    }; + +    // Immediate non-optional member. Note that AnyAttribute is always +    // mapped to a sequence. +    // +    struct FromBaseCtorArg: Traversal::Any, +                            Traversal::Element, +                            Traversal::Attribute, +                            Context +    { +      FromBaseCtorArg (Context& c, CtorArgType, bool arg); + +      virtual void +      traverse (SemanticGraph::Any&); + +      virtual void +      traverse (SemanticGraph::Attribute&); + +      virtual void +      traverse (SemanticGraph::Element&); + +    private: +      CtorArgType arg_type_; +      bool arg_; +    }; + +    // List of all non-optional members and a simple base. Note that +    // AnyAttribute is always mapped to a sequence. +    // +    struct CtorArgs: Traversal::Complex, +                     Traversal::Enumeration, +                     Traversal::Type, +                     Traversal::Any, +                     Traversal::Element, +                     Traversal::Attribute, +                     Context +    { +      using Complex::traverse; + +      // The second version outputs the argument name and stores +      // in in the base_arg string. +      // +      CtorArgs (Context&, CtorArgType); +      CtorArgs (Context&, CtorArgType, String& base_arg); + +      virtual void +      traverse (SemanticGraph::Type&); + +      virtual void +      traverse (SemanticGraph::Enumeration&); + +      virtual void +      traverse (SemanticGraph::Any&); + +      virtual void +      traverse (SemanticGraph::Attribute&); + +      virtual void +      traverse (SemanticGraph::Element&); + +    private: +      String +      comma (); + +    private: +      CtorArgType arg_type_; +      String base_; +      String* base_arg_; +      bool first_; + +    private: +      Traversal::Inherits inherits_; +      Traversal::Names names_; + +      MemberTypeName member_name_; +    }; + + +    // Check whether we need to generate c-tor without the base argument. +    // +    struct GenerateWithoutBaseCtor: Traversal::List, +                                    Traversal::Union, +                                    Traversal::Complex, +                                    Traversal::Enumeration, + +                                    Traversal::AnyType, +                                    Traversal::AnySimpleType, + +                                    Traversal::Fundamental::String, +                                    Traversal::Fundamental::NormalizedString, +                                    Traversal::Fundamental::Token, + +                                    Traversal::Fundamental::NameTokens, +                                    Traversal::Fundamental::IdRefs, + +                                    Traversal::Fundamental::Base64Binary, +                                    Traversal::Fundamental::HexBinary +    { +      // generate should initially be false. +      // +      GenerateWithoutBaseCtor (bool& generate) +          : generate_ (generate) +      { +        *this >> inherits_ >> *this; +      } + +      virtual void +      traverse (SemanticGraph::List&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Union&) +      { +        // No default initialization. +      } + +      virtual void +      traverse (SemanticGraph::Complex& c) +      { +        Complex::inherits (c); +      } + +      virtual void +      traverse (SemanticGraph::Enumeration&) +      { +        // No default initialization. +      } + +      virtual void +      traverse (SemanticGraph::AnyType&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::AnySimpleType&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::String&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NormalizedString&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Token&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NameTokens&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRefs&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Base64Binary&) +      { +        generate_ = true; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::HexBinary&) +      { +        generate_ = true; +      } + +    private: +      bool& generate_; +      Traversal::Inherits inherits_; +    }; + + +    // List of all non-optional members sans simple base. Note that +    // AnyAttribute is always mapped to a sequence. +    // +    struct CtorArgsWithoutBase: Traversal::Complex, +                                Traversal::Any, +                                Traversal::Element, +                                Traversal::Attribute, +                                Context +    { +      using Complex::traverse; + +      CtorArgsWithoutBase (Context& c, CtorArgType, bool arg, bool first); + +      virtual void +      traverse (SemanticGraph::Any&); + +      virtual void +      traverse (SemanticGraph::Element&); + +      virtual void +      traverse (SemanticGraph::Attribute&); + +    private: +      String +      comma (); + +    private: +      CtorArgType arg_type_; +      bool arg_; +      bool first_; + +    private: +      Traversal::Inherits inherits_; +      Traversal::Names names_; +    }; + +    // +    // +    struct GlobalElementBase +    { +      GlobalElementBase (Context& c) +          : ctx_ (c) +      { +      } + +      bool +      generate_p (SemanticGraph::Element&); + +      bool +      doc_root_p (SemanticGraph::Element&); + +    private: +      Context& ctx_; +    }; + + +    // +    // +    struct Namespace: CXX::Namespace, +                      GlobalElementBase, +                      CXX::Namespace::ScopeTracker +    { +      Namespace (Context&, +                 size_t first = 1, +                 size_t last = 0); + +      virtual void +      traverse (Type&); + +    protected: +      virtual void +      enter (Type&, String const& name, bool last); + +      virtual void +      leave (); + +    protected: +      Context& ctx_; + +    private: +      size_t first_; +      size_t last_; +      size_t count_; +    }; + +    // +    // +    struct DocumentedNamespace: Namespace +    { +      DocumentedNamespace (Context& c) +          : Namespace (c) +      { +      } + +      virtual void +      enter (Type& ns, String const& name, bool last) +      { +        Namespace::enter (ns, name, last); + +        // Only add documentation to the innermost namespace. +        // +        if (ctx_.doxygen && name && last) +        { +          ctx_.os << "/**" << endl +                  << " * @brief C++ namespace for the %" << +		  ctx_.comment (ns.name ()) << endl +                  << " * schema namespace." << endl +                  << " */" << endl; +        } +      } +    }; + +    // +    // +    struct TypeForward: Traversal::Type, Context +    { +      TypeForward (Context& c) +          : Context (c) +      { +      } + +      virtual void +      traverse (SemanticGraph::Type& t); +    }; + +    struct Includes: Traversal::Imports, +                     Traversal::Includes +    { +      enum Type +      { +        forward, +        header, +        inline_, +        source +      }; + +      Includes (Context& c, Type type) +          : ctx_ (c), +            type_ (type), +            forward_ (c.options.generate_forward ()), +            namespace_ (c), +            type_forward_ (c) +      { +        schema_ >> schema_names_ >> namespace_ >> names_ >> type_forward_; +      } + +      virtual void +      traverse (SemanticGraph::Imports& i) +      { +        traverse_ (i); +      } + +      virtual void +      traverse (SemanticGraph::Includes& i) +      { +        traverse_ (i); +      } + +    private: +      void +      traverse_ (SemanticGraph::Uses&); + +    private: +      Context& ctx_; +      Type type_; +      bool forward_; + +      Traversal::Schema schema_; +      Traversal::Names schema_names_; +      Namespace namespace_; +      Traversal::Names names_; +      TypeForward type_forward_; +    }; + +    // +    // +    struct FundIncludes: Traversal::Fundamental::Byte, +                         Traversal::Fundamental::UnsignedByte, +                         Traversal::Fundamental::Short, +                         Traversal::Fundamental::UnsignedShort, +                         Traversal::Fundamental::Int, +                         Traversal::Fundamental::UnsignedInt, +                         Traversal::Fundamental::Long, +                         Traversal::Fundamental::UnsignedLong, +                         Traversal::Fundamental::Integer, +                         Traversal::Fundamental::NonPositiveInteger, +                         Traversal::Fundamental::NonNegativeInteger, +                         Traversal::Fundamental::PositiveInteger, +                         Traversal::Fundamental::NegativeInteger, + +                         Traversal::Fundamental::Boolean, + +                         Traversal::Fundamental::Float, +                         Traversal::Fundamental::Double, +                         Traversal::Fundamental::Decimal, +                         Context +    { +      FundIncludes (Context& c, String const& prefix) +          : Context (c), prefix_ (prefix), +            long_ (false), unsigned_long_ (false) +      { +      } + +      // Integral types. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Byte& t) +      { +        gen_include (t, "byte.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedByte& t) +      { +        gen_include (t, "unsigned-byte.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Short& t) +      { +        gen_include (t, "short.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedShort& t) +      { +        gen_include (t, "unsigned-short.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Int& t) +      { +        gen_include (t, "int.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedInt& t) +      { +        gen_include (t, "unsigned-int.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Long& t) +      { +        if (!long_) +          long_ = gen_include (t, "long.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedLong& t) +      { +        if (!unsigned_long_) +          unsigned_long_ = gen_include (t, "unsigned-long.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Integer& t) +      { +        if (!long_) +          long_ = gen_include (t, "long.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +      { +        if (!long_) +          long_ = gen_include (t, "long.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +      { +        if (!unsigned_long_) +          unsigned_long_ = gen_include (t, "unsigned-long.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::PositiveInteger& t) +      { +        if (!unsigned_long_) +          unsigned_long_ = gen_include (t, "unsigned-long.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NegativeInteger& t) +      { +        if (!long_) +          long_ = gen_include (t, "long.hxx"); +      } + +      // Boolean. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Boolean& t) +      { +        gen_include (t, "boolean.hxx"); +      } + +      // Floats. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Float& t) +      { +        gen_include (t, "float.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Double& t) +      { +        gen_include (t, "double.hxx"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Decimal& t) +      { +        gen_include (t, "decimal.hxx"); +      } + +    private: +      bool +      gen_include (SemanticGraph::Type& t, String const& file) +      { +        String custom; + +        // XML Schema built-in type customization is only possible when +        // we are generating separate header. +        // +        if (generate_xml_schema && custom_type (t, custom)) +        { +          String new_name; +          renamed_type (t, new_name); + +          if (!new_name) +            return false; +        } + +        os << "#include <xsd/cxx/tree/" << prefix_ << "/" << file << ">" +           << endl; + +        return true; +      } + +    private: +      String prefix_; +      bool long_; +      bool unsigned_long_; +    }; +  } +} + +#endif  // XSD_CXX_TREE_ELEMENTS_HXX diff --git a/xsd/cxx/tree/fundamental-header.hxx b/xsd/cxx/tree/fundamental-header.hxx new file mode 100644 index 0000000..0ea82cf --- /dev/null +++ b/xsd/cxx/tree/fundamental-header.hxx @@ -0,0 +1,1337 @@ +// file      : xsd/cxx/tree/fundamental-header.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_FUNDAMENTAL_HEADER_HXX +#define XSD_CXX_TREE_FUNDAMENTAL_HEADER_HXX + +#include <set> +#include <vector> +#include <algorithm> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    struct FundamentalNamespace : DocumentedNamespace, + +                                  Traversal::AnyType, +                                  Traversal::AnySimpleType, + +                                  Traversal::Fundamental::Byte, +                                  Traversal::Fundamental::UnsignedByte, +                                  Traversal::Fundamental::Short, +                                  Traversal::Fundamental::UnsignedShort, +                                  Traversal::Fundamental::Int, +                                  Traversal::Fundamental::UnsignedInt, +                                  Traversal::Fundamental::Long, +                                  Traversal::Fundamental::UnsignedLong, +                                  Traversal::Fundamental::Integer, +                                  Traversal::Fundamental::NonPositiveInteger, +                                  Traversal::Fundamental::NonNegativeInteger, +                                  Traversal::Fundamental::PositiveInteger, +                                  Traversal::Fundamental::NegativeInteger, + +                                  Traversal::Fundamental::Boolean, + +                                  Traversal::Fundamental::Float, +                                  Traversal::Fundamental::Double, +                                  Traversal::Fundamental::Decimal, + +                                  Traversal::Fundamental::String, +                                  Traversal::Fundamental::NormalizedString, +                                  Traversal::Fundamental::Token, +                                  Traversal::Fundamental::Name, +                                  Traversal::Fundamental::NameToken, +                                  Traversal::Fundamental::NameTokens, +                                  Traversal::Fundamental::NCName, +                                  Traversal::Fundamental::Language, + +                                  Traversal::Fundamental::Id, +                                  Traversal::Fundamental::IdRef, +                                  Traversal::Fundamental::IdRefs, + +                                  Traversal::Fundamental::AnyURI, + +                                  Traversal::Fundamental::QName, + +                                  Traversal::Fundamental::Base64Binary, +                                  Traversal::Fundamental::HexBinary, + +                                  Traversal::Fundamental::Date, +                                  Traversal::Fundamental::DateTime, +                                  Traversal::Fundamental::Duration, +                                  Traversal::Fundamental::Day, +                                  Traversal::Fundamental::Month, +                                  Traversal::Fundamental::MonthDay, +                                  Traversal::Fundamental::Year, +                                  Traversal::Fundamental::YearMonth, +                                  Traversal::Fundamental::Time, + +                                  Traversal::Fundamental::Entity, +                                  Traversal::Fundamental::Entities, +                                  Context +    { +      using Namespace::traverse; + +      FundamentalNamespace (Context& c) +          : DocumentedNamespace (c), +            Context (c), +            export_ (c.options.export_xml_schema () && type_exp) +      { +        *this >> names_ >> *this; + +        if (export_) +          xs_ns_ = ns_name (xs_ns ()); +      } + +      void +      gen_typedef (String const& name, +                   String const& type, +                   String const& arg1 = L"", +                   String const& arg2 = L"", +                   String const& arg3 = L"", +                   bool export_type = true) +      { +        os << "typedef " << type; + +        // Use unqualified arguments since we are in the same +        // namespace. +        // +        if (arg1) +        { +          os << arg1; + +          if (arg2) +          { +            os << ", " << arg2; + +            if (arg3) +              os << ", " << arg3; +          } + +          os << " >"; +        } + +        os << " " << name << ";"; + +        if (export_type && export_ && type.find (L'<') != String::npos) +        { +          String s (type); + +          // Use qualified arguments. +          // +          if (arg1) +          { +            s += xs_ns_; +            s += L"::"; +            s += arg1; + +            if (arg2) +            { +              s += L", "; +              s += xs_ns_; +              s += L"::"; +              s += arg2; + +              if (arg3) +              { +                s += L", "; +                s += xs_ns_; +                s += L"::"; +                s += arg3; +              } +            } + +            s += " >"; +          } + +          if (exports_set_.count (s) == 0) +          { +            exports_.push_back (s); +            exports_set_.insert (s); +          } +        } +      } + +      String +      built_in_type (SemanticGraph::Type& t, +                     String const& type, +                     String const& arg1 = L"", +                     String const& arg2 = L"", +                     String const& arg3 = L"") +      { +        String custom; + +        String name (ename (t)); + +        // XML Schema built-in type customization is only possible when +        // we are generating separate header. +        // +        if (generate_xml_schema && custom_type (t, custom)) +        { +          if (custom.empty ()) +            custom = name; + +          String new_name; +          renamed_type (t, new_name); + +          if (new_name) +          { +            gen_typedef (new_name, type, arg1, arg2, arg3); + +            if (doxygen) +              os << endl; +          } + +          if (doxygen) +            os << "/**" << endl +               << " * @brief C++ type corresponding to the " << +              comment (t.name ()) << " XML Schema" << endl +               << " * built-in type." << endl +               << " */" << endl; + +          if (custom == name) +            os << "class " << name << ";"; +          else +            os << "typedef " << custom << " " << name << ";"; + +          if (doxygen) +            os << endl; +        } +        else +        { +          // Otherwise generate simple typedef. +          // + +          if (doxygen) +            os << "/**" << endl +               << " * @brief C++ type corresponding to the " << +              comment (t.name ()) << " XML Schema" << endl +               << " * built-in type." << endl +               << " */" << endl; + +          gen_typedef (name, type, arg1, arg2, arg3); + +          if (doxygen) +            os << endl; +        } + +        return name; +      } + +      // anyType and anySimpleType +      // +      virtual void +      traverse (SemanticGraph::AnyType& t) +      { +        os << "// anyType and anySimpleType." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        type_ = built_in_type (t, "::xsd::cxx::tree::type"); +      } + +      virtual void +      traverse (SemanticGraph::AnySimpleType& t) +      { +        simple_type_ = built_in_type ( +          t, L"::xsd::cxx::tree::simple_type< " + char_type + L", ", type_); + +        if (doxygen) +          os << "/**" << endl +             << " * @brief Alias for the anyType type." << endl +             << " */" << endl; + +        gen_typedef (xs_ns ().context().get<String> ("container"), +                     "::xsd::cxx::tree::type"); + +        os << endl; + +        if (doxygen) +          os << endl; +      } + +      // Integrals. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Byte& t) +      { +        os << "// 8-bit" << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        built_in_type (t, "signed char"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedByte& t) +      { +        built_in_type (t, "unsigned char"); +        os << endl; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Short& t) +      { +        os << "// 16-bit" << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        built_in_type (t, "short"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedShort& t) +      { +        built_in_type (t, "unsigned short"); +        os << endl; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Int& t) +      { +        os << "// 32-bit" << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        built_in_type (t, "int"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedInt& t) +      { +        built_in_type (t, "unsigned int"); +        os << endl; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Long& t) +      { +        os << "// 64-bit" << endl +           << "//" <<endl; + +        if (doxygen) +          os << endl; + +        built_in_type (t, "long long"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::UnsignedLong& t) +      { +        built_in_type (t, "unsigned long long"); +        os << endl; +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Integer& t) +      { +        os << "// Supposed to be arbitrary-length integral types." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        built_in_type (t, "long long"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +      { +        built_in_type (t, "long long"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +      { +        built_in_type (t, "unsigned long long"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::PositiveInteger& t) +      { +        built_in_type (t, "unsigned long long"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NegativeInteger& t) +      { +        built_in_type (t, "long long"); +        os << endl; +      } + +      // Boolean. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Boolean& t) +      { +        os << "// Boolean." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        built_in_type (t, "bool"); + +        os << endl; +      } + +      // Floats. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Float& t) +      { +        os << "// Floating-point types." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        built_in_type (t, "float"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Double& t) +      { +        double_ = built_in_type (t, "double"); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Decimal& t) +      { +        decimal_ = built_in_type (t, "double"); +        os << endl; +      } + + +      // Strings. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::String& t) +      { +        os << "// String types." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        string_ = built_in_type ( +          t, L"::xsd::cxx::tree::string< " + char_type + L", ", simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NormalizedString& t) +      { +        norm_string_ = built_in_type ( +          t, +          L"::xsd::cxx::tree::normalized_string< " + char_type + L", ", +          string_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Token& t) +      { +        token_ = built_in_type ( +          t, L"::xsd::cxx::tree::token< " + char_type + L", ", norm_string_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NameToken& t) +      { +        nmtoken_ = built_in_type ( +          t, L"::xsd::cxx::tree::nmtoken< " + char_type + L", ", token_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NameTokens& t) +      { +        built_in_type ( +          t, +          L"::xsd::cxx::tree::nmtokens< " + char_type + L", ", +          simple_type_, +          nmtoken_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Name& t) +      { +        name_ = built_in_type ( +          t, L"::xsd::cxx::tree::name< " + char_type + L", ", token_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::NCName& t) +      { +        ncname_ = built_in_type ( +          t, L"::xsd::cxx::tree::ncname< " + char_type + L", ", name_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Language& t) +      { +        built_in_type ( +          t, L"::xsd::cxx::tree::language< " + char_type + L", ", token_); + +        os << endl; +      } + +      // ID/IDREF. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Id& t) +      { +        os << "// ID/IDREF." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        built_in_type ( +          t, L"::xsd::cxx::tree::id< " + char_type + L", ", ncname_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRef& t) +      { +        idref_ = built_in_type ( +          t, L"::xsd::cxx::tree::idref< " + char_type + L", ", ncname_, type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::IdRefs& t) +      { +        built_in_type ( +          t, +          L"::xsd::cxx::tree::idrefs< " + char_type + L", ", +          simple_type_, +          idref_); + +        os << endl; +      } + + +      // URI. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::AnyURI& t) +      { +        os << "// URI." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        uri_ = built_in_type ( +          t, L"::xsd::cxx::tree::uri< " + char_type + L", ", simple_type_); + +        os << endl; +      } + +      // Qualified name. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::QName& t) +      { +        os << "// Qualified name." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        built_in_type ( +          t, +          L"::xsd::cxx::tree::qname< " + char_type + L", ", +          simple_type_, +          uri_, +          ncname_); + +        os << endl; +      } + +      // Binary. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Base64Binary& t) +      { +        os << "// Binary." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl +             << "/**" << endl +             << " * @brief Binary buffer type." << endl +             << " */" << endl; + +        gen_typedef (xs_ns ().context().get<String> ("buffer"), +                     L"::xsd::cxx::tree::buffer< " + char_type + L" >"); + +        if (doxygen) +          os << endl; + +        built_in_type ( +          t, +          L"::xsd::cxx::tree::base64_binary< " + char_type + L", ", +          simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::HexBinary& t) +      { +        built_in_type ( +          t, +          L"::xsd::cxx::tree::hex_binary< " + char_type + L", ", +          simple_type_); + +        os << endl; +      } + + +      // Date/time. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Date& t) +      { +        os << "// Date/time." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl +             << "/**" << endl +             << " * @brief Time zone type." << endl +             << " */" << endl; + +        gen_typedef (xs_ns ().context().get<String> ("time-zone"), +                     "::xsd::cxx::tree::time_zone"); + +        if (doxygen) +          os << endl; + +        built_in_type ( +          t, L"::xsd::cxx::tree::date< " + char_type + L", ", simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::DateTime& t) +      { +        built_in_type ( +          t, +          L"::xsd::cxx::tree::date_time< " + char_type + L", ", +          simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Duration& t) +      { +        built_in_type ( +          t, +          L"::xsd::cxx::tree::duration< " + char_type + L", ", +          simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Day& t) +      { +        built_in_type ( +          t, L"::xsd::cxx::tree::gday< " + char_type + L", ", simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Month& t) +      { +        built_in_type ( +          t, L"::xsd::cxx::tree::gmonth< " + char_type + L", ", simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::MonthDay& t) +      { +        built_in_type ( +          t, +          L"::xsd::cxx::tree::gmonth_day< " + char_type + L", ", +          simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Year& t) +      { +        built_in_type ( +          t, L"::xsd::cxx::tree::gyear< " + char_type + L", ", simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::YearMonth& t) +      { +        built_in_type ( +          t, +          L"::xsd::cxx::tree::gyear_month< " + char_type + L", ", +          simple_type_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Time& t) +      { +        built_in_type ( +          t, L"::xsd::cxx::tree::time< " + char_type + L", ", simple_type_); + +        os << endl; +      } + +      // Entity. +      // +      virtual void +      traverse (SemanticGraph::Fundamental::Entity& t) +      { +        os << "// Entity." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl; + +        entity_ = built_in_type ( +          t, L"::xsd::cxx::tree::entity< " + char_type + L", ", ncname_); +      } + +      virtual void +      traverse (SemanticGraph::Fundamental::Entities& t) +      { +        built_in_type ( +          t, +          L"::xsd::cxx::tree::entities< " + char_type + L", ", +          simple_type_, +          entity_); + +        os << endl; +      } + +      virtual void +      post (SemanticGraph::Namespace& n) +      { +        SemanticGraph::Context& c (xs_ns ().context()); + +        bool parsing (!options.suppress_parsing ()); +        bool serialization (options.generate_serialization ()); +        bool element_map (options.generate_element_map ()); + +        { +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Content order sequence entry." << endl +               << " */" << endl; + +          gen_typedef (c.get<String> ("content-order"), +                       "::xsd::cxx::tree::content_order"); +        } + +        if (options.generate_element_type ()) +        { +          if (doxygen) +            os << "/**" << endl +               << " * @brief Base class for element types." << endl +               << " */" << endl; +          else +            os << "// Base class for element types." << endl +               << "//" << endl; + +          gen_typedef ( +            c.get<String> ("element-type"), +            L"::xsd::cxx::tree::element_type< " + char_type + L", ", +            type_); + +          os << endl; +        } + +        if (element_map) +        { +          if (doxygen) +            os << "/**" << endl +               << " * @brief Root element map." << endl +               << " */" << endl; +          else +            os << "// Root element map." << endl +               << "//" << endl; + +          gen_typedef ( +            c.get<String> ("element-map"), +            L"::xsd::cxx::tree::element_map< " + char_type + L", ", +            type_); + +          os << endl; +        } + +        if (serialization) +        { +          os << "// Namespace information and list stream. Used in" << endl +             << "// serialization functions." << endl +             << "//" << endl; + +          if (doxygen) +            os << "/**" << endl +               << " * @brief Namespace serialization information." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("namespace-info"), +            L"::xsd::cxx::xml::dom::namespace_info< " + char_type + L" >"); + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Namespace serialization information map." << endl +                 << " */" << endl; + +            gen_typedef (c.get<String> ("namespace-infomap"), +                         L"::xsd::cxx::xml::dom::namespace_infomap< " + +                         char_type + L" >"); + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief List serialization stream." << endl +                 << " */" << endl; + +            gen_typedef ( +              c.get<String> ("list-stream"), +              L"::xsd::cxx::tree::list_stream< " + char_type + L" >"); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Serialization wrapper for the %double type." << endl +               << " */" << endl; + +          // Do not export as_double and as_decimal since they are already +          // instantiated. +          // +          gen_typedef (c.get<String> ("as-double"), +                       L"::xsd::cxx::tree::as_double< ", +                       double_, +                       "", +                       "", +                       false); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Serialization wrapper for the %decimal type." << endl +               << " */" << endl; + +          gen_typedef (c.get<String> ("as-decimal"), +                       L"::xsd::cxx::tree::as_decimal< ", +                       decimal_, +                       "", +                       "", +                       false); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Simple type facet." << endl +               << " */" << endl; + +          gen_typedef (c.get<String> ("facet"), "::xsd::cxx::tree::facet"); + +          os << endl; +        } + +        //@@ Can't change names of ostream/istream since they are +        //   templates. +        // +        if (!options.generate_insertion ().empty ()) +        { +          if (doxygen) +            os << "/**" << endl +               << " * @brief Data representation output stream template." << endl +               << " */" << endl; +          else +            os << "// Data representation output stream template." << endl +               << "//" << endl; + +          os << "using ::xsd::cxx::tree::ostream;" +             << endl; +        } + +        if (!options.generate_extraction ().empty ()) +        { +          if (doxygen) +            os << "/**" << endl +               << " * @brief Data representation input stream template." << endl +               << " */" << endl; +          else +            os << "// Data representation input stream template." << endl +               << "//" << endl; + +          os << "using ::xsd::cxx::tree::istream;" +             << endl; +        } + +        os << "// Flags and properties." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl +             << "/**" << endl +             << " * @brief Parsing and serialization flags." << endl +             << " */" << endl; + +        gen_typedef (c.get<String> ("flags"), "::xsd::cxx::tree::flags"); + +        if (doxygen) +          os << endl +             << "/**" << endl +             << " * @brief Parsing properties." << endl +             << " */" << endl; + +        gen_typedef (c.get<String> ("properties"), +                     L"::xsd::cxx::tree::properties< " + char_type + L" >"); +        os << endl; + + +        // +        // +        if (parsing || serialization) +        { +          os << "// Parsing/serialization diagnostics." << endl +             << "//" << endl; + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Error severity." << endl +               << " */" << endl; + +          gen_typedef (c.get<String> ("severity"), +                       "::xsd::cxx::tree::severity"); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Error condition." << endl +               << " */" << endl; + +          gen_typedef (c.get<String> ("error"), +                       L"::xsd::cxx::tree::error< " + char_type + L" >"); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief List of %error conditions." << endl +               << " */" << endl; + +          gen_typedef (c.get<String> ("diagnostics"), +                       L"::xsd::cxx::tree::diagnostics< " + char_type + L" >"); +          os << endl; +        } + +        // +        // +        os << "// Exceptions." << endl +           << "//" << endl; + +        if (doxygen) +          os << endl +             << "/**" << endl +             << " * @brief Root of the C++/Tree %exception hierarchy." << endl +             << " */" << endl; + +        gen_typedef (c.get<String> ("exception"), +                     L"::xsd::cxx::tree::exception< " + char_type + L" >"); + +        if (doxygen) +          os << endl +             << "/**" << endl +             << " * @brief Exception indicating that the size argument exceeds" << +            endl +             << " * the capacity argument." << endl +             << " */" << endl; + +        gen_typedef (c.get<String> ("bounds"), +                     L"::xsd::cxx::tree::bounds< " + char_type + L" >"); + +        if (doxygen) +          os << endl +             << "/**" << endl +             << " * @brief Exception indicating that a duplicate ID value" << +            endl +             << " * was encountered in the object model." << endl +             << " */" << endl; + +        gen_typedef (c.get<String> ("duplicate-id"), +                     L"::xsd::cxx::tree::duplicate_id< " + char_type + L" >"); + +        if (parsing) +        { +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating a parsing failure." << endl +               << " */" << endl; + +          gen_typedef (c.get<String> ("parsing"), +                       L"::xsd::cxx::tree::parsing< " + char_type + L" >"); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating that an expected element" << +              endl +               << " * was not encountered." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("expected-element"), +            L"::xsd::cxx::tree::expected_element< " + char_type + L" >"); +        } + +        if (parsing || serialization) +        { +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating that an unexpected " << +              "element" << endl +               << " * was encountered." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("unexpected-element"), +            L"::xsd::cxx::tree::unexpected_element< " + char_type + L" >"); +        } + +        if (parsing) +        { +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating that an expected " << +              "attribute" << endl +               << " * was not encountered." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("expected-attribute"), +            L"::xsd::cxx::tree::expected_attribute< " + char_type + L" >"); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating that an unexpected " << +              "enumerator" << endl +               << " * was encountered." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("unexpected-enumerator"), +            L"::xsd::cxx::tree::unexpected_enumerator< " + char_type + L" >"); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating that the text content " << +              "was" << endl +               << " * expected for an element." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("expected-text-content"), +            L"::xsd::cxx::tree::expected_text_content< " + char_type + L" >"); + +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating that a prefix-namespace" << +              endl +               << " * mapping was not provided." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("no-prefix-mapping"), +            L"::xsd::cxx::tree::no_prefix_mapping< " + char_type + L" >"); +        } + +        if (options.generate_polymorphic ()) +        { +          if (parsing || serialization) +          { +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Exception indicating that the type " << +                "information" << endl +                 << " * is not available for a type." << endl +                 << " */" << endl; + +            gen_typedef ( +              c.get<String> ("no-type-info"), +              L"::xsd::cxx::tree::no_type_info< " + char_type + L" >"); +          } + +          if (parsing) +          { +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Exception indicating that the types are not" << +                endl +                 << " * related by inheritance." << endl +                 << " */" << endl; + +            gen_typedef ( +              c.get<String> ("not-derived"), +              L"::xsd::cxx::tree::not_derived< " + char_type + L" >"); +          } +        } + +        if (element_map) +        { +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating that parsing or " << +              "serialization" << endl +               << " * information is not available for an element." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("no-element-info"), +            L"::xsd::cxx::tree::no_element_info< " + char_type + L" >"); +        } + +        if (serialization) +        { +          if (doxygen) +            os << endl +               << "/**" << endl +               << " * @brief Exception indicating a serialization " << +              "failure." << endl +               << " */" << endl; + +          gen_typedef ( +            c.get<String> ("serialization"), +            L"::xsd::cxx::tree::serialization< " + char_type + L" >"); +        } + +        os << endl; + +        if (parsing || serialization) +        { +          if (doxygen) +            os << "/**" << endl +               << " * @brief Error handler callback interface." << endl +               << " */" << endl; +          else +            os << "// Error handler callback interface." << endl +               << "//" << endl; + +          gen_typedef ( +            c.get<String> ("error-handler"), +            L"::xsd::cxx::xml::error_handler< " + char_type + L" >"); + +          os << endl; +        } + +        if (parsing || serialization) +        { +          if (doxygen) +            os << "/**" << endl +               << " * @brief DOM interaction." << endl +               << " */" << endl; +          else +            os << "// DOM interaction." << endl +               << "//" << endl; + +          os << "namespace dom" +             << "{"; + +          // @@ Disregarding current naming convention by using the +          //    fixed name (even in C++11, template alias is not yet +          //    widely supported). +          // +          if (doxygen) +            os << "/**" << endl +               << " * @brief Automatic pointer for DOMDocument." << endl +               << " */" << endl; +          else +            os << "// Automatic pointer for DOMDocument." << endl +               << "//" << endl; + +          if (std >= cxx_version::cxx11) +            os << "using ::xsd::cxx::xml::dom::unique_ptr;"; +          else +            os << "using ::xsd::cxx::xml::dom::auto_ptr;"; + +          os << endl; + +          if (parsing) +          { +            if (!generate_xml_schema) +            { +              String g (L"XSD_CXX_TREE_TREE_NODE_KEY" + ns_name (n)); + +              std::transform (g.begin (), g.end(), g.begin (), upcase); +              g = escape (g); // Make it a C++ id. + +              os << "#ifndef " << g << endl +                 << "#define " << g << endl; +            } + +            if (doxygen) +              os << "/**" << endl +                 << " * @brief DOM user data key for back pointers to " << +                "tree nodes." << endl +                 << " */" << endl; +            else +              os << "// DOM user data key for back pointers to tree nodes." << endl +                 << "//" << endl; + +            os << "const XMLCh* const " << c.get<String> ("tree-node-key") << +              " = ::xsd::cxx::tree::user_data_keys::node;"; + +            if (!generate_xml_schema) +              os << "#endif" << endl; +          } + +          os << "}"; // namespace dom +        } + +        if (element_map) +        { +          if (doxygen) +            os << "//@cond" << endl +               << endl; + +          if (!generate_xml_schema) +          { +            String g (L"XSD_CXX_TREE_ELEMENT_MAP_INIT" + ns_name (n)); + +            std::transform (g.begin (), g.end(), g.begin (), upcase); +            g = escape (g); // Make it a C++ id. + +            os << "#ifndef " << g << endl +               << "#define " << g << endl; +          } + +          os << "static" << endl +             << "const ::xsd::cxx::tree::element_map_init< " << +            char_type << ", " << type_ << " >" << endl +             << "_xsd_element_map_init;"; + +          if (!generate_xml_schema) +            os << "#endif" << endl; + +          if (doxygen) +            os << endl +               << "//@endcond" << endl; +        } + +        Namespace::post (n); + +        // Generate exports. +        // +        if (export_) +        { +          StringSet ns_set; + +          for (StringList::const_iterator i (exports_.begin ()); +               i != exports_.end (); ++i) +          { +            String const& e (*i); + +            // 12 is to skip ::xsd::cxx:: +            // +            ns_set.insert (String (e, 12, e.rfind (':', e.find ('<')) - 13)); +          } + +          os << "#ifndef XSD_NO_EXPORT" << endl +             << endl +             << "namespace xsd" +             << "{" +             << "namespace cxx" +             << "{"; + +          for (StringSet::const_iterator i (ns_set.begin ()); +               i != ns_set.end (); ++i) +          { +            String const& ns (*i); +            String prefix (L"::xsd::cxx::" + ns); + +            size_t n (1); +            for (size_t b (0), e (ns.find (':')); ; n++) +            { +              os << "namespace " << String (ns, b, e) +                 << "{"; + +              if (e == String::npos) +                break; + +              b = e + 2; +              e = ns.find (':', b); +            } + +            for (StringList::const_iterator i (exports_.begin ()); +                 i != exports_.end (); ++i) +            { +              String const& e (*i); +              String ens (e, 12, e.rfind (':', e.find ('<')) - 13); + +              if (ns == ens) +              { +                String type (e, e.rfind (':', e.find ('<')) + 1); +                os << "template class " << type_exp << type << ";"; +              } +            } + +            while (n--) +              os << "}"; +          } + +          os << "}"  // cxx +             << "}"  // xsd +             << "#endif // XSD_NO_EXPORT" << endl +             << endl; +        } +      } + +    private: +      typedef std::set<String> StringSet; +      typedef std::vector<String> StringList; + +      bool export_; +      StringList exports_; +      StringSet exports_set_; +      String xs_ns_; + +      Traversal::Names names_; + +      String type_; +      String simple_type_; +      String string_; +      String norm_string_; +      String token_; +      String nmtoken_; +      String name_; +      String ncname_; +      String idref_; +      String uri_; +      String entity_; + +      String double_; +      String decimal_; +    }; +  } +} + +#endif // XSD_CXX_TREE_FUNDAMENTAL_HEADER_HXX diff --git a/xsd/cxx/tree/generator.cxx b/xsd/cxx/tree/generator.cxx new file mode 100644 index 0000000..9782b4d --- /dev/null +++ b/xsd/cxx/tree/generator.cxx @@ -0,0 +1,1268 @@ +// file      : xsd/cxx/tree/generator.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <vector> +#include <algorithm> +#include <iostream> +#include <fstream> + +#include <libcutl/re.hxx> +#include <libcutl/shared-ptr.hxx> + +#include <libcutl/compiler/code-stream.hxx> +#include <libcutl/compiler/cxx-indenter.hxx> +#include <libcutl/compiler/sloc-counter.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/generators/dependencies.hxx> + +#include <xsd/version.hxx> + +#include <xsd/cxx/tree/generator.hxx> + +#include <xsd/cxx/tree/elements.hxx> + +#include <xsd/cxx/tree/counter.hxx> +#include <xsd/cxx/tree/validator.hxx> +#include <xsd/cxx/tree/name-processor.hxx> +#include <xsd/cxx/tree/order-processor.hxx> +#include <xsd/cxx/tree/polymorphism-processor.hxx> + +#include <xsd/cxx/tree/tree-forward.hxx> +#include <xsd/cxx/tree/tree-header.hxx> +#include <xsd/cxx/tree/tree-inline.hxx> +#include <xsd/cxx/tree/tree-source.hxx> + +#include <xsd/cxx/tree/parser-header.hxx> +#include <xsd/cxx/tree/parser-source.hxx> + +#include <xsd/cxx/tree/stream-header.hxx> +#include <xsd/cxx/tree/stream-source.hxx> + +#include <xsd/cxx/tree/serialization-header.hxx> +#include <xsd/cxx/tree/serialization-source.hxx> + +#include <xsd/cxx/tree/stream-insertion-header.hxx> +#include <xsd/cxx/tree/stream-insertion-source.hxx> +#include <xsd/cxx/tree/stream-extraction-source.hxx> + +#include <xsd/cxx/tree/options.hxx> + +using namespace std; +using namespace cutl; +using namespace XSDFrontend::SemanticGraph; + +// +// +typedef std::wostream WideOutputStream; + +typedef std::wifstream WideInputFileStream; +typedef std::wofstream WideOutputFileStream; + +namespace CXX +{ +  namespace +  { +    char const copyright_gpl[] = +    "// Copyright (c) " XSD_COPYRIGHT ".\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 gives permission\n" +    "// to link this program with the Xerces-C++ library (or with modified\n" +    "// versions of Xerces-C++ that use the same license as Xerces-C++), and\n" +    "// distribute linked combinations including the two. You must obey the GNU\n" +    "// General Public License version 2 in all respects for all of the code\n" +    "// used other than Xerces-C++. If you modify this copy of the program, you\n" +    "// may extend this exception to your version of the program, but you are\n" +    "// not obligated to do so. If you do not wish to do so, delete this\n" +    "// exception statement from your version.\n" +    "//\n" +    "// Furthermore, Code Synthesis makes a special exception for the Free/Libre\n" +    "// and Open Source Software (FLOSS) which is described in the accompanying\n" +    "// FLOSSE file.\n" +    "//\n\n"; + +    char const copyright_proprietary[] = +    "// Copyright (c) " XSD_COPYRIGHT ".\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" +    "// prior to generating this code. See the license text for conditions.\n" +    "//\n\n"; +  } + +  void Tree::Generator:: +  usage () +  { +    CXX::Tree::options::print_usage (wcout); +    CXX::options::print_usage (wcout); +  } + +  namespace +  { +    void +    open (WideInputFileStream& ifs, NarrowString const& path) +    { +      try +      { +        Path fs_path (path); +        ifs.open (fs_path.string ().c_str (), +                  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, +            NarrowStrings const& primary, +            NarrowStrings const& def) +    { +      NarrowStrings const& v (primary.empty () ? def : primary); + +      for (NarrowStrings::const_iterator i (v.begin ()), e (v.end ()); +           i != e; ++i) +      { +        os << i->c_str () << endl; +      } +    } +  } + + +  size_t Tree::Generator:: +  generate (Tree::options const& ops, +            Schema& schema, +            Path const& file_path, +            bool fpt, +            StringLiteralMap const& string_literal_map, +            const WarningSet& disabled_warnings, +            FileList& file_list, +            AutoUnlinks& unlinks) +  { +    using cutl::shared_ptr; +    typedef cutl::re::regexsub Regex; + +    typedef vector<Path> Paths; +    typedef vector<shared_ptr<WideOutputFileStream> > WideOutputFileStreams; + +    try +    { +      // Do option validation. +      // +      if (ops.parts () < 1) +      { +        wcerr << "error: invalid value for option --parts: " << +          ops.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 (); +      } + +      bool gen_cxx (!ops.generate_dep_only () && !ops.file_list_only ()); + +      // Process ordered types. +      // +      if (gen_cxx) +      { +        OrderProcessor proc; +        if (!proc.process (ops, schema, file_path)) +          throw Failed (); +      } + +      // Process names. +      // +      if (gen_cxx) +      { +        NameProcessor proc; +        if (!proc.process (ops, schema, file_path, string_literal_map)) +          throw Failed (); +      } + +      // Process polymorphic types. +      // +      if (gen_cxx && +          ops.generate_polymorphic () && +          !ops.polymorphic_type_all ()) +      { +        PolymorphismProcessor proc; +        if (!proc.process (ops, schema, file_path, disabled_warnings)) +          throw Failed (); +      } + +      // Parts. +      // +      size_t parts (ops.parts ()); +      size_t units (counts.global_types + counts.generated_global_elements); +      size_t units_per_part (units / parts); + +      if (parts != 1 && units_per_part < 1) +      { +        wcerr << "error: too many parts specified: " << parts << endl; +        throw Failed (); +      } + +      size_t complexity_per_part (counts.complexity_total / parts); + + +      NarrowString parts_suffix (ops.parts_suffix ()); + +      // +      // +      bool generate_xml_schema (ops.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.extern_xml_schema ()) +        { +          if (file_path.string () != name) +            generate_xml_schema = false; +        } +      } + +      bool header (true); +      bool inline_ (ops.generate_inline () && !generate_xml_schema); +      bool forward (ops.generate_forward () && !generate_xml_schema); +      bool source (!generate_xml_schema); +      bool gen_dep ((ops.generate_dep () || ops.generate_dep_only ()) && +                    !generate_xml_schema); + +      if (ops.generate_dep_only () && generate_xml_schema) +      { +        wcerr << "error: no dependency information can be generated for " +          "XML Schema header" << endl; +        throw Failed (); +      } + +      if (gen_dep && fpt) +      { +        wcerr << "error: dependency generation not support in the " << +          "file-per-type mode" << endl; +        throw Failed (); +      } + +      // Generate code. +      // +      NarrowString name (file_path.leaf ().string ()); + +      NarrowString hxx_suffix (ops.hxx_suffix ()); +      NarrowString ixx_suffix (ops.ixx_suffix ()); +      NarrowString cxx_suffix (ops.cxx_suffix ()); +      NarrowString fwd_suffix (ops.fwd_suffix ()); +      NarrowString dep_suffix (ops.dep_suffix ()); + +      Regex hxx_expr (ops.hxx_regex ().empty () +                      ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#" +                      : ops.hxx_regex ()); + +      Regex ixx_expr (ops.ixx_regex ().empty () +                      ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + ixx_suffix + "#" +                      : ops.ixx_regex ()); + +      Regex cxx_expr (ops.cxx_regex ().empty () +                      ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + cxx_suffix + "#" +                      : ops.cxx_regex ()); + +      Regex fwd_expr (ops.fwd_regex ().empty () +                      ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + fwd_suffix + "#" +                      : ops.fwd_regex ()); + +      // @@ This will blow up if --dep-file value contains backslashes (e.g., +      //    it's a Windows path). +      // +      Regex dep_expr ( +        ops.dep_regex_specified () ? ops.dep_regex () : +        ops.dep_file_specified () ? "#.+#" + ops.dep_file () + "#" : +        "#^(.+?)(\\.[^./\\\\]+)?$#$1" + dep_suffix + "#"); + +      if (header && !hxx_expr.match (name)) +      { +        wcerr << "error: header expression '" << +          hxx_expr.regex ().str ().c_str () << "' does not match '" << +          name.c_str () << "'" << endl; +        throw Failed (); +      } + +      if (inline_ && !ixx_expr.match (name)) +      { +        wcerr << "error: inline expression '" << +          ixx_expr.regex ().str ().c_str () << "' does not match '" << +          name.c_str () << "'" << endl; +        throw Failed (); +      } + +      if (source && parts == 1 && !cxx_expr.match (name)) +      { +        wcerr << "error: source expression '" << +          cxx_expr.regex ().str ().c_str () << "' does not match '" << +          name.c_str () << "'" << endl; +        throw Failed (); +      } + +      if (forward && !fwd_expr.match (name)) +      { +        wcerr << "error: forward expression '" << +          fwd_expr.regex ().str ().c_str () << "' does not match '" << +          name.c_str () << "'" << endl; +        throw Failed (); +      } + +      if (gen_dep && !dep_expr.match (name)) +      { +        wcerr << "error: dependency expression '" << +          dep_expr.regex ().str ().c_str () << "' does not match '" << +          name.c_str () << "'" << endl; +        throw Failed (); +      } + +      NarrowString hxx_name (header ? hxx_expr.replace (name) : NarrowString ()); +      NarrowString ixx_name (inline_ ? ixx_expr.replace (name) : NarrowString ()); +      NarrowString fwd_name (forward ? fwd_expr.replace (name) : NarrowString ()); +      NarrowString dep_name (gen_dep ? dep_expr.replace (name) : NarrowString ()); + +      Path hxx_path (hxx_name); +      Path ixx_path (ixx_name); +      Path fwd_path (fwd_name); +      Path dep_path (dep_name != "-" ? dep_name : NarrowString ()); +      Paths cxx_paths; + +      if (source) +      { +        if (parts > 1) +        { +          for (size_t i (0); i < parts; ++i) +          { +            std::ostringstream os; +            os << i; + +            Regex expr ( +              "#^(.+?)(\\.[^./\\\\]+)?$#$1" + parts_suffix + os.str () + "$2#"); + +            NarrowString part_name (expr.replace (name)); + +            if (!cxx_expr.match (part_name)) +            { +              wcerr << "error: source expression '" << +                cxx_expr.regex ().str ().c_str () << "' does not match '" << +                part_name.c_str () << "'" << endl; +              throw Failed (); +            } + +            cxx_paths.push_back (Path (cxx_expr.replace (part_name))); +          } +        } +        else +          cxx_paths.push_back (Path (cxx_expr.replace (name))); +      } + +      Path out_dir; + +      if (NarrowString dir = ops.output_dir ()) +      { +        try +        { +          out_dir = Path (dir); +        } +        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.directory ()); + +        if (!fpt_dir.empty ()) +          out_dir /= fpt_dir; +      } + +      if (!out_dir.empty ()) +      { +        if (!hxx_path.empty ())    hxx_path = out_dir / hxx_path; +        if (!ixx_path.empty ())    ixx_path = out_dir / ixx_path; +        if (!fwd_path.empty ())    fwd_path = out_dir / fwd_path; +        if (!dep_path.empty () && +            !dep_path.absolute ()) dep_path = out_dir / dep_path; + +        for (Paths::iterator i (cxx_paths.begin ()); +             i != cxx_paths.end (); ++i) +          *i = out_dir / *i; +      } + +      // +      // +      WideOutputFileStream hxx; +      WideOutputFileStream ixx; +      WideOutputFileStream fwd; +      WideOutputFileStream depf; // See dep below. +      WideOutputFileStreams cxx; + +      // DEP +      // +      if (gen_dep) +      { +        if (!dep_path.empty ()) +        { +          depf.open (dep_path.string ().c_str (), ios_base::out); + +          if (!depf.is_open ()) +          { +            wcerr << dep_path << ": error: unable to open in write mode" +                  << endl; +            throw Failed (); +          } + +          unlinks.add (dep_path); +        } + +        // Note: not adding to file_list. +      } + +      WideOutputStream& dep (gen_dep && !dep_path.empty () ? depf : wcout); + +      // FWD +      // +      if (forward) +      { +        if (gen_cxx) +        { +          fwd.open (fwd_path.string ().c_str (), 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.string ()); +      } + +      // HXX +      // +      if (header) +      { +        if (gen_cxx) +        { +          hxx.open (hxx_path.string ().c_str (), 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.string ()); +      } + +      // IXX +      // +      if (inline_) +      { +        if (gen_cxx) +        { +          ixx.open (ixx_path.string ().c_str (), 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.string ()); +      } + +      // CXX +      // +      if (source) +      { +        for (Paths::iterator i (cxx_paths.begin ()); +             i != cxx_paths.end (); ++i) +        { +          if (gen_cxx) +          { +            shared_ptr<WideOutputFileStream> s ( +              new (shared) WideOutputFileStream ( +                i->string ().c_str (), ios_base::out)); + +            if (!s->is_open ()) +            { +              wcerr << *i << ": error: unable to open in write mode" << endl; +              throw Failed (); +            } + +            cxx.push_back (s); +            unlinks.add (*i); +          } + +          file_list.push_back (i->string ()); +        } +      } + +      // Print copyright and license. +      // +      char const* copyright ( +        ops.proprietary_license () ? copyright_proprietary : copyright_gpl); + +      if (gen_cxx && header) +        hxx << copyright; + +      if (gen_cxx && forward) +        fwd << copyright; + +      if (ops.generate_doxygen ()) +      { +        // Use native path format. +        // +        hxx << "/**" << endl +            << " * @file" << endl +            << " * @brief Generated from " << name.c_str () << "." << endl +            << " */" << endl +            << endl; + +      } + +      if (gen_cxx && inline_) +        ixx << copyright; + +      if (gen_cxx && source) +      { +        for (WideOutputFileStreams::iterator i (cxx.begin ()); +             i != cxx.end (); ++i) +          **i << copyright; +      } + + +      // Prologue. +      // +      WideInputFileStream prologue; +      { +        NarrowString name (ops.prologue_file ()); + +        if (name) +          open (prologue, name); +      } + +      // Epilogue. +      // +      WideInputFileStream epilogue; +      { +        NarrowString name (ops.epilogue_file ()); + +        if (name) +          open (epilogue, name); +      } + +      // SLOC counter. +      // +      size_t sloc_total (0); +      bool show_sloc (ops.show_sloc ()); + +      typedef +      compiler::ostream_filter<compiler::cxx_indenter, wchar_t> +      ind_filter; + +      typedef +      compiler::ostream_filter<compiler::sloc_counter, wchar_t> +      sloc_filter; + +      // +      // +      Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. +      NarrowString guard_prefix (ops.guard_prefix ()); + +      if (!guard_prefix) +        guard_prefix = file_path.directory ().string (); + +      if (guard_prefix) +        guard_prefix += '_'; + +      // DEP +      // +      if (gen_dep) +      { +        NarrowString target; +        NarrowStrings const& ts (ops.dep_target ()); + +        if (!ts.empty ()) +        { +          for (NarrowStrings::const_iterator i (ts.begin ()); +               i != ts.end (); ++i) +            target += (target.empty () ? "" : " \\\n") + *i; +        } +        else +        { +          target = hxx_path.string (); + +          if (forward) +            target += " \\\n" + fwd_path.string (); + +          if (inline_) +            target += " \\\n" + ixx_path.string (); + +          for (Paths::iterator i (cxx_paths.begin ()); +               i != cxx_paths.end (); ++i) +            target += " \\\n" + i->string (); + +          if (!dep_path.empty ()) +            target += " \\\n" + dep_path.string (); +        } + +        dep << target.c_str () << ':'; + +        XSDFrontend::Generators::Dependencies gen; +        Paths prq (gen.generate (schema, file_path)); + +        for (Paths::iterator i (prq.begin ()); i != prq.end (); ++i) +          dep << " \\" << endl +              << "  " << *i; + +        dep << endl; + +        // If requested, generate phony rules for included/imported schemas +        // but not the main file which is the first in the list. +        // +        if (ops.dep_phony () && prq.size () > 1) +        { +          for (Paths::iterator i (prq.begin () + 1); i != prq.end (); ++i) +            dep << endl +                << *i << ':' << endl; +        } +      } + +      // FWD +      // +      if (gen_cxx && forward) +      { +        Context ctx (fwd, +                     schema, +                     file_path, +                     ops, +                     counts, +                     generate_xml_schema, +                     &string_literal_map, +                     &fwd_expr, +                     &hxx_expr, +                     &ixx_expr); + +        sloc_filter sloc (fwd); + +        // Guard +        // +        String guard (guard_expr.replace (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; + +        if (ctx.std >= cxx_version::cxx11) +        { +          fwd << "#ifndef XSD_CXX11" << endl +              << "#define XSD_CXX11" << endl +              << "#endif" << 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; +        } + +        // Copy prologue. +        // +        fwd << "// Begin prologue." << endl +            << "//" << endl; + +        append (fwd, ops.fwd_prologue (), ops.prologue ()); +        append (fwd, ops.fwd_prologue_file (), prologue); + +        fwd << "//" << endl +            << "// End prologue." << endl +            << endl; + +        // Version check. +        // +        fwd << "#include <xsd/cxx/version.hxx>" << endl +            << endl +            << "#if (LIBXSD_VERSION != " << XSD_VERSION << "L)" << endl +            << "#error XSD runtime version mismatch" << endl +            << "#endif" << endl +            << endl; + +        fwd << "#include <xsd/cxx/pre.hxx>" << endl +              << endl; + +        // Generate. +        // +        { +          ind_filter ind (fwd); // We don't want to indent prologues/epilogues. +          generate_forward (ctx); +        } + +        fwd << "#include <xsd/cxx/post.hxx>" << endl +            << endl; + +        // Copy epilogue. +        // +        fwd << "// Begin epilogue." << endl +            << "//" << endl; + +        append (fwd, ops.fwd_epilogue_file (), epilogue); +        append (fwd, ops.fwd_epilogue (), ops.epilogue ()); + +        fwd << "//" << endl +            << "// End epilogue." << endl +            << endl; + +        fwd << "#endif // " << guard << endl; + +        if (show_sloc) +          wcerr << fwd_path << ": " << sloc.stream ().count () << endl; + +        sloc_total += sloc.stream ().count (); +      } + +      // HXX +      // +      if (gen_cxx && header) +      { +        Context ctx (hxx, +                     schema, +                     file_path, +                     ops, +                     counts, +                     generate_xml_schema, +                     &string_literal_map, +                     &fwd_expr, +                     &hxx_expr, +                     &ixx_expr); + +        sloc_filter sloc (hxx); + +        // Guard +        // +        String guard (guard_expr.replace (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; + +        if (!forward) +        { +          if (ctx.std >= cxx_version::cxx11) +          { +            hxx << "#ifndef XSD_CXX11" << endl +                << "#define XSD_CXX11" << endl +                << "#endif" << endl +                << endl; +          } + +          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; +          } +        } +        else if (!generate_xml_schema) +        { +          // Generate it before the prologue so that we get the above +          // defines. +          // +          hxx << "#include " << ctx.process_include_path (fwd_name) +              << endl << endl; +        } + +        // Copy prologue. +        // +        hxx << "// Begin prologue." << endl +            << "//" << endl; + +        append (hxx, ops.hxx_prologue (), ops.prologue ()); +        append (hxx, ops.hxx_prologue_file (), prologue); + +        hxx << "//" << endl +            << "// End prologue." << endl +            << endl; + +        // Version check. +        // +        hxx << "#include <xsd/cxx/config.hxx>" << endl +            << endl +            << "#if (LIBXSD_VERSION != " << XSD_VERSION << "L)" << endl +            << "#error XSD runtime version mismatch" << endl +            << "#endif" << endl +            << endl; + +        hxx << "#include <xsd/cxx/pre.hxx>" << endl +            << endl; + +        // Generate. +        // +        { +          ind_filter ind (hxx); // We don't want to indent prologues/epilogues. + +          if (!generate_xml_schema && !forward) +            generate_forward (ctx); + +          generate_tree_header (ctx); + +          if (!generate_xml_schema) +          { +            if (ops.generate_ostream ()) +              generate_stream_header (ctx); + +            if (!ops.generate_element_type () && !ops.suppress_parsing ()) +              generate_parser_header (ctx); + +            if (ops.generate_serialization ()) +              generate_serialization_header (ctx); + +            if (!ops.generate_insertion ().empty ()) +              generate_stream_insertion_header (ctx); +          } +        } + +        hxx << "#include <xsd/cxx/post.hxx>" << endl +              << endl; + +        // Copy epilogue. +        // +        // Note that it goes before the inline file in case it defines +        // something (such as a custom type) which is needed by this file. +        // And if something in the epilogue needs something from the inline +        // file, then it should be the inline rather than header epilogue. +        // +        hxx << "// Begin epilogue." << endl +            << "//" << endl; + +        append (hxx, ops.hxx_epilogue_file (), epilogue); +        append (hxx, ops.hxx_epilogue (), ops.epilogue ()); + +        hxx << "//" << endl +            << "// End epilogue." << endl +            << endl; + +        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 << "#endif // " << guard << endl; + +        if (show_sloc) +          wcerr << hxx_path << ": " << sloc.stream ().count () << endl; + +        sloc_total += sloc.stream ().count (); +      } + + +      // IXX +      // +      if (gen_cxx && inline_) +      { +        Context ctx (ixx, +                     schema, +                     file_path, +                     ops, +                     counts, +                     generate_xml_schema, +                     &string_literal_map, +                     &fwd_expr, +                     &hxx_expr, +                     &ixx_expr); + +        sloc_filter sloc (ixx); + +        // Guard +        // +        String guard (guard_expr.replace (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.ixx_prologue (), ops.prologue ()); +        append (ixx, ops.ixx_prologue_file (), prologue); + +        ixx << "//" << endl +            << "// End prologue." << endl +            << endl; + +        ixx << "#include <xsd/cxx/pre.hxx>" << endl +            << endl; + +        // Generate. +        // +        { +          ind_filter ind (ixx); // We don't want to indent prologues/epilogues. +          generate_tree_inline (ctx, 1, 0); +        } + +        ixx << "#include <xsd/cxx/post.hxx>" << endl +            << endl; + +        // Copy epilogue. +        // +        ixx << "// Begin epilogue." << endl +            << "//" << endl; + +        append (ixx, ops.ixx_epilogue_file (), epilogue); +        append (ixx, ops.ixx_epilogue (), ops.epilogue ()); + +        ixx << "//" << endl +            << "// End epilogue." << endl +            << endl; + +        ixx << "#endif // " << guard.c_str () << endl; + +        if (show_sloc) +          wcerr << ixx_path << ": " << sloc.stream ().count () << endl; + +        sloc_total += sloc.stream ().count (); +      } + +      // CXX +      // +      if (gen_cxx && source) +      { +        size_t first_unit (0); // First unit in the current part. + +        for (size_t part (0); part < parts; ++part) +        { +          // Figure out the range of units for this part. +          // +          size_t last_unit (first_unit); + +          if (units != 0) +          { +            size_t 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. +              // +              size_t 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; +            } +          } + +          // +          // +          size_t first (first_unit); +          size_t 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); + +          sloc_filter sloc (os); + +          // Copy prologue. +          // +          os << "// Begin prologue." << endl +             << "//" << endl; + +          append (os, ops.cxx_prologue (), ops.prologue ()); +          append (os, ops.cxx_prologue_file (), prologue); + +          os << "//" << endl +             << "// End prologue." << endl +             << endl; + +          os << "#include <xsd/cxx/pre.hxx>" << endl +             << endl; + +          os << "#include " << ctx.process_include_path (hxx_name) << endl +             << endl; + +          // Generate. +          // +          { +            // We don't want to indent prologues/epilogues. +            // +            ind_filter ind (os); + +            if (!inline_) +              generate_tree_inline (ctx, first, last); + +            generate_tree_source (ctx, first, last); + +            if (ops.generate_ostream ()) +              generate_stream_source (ctx, first, last); + +            if (!ops.generate_element_type () && !ops.suppress_parsing ()) +              generate_parser_source (ctx, first, last); + +            if (ops.generate_serialization ()) +              generate_serialization_source (ctx, first, last); + +            if (!ops.generate_extraction ().empty ()) +              generate_stream_extraction_source (ctx); + +            if (!ops.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.cxx_epilogue_file (), epilogue); +          append (os, ops.cxx_epilogue (), ops.epilogue ()); + +          os << "//" << endl +             << "// End epilogue." << endl +             << endl; + +          if (show_sloc) +            wcerr << cxx_paths[part] << ": " << sloc.stream ().count () +                  << endl; + +          sloc_total += sloc.stream ().count (); +        } +      } + +      return sloc_total; +    } +    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 (cutl::re::format const& e) +    { +      wcerr << "error: invalid regex: '" << +        e.regex ().c_str () << "': " << +        e.description ().c_str () << endl; + +      throw Failed (); +    } +    catch (cutl::re::wformat const& e) +    { +      wcerr << "error: invalid regex: '" << +        e.regex () << "': " << e.description ().c_str () << endl; + +      throw Failed (); +    } +  } +} diff --git a/xsd/cxx/tree/generator.hxx b/xsd/cxx/tree/generator.hxx new file mode 100644 index 0000000..a9b96fe --- /dev/null +++ b/xsd/cxx/tree/generator.hxx @@ -0,0 +1,44 @@ +// file      : xsd/cxx/tree/generator.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_GENERATOR_HXX +#define XSD_CXX_TREE_GENERATOR_HXX + +#include <libxsd-frontend/semantic-graph/elements.hxx> // Path +#include <libxsd-frontend/semantic-graph/schema.hxx> + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> + +#include <xsd/cxx/literal-map.hxx> +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ +  namespace Tree +  { +    class Generator +    { +    public: +      static void +      usage (); + +      struct Failed {}; + +      static size_t +      generate (options const&, +                XSDFrontend::SemanticGraph::Schema&, +                XSDFrontend::SemanticGraph::Path const& file, +                bool file_per_type, +                StringLiteralMap const&, +                const WarningSet& disabled_warnings, +                FileList& file_list, +                AutoUnlinks& unlinks); + +    private: +      Generator (); +    }; +  } +} + +#endif // XSD_CXX_TREE_GENERATOR_HXX diff --git a/xsd/cxx/tree/name-processor.cxx b/xsd/cxx/tree/name-processor.cxx new file mode 100644 index 0000000..325870a --- /dev/null +++ b/xsd/cxx/tree/name-processor.cxx @@ -0,0 +1,2427 @@ +// file      : xsd/cxx/tree/name-processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <map> +#include <vector> +#include <sstream> +#include <iostream> + +#include <libcutl/re.hxx> + +#include <xsd/cxx/tree/default-value.hxx> +#include <xsd/cxx/tree/name-processor.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      // +      // +      typedef set<String> NameSet; + +      class Context: public Tree::Context +      { +      public: +        struct Failed {}; + +        Context (Tree::options const& ops, +                 Counts const& counts, +                 bool generate_xml_schema, +                 SemanticGraph::Schema& root, +                 SemanticGraph::Path const& path, +                 StringLiteralMap const& map) +            : Tree::Context (std::wcerr, +                             root, +                             path, +                             ops, +                             counts, +                             generate_xml_schema, +                             &map, +                             0, +                             0, +                             0), +              global_type_names (global_type_names_), +              global_element_names (global_element_names_), +              detach (ops.generate_detach ()), +              type_regex (type_regex_), +              accessor_regex (accessor_regex_), +              one_accessor_regex (one_accessor_regex_), +              opt_accessor_regex (opt_accessor_regex_), +              seq_accessor_regex (seq_accessor_regex_), +              modifier_regex (modifier_regex_), +              one_modifier_regex (one_modifier_regex_), +              opt_modifier_regex (opt_modifier_regex_), +              seq_modifier_regex (seq_modifier_regex_), +              parser_regex (parser_regex_), +              serializer_regex (serializer_regex_), +              const_regex (const_regex_), +              enumerator_regex (enumerator_regex_), +              element_type_regex (element_type_regex_) +        { +          NarrowString tn (options.type_naming ()); +          NarrowString fn (options.function_naming ()); + +          // Type name regex. +          // +          { +            // Predefined rules. The most frequently used come last: global +            // names, two components (<name>,type), three components +            // (<name>,const,iterator), and one component (value in enum). +            // +            if (tn == "knr") +            { +              type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/"); +              type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); +              type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/$1_$2/"); +              type_regex.push_back ("/(?:[^ ]* )?([^,]+)/$1/"); + +              /* +              type_regex.push_back ("/([^,]+)/$1/"); +              type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/"); +              type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); +              type_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); +              type_regex.push_back ("/[^ ]* (.+)/$1/"); +              */ +            } +            else +            { +              // Upper camel case or Java. +              // +              type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/"); +              type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); +              type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/\\u$1\\u$2/"); +              type_regex.push_back ("/(?:[^ ]* )?([^,]+)/\\u$1/"); + +              /* +              type_regex.push_back ("/([^,]+)/\\u$1/"); +              type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/"); +              type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); +              type_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); +              type_regex.push_back ("/[^ ]* (.+)/\\u$1/"); +              */ + +            } + +            compile_regex (options.type_regex (), type_regex, "type"); +          } + +          // Accessor name regex. +          // +          { +            // Predefined rules. The most frequently used come last: one +            // component, three components (<name>,default,value) and two +            // component (dom,document). +            // +            if (fn == "knr") +            { +              accessor_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); +              accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); +              accessor_regex.push_back ("/([^,]+)/$1/"); +            } +            else if (fn == "lcc") +            { +              accessor_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); +              accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\l$1\\u$2\\u$3/"); +              accessor_regex.push_back ("/([^,]+)/\\l$1/"); +            } +            else if (fn == "ucc") +            { +              accessor_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); +              accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); +              accessor_regex.push_back ("/([^,]+)/\\u$1/"); +            } +            else +            { +              // Java: add get. +              // +              accessor_regex.push_back ("/([^,]+),([^,]+)/get\\u$1\\u$2/"); +              accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/get\\u$1\\u$2\\u$3/"); +              accessor_regex.push_back ("/([^,]+)/get\\u$1/"); +            } + +            compile_regex (options.accessor_regex (), +                           accessor_regex, +                           "accessor"); + +            compile_regex (options.one_accessor_regex (), +                           one_accessor_regex, +                           "one accessor"); + +            compile_regex (options.opt_accessor_regex (), +                           opt_accessor_regex, +                           "optional accessor"); + +            compile_regex (options.seq_accessor_regex (), +                           seq_accessor_regex, +                           "sequence accessor"); +          } + +          // Modifier name regex. +          // +          { +            if (fn == "knr") +            { +              // any,attribute +              // +              modifier_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); +            } +            else if (fn == "lcc") +            { +              modifier_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); +              modifier_regex.push_back ("/([^,]+)/\\l$1/"); +            } +            else if (fn == "ucc") +            { +              modifier_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); +              modifier_regex.push_back ("/([^,]+)/\\u$1/"); +            } +            else +            { +              // Java: add set. +              // +              modifier_regex.push_back ("/([^,]+),([^,]+)/set\\u$1\\u$2/"); +              modifier_regex.push_back ("/([^,]+)/set\\u$1/"); +              modifier_regex.push_back ("/detach,([^,]+)/detach\\u$1/"); +            } + +            compile_regex (options.modifier_regex (), +                           modifier_regex, +                           "modifier"); + +            compile_regex (options.one_modifier_regex (), +                           one_modifier_regex, +                           "one modifier"); + +            compile_regex (options.opt_modifier_regex (), +                           opt_modifier_regex, +                           "optional modifier"); + +            compile_regex (options.seq_modifier_regex (), +                           seq_modifier_regex, +                           "sequence modifier"); +          } + +          // Parser name regex. +          // +          { +            if (fn == "lcc") +            { +              parser_regex.push_back ("/(.+)/\\l$1/"); +            } +            else if (fn == "ucc") +            { +              parser_regex.push_back ("/(.+)/\\u$1/"); +            } +            else if (fn == "java") +            { +              // Java: add parse. +              // +              parser_regex.push_back ("/(.+)/parse\\u$1/"); +            } + +            compile_regex (options.parser_regex (), parser_regex, "parser"); +          } + +          // Serializer name regex. +          // +          { +            if (fn == "lcc") +            { +              serializer_regex.push_back ("/(.+)/\\l$1/"); +            } +            else if (fn == "ucc") +            { +              serializer_regex.push_back ("/(.+)/\\u$1/"); +            } +            else if (fn == "java") +            { +              // Java: add serialize. +              // +              serializer_regex.push_back ("/(.+)/serialize\\u$1/"); +            } + +            compile_regex (options.serializer_regex (), +                           serializer_regex, +                           "serializer"); +          } + +          // Const regex. +          // +          { +            if (fn == "knr") +            { +              const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); +              const_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); +            } +            else if (fn == "lcc") +            { +              const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\l$1_\\u$2_\\u$3/"); +              const_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); +            } +            else if (fn == "ucc") +            { +              const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1_\\u$2_\\u$3/"); +              const_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); +            } +            else +            { +              // Java: all uppercase. +              // +              const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\U$1_$2_$3/"); +              const_regex.push_back ("/([^,]+),([^,]+)/\\U$1_$2/"); +            } + +            compile_regex (options.const_regex (), const_regex, "const"); +          } + +          // Enumerator name regex. +          // +          { +            // By default map an empty enumerator to the 'empty' word. +            // +            enumerator_regex.push_back ("/^$/empty/"); + +            compile_regex (options.enumerator_regex (), +                           enumerator_regex, +                           "enumerator"); +          } + +          // Element type regex. +          // +          compile_regex (options.element_type_regex (), +                         element_type_regex, +                         "element_type"); +        } + +      protected: +        Context (Context& c) +            : Tree::Context (c), +              global_type_names (c.global_type_names), +              global_element_names (c.global_element_names), +              detach (c.detach), +              type_regex (c.type_regex), +              accessor_regex (c.accessor_regex), +              one_accessor_regex (c.one_accessor_regex), +              opt_accessor_regex (c.opt_accessor_regex), +              seq_accessor_regex (c.seq_accessor_regex), +              modifier_regex (c.modifier_regex), +              one_modifier_regex (c.one_modifier_regex), +              opt_modifier_regex (c.opt_modifier_regex), +              seq_modifier_regex (c.seq_modifier_regex), +              parser_regex (c.parser_regex), +              serializer_regex (c.serializer_regex), +              const_regex (c.const_regex), +              enumerator_regex (c.enumerator_regex), +              element_type_regex (c.element_type_regex) +        { +        } + +      public: +        typedef cutl::re::wregexsub Regex; +        typedef cutl::re::wformat RegexFormat; + +        struct RegexVector: vector<Regex> +        { +          void +          push_back (String const& r) +          { +            vector<Regex>::push_back (Regex (r)); +          } +        }; + +        String +        process_regex (String const& name, +                       RegexVector const& rv, +                       String const& id) +        { +          bool trace (options.name_regex_trace ()); + +          if (trace) +            os << id << " name: '" << name << "'" << endl; + +          for (RegexVector::const_reverse_iterator i (rv.rbegin ()); +               i != rv.rend (); ++i) +          { +            if (trace) +              os << "try: '" << i->regex () << "' : "; + +            if (i->match (name)) +            { +              String r (i->replace (name)); + +              if (trace) +                os << "'" << r << "' : +" << endl; + +              return r; +            } + +            if (trace) +              os << '-' << endl; +          } + +          return name; +        } + +        String +        process_regex (String const& name, +                       RegexVector const& primary, +                       RegexVector const& backup, +                       String const& id) +        { +          bool trace (options.name_regex_trace ()); + +          if (trace) +            os << id << " name: '" << name << "'" << endl; + +          for (RegexVector::const_reverse_iterator i (primary.rbegin ()); +               i != primary.rend (); ++i) +          { +            if (trace) +              os << "try: '" << i->regex () << "' : "; + +            if (i->match (name)) +            { +              String r (i->replace (name)); + +              if (trace) +                os << "'" << r << "' : +" << endl; + +              return r; +            } + +            if (trace) +              os << '-' << endl; +          } + +          for (RegexVector::const_reverse_iterator i (backup.rbegin ()); +               i != backup.rend (); ++i) +          { +            if (trace) +              os << "try: '" << i->regex () << "' : "; + +            if (i->match (name)) +            { +              String r (i->replace (name)); + +              if (trace) +                os << "'" << r << "' : +" << endl; + +              return r; +            } + +            if (trace) +              os << '-' << endl; +          } + +          return name; +        } + +        String +        process_regex (String const& ns, +                       String const& name, +                       RegexVector const& rv, +                       String const& id) +        { +          String s (ns + L' ' + name); +          bool trace (options.name_regex_trace ()); + +          if (trace) +            os << id << " name: '" << s << "'" << endl; + +          for (RegexVector::const_reverse_iterator i (rv.rbegin ()); +               i != rv.rend (); ++i) +          { +            if (trace) +              os << "try: '" << i->regex () << "' : "; + +            if (i->match (s)) +            { +              String r (i->replace (s)); + +              if (trace) +                os << "'" << r << "' : +" << endl; + +              return r; +            } + +            if (trace) +              os << '-' << endl; +          } + +          return name; +        } + +        String +        process_regex (String const& ns, +                       String const& name, +                       RegexVector const& primary, +                       RegexVector const& backup, +                       String const& id) +        { +          String s (ns + L' ' + name); +          bool trace (options.name_regex_trace ()); + +          if (trace) +            os << id << " name: '" << s << "'" << endl; + +          for (RegexVector::const_reverse_iterator i (primary.rbegin ()); +               i != primary.rend (); ++i) +          { +            if (trace) +              os << "try: '" << i->regex () << "' : "; + +            if (i->match (s)) +            { +              String r (i->replace (s)); + +              if (trace) +                os << "'" << r << "' : +" << endl; + +              return r; +            } + +            if (trace) +              os << '-' << endl; +          } + +          for (RegexVector::const_reverse_iterator i (backup.rbegin ()); +               i != backup.rend (); ++i) +          { +            if (trace) +              os << "try: '" << i->regex () << "' : "; + +            if (i->match (s)) +            { +              String r (i->replace (s)); + +              if (trace) +                os << "'" << r << "' : +" << endl; + +              return r; +            } + +            if (trace) +              os << '-' << endl; +          } + +          return name; +        } + +      public: +        String +        find_name (String const& base_name, +                   NameSet& set, +                   bool insert = true) +        { +          String name (base_name); + +          for (size_t i (1); set.find (name) != set.end (); ++i) +          { +            std::wostringstream os; +            os << i; +            name = base_name + os.str (); +          } + +          if (insert) +            set.insert (name); + +          return name; +        } + +      private: +        void +        compile_regex (NarrowStrings const& sv, +                       RegexVector& rv, +                       String const& id) +        { +          for (NarrowStrings::const_iterator i (sv.begin ()); i != sv.end (); +               ++i) +          { +            try +            { +              rv.push_back (*i); +            } +            catch (RegexFormat const& e) +            { +              os << "error: invalid " << id << " name regex: '" << +                e.regex () << "': " << e.description ().c_str () << endl; + +              throw Failed (); +            } +          } +        } + +      private: +        map<String, NameSet> global_type_names_; +        map<String, NameSet> global_element_names_; + +        RegexVector type_regex_; +        RegexVector accessor_regex_; +        RegexVector one_accessor_regex_; +        RegexVector opt_accessor_regex_; +        RegexVector seq_accessor_regex_; +        RegexVector modifier_regex_; +        RegexVector one_modifier_regex_; +        RegexVector opt_modifier_regex_; +        RegexVector seq_modifier_regex_; +        RegexVector parser_regex_; +        RegexVector serializer_regex_; +        RegexVector const_regex_; +        RegexVector enumerator_regex_; +        RegexVector element_type_regex_; + +      public: +        map<String, NameSet>& global_type_names; +        map<String, NameSet>& global_element_names; + +        bool detach; + +        RegexVector& type_regex; +        RegexVector& accessor_regex; +        RegexVector& one_accessor_regex; +        RegexVector& opt_accessor_regex; +        RegexVector& seq_accessor_regex; +        RegexVector& modifier_regex; +        RegexVector& one_modifier_regex; +        RegexVector& opt_modifier_regex; +        RegexVector& seq_modifier_regex; +        RegexVector& parser_regex; +        RegexVector& serializer_regex; +        RegexVector& const_regex; +        RegexVector& enumerator_regex; +        RegexVector& element_type_regex; +      }; + +      // +      // +      struct Enumerator: Traversal::Enumerator, Context +      { +        Enumerator (Context& c, NameSet& set) +            : Context (c), set_ (set) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          // Process the name with enumerator name regex. +          // +          String name ( +            process_regex (e.name (), enumerator_regex, L"enumerator")); + +          // Escape and unclash. +          // +          name = find_name (escape (name), set_); +          e.context ().set ("name", name); +        } + +      private: +        NameSet& set_; +      }; + +      // +      // +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          // Use processed name. +          // +          String name (e.context ().get<String> ("name")); + +          // If renamed name is empty then we are not generating +          // anything for this type and name processing is not +          // required. +          // +          if (renamed_type (e, name) && !name) +            return; + +          NameSet enum_set; +          enum_set.insert (name); + +          Enumerator enumerator (*this, enum_set); +          Traversal::Names names (enumerator); + +          Traversal::Enumeration::names (e, names); + +          // Assign name to the value type. First process the name +          // with type name regex. +          // +          String value_name ( +            escape (process_regex ("value", type_regex, L"type"))); +          e.context ().set ("value", find_name (value_name, enum_set)); +        } +      }; + +      // +      // +      struct PrimaryMember: Traversal::Member, Context +      { +        PrimaryMember (Context& c, NameSet& name_set, NameSet& stem_set) +            : Context (c), name_set_ (name_set), stem_set_ (stem_set) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (Tree::Context::skip (m)) +            return; + +          String stem (find_name (m.name (), stem_set_)); + +          m.context ().set ("stem", stem); +          m.context ().set ("name", +                            find_name (escape (stem), name_set_, false)); +        } + +      private: +        NameSet& name_set_; +        NameSet& stem_set_; +      }; + +      // +      // +      struct DerivedMember: Traversal::Member, Context +      { +        DerivedMember (Context& c, NameSet& name_set) +            : Context (c), name_set_ (name_set) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (Tree::Context::skip (m)) +            return; + +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (m.scope ())); + +          size_t max (Tree::Context::max (m)); +          size_t min (Tree::Context::min (m)); + +          String const& s (m.context ().get<String> ("stem")); +          String const& b (m.context ().get<String> ("name")); + +          bool def_attr (m.default_p () && +                         m.is_a<SemanticGraph::Attribute> ()); + +          // Accessors/modifiers. Note that we postpone inserting +          // the names into the name_set to avoid over-escaping. +          // +          String an, mn; + +          if (max != 1) +          { +            an = find_name ( +              escape (process_regex (s, +                                     seq_accessor_regex, +                                     accessor_regex, +                                     L"sequence accessor")), +              name_set_, +              false); + +            mn = find_name ( +              escape (process_regex (s, +                                     seq_modifier_regex, +                                     modifier_regex, +                                     L"sequence modifier")), +              name_set_, +              false); +          } +          else if (min == 0 && !def_attr) +          { +            an = find_name ( +              escape (process_regex (s, +                                     opt_accessor_regex, +                                     accessor_regex, +                                     L"optional accessor")), +              name_set_, +              false); + +            mn = find_name ( +              escape (process_regex (s, +                                     opt_modifier_regex, +                                     modifier_regex, +                                     L"optional modifier")), +              name_set_, +              false); +          } +          else +          { +            an = find_name ( +              escape (process_regex (s, +                                     one_accessor_regex, +                                     accessor_regex, +                                     L"one accessor")), +              name_set_, +              false); + +            mn = find_name ( +              escape (process_regex (s, +                                     one_modifier_regex, +                                     modifier_regex, +                                     L"one modifier")), +              name_set_, +              false); +          } + +          m.context ().set ("aname", an); +          m.context ().set ("mname", mn); + +          name_set_.insert (b); + +          if (an != b) +            name_set_.insert (an); + +          if (mn != b && mn != an) +            name_set_.insert (mn); + +          // Detach. +          // +          if (detach && max == 1 && (min == 1 || def_attr)) +          { +            String dn (find_name ( +                         escape (process_regex (L"detach," + s, +                                                one_modifier_regex, +                                                modifier_regex, +                                                L"one modifier")), +                         name_set_)); + +            m.context ().set ("dname", dn); +          } + +          // Types. +          // +          m.context ().set ( +            "type", +            find_name ( +              escape (process_regex (s + L",type", type_regex, L"type")), +              name_set_)); + +          m.context ().set ( +            "traits", +            find_name ( +              escape (process_regex (s + L",traits", type_regex, L"type")), +              name_set_)); + +          if (max != 1) +          { +            m.context ().set ( +              "container", +              find_name ( +                escape (process_regex (s + L",sequence", type_regex, L"type")), +                name_set_)); + +            m.context ().set ( +              "iterator", +              find_name ( +                escape (process_regex (s + L",iterator", type_regex, L"type")), +                name_set_)); + +            m.context ().set ( +              "const-iterator", +              find_name ( +                escape ( +                  process_regex (s + L",const,iterator", type_regex, L"type")), +                name_set_)); +          } +          else if (min == 0 && !def_attr) +          { +            m.context ().set ( +              "container", +              find_name ( +                escape (process_regex (s + L",optional", type_regex, L"type")), +                name_set_)); +          } + +          // Data member. +          // +          m.context ().set ("member", find_name (b + L"_", name_set_)); + +          // Default value. +          // +          if (m.default_p ()) +          { +            bool simple (true); + +            if (m.is_a<SemanticGraph::Element> ()) +            { +              IsSimpleType test (simple); +              test.dispatch (m.type ()); +            } + +            if (simple) +            { +              String an ( +                escape ( +                  process_regex ( +                    s + L",default,value", accessor_regex, L"accessor"))); + +              m.context ().set ("default-value", find_name (an, name_set_)); + +              bool lit (false); +              { +                IsLiteralValue test (lit); +                test.dispatch (m.type ()); +              } + +              if (!lit) +              { +                m.context ().set ( +                  "default-value-member", +                  find_name (b + L"_default_value_", name_set_)); +              } +            } +          } + +          // Element id. +          // +          if (m.is_a<SemanticGraph::Element> () && ordered_p (c)) +          { +            String id ( +              escape ( +                process_regex ( +                  s + L",id", const_regex, L"const"))); + +            m.context ().set ("ordered-id-name", find_name (id, name_set_)); +          } +        } + +      private: +        NameSet& name_set_; +      }; + + +      // +      // +      struct Any: Traversal::Any, Traversal::AnyAttribute, Context +      { +        Any (Context& c, +             NameSet& name_set, +             NameSet& stem_set, +             bool& has_wildcard) +            : Context (c), +              name_set_ (name_set), +              stem_set_ (stem_set), +              has_wildcard_ (has_wildcard) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + +          size_t max (Tree::Context::max (a)); +          size_t min (Tree::Context::min (a)); + +          String s (find_name (L"any", stem_set_)); + +          String b (find_name (escape (s), name_set_, false)); +          a.context ().set ("name", b); + +          // Accessors/modifiers. Note that we postpone inserting the +          // names into the name_set to avoid over-escaping. +          // +          String an, mn; + +          if (max != 1) +          { +            an = find_name ( +              escape (process_regex (s, +                                     seq_accessor_regex, +                                     accessor_regex, +                                     L"sequence accessor")), +              name_set_, +              false); + +            mn = find_name ( +              escape (process_regex (s, +                                     seq_modifier_regex, +                                     modifier_regex, +                                     L"sequence modifier")), +              name_set_, +              false); +          } +          else if (min == 0) +          { +            an = find_name ( +              escape (process_regex (s, +                                     opt_accessor_regex, +                                     accessor_regex, +                                     L"optional accessor")), +              name_set_, +              false); + +            mn = find_name ( +              escape (process_regex (s, +                                     opt_modifier_regex, +                                     modifier_regex, +                                     L"optional modifier")), +              name_set_, +              false); +          } +          else +          { +            an = find_name ( +              escape (process_regex (s, +                                     one_accessor_regex, +                                     accessor_regex, +                                     L"one accessor")), +              name_set_, +              false); + +            mn = find_name ( +              escape (process_regex (s, +                                     one_modifier_regex, +                                     modifier_regex, +                                     L"one modifier")), +              name_set_, +              false); +          } + +          a.context ().set ("aname", an); +          a.context ().set ("mname", mn); + +          name_set_.insert (b); + +          if (an != b) +            name_set_.insert (an); + +          if (mn != b && mn != an) +            name_set_.insert (mn); + +          // Types +          // +          if (max != 1) +          { +            a.context ().set ( +              "container", +              find_name ( +                escape (process_regex (s + L",sequence", type_regex, L"type")), +                name_set_)); + +            a.context ().set ( +              "iterator", +              find_name ( +                escape (process_regex (s + L",iterator", type_regex, L"type")), +                name_set_)); + +            a.context ().set ( +              "const-iterator", +              find_name ( +                escape ( +                  process_regex (s + L",const,iterator", type_regex, L"type")), +                name_set_)); +          } +          else if (min == 0) +          { +            a.context ().set ( +              "container", +              find_name ( +                escape (process_regex (s + L",optional", type_regex, L"type")), +                name_set_)); +          } + +          // Data member. +          // +          a.context ().set ("member", find_name (b + L"_", name_set_)); + +          // Wildcard id. +          // +          if (ordered_p (c)) +          { +            String id ( +              escape ( +                process_regex ( +                  s + L",id", const_regex, L"const"))); + +            a.context ().set ("ordered-id-name", find_name (id, name_set_)); +          } + +          if (!has_wildcard_) +            has_wildcard_ = true; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String s (find_name (L"any,attribute", stem_set_)); + +          String b (find_name (escape (s), name_set_, false)); +          a.context ().set ("name", b); + +          // Accessors/modifiers. Note that we postpone inserting the +          // names into the name_set to avoid over-escaping. +          // +          String an ( +            find_name ( +              escape (process_regex (s, accessor_regex, L"accessor")), +              name_set_, +              false)); + +          String mn ( +            find_name ( +              escape (process_regex (s, modifier_regex, L"modifier")), +              name_set_, +              false)); + +          a.context ().set ("aname", an); +          a.context ().set ("mname", mn); + +          name_set_.insert (b); + +          if (an != b) +            name_set_.insert (an); + +          if (mn != b && mn != an) +            name_set_.insert (mn); + +          // Types +          // +          a.context ().set ( +            "container", +            find_name ( +              escape (process_regex (s + L",set", type_regex, L"type")), +              name_set_)); + +          a.context ().set ( +            "iterator", +            find_name ( +              escape (process_regex (s + L",iterator", type_regex, L"type")), +              name_set_)); + +          a.context ().set ( +            "const-iterator", +            find_name ( +              escape ( +                process_regex (s + L",const,iterator", type_regex, L"type")), +              name_set_)); + +          // Data member. +          // +          a.context ().set ("member", find_name (b + L"_", name_set_)); + +          if (!has_wildcard_) +            has_wildcard_ = true; +        } + +      private: +        NameSet& name_set_; +        NameSet& stem_set_; +        bool& has_wildcard_; +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          SemanticGraph::Context& ctx (c.context ()); + +          // We leave this set around to allow other mappings to use +          // this information. +          // +          ctx.set ("cxx-tree-name-processor-stem-set", NameSet ()); +          ctx.set ("cxx-tree-name-processor-member-set", NameSet ()); + +          // Use processed name. +          // +          String name (ctx.get<String> ("name")); + +          // If renamed name is empty then we are not generating +          // anything for this type and name processing is not +          // required. +          // +          if (renamed_type (c, name) && !name) +            return; + +          NameSet& stem_set ( +            ctx.get<NameSet> ("cxx-tree-name-processor-stem-set")); + +          NameSet& member_set ( +            ctx.get<NameSet> ("cxx-tree-name-processor-member-set")); + +          stem_set.insert (c.name ()); +          member_set.insert (name); + +          // Add our base's stems and members to the initial list. +          // +          if (c.inherits_p ()) +          { +            // @@ What if this types name is the same as one of base's +            //    members? +            // +            SemanticGraph::Type& base (c.inherits ().base ()); + +            if (base.is_a<SemanticGraph::Complex> () && +                !base.is_a<SemanticGraph::Enumeration> ()) +            { +              if (!base.context ().count ( +                    "cxx-tree-name-processor-member-set")) +              { +                dispatch (base); +              } + +              NameSet const& base_stem_set ( +                base.context ().get<NameSet> ( +                  "cxx-tree-name-processor-stem-set")); + +              stem_set.insert (base_stem_set.begin (), base_stem_set.end ()); + +              NameSet const& base_member_set ( +                base.context ().get<NameSet> ( +                  "cxx-tree-name-processor-member-set")); + +              member_set.insert (base_member_set.begin (), +                                 base_member_set.end ()); +            } +          } + +          // First assign the "primary" names. +          // +          { +            PrimaryMember member (*this, member_set, stem_set); +            Traversal::Names names (member); + +            Complex::names (c, names); +          } + +          // Derived names for members. +          // +          { +            DerivedMember member (*this, member_set); +            Traversal::Names names (member); + +            Complex::names (c, names); +          } + +          // Names for the mixed content. +          // +          if (mixed_p (c)) +          { +            // Check if we already have the mixed content down inheritance +            // hierarchy. +            // +            using SemanticGraph::Complex; + +            for (Complex* p (&c); p->inherits_p ();) +            { +              if (Complex* b = dynamic_cast<Complex*> ( +                    &p->inherits ().base ())) +              { +                if (mixed_p (*b)) +                { +                  SemanticGraph::Context& bctx (b->context ()); +                  ctx.set ("mixed-type", bctx.get<String> ("mixed-type")); +                  ctx.set ("mixed-const-iterator", +                           bctx.get<String> ("mixed-const-iterator")); +                  ctx.set ("mixed-ordered-id-name", +                           bctx.get<String> ("mixed-ordered-id-name")); +                  ctx.set ("mixed-aname", bctx.get<String> ("mixed-aname")); +                  ctx.set ("mixed-member", bctx.get<String> ("mixed-member")); +                  ctx.set ("mixed-in-base", true); +                  break; +                } + +                p = b; +              } +              else +                break; +            } + +            // If not, set up the names. +            // +            if (!ctx.count ("mixed-in-base")) +            { +              String s (find_name (L"text,content", stem_set)); +              String n (find_name (escape (s), member_set, false)); + +              String an (find_name ( +                           escape (process_regex (s, +                                                  seq_accessor_regex, +                                                  accessor_regex, +                                                  L"sequence accessor")), +                           member_set, +                           false)); + +              String mn (find_name ( +                           escape (process_regex (s, +                                                  seq_modifier_regex, +                                                  modifier_regex, +                                                  L"sequence modifier")), +                           member_set, +                           false)); + +              ctx.set ("mixed-aname", an); +              ctx.set ("mixed-mname", mn); + +              member_set.insert (name); + +              if (an != n) +                member_set.insert (an); + +              if (mn != n && mn != an) +                member_set.insert (mn); + +              // Types. +              // +              ctx.set ( +                "mixed-type", +                find_name ( +                  escape (process_regex (s + L",type", type_regex, L"type")), +                  member_set)); + +              ctx.set ( +                "mixed-container", +                find_name ( +                  escape (process_regex (s + L",sequence", type_regex, L"type")), +                  member_set)); + +              ctx.set ( +                "mixed-iterator", +                find_name ( +                  escape (process_regex (s + L",iterator", type_regex, L"type")), +                  member_set)); + +              ctx.set ( +                "mixed-const-iterator", +                find_name ( +                  escape ( +                    process_regex (s + L",const,iterator", type_regex, L"type")), +                  member_set)); + +              // Text content id. +              // +              ctx.set ( +                "mixed-ordered-id-name", +                find_name ( +                  escape ( +                    process_regex (s + L",id", const_regex, L"const")), +                  member_set)); + +              // Data member. +              // +              ctx.set ("mixed-member", find_name (n + L"_", member_set)); +            } +          } + +          // Names for wildcards. +          // +          if (options.generate_wildcard ()) +          { +            bool has_wildcard (false); +            Any any (*this, member_set, stem_set, has_wildcard); +            Traversal::Names names (any); +            Complex::names (c, names); + +            // Assign names for dom_document. +            // +            if (has_wildcard) +            { +              // Check if we already have dom_document down inheritance +              // hierarchy. +              // +              for (SemanticGraph::Complex* p (&c); p->inherits_p ();) +              { +                if (SemanticGraph::Complex* base = +                    dynamic_cast<SemanticGraph::Complex*> ( +                      &p->inherits ().base ())) +                { +                  if (base->context ().count ("dom-document")) +                  { +                    c.context ().set ( +                      "dom-document", +                      base->context ().get<String> ("dom-document")); +                    break; +                  } + +                  p = base; +                } +                else +                  break; +              } + +              // If not, set up the names. +              // +              if (!c.context ().count ("dom-document")) +              { +                String stem (find_name (L"dom,document", stem_set)); + +                String an ( +                  escape ( +                    process_regex (stem, accessor_regex, L"accessor"))); + +                c.context ().set ("dom-document", find_name (an, member_set)); + +                c.context ().set ( +                  "dom-document-member", +                  find_name (escape (stem + L"_"), member_set)); +              } +            } +          } + +          // Names for the order container. +          // +          if (ordered_p (c)) +          { +            // Check if we already have the order container down +            // inheritance hierarchy. +            // +            using SemanticGraph::Complex; + +            for (Complex* p (&c); p->inherits_p ();) +            { +              if (Complex* b = dynamic_cast<Complex*> ( +                    &p->inherits ().base ())) +              { +                if (ordered_p (*b)) +                { +                  SemanticGraph::Context& bctx (b->context ()); +                  ctx.set ("order-type", bctx.get<String> ("order-type")); +                  ctx.set ("order-const-iterator", +                           bctx.get<String> ("order-const-iterator")); +                  ctx.set ("order-aname", bctx.get<String> ("order-aname")); +                  ctx.set ("order-member", bctx.get<String> ("order-member")); +                  ctx.set ("order-in-base", true); +                  break; +                } + +                p = b; +              } +              else +                break; +            } + +            // If not, set up the names. +            // +            if (!ctx.count ("order-in-base")) +            { +              String s (find_name (L"content,order", stem_set)); +              String n (find_name (escape (s), member_set, false)); + +              String an (find_name ( +                           escape (process_regex (s, +                                                  seq_accessor_regex, +                                                  accessor_regex, +                                                  L"sequence accessor")), +                           member_set, +                           false)); + +              String mn (find_name ( +                           escape (process_regex (s, +                                                  seq_modifier_regex, +                                                  modifier_regex, +                                                  L"sequence modifier")), +                           member_set, +                           false)); + +              ctx.set ("order-aname", an); +              ctx.set ("order-mname", mn); + +              member_set.insert (name); + +              if (an != n) +                member_set.insert (an); + +              if (mn != n && mn != an) +                member_set.insert (mn); + +              // Types. +              // +              ctx.set ( +                "order-type", +                find_name ( +                  escape (process_regex (s + L",type", type_regex, L"type")), +                  member_set)); + +              ctx.set ( +                "order-container", +                find_name ( +                  escape (process_regex (s + L",sequence", type_regex, L"type")), +                  member_set)); + +              ctx.set ( +                "order-iterator", +                find_name ( +                  escape (process_regex (s + L",iterator", type_regex, L"type")), +                  member_set)); + +              ctx.set ( +                "order-const-iterator", +                find_name ( +                  escape ( +                    process_regex (s + L",const,iterator", type_regex, L"type")), +                  member_set)); + +              // Data member. +              // +              ctx.set ("order-member", find_name (n + L"_", member_set)); +            } +          } +        } +      }; + + +      // +      // +      struct GlobalType: Traversal::Type, Context +      { +        GlobalType (Context& c, NameSet& set) +            : Context (c), set_ (set) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          // Process the name with type name regex. +          // +          String name (process_regex ( +                         namespace_ (t).name (), +                         t.name (), +                         type_regex, +                         L"type")); + +          // Escape and unclash. +          // +          name = find_name (escape (name), set_); +          t.context ().set ("name", name); + +          // Also add renamed name if any. +          // +          if (renamed_type (t, name) && name) +            set_.insert (name); +        } + +      private: +        NameSet& set_; +      }; + + +      // +      // +      struct GlobalElement: Traversal::Element, +                            GlobalElementBase, +                            Context +      { +        GlobalElement (Context& c, +                       NameSet const& type_set, +                       NameSet& element_set) +            : GlobalElementBase (c), +              Context (c), +              type_set_ (type_set), +              element_set_ (element_set) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          // First we need to figure out if we need to process this +          // global element. +          // +          if (!generate_p (e)) +            return; + +          if (options.generate_element_type ()) +          { +            SemanticGraph::Context& ec (e.context ()); + +            String name; + +            if (doc_root_p (e)) +            { +              name = find_name ( +                escape ( +                  process_regex ( +                    namespace_ (e).name (), +                    e.name (), +                    element_type_regex, +                    type_regex, +                    L"element type"))); + +              // Assign inner names. +              // +              NameSet set; +              set.insert (name); + +              ec.set ( +                "type", +                Context::find_name ( +                  escape (process_regex (L"value,type", type_regex, L"type")), +                  set)); + +              ec.set ( +                "traits", +                Context::find_name ( +                  escape (process_regex (L"value,traits", type_regex, L"type")), +                  set)); + +              String an (Context::find_name ( +                escape (process_regex ("value", +                                       one_accessor_regex, +                                       accessor_regex, +                                       L"one accessor")), +                set, +                false)); + +              String mn (Context::find_name ( +                escape (process_regex ("value", +                                       one_modifier_regex, +                                       modifier_regex, +                                       L"one modifier")), +                set, +                false)); + +              ec.set ("aname", an); +              ec.set ("mname", mn); + +              set.insert (an); + +              if (an != mn) +                set.insert (mn); + +              // Detach. +              // +              if (detach) +              { +                String dn (Context::find_name ( +                             escape (process_regex (L"detach,value", +                                                    one_modifier_regex, +                                                    modifier_regex, +                                                    L"one modifier")), +                             set)); + +                ec.set ("dname", dn); +              } + +              // Assign name() and namespace_() names. +              // +              ec.set ( +                "element-name", +                Context::find_name ( +                  escape ( +                    process_regex ("name", accessor_regex, L"modifier")), +                  set)); + +              ec.set ( +                "element-ns", +                Context::find_name ( +                  escape ( +                    process_regex ("namespace", accessor_regex, L"modifier")), +                  set)); + +              // Data members. +              // +              ec.set ("member", Context::find_name ("value_", set)); +              ec.set ("element-name-member", +                      Context::find_name ("name_", set)); +              ec.set ("element-ns-member", +                      Context::find_name ("namespace__", set)); +            } +            else +              name = find_name (escape (e.name ())); + +            ec.set ("name", name); +            element_set_.insert (name); +          } +          else +          { +            // Make sure the name is unique among global elements and +            // does not collide with a global type name. +            // +            String base (find_name (escape (e.name ()))); +            e.context ().set ("name", base); + +            String n (e.name ()); + +            // Assign the parsing function name. +            // +            String p; + +            if (!options.suppress_parsing () && doc_root_p (e)) +            { +              p = find_name ( +                escape ( +                  process_regex (n, parser_regex, L"parsing function"))); + +              e.context ().set ("parser", p); +            } + +            // Assign the serialization function name. +            // +            String s; + +            if (options.generate_serialization () && doc_root_p (e)) +            { +              s = find_name ( +                escape ( +                  process_regex ( +                    n, serializer_regex, L"serialization function"))); + +              e.context ().set ("serializer", s); +            } + +            // Add the names to the set only after processing parsing and +            // serialization function names so that we do not over-escape +            // them. +            // +            element_set_.insert (base); + +            if (p && p != base) +              element_set_.insert (p); + +            if (s && s != base && s != p) +              element_set_.insert (s); +          } +        } + +      private: +        String +        find_name (String const& name) +        { +          String r (name); + +          // If we are conflicting with a type name let's first try to +          // simply append an underscore and only resort to ugly names +          // like name1, etc., if this fails. +          // +          if (type_set_.find (r) != type_set_.end ()) +            r += L"_"; + +          for (size_t i (1); +               element_set_.find (r) != element_set_.end () || +                 type_set_.find (r) != type_set_.end (); ++i) +          { +            std::wostringstream os; +            os << i; +            r = name + os.str (); +          } + +          return r; +        } + +      private: +        NameSet const& type_set_; +        NameSet& element_set_; +      }; + +      struct NamespacePassOne: Traversal::Namespace, Context +      { +        NamespacePassOne (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& ns) +        { +          NameSet& type_set (global_type_names[ns.name ()]); + +          GlobalType type (*this, type_set); +          Traversal::Names names (type); + +          Traversal::Namespace::names (ns, names); +          Traversal::Namespace::names (ns); +        } +      }; + + +      struct NamespacePassThree: Traversal::Namespace, Context +      { +        NamespacePassThree (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& ns) +        { +          String const& name (ns.name ()); + +          NameSet const& type_set (global_type_names[name]); +          NameSet& element_set (global_element_names[name]); + +          GlobalElement element (*this, type_set, element_set); +          Traversal::Names names (element); + +          Traversal::Namespace::names (ns, names); +        } +      }; + + +      struct FundamentalNamespace: Traversal::Namespace, + +                                   Traversal::AnyType, +                                   Traversal::AnySimpleType, + +                                   Traversal::Fundamental::Byte, +                                   Traversal::Fundamental::UnsignedByte, +                                   Traversal::Fundamental::Short, +                                   Traversal::Fundamental::UnsignedShort, +                                   Traversal::Fundamental::Int, +                                   Traversal::Fundamental::UnsignedInt, +                                   Traversal::Fundamental::Long, +                                   Traversal::Fundamental::UnsignedLong, +                                   Traversal::Fundamental::Integer, +                                   Traversal::Fundamental::NonPositiveInteger, +                                   Traversal::Fundamental::NonNegativeInteger, +                                   Traversal::Fundamental::PositiveInteger, +                                   Traversal::Fundamental::NegativeInteger, + +                                   Traversal::Fundamental::Boolean, + +                                   Traversal::Fundamental::Float, +                                   Traversal::Fundamental::Double, +                                   Traversal::Fundamental::Decimal, + +                                   Traversal::Fundamental::String, +                                   Traversal::Fundamental::NormalizedString, +                                   Traversal::Fundamental::Token, +                                   Traversal::Fundamental::Name, +                                   Traversal::Fundamental::NameToken, +                                   Traversal::Fundamental::NameTokens, +                                   Traversal::Fundamental::NCName, +                                   Traversal::Fundamental::Language, + +                                   Traversal::Fundamental::Id, +                                   Traversal::Fundamental::IdRef, +                                   Traversal::Fundamental::IdRefs, + +                                   Traversal::Fundamental::AnyURI, + +                                   Traversal::Fundamental::QName, + +                                   Traversal::Fundamental::Base64Binary, +                                   Traversal::Fundamental::HexBinary, + +                                   Traversal::Fundamental::Date, +                                   Traversal::Fundamental::DateTime, +                                   Traversal::Fundamental::Duration, +                                   Traversal::Fundamental::Day, +                                   Traversal::Fundamental::Month, +                                   Traversal::Fundamental::MonthDay, +                                   Traversal::Fundamental::Year, +                                   Traversal::Fundamental::YearMonth, +                                   Traversal::Fundamental::Time, + +                                   Traversal::Fundamental::Entity, +                                   Traversal::Fundamental::Entities, + +                                   Context +      { +        using Namespace::traverse; + +        FundamentalNamespace (Context& c) +            : Context (c) +        { +          *this >> names_ >> *this; +        } + +        void +        process_name (SemanticGraph::Type& t, String const& name) +        { +          String r ( +            process_regex ( +              namespace_ (t).name (), name, type_regex, L"type")); + +          t.context ().set ("name", escape (r)); +        } + +        void +        process_name (SemanticGraph::Namespace& n, +                      String const& name, +                      char const* key) +        { +          String r (process_regex (name, type_regex, L"type")); +          n.context ().set (key, escape (r)); +        } + +        // anyType and anySimpleType +        // +        virtual void +        traverse (SemanticGraph::AnyType& t) +        { +          process_name (t, "type"); +        } + +        virtual void +        traverse (SemanticGraph::AnySimpleType& t) +        { +          process_name (t, "simple,type"); +        } + +        // Integrals. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Byte& t) +        { +          process_name (t, "byte"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedByte& t) +        { +          process_name (t, "unsigned,byte"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Short& t) +        { +          process_name (t, "short"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedShort& t) +        { +          process_name (t, "unsigned,short"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Int& t) +        { +          process_name (t, "int"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedInt& t) +        { +          process_name (t, "unsigned,int"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Long& t) +        { +          process_name (t, "long"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedLong& t) +        { +          process_name (t, "unsigned,long"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Integer& t) +        { +          process_name (t, "integer"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +        { +          process_name (t, "non,positive,integer"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +        { +          process_name (t, "non,negative,integer"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::PositiveInteger& t) +        { +          process_name (t, "positive,integer"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NegativeInteger& t) +        { +          process_name (t, "negative,integer"); +        } + +        // Boolean. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Boolean& t) +        { +          process_name (t, "boolean"); +        } + +        // Floats. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Float& t) +        { +          process_name (t, "float"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Double& t) +        { +          process_name (t, "double"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Decimal& t) +        { +          process_name (t, "decimal"); +        } + +        // Strings. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::String& t) +        { +          process_name (t, "string"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NormalizedString& t) +        { +          process_name (t, "normalized,string"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Token& t) +        { +          process_name (t, "token"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameToken& t) +        { +          process_name (t, "nmtoken"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameTokens& t) +        { +          process_name (t, "nmtokens"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Name& t) +        { +          process_name (t, "name"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NCName& t) +        { +          process_name (t, "ncname"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Language& t) +        { +          process_name (t, "language"); +        } + +        // ID/IDREF. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Id& t) +        { +          process_name (t, "id"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRef& t) +        { +          process_name (t, "idref"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRefs& t) +        { +          process_name (t, "idrefs"); +        } + + +        // URI. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::AnyURI& t) +        { +          process_name (t, "uri"); +        } + +        // Qualified name. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::QName& t) +        { +          process_name (t, "qname"); +        } + +        // Binary. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Base64Binary& t) +        { +          process_name (t, "base64,binary"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::HexBinary& t) +        { +          process_name (t, "hex,binary"); +        } + + +        // Date/time. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Date& t) +        { +          process_name (t, "date"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::DateTime& t) +        { +          process_name (t, "date,time"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Duration& t) +        { +          process_name (t, "duration"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Day& t) +        { +          process_name (t, "gday"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Month& t) +        { +          process_name (t, "gmonth"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::MonthDay& t) +        { +          process_name (t, "gmonth,day"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Year& t) +        { +          process_name (t, "gyear"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::YearMonth& t) +        { +          process_name (t, "gyear,month"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Time& t) +        { +          process_name (t, "time"); +        } + +        // Entity. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Entity& t) +        { +          process_name (t, "entity"); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Entities& t) +        { +          process_name (t, "entities"); +        } + +        virtual void +        post (SemanticGraph::Namespace& n) +        { +          // Assign names to extra stuff in the XML Schema namespace. +          // +          process_name (n, "container", "container"); +          process_name (n, "buffer", "buffer"); +          process_name (n, "time,zone", "time-zone"); + +          process_name (n, "content,order", "content-order"); + +          if (options.generate_element_type ()) +            process_name (n, "element,type", "element-type"); + +          if (options.generate_element_map ()) +            process_name (n, "element,map", "element-map"); + +          if (options.generate_serialization ()) +          { +            process_name (n, "namespace,info", "namespace-info"); +            process_name (n, "namespace,infomap", "namespace-infomap"); +            process_name (n, "list,stream", "list-stream"); +            process_name (n, "as,double", "as-double"); +            process_name (n, "as,decimal", "as-decimal"); +            process_name (n, "facet", "facet"); +          } + +          if (!options.generate_insertion ().empty ()) +          { +            process_name (n, "ostream", "ostream"); +          } + +          if (!options.generate_extraction ().empty ()) +          { +            process_name (n, "istream", "istream"); +          } + +          process_name (n, "flags", "flags"); +          process_name (n, "properties", "properties"); + +          NarrowString fn (options.function_naming ()); + +          if (fn == "knr") +            n.context ().set ("tree-node-key", String ("tree_node_key")); +          else if (fn == "ucc") +            n.context ().set ("tree-node-key", String ("TreeNodeKey")); +          else +            n.context ().set ("tree-node-key", String ("treeNodeKey")); + +          process_name (n, "exception", "exception"); +          process_name (n, "parsing", "parsing"); +          process_name (n, "expected,element", "expected-element"); +          process_name (n, "unexpected,element", "unexpected-element"); +          process_name (n, "expected,attribute", "expected-attribute"); +          process_name (n, "unexpected,enumerator", "unexpected-enumerator"); +          process_name (n, "expected,text,content", "expected-text-content"); +          process_name (n, "no,type,info", "no-type-info"); +          process_name (n, "no,element,info", "no-element-info"); +          process_name (n, "not,derived", "not-derived"); +          process_name (n, "duplicate,id", "duplicate-id"); +          process_name (n, "serialization", "serialization"); +          process_name (n, "no,namespace,mapping", "no-namespace-mapping"); +          process_name (n, "no,prefix,mapping", "no-prefix-mapping"); +          process_name (n, "xsi,already,in,use", "xsi-already-in-use"); +          process_name (n, "bounds", "bounds"); + +          process_name (n, "severity", "severity"); +          process_name (n, "error", "error"); +          process_name (n, "diagnostics", "diagnostics"); + +          if (!options.suppress_parsing () || +              options.generate_serialization ()) +          { +            process_name (n, "error,handler", "error-handler"); +          } + +          Namespace::post (n); +        } + +      private: +        Traversal::Names names_; +      }; + + +      // Go into sourced/included/imported schemas while making sure +      // we don't process the same stuff more than once. +      // +      struct UsesPassOne: Traversal::Uses +      { +        virtual void +        traverse (Type& u) +        { +          SemanticGraph::Schema& s (u.schema ()); + +          if (!s.context ().count ("cxx-tree-name-processor-pass-1")) +          { +            s.context ().set ("cxx-tree-name-processor-pass-1", true); +            Traversal::Uses::traverse (u); +          } +        } +      }; + +      struct UsesPassThree: Traversal::Uses +      { +        virtual void +        traverse (Type& u) +        { +          SemanticGraph::Schema& s (u.schema ()); + +          if (!s.context ().count ("cxx-tree-name-processor-pass-3")) +          { +            s.context ().set ("cxx-tree-name-processor-pass-3", true); +            Traversal::Uses::traverse (u); +          } +        } +      }; + +      // Go into implied schemas while making sure we don't process +      // the same stuff more than once. +      // +      struct Implies: Traversal::Implies +      { +        virtual void +        traverse (SemanticGraph::Implies& i) +        { +          SemanticGraph::Schema& s (i.schema ()); + +          if (!s.context ().count ("cxx-tree-name-processor-seen")) +          { +            s.context ().set ("cxx-tree-name-processor-seen", true); +            Traversal::Implies::traverse (i); +          } +        } +      }; + +      bool +      process_impl (options const& ops, +                    SemanticGraph::Schema& tu, +                    SemanticGraph::Path const& file, +                    StringLiteralMap const& map) +      { +        try +        { +          Counts counts; +          Context ctx (ops, counts, false, tu, file, map); + +          if (tu.names_begin ()->named ().name () == +              L"http://www.w3.org/2001/XMLSchema") +          { +            // XML Schema namespace. +            // +            Traversal::Schema xs_schema; +            Traversal::Names xs_schema_names; +            FundamentalNamespace xs_ns (ctx); + +            xs_schema >> xs_schema_names >> xs_ns; + +            xs_schema.dispatch (tu); +          } +          else +          { + +            // Pass one - assign names to global types. This pass cannot +            // be combined with pass two because of possible recursive +            // schema inclusions. Also note that we check first if this +            // schema has already been processed which may happen in the +            // file-per-type compilation mode. +            // +            if (!tu.context ().count ("cxx-tree-name-processor-pass-1")) +            { +              Traversal::Schema schema; +              Traversal::Schema xs_schema; +              UsesPassOne uses; +              Implies implies; + +              schema >> uses >> schema; +              schema >> implies >> xs_schema; + +              Traversal::Names schema_names; +              Traversal::Names xs_schema_names; +              NamespacePassOne ns (ctx); +              FundamentalNamespace xs_ns (ctx); + +              schema >> schema_names >> ns; +              xs_schema >> xs_schema_names >> xs_ns; + +              // Some twisted schemas do recusive self-inclusion. +              // +              tu.context ().set ("cxx-tree-name-processor-pass-1", true); + +              schema.dispatch (tu); +            } + +            // Pass two - assign names inside complex types. Here +            // we don't need to go into included/imported schemas. +            // +            { +              Traversal::Schema schema; +              Sources sources; + +              schema >> sources >> schema; + +              Traversal::Names schema_names; +              Traversal::Namespace ns; +              Traversal::Names ns_names; + +              schema >> schema_names >> ns >> ns_names; + +              Complex complex (ctx); +              Traversal::Enumeration enumeration; // Avoid fallback on complex. + +              ns_names >> complex; +              ns_names >> enumeration; + +              schema.dispatch (tu); +            } + +            // Pass three - assign names to global elements as well as +            // inside enums. Also note that we check first if this schema +            // has already been processed which may happen in the file-per- +            // type compilation mode. +            // +            if (!tu.context ().count ("cxx-tree-name-processor-pass-3")) +            { +              Traversal::Schema schema; +              UsesPassThree uses; + +              schema >> uses >> schema; + +              Traversal::Names schema_names; +              NamespacePassThree ns (ctx); +              Traversal::Namespace ns_enum; + +              schema >> schema_names; + +              schema_names >> ns; +              schema_names >> ns_enum; + +              Traversal::Names ns_names; +              Enumeration enumeration (ctx); + +              ns_enum >> ns_names >> enumeration; + +              // Some twisted schemas do recusive self-inclusion. +              // +              tu.context ().set ("cxx-tree-name-processor-pass-3", true); + +              schema.dispatch (tu); +            } +          } +        } +        catch (Context::Failed const&) +        { +          // Diagnostics has already been issued. +          // +          return false; +        } + +        return true; +      } +    } + +    bool NameProcessor:: +    process (options const& ops, +             SemanticGraph::Schema& tu, +             SemanticGraph::Path const& file, +             StringLiteralMap const& map) +    { +      return process_impl (ops, tu, file, map); +    } +  } +} diff --git a/xsd/cxx/tree/name-processor.hxx b/xsd/cxx/tree/name-processor.hxx new file mode 100644 index 0000000..632b05e --- /dev/null +++ b/xsd/cxx/tree/name-processor.hxx @@ -0,0 +1,28 @@ +// file      : xsd/cxx/tree/name-processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_NAME_PROCESSOR_HXX +#define XSD_CXX_TREE_NAME_PROCESSOR_HXX + +#include <xsd/types.hxx> + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ +  namespace Tree +  { +    class NameProcessor +    { +    public: +      bool +      process (options const&, +               XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file, +               StringLiteralMap const&); +    }; +  } +} + +#endif // XSD_CXX_TREE_NAME_PROCESSOR_HXX diff --git a/xsd/cxx/tree/options.cli b/xsd/cxx/tree/options.cli new file mode 100644 index 0000000..0230429 --- /dev/null +++ b/xsd/cxx/tree/options.cli @@ -0,0 +1,479 @@ +// file      : xsd/cxx/tree/options.cli +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include <cstddef>; // std::size_t + +include <xsd/types.hxx>; // NarrowString, NarrowStrings + +include <xsd/cxx/options.cli>; + +namespace CXX +{ +  namespace Tree +  { +    class options: CXX::options +    { +      // Polymorphism. +      // +      bool --generate-polymorphic +      { +        "Generate polymorphism-aware code. Specify this option if you use +         substitution groups or \cb{xsi:type}. Use the \cb{--polymorphic-type} +         or \cb{--polymorphic-type-all} option to specify which type +         hierarchies are polymorphic." +      }; + +      NarrowStrings --polymorphic-type +      { +        "<type>", +        "Indicate that <type> is a root of a polymorphic type hierarchy. The +         compiler can often automatically determine which types are +         polymorphic based on the substitution group declarations. However, +         you may need to use this option if you are not using substitution +         groups or if substitution groups are defined in another schema. You +         need to specify this option when compiling every schema file that +         references <type>. The <type> argument is an XML Schema type name +         that can be optionally qualified with a namespace in the +         \c{\i{namespace}\b{#}\i{name}} form." +      }; + +      bool --polymorphic-type-all +      { +        "Indicate that all types should be treated as polymorphic." +      }; + +      unsigned long --polymorphic-plate = 0 +      { +        "<num>", +        "Specify the polymorphic map plate the generated code should register +         on. This functionality is primarily useful to segregate multiple +         schemas that define the same polymorphic types." +      }; + +      // Ordered content. +      // +      NarrowStrings --ordered-type +      { +        "<type>", +        "Indicate that element order in <type> is significant. An example +         would be a complex type with unbounded choice as a content model +         where the element order in XML has application-specific semantics. +         For ordered types the compiler generates a special container data +         member and a corresponding set of accessors and modifiers that are +         used to capture the order of elements and, for mixed content, of +         text. + +         The <type> argument is an XML Schema type name that can be optionally +         qualified with a namespace in the \c{\i{namespace}\b{#}\i{name}} form. +         Note also that you will need to specify this option when compiling +         every schema file that has other ordered types derived from this +         type." +      }; + +      bool --ordered-type-derived +      { +        "Automatically treat types derived from ordered bases as also +         ordered. This is primarily useful if you would like to be able +         to iterate over the complete content using the content order +         container." +      }; + +      bool --ordered-type-mixed +      { +        "Automatically treat complex types with mixed content as ordered." +      }; + +      bool --ordered-type-all +      { +        "Indicate that element order in all types is significant." +      }; + +      NarrowString --order-container +      { +        "<type>", +        "Specify a custom class template that should be used as a container +         for the content order in ordered types instead of the default +         \cb{std::vector}. See \cb{--ordered-type} for more information on +         ordered type. This option is primarily useful if you need to +         perform more complex lookups in the content order container, for +         example by element id. In this case, a container like Boost +         multi-index may be more convenient. Note that if using a custom +         container, you will also most likely need to include the relevant +         headers using the \cb{--hxx-prologue*} options." +      }; + +      // Features. +      // +      bool --generate-serialization +      { +        "Generate serialization functions. Serialization functions convert +         the object model back to XML." +      }; + +      bool --generate-ostream +      { +        "Generate ostream insertion operators (\cb{operator<<}) for generated +         types. This allows one to easily print a fragment or the whole object +         model for debugging or logging." +      }; + +      bool --generate-doxygen +      { +        "Generate documentation comments suitable for extraction by the +         Doxygen documentation system. Documentation from annotations is +         added to the comments if present in the schema." +      }; + +      bool --generate-comparison +      { +        "Generate comparison operators (\cb{operator==} and \cb{operator!=}) +         for complex types. Comparison is performed member-wise." +      }; + +      bool --generate-default-ctor +      { +        "Generate default constructors even for types that have required +         members. Required members of an instance constructed using such a +         constructor are not initialized and accessing them results in +         undefined behavior." +      }; + +      bool --generate-from-base-ctor +      { +        "Generate constructors that expect an instance of a base type +         followed by all required members." +      }; + +      bool --suppress-assignment +      { +        "Suppress the generation of copy assignment operators for complex +         types. If this option is specified, the copy assignment operators +         for such types are declared private and left unimplemented." +      }; + +      bool --generate-detach +      { +        "Generate detach functions for required elements and attributes. +         Detach functions for optional and sequence cardinalities are +         provided by the respective containers. These functions, for +         example, allow you to move sub-trees in the object model either +         within the same tree or between different trees." +      }; + +      bool --generate-wildcard +      { +        "Generate accessors and modifiers as well as parsing and serialization +         code for XML Schema wildcards (\cb{any} and \cb{anyAttribute}). XML +         content matched by wildcards is presented as DOM fragments. Note +         that you need to initialize the Xerces-C++ runtime if you are using +         this option." +      }; + +      bool --generate-any-type +      { +        "Extract and store content of the XML Schema \cb{anyType} type as a +         DOM fragment. Note that you need to initialize the Xerces-C++ runtime +         if you are using this option." +      }; + +      NarrowStrings --generate-insertion +      { +        "<os>", +        "Generate data representation stream insertion operators for the <os> +         output stream type. Repeat this option to specify more than one +         stream type. The ACE CDR stream (\cb{ACE_OutputCDR}) and RPC XDR +         are recognized by the compiler and the necessary \cb{#include} +         directives are automatically generated. For custom stream types use +         the \cb{--hxx-prologue*} options to provide the necessary +         declarations." +      }; + +      NarrowStrings --generate-extraction +      { +        "<is>", +        "Generate data representation stream extraction constructors for the +         <is> input stream type. Repeat this option to specify more than one +         stream type. The ACE CDR stream (\cb{ACE_InputCDR}) and RPC XDR are +         recognized by the compiler and the necessary \cb{#include} directives +         are automatically generated. For custom stream types use the +         \cb{--hxx-prologue*} options to provide the necessary declarations." +      }; + +      bool --generate-forward +      { +        "Generate a separate header file with forward declarations for the +         types being generated." +      }; + +      bool --suppress-parsing +      { +        "Suppress the generation of the parsing functions and constructors. +         Use this option to reduce the generated code size when parsing from +         XML is not needed." +      }; + +      bool --generate-element-type +      { +        "Generate types instead of parsing and serialization functions for +         root elements. This is primarily useful to distinguish object models +         with the same root type but with different root elements." +      }; + +      bool --generate-element-map +      { +        "Generate a root element map that allows uniform parsing and +         serialization of multiple root elements. This option is only valid +         together with \cb{--generate-element-type}." +      }; + +      bool --generate-intellisense +      { +        "Generate workarounds for IntelliSense bugs in Visual Studio 2005 +         (8.0). When this option is used, the resulting code is slightly +         more verbose. IntelliSense in Visual Studio 2008 (9.0) and later +         does not require these workarounds. Support for IntelliSense in +         Visual Studio 2003 (7.1) is improved with this option but is +         still incomplete." +      }; + +      bool --omit-default-attributes +      { +        "Omit attributes with default and fixed values from serialized XML +         documents." +      }; + +      // Naming. +      // +      NarrowString --type-naming = "knr" +      { +        "<style>", +        "Specify the type naming convention that should be used in the +         generated code. Valid styles are \cb{knr} (default), \cb{ucc}, +         and \cb{java}. See the NAMING CONVENTION section below for more +         information." +      }; + +      NarrowString --function-naming = "knr" +      { +        "<style>", +        "Specify the function naming convention that should be used in the +         generated code. Valid styles are \cb{knr} (default), \cb{lcc}, +         \cb{ucc}, and \cb{java}. See the NAMING CONVENTION section below +         for more information." +      }; + +      NarrowStrings --type-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema type names to C++ type names. See the NAMING CONVENTION +         section below for more information." +      }; + +      NarrowStrings --accessor-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema names of elements/attributes to C++ accessor function +         names. See the NAMING CONVENTION section below for more information." +      }; + +      NarrowStrings --one-accessor-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema names of elements/attributes with cardinality one to +         C++ accessor function names. See the NAMING CONVENTION section +         below for more information." +      }; + +      NarrowStrings --opt-accessor-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema names of elements/attributes with cardinality optional +         to C++ accessor function names. See the NAMING CONVENTION section +         below for more information." +      }; + +      NarrowStrings --seq-accessor-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema names of elements/attributes with cardinality sequence +         to C++ accessor function names. See the NAMING CONVENTION section +         below for more information." +      }; + +      NarrowStrings --modifier-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema names of elements/attributes to C++ modifier function +         names. See the NAMING CONVENTION section below for more information." +      }; + +      NarrowStrings --one-modifier-regex + +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema names of elements/attributes with cardinality one to C++ +         modifier function names. See the NAMING CONVENTION section below +         for more information." +      }; + +      NarrowStrings --opt-modifier-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema names of elements/attributes with cardinality optional +         to C++ modifier function names. See the NAMING CONVENTION section +         below for more information." +      }; + +      NarrowStrings --seq-modifier-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema names of elements/attributes with cardinality sequence +         to C++ modifier function names. See the NAMING CONVENTION section +         below for more information." +      }; + +      NarrowStrings --parser-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema element names to C++ parsing function names. See the +         NAMING CONVENTION section below for more information." +      }; + +      NarrowStrings --serializer-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema element names to C++ serialization function names. See +         the NAMING CONVENTION section below for more information." +      }; + +      NarrowStrings --const-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema-derived names to C++ constant names. See the NAMING +         CONVENTION section below for more information." +      }; + +      NarrowStrings --enumerator-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema enumeration values to C++ enumerator names. See the +         NAMING CONVENTION section below for more information." +      }; + +      NarrowStrings --element-type-regex +      { +        "<regex>", +        "Add <regex> to the list of regular expressions used to translate +         XML Schema element names to C++ element type names. See the NAMING +         CONVENTION section below for more information." +      }; + +      bool --name-regex-trace +      { +        "Trace the process of applying regular expressions specified with +         the name transformation options. Use this option to find out why +         your regular expressions don't do what you expected them to do." +      }; + +      // Root element. +      // +      bool --root-element-first +      { +        "Treat only the first global element as a document root. By default +         all global elements are considered document roots." +      }; + +      bool --root-element-last +      { +        "Treat only the last global element as a document root. By default +         all global elements are considered document roots." +      }; + +      bool --root-element-all +      { +        "Treat all global elements as document roots. This is the default +         behavior. By explicitly specifying this option you can suppress +         the warning that is issued if more than one global element is +         defined." +      }; + +      bool --root-element-none +      { +        "Do not treat any global elements as document roots. By default all +         global elements are considered document roots." +      }; + +      NarrowStrings --root-element +      { +        "<element>", +        "Treat only <element> as a document root. Repeat this option to +         specify more than one root element." +      }; + +      // Custom type. +      // +      NarrowStrings --custom-type +      { +        "<map>", +        "Use a custom C++ type instead of the generated class. The <map> +         argument is in the form \c{\i{name}[\b{=}\i{type}[\b{/}\i{base}]]}, +         where \i{name} is a type name as defined in XML Schema and \i{type} +         is a C++ type name that should be used instead. If \i{type} is not +         present or empty then the custom type is assumed to have the same +         name and be defined in the same namespace as the generated class +         would have. If \i{base} is specified then the generated class is +         still generated but with that name." +      }; + +      NarrowStrings --custom-type-regex +      { +        "<regex>", +        "Use custom C++ types instead of the generated classes. The <regex> +         argument is in the form +         \c{\b{/}\i{name-pat}\b{/}[\i{type-sub}\b{/}[\i{base-sub}\b{/}]]}, +         where \i{name-pat} is a regex pattern that will be matched against +         type names as defined in XML Schema and \i{type-sub} is a C++ type +         name substitution that should be used instead. If \i{type-sub} is +         not present or its substitution results in an empty string then +         the custom type is assumed to have the same name and be defined +         in the same namespace as the generated class would have. If +         \i{base-sub} is present and its substitution results in a +         non-empty string then the generated class is still generated +         but with the result of this substitution as its name. The pattern +         and substitutions are in the Perl regular expression format. +         See also the REGEX AND SHELL QUOTING section below." +      }; + +      // Parts. +      // +      std::size_t --parts = 1 +      { +        "<num>", +        "Split generated source code into <num> parts. This is useful when +         translating large, monolithic schemas and a C++ compiler is not +         able to compile the resulting source code at once (usually due +         to insufficient memory)." +      }; + +      NarrowString --parts-suffix = "-" +      { +        "<suffix>", +        "Use <suffix> instead of the default '\cb{-}' to separate the file +         name from the part number." +      }; +    }; +  } +} diff --git a/xsd/cxx/tree/order-processor.cxx b/xsd/cxx/tree/order-processor.cxx new file mode 100644 index 0000000..ccc3dc5 --- /dev/null +++ b/xsd/cxx/tree/order-processor.cxx @@ -0,0 +1,243 @@ +// file      : xsde/cxx/tree/order-processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <iostream> + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/order-processor.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct Member: Traversal::Element, Traversal::Any +      { +        Member (size_t count): count_ (count) {} + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          if (Context::skip (e)) +            return; + +          e.context ().set ("ordered-id", count_++); +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          a.context ().set ("ordered-id", count_++); +        } + +        size_t count_; +      }; + +      // +      // +      struct Type: Traversal::Complex +      { +        Type (TypeNameSet& ordered_types, bool derived, bool mixed, bool all) +            : ordered_types_ (ordered_types), +              derived_ (derived), +              mixed_ (mixed), +              all_ (all) +        { +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          SemanticGraph::Context& ctx (c.context ()); + +          if (!ctx.count ("ordered")) +          { +            // First process our base. +            // +            if (c.inherits_p ()) +            { +              SemanticGraph::Type& b (c.inherits ().base ()); + +              if (!b.context ().count ("ordered")) +                dispatch (b); +            } + +            // See if our base (not necessarily immediate) is ordered. +            // +            using SemanticGraph::Complex; + +            Complex* b (0); + +            for (Complex* p (&c); p->inherits_p ();) +            { +              if ((b = dynamic_cast<Complex*> (&p->inherits ().base ()))) +              { +                if (Context::ordered_p (*b)) +                  break; + +                p = b; +              } +              else +                break; +            } + +            bool o (all_ || +                    (derived_ && b != 0 && Context::ordered_p (*b)) || +                    (mixed_ && c.mixed_p ()) || +                    ordered_types_.find (c)); +            ctx.set ("ordered", o); + +            // Assign ids to elements and wildcards, calculate total count. +            // +            if (o) +            { +              size_t count ( +                b != 0 && Context::ordered_p (*b) +                ? b->context ().get<size_t> ("ordered-count") +                : 1); + +              ctx.set ("ordered-start", count); + +              Member m (count); +              Traversal::Names n (m); +              names (c, n); + +              // Assign content id for mixed text. +              // +              if (Context::mixed_p (c) && count == 1) +                ctx.set ("mixed-ordered-id", m.count_++); + +              ctx.set ("ordered-count", m.count_); +            } +          } +        } + +      private: +        TypeNameSet& ordered_types_; +        bool derived_; +        bool mixed_; +        bool all_; +      }; + +      // Go into sourced/included/imported schemas while making sure +      // we don't process the same stuff more than once. +      // +      struct Uses: Traversal::Sources, +                   Traversal::Includes, +                   Traversal::Imports +      { +        Uses (char const* seen_key) +            : seen_key_ (seen_key) +        { +        } + +        virtual void +        traverse (SemanticGraph::Sources& sr) +        { +          SemanticGraph::Schema& s (sr.schema ()); + +          if (!s.context ().count (seen_key_)) +          { +            s.context ().set (seen_key_, true); +            Traversal::Sources::traverse (sr); +          } +        } + +        virtual void +        traverse (SemanticGraph::Includes& i) +        { +          SemanticGraph::Schema& s (i.schema ()); + +          if (!s.context ().count (seen_key_)) +          { +            s.context ().set (seen_key_, true); +            Traversal::Includes::traverse (i); +          } +        } + +        virtual void +        traverse (SemanticGraph::Imports& i) +        { +          SemanticGraph::Schema& s (i.schema ()); + +          if (!s.context ().count (seen_key_)) +          { +            s.context ().set (seen_key_, true); +            Traversal::Imports::traverse (i); +          } +        } + +      private: +        char const* seen_key_; +      }; + +      char const* seen_key = "cxx-tree-order-processor-seen"; + +      bool +      process_impl (options const& ops, +                    SemanticGraph::Schema& tu, +                    SemanticGraph::Path const&) +      { +        // Prepare a set of ordered types. +        // +        TypeNameSet ordered_types (ops.ordered_type ().begin (), +                                   ops.ordered_type ().end ()); + +        // Root schema in the file-per-type mode is just a bunch +        // of includes without a namespace. +        // +        SemanticGraph::Schema::NamesIterator i (tu.names_begin ()); + +        // Nothing to do if this is the XML Schema namespace. +        // +        if (i == tu.names_end () || +            i->named ().name () != L"http://www.w3.org/2001/XMLSchema") +        { +          // Note that we check first if this schema has already been +          // processed which may happen in the file-per-type compilation +          // mode. +          // +          if (!tu.context ().count (seen_key)) +          { +            Traversal::Schema schema; +            Uses uses (seen_key); + +            schema >> uses >> schema; + +            Traversal::Names schema_names; +            Traversal::Namespace ns; +            Traversal::Names ns_names; +            Type type (ordered_types, +                       ops.ordered_type_derived (), +                       ops.ordered_type_mixed (), +                       ops.ordered_type_all ()); + +            schema >> schema_names >> ns >> ns_names >> type; + +            // Some twisted schemas do recusive self-inclusion. +            // +            tu.context ().set (seen_key, true); + +            schema.dispatch (tu); +          } +        } + +        return true; +      } +    } + +    bool OrderProcessor:: +    process (options const& ops, +             SemanticGraph::Schema& tu, +             SemanticGraph::Path const& file) +    { +      return process_impl (ops, tu, file); +    } +  } +} diff --git a/xsd/cxx/tree/order-processor.hxx b/xsd/cxx/tree/order-processor.hxx new file mode 100644 index 0000000..868547d --- /dev/null +++ b/xsd/cxx/tree/order-processor.hxx @@ -0,0 +1,29 @@ +// file      : xsde/cxx/tree/order-processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_ORDER_PROCESSOR_HXX +#define XSD_CXX_TREE_ORDER_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph.hxx> + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> + +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ +  namespace Tree +  { +    class OrderProcessor +    { +    public: +      bool +      process (options const&, +               XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file); +    }; +  } +} + +#endif // XSD_CXX_TREE_ORDER_PROCESSOR_HXX diff --git a/xsd/cxx/tree/parser-header.cxx b/xsd/cxx/tree/parser-header.cxx new file mode 100644 index 0000000..9ef9e89 --- /dev/null +++ b/xsd/cxx/tree/parser-header.cxx @@ -0,0 +1,472 @@ +// file      : xsd/cxx/tree/parser-header.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/parser-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct ElementFunction: Traversal::Element, +                              GlobalElementBase, +                              Context +      { +        ElementFunction (Context& c) +            : GlobalElementBase (c), Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (!doc_root_p (e)) +            return; + +          String const& name (eparser (e)); +          String const& error_handler (error_handler_type); + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name Parsing functions for the %" << +	       comment (e.name ()) << " document root." << endl; + +            if (e.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (e.annotation ()); +            } + +            os << " */" << endl +               << "//@{" << endl +               << endl; +          } + +          if (!doxygen) +          { +            os << "// Parse a URI or a local file." << endl +               << "//" << endl +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a URI or a local file." << endl +               << " *" << endl +               << " * @param uri A URI or a local file name." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function uses exceptions to report parsing errors." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (const " << string_type << "& uri," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a URI or a local file with an error handler." << endl +               << " *" << endl +               << " * @param uri A URI or a local file name." << endl +               << " * @param eh An error handler." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function reports parsing errors by calling the " << +              "error handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (const " << string_type << "& uri," << endl +             << error_handler << "& eh," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a URI or a local file with a Xerces-C++ " << +              "DOM error" << endl +               << " * handler." << endl +               << " *" << endl +               << " * @param uri A URI or a local file name." << endl +               << " * @param eh A Xerces-C++ DOM error handler." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function reports parsing errors by calling the " << +              "error handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (const " << string_type << "& uri," << endl +             << xerces_ns << "::DOMErrorHandler& eh," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (!doxygen) +          { +            os << "// Parse std::istream." << endl +               << "//" << endl +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a standard input stream." << endl +               << " *" << endl +               << " * @param is A standrad input stream." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function uses exceptions to report parsing errors." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (::std::istream& is," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a standard input stream with an error handler." << endl +               << " *" << endl +               << " * @param is A standrad input stream." << endl +               << " * @param eh An error handler." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function reports parsing errors by calling the " << +              "error handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (::std::istream& is," << endl +             << error_handler << "& eh," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a standard input stream with a " << +              "Xerces-C++ DOM error" << endl +               << " * handler." << endl +               << " *" << endl +               << " * @param is A standrad input stream." << endl +               << " * @param eh A Xerces-C++ DOM error handler." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function reports parsing errors by calling the " << +              "error handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (::std::istream& is," << endl +             << xerces_ns << "::DOMErrorHandler& eh," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a standard input stream with a resource id." << endl +               << " *" << endl +               << " * @param is A standrad input stream." << endl +               << " * @param id A resource id." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * The resource id is used to identify the document " << +              "being parsed in" << endl +               << " * diagnostics as well as to resolve relative paths." << endl +               << " *" << endl +               << " * This function uses exceptions to report parsing errors." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (::std::istream& is," << endl +             << "const " << string_type << "& id," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a standard input stream with a resource " << +              "id and an" << endl +               << " * error handler." << endl +               << " *" << endl +               << " * @param is A standrad input stream." << endl +               << " * @param id A resource id." << endl +               << " * @param eh An error handler." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * The resource id is used to identify the document " << +              "being parsed in" << endl +               << " * diagnostics as well as to resolve relative paths." << endl +               << " *" << endl +               << " * This function reports parsing errors by calling the " << +              "error handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (::std::istream& is," << endl +             << "const " << string_type << "& id," << endl +             << error_handler << "& eh," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a standard input stream with a resource " << +              "id and a" << endl +               << " * Xerces-C++ DOM error handler." << endl +               << " *" << endl +               << " * @param is A standrad input stream." << endl +               << " * @param id A resource id." << endl +               << " * @param eh A Xerces-C++ DOM error handler." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * The resource id is used to identify the document " << +              "being parsed in" << endl +               << " * diagnostics as well as to resolve relative paths." << endl +               << " *" << endl +               << " * This function reports parsing errors by calling the " << +              "error handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (::std::istream& is," << endl +             << "const " << string_type << "& id," << endl +             << xerces_ns << "::DOMErrorHandler& eh," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (!doxygen) +          { +            os << "// Parse xercesc::InputSource." << endl +               << "//" << endl +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a Xerces-C++ input source." << endl +               << " *" << endl +               << " * @param is A Xerces-C++ input source." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function uses exceptions to report parsing errors." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (" << xerces_ns << "::InputSource& is," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a Xerces-C++ input source with an " << +              "error handler." << endl +               << " *" << endl +               << " * @param is A Xerces-C++ input source." << endl +               << " * @param eh An error handler." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function reports parsing errors by calling the " << +              "error handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (" << xerces_ns << "::InputSource& is," << endl +             << error_handler << "& eh," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a Xerces-C++ input source with a " << +              "Xerces-C++ DOM" << endl +               << " * error handler." << endl +               << " *" << endl +               << " * @param is A Xerces-C++ input source." << endl +               << " * @param eh A Xerces-C++ DOM error handler." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function reports parsing errors by calling the " << +              "error handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (" << xerces_ns << "::InputSource& is," << endl +             << xerces_ns << "::DOMErrorHandler& eh," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (!doxygen) +          { +            os << "// Parse xercesc::DOMDocument." << endl +               << "//" << endl +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a Xerces-C++ DOM document." << endl +               << " *" << endl +               << " * @param d A Xerces-C++ DOM document." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (const " << xerces_ns << "::DOMDocument& d," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Parse a Xerces-C++ DOM document." << endl +               << " *" << endl +               << " * @param d A pointer to the Xerces-C++ DOM document." << endl +               << " * @param f Parsing flags." << endl +               << " * @param p Parsing properties. " << endl +               << " * @return A pointer to the root of the object model." << endl +               << " *" << endl +               << " * This function is normally used together with the " << +              "keep_dom and" << endl +               << " * own_dom parsing flags to assign ownership of the DOM " << +              "document" << endl +               << " * to the object model." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << auto_ptr << "< " << type_name (e) << " >" << endl +             << name << " (" << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d," << endl +             << flags_type << " f = 0," << endl +             << "const " << properties_type << "& p = " << properties_type << " ());" +             << endl; + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } +        } + +      private: +        String +        type_name (Type& e) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (e.type ()); + +          return o.str (); +        } +      }; +    } + + +    void +    generate_parser_header (Context& ctx) +    { +      ctx.os << "#include <iosfwd>" << endl +             << endl +             << "#include <xercesc/sax/InputSource.hpp>" << endl +               << "#include <xercesc/dom/DOMDocument.hpp>" << endl +             << "#include <xercesc/dom/DOMErrorHandler.hpp>" << endl +             << endl; + +      Traversal::Schema schema; +      Sources sources; +      Traversal::Names names_ns, names; +      Namespace ns (ctx); +      ElementFunction element (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names >> element; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/parser-header.hxx b/xsd/cxx/tree/parser-header.hxx new file mode 100644 index 0000000..b7860c4 --- /dev/null +++ b/xsd/cxx/tree/parser-header.hxx @@ -0,0 +1,19 @@ +// file      : xsd/cxx/tree/parser-header.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_PARSER_HEADER_HXX +#define XSD_CXX_TREE_PARSER_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_parser_header (Context&); +  } +} + +#endif  // XSD_CXX_TREE_PARSER_HEADER_HXX diff --git a/xsd/cxx/tree/parser-source.cxx b/xsd/cxx/tree/parser-source.cxx new file mode 100644 index 0000000..cee5ea6 --- /dev/null +++ b/xsd/cxx/tree/parser-source.cxx @@ -0,0 +1,541 @@ +// file      : xsd/cxx/tree/parser-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/parser-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct ElementFunction: Traversal::Element, +                              GlobalElementBase, +                              Context +      { +        ElementFunction (Context& c) +            : GlobalElementBase (c), Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (!doc_root_p (e)) +            return; + +          SemanticGraph::Type& t (e.type ()); + +          // Check if we need to handle xsi:type and substitution groups. +          // If this element's type is anonymous then we don't need to do +          // anything. +          // +          bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + +          // Check if this element is abstract. +          // +          bool abst; +          { +            SemanticGraph::Complex* tc; +            abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && +              tc->abstract_p (); +          } + +          // Nothing to do if we are abstract and not polymorphic. +          // +          if (abst && !polymorphic) +            return; + +          String const& name (eparser (e)); +          String type (type_name (e)); +          String const& error_handler (error_handler_type); + +          // Note that I am using fq-name in function calls because g++ gets +          // confused if the name is 'type'. (see tests/schema/anonymous) +          // + +          char const* d (std >= cxx_version::cxx11 ? "std::move (d)" : "d"); + +          // URI. +          // +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (const " << string_type << "& u," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::xml::auto_initializer i (" << endl +             << "(f & " << flags_type << "::dont_initialize) == 0," << endl +             << "(f & " << flags_type << "::keep_dom) == 0);" +             << endl +             << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" +             << endl +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl +             << "u, h, p, f"; + +          if (options.disable_multi_import ()) +            os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + +          os << "));" +             << endl +             << "h.throw_if_failed< ::xsd::cxx::tree::parsing< " << +            char_type << " > > ();" +             << endl +             << "return " << auto_ptr << "< " << type << " > (" << endl +             << fq_name (e, "parser") << " (" << endl +             << d << ", f | " << flags_type << "::own_dom, p));" +             << "}"; + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (const " << string_type << "& u," << endl +             << error_handler << "& h," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::xml::auto_initializer i (" << endl +             << "(f & " << flags_type << "::dont_initialize) == 0," << endl +             << "(f & " << flags_type << "::keep_dom) == 0);" +             << endl +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl +             << "u, h, p, f"; + +          if (options.disable_multi_import ()) +            os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + +          os << "));" +             << endl +             << "if (!d.get ())" << endl +             << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" +             << endl +             << "return " << auto_ptr << "< " << type << " > (" << endl +             << fq_name (e, "parser") << " (" << endl +             << d << ", f | " << flags_type << "::own_dom, p));" +             << "}"; + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (const " << string_type << "& u," << endl +             << xerces_ns << "::DOMErrorHandler& h," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl +             << "u, h, p, f"; + +          if (options.disable_multi_import ()) +            os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + +          os << "));" +             << endl +             << "if (!d.get ())" << endl +             << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" +             << endl +             << "return " << auto_ptr << "< " << type << " > (" << endl +             << fq_name (e, "parser") << " (" << endl +             << d << ", f | " << flags_type << "::own_dom, p));" +             << "}"; + + +          // istream +          // +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (::std::istream& is," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::xml::auto_initializer i (" << endl +             << "(f & " << flags_type << "::dont_initialize) == 0," << endl +             << "(f & " << flags_type << "::keep_dom) == 0);" +             << endl +             << "::xsd::cxx::xml::sax::std_input_source isrc (is);" +             << "return " << fq_name (e, "parser") << " (isrc, f, p);" +             << "}"; + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (::std::istream& is," << endl +             << error_handler << "& h," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::xml::auto_initializer i (" << endl +             << "(f & " << flags_type << "::dont_initialize) == 0," << endl +             << "(f & " << flags_type << "::keep_dom) == 0);" +             << endl +             << "::xsd::cxx::xml::sax::std_input_source isrc (is);" +             << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" +             << "}"; + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (::std::istream& is," << endl +             << xerces_ns << "::DOMErrorHandler& h," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::xml::sax::std_input_source isrc (is);" +             << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" +             << "}"; + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (::std::istream& is," << endl +             << "const " << string_type << "& sid," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::xml::auto_initializer i (" << endl +             << "(f & " << flags_type << "::dont_initialize) == 0," << endl +             << "(f & " << flags_type << "::keep_dom) == 0);" +             << endl +             << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" +             << "return " << fq_name (e, "parser") << " (isrc, f, p);" +             << "}"; + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (::std::istream& is," << endl +             << "const " << string_type << "& sid," << endl +             << error_handler << "& h," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::xml::auto_initializer i (" << endl +             << "(f & " << flags_type << "::dont_initialize) == 0," << endl +             << "(f & " << flags_type << "::keep_dom) == 0);" +             << endl +             << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" +             << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" +             << "}"; + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (::std::istream& is," << endl +             << "const " << string_type << "& sid," << endl +             << xerces_ns << "::DOMErrorHandler& h," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" +             << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" +             << "}"; + + +          // InputSource. +          // +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (" << xerces_ns << "::InputSource& i," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" +             << endl +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl +             << "i, h, p, f"; + +          if (options.disable_multi_import ()) +            os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + +          os << "));" +             << endl +             << "h.throw_if_failed< ::xsd::cxx::tree::parsing< " << +            char_type << " > > ();" +             << endl +             << "return " << auto_ptr << "< " << type << " > (" << endl +             << fq_name (e, "parser") << " (" << endl +             << d << ", f | " << flags_type << "::own_dom, p));" +             << "}"; + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (" << xerces_ns << "::InputSource& i," << endl +             << error_handler << "& h," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl +             << "i, h, p, f"; + +          if (options.disable_multi_import ()) +            os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + +          os << "));" +             << endl +             << "if (!d.get ())" << endl +             << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" +             << endl +             << "return " << auto_ptr << "< " << type << " > (" << endl +             << fq_name (e, "parser") << " (" << endl +             << d << ", f | " << flags_type << "::own_dom, p));" +             << "}"; + + +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (" << xerces_ns << "::InputSource& i," << endl +             << xerces_ns << "::DOMErrorHandler& h," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl +             << "i, h, p, f"; + +          if (options.disable_multi_import ()) +            os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + +          os << "));" +             << endl +             << "if (!d.get ())" << endl +             << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" +             << endl +             << "return " << auto_ptr << "< " << type << " > (" << endl +             << fq_name (e, "parser") << " (" << endl +             << d << ", f | " << flags_type << "::own_dom, p));" +             << "}"; + + +          // DOM. +          // + +          bool fund (false); +          { +            IsFundamentalType test (fund); +            test.dispatch (t); +          } + +          // const DOMDocument& +          // +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (const " << xerces_ns << "::DOMDocument& doc," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "& p)" +             << "{" +             << "if (f & " << flags_type << "::keep_dom)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << "static_cast< " << xerces_ns << +            "::DOMDocument* > (doc.cloneNode (true)));" +             << endl +             << "return " << auto_ptr << "< " << type << " > (" << endl +             << fq_name (e, "parser") << " (" << endl +             << d << ", f | " << flags_type << "::own_dom, p));" +             << "}" +             << "const " << xerces_ns << "::DOMElement& e (*doc.getDocumentElement ());" +             << "const " << qname_type << " n (" << endl +             << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" +             << endl; + +          if (poly) +          { +            os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl +               << "::xsd::cxx::tree::type_factory_map_instance< " << +              poly_plate << ", " << char_type << " > ().create (" << endl +               << strlit (e.name ()) << "," << endl +               << strlit (e.namespace_().name ()) << "," << endl; + +            if (abst) +              os << "0,"; +            else +              os << "&::xsd::cxx::tree::factory_impl< " << type << " >,"; + +            os << endl +               << "true, true, e, n, f, 0));" +               << endl +               << "if (tmp.get () != 0)" +               << "{" +               << auto_ptr << "< " << type << " > r (" << endl +               << "dynamic_cast< " << type << "* > (tmp.get ()));" +               << endl +               << "if (r.get ())" << endl +               << "tmp.release ();" +               << "else" << endl +               << "throw ::xsd::cxx::tree::not_derived< " << char_type << +              " > ();" +               << endl; +          } +          else +          { +            os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl +               << "n.namespace_ () == " << strlit (e.namespace_().name ()) << ")" +               << "{"; + +            if (fund) +            { +              os << auto_ptr << "< " << type << " > r (" << endl +                 << "new " << type << " (" << endl +                 << "::xsd::cxx::tree::traits< " << type << ", " << +                char_type; + +              if (t.is_a<SemanticGraph::Fundamental::Double> ()) +                os << ", ::xsd::cxx::tree::schema_type::double_"; +              else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) +                os << ", ::xsd::cxx::tree::schema_type::decimal"; + +              os << " >::create (" << endl +                 << "e, f, 0)));"; +            } +            else +            { +              os << auto_ptr << "< " << type << " > r (" << endl +                 << "::xsd::cxx::tree::traits< " << type << ", " << +                char_type << " >::create (" << endl +                 << "e, f, 0));"; +            } +          } + +          os << "return r;" +             << "}" +             << "throw ::xsd::cxx::tree::unexpected_element < " << +            char_type << " > (" << endl +             << "n.name ()," << endl +             << "n.namespace_ ()," << endl +             << strlit (e.name ()) << "," << endl +             << strlit (e.namespace_().name ()) << ");" +             << "}"; + + +          // dom::auto_ptr/unique_ptr<DOMDocument> +          // +          os << auto_ptr << "< " << type << " >" << endl +             << name << " (" << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d," << endl +             << flags_type << " f," << endl +             << "const " << properties_type << "&)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > c (" << endl +             << "((f & " << flags_type << "::keep_dom) &&" << endl +             << "!(f & " << flags_type << "::own_dom))" << endl +             << "? static_cast< " << xerces_ns << "::DOMDocument* > (" << +            "d->cloneNode (true))" << endl +             << ": 0);" +             << endl +             << xerces_ns << "::DOMDocument& doc (c.get () ? *c : *d);" +             << "const " << xerces_ns << "::DOMElement& e (" << +            "*doc.getDocumentElement ());" +             << endl +             << "const " << qname_type << " n (" << endl +             << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" +             << endl +             << "if (f & " << flags_type << "::keep_dom)" << endl +             << "doc.setUserData (" << dom_node_key << "," << endl +             << "(c.get () ? &c : &d)," << endl +             << "0);" +             << endl; + +          if (poly) +          { +            os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl +               << "::xsd::cxx::tree::type_factory_map_instance< " << +              poly_plate << ", " << char_type << " > ().create (" << endl +               << strlit (e.name ()) << "," << endl +               << strlit (e.namespace_().name ()) << "," << endl; + +            if (abst) +              os << "0,"; +            else +              os << "&::xsd::cxx::tree::factory_impl< " << type << " >,"; + +            os << endl +               << "true, true, e, n, f, 0));" +               << endl +               << "if (tmp.get () != 0)" +               << "{"; +          } +          else +          { +            os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl +               << "n.namespace_ () == " << strlit (e.namespace_().name ()) << ")" +               << "{"; + +            if (fund) +            { +              os << auto_ptr << "< " << type << " > r (" << endl +                 << "new " << type << " (" << endl +                 << "::xsd::cxx::tree::traits< " << type << ", " << +                char_type; + +              if (t.is_a<SemanticGraph::Fundamental::Double> ()) +                os << ", ::xsd::cxx::tree::schema_type::double_"; +              else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) +                os << ", ::xsd::cxx::tree::schema_type::decimal"; + +              os << " >::create (" << endl +                 << "e, f, 0)));"; +            } +            else +            { +              os << auto_ptr << "< " << type << " > r (" << endl +                 << "::xsd::cxx::tree::traits< " << type << ", " << +                char_type << " >::create (" << endl +                 << "e, f, 0));"; +            } +          } + +          if (poly) +          { +            os << endl +               << auto_ptr << "< " << type << " > r (" << endl +               << "dynamic_cast< " << type << "* > (tmp.get ()));" +               << endl +               << "if (r.get ())" << endl +               << "tmp.release ();" +               << "else" << endl +               << "throw ::xsd::cxx::tree::not_derived< " << char_type << +              " > ();" +               << endl; +          } + +          os << "return r;" +             << "}" +             << "throw ::xsd::cxx::tree::unexpected_element < " << +            char_type << " > (" << endl +             << "n.name ()," << endl +             << "n.namespace_ ()," << endl +             << strlit (e.name ()) << "," << endl +             << strlit (e.namespace_().name ()) << ");" +             << "}"; +        } + +      private: +        String +        type_name (Type& e) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (e.type ()); + +          return o.str (); +        } +      }; +    } + +    void +    generate_parser_source (Context& ctx, size_t first, size_t last) +    { +      ctx.os << "#include <istream>" << endl +             << "#include <xsd/cxx/xml/sax/std-input-source.hxx>" << endl +             << "#include <xsd/cxx/tree/error-handler.hxx>" << endl +             << endl; + +      Traversal::Schema schema; +      Sources sources; +      Traversal::Names names_ns, names; +      Namespace ns (ctx, first, last); +      ElementFunction element (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names >> element; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/parser-source.hxx b/xsd/cxx/tree/parser-source.hxx new file mode 100644 index 0000000..1bb70d9 --- /dev/null +++ b/xsd/cxx/tree/parser-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/parser-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_PARSER_SOURCE_HXX +#define XSD_CXX_TREE_PARSER_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_parser_source (Context&, size_t first, size_t last); +  } +} + +#endif  // XSD_CXX_TREE_PARSER_SOURCE_HXX diff --git a/xsd/cxx/tree/polymorphism-processor.cxx b/xsd/cxx/tree/polymorphism-processor.cxx new file mode 100644 index 0000000..4d07c69 --- /dev/null +++ b/xsd/cxx/tree/polymorphism-processor.cxx @@ -0,0 +1,740 @@ +// file      : xsde/cxx/tree/polymorphism-processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <iostream> + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/polymorphism-processor.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      // +      // +      struct Type: Traversal::Type, +                   Traversal::Complex +      { +        Type (TypeNameSet& poly_types) +            : poly_types_ (poly_types) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          SemanticGraph::Context& ctx (t.context ()); + +          if (!ctx.count ("polymorphic")) +            ctx.set ("polymorphic", poly_types_.find (t)); +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          SemanticGraph::Context& ctx (c.context ()); + +          if (!ctx.count ("polymorphic")) +          { +            // First check our base. +            // +            bool pb (false); +            if (c.inherits_p ()) +            { +              SemanticGraph::Type& b (c.inherits ().base ()); + +              if (!b.context ().count ("polymorphic")) +                dispatch (b); + +              pb = b.context ().get<bool> ("polymorphic"); +            } + +            ctx.set ("polymorphic", pb || poly_types_.find (c)); +          } +        } + +      private: +        TypeNameSet& poly_types_; +      }; + +      struct FundType: Traversal::AnyType, +                       Traversal::AnySimpleType, + +                       Traversal::Fundamental::Byte, +                       Traversal::Fundamental::UnsignedByte, +                       Traversal::Fundamental::Short, +                       Traversal::Fundamental::UnsignedShort, +                       Traversal::Fundamental::Int, +                       Traversal::Fundamental::UnsignedInt, +                       Traversal::Fundamental::Long, +                       Traversal::Fundamental::UnsignedLong, +                       Traversal::Fundamental::Integer, +                       Traversal::Fundamental::NonPositiveInteger, +                       Traversal::Fundamental::NonNegativeInteger, +                       Traversal::Fundamental::PositiveInteger, +                       Traversal::Fundamental::NegativeInteger, + +                       Traversal::Fundamental::Boolean, + +                       Traversal::Fundamental::Float, +                       Traversal::Fundamental::Double, +                       Traversal::Fundamental::Decimal, + +                       Traversal::Fundamental::String, +                       Traversal::Fundamental::NormalizedString, +                       Traversal::Fundamental::Token, +                       Traversal::Fundamental::Name, +                       Traversal::Fundamental::NameToken, +                       Traversal::Fundamental::NameTokens, +                       Traversal::Fundamental::NCName, +                       Traversal::Fundamental::Language, + +                       Traversal::Fundamental::QName, + +                       Traversal::Fundamental::Id, +                       Traversal::Fundamental::IdRef, +                       Traversal::Fundamental::IdRefs, + +                       Traversal::Fundamental::AnyURI, + +                       Traversal::Fundamental::Base64Binary, +                       Traversal::Fundamental::HexBinary, + +                       Traversal::Fundamental::Date, +                       Traversal::Fundamental::DateTime, +                       Traversal::Fundamental::Duration, +                       Traversal::Fundamental::Day, +                       Traversal::Fundamental::Month, +                       Traversal::Fundamental::MonthDay, +                       Traversal::Fundamental::Year, +                       Traversal::Fundamental::YearMonth, +                       Traversal::Fundamental::Time, + +                       Traversal::Fundamental::Entity, +                       Traversal::Fundamental::Entities +      { +        FundType (TypeNameSet& poly_types, bool& valid) +            : poly_types_ (poly_types), valid_ (valid) +        { +        } + +        void +        check (SemanticGraph::Type& t, bool fund) +        { +          SemanticGraph::Context& ctx (t.context ()); + +          if (poly_types_.find (t)) +          { +            if (!fund) +              ctx.set ("polymorphic", true); +            else +            { +              wcerr << "error: built-in type '" << t.name () << "' cannot " +                    << "be polymorphic because it is mapped to a fundamental " +                    << "C++ type" +                    << endl; + +              valid_ = false; +            } +          } +          else +            ctx.set ("polymorphic", false); +        } + +        // anyType & anySimpleType. +        // +        virtual void +        traverse (SemanticGraph::AnyType& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::AnySimpleType& t) +        { +          check (t, false); +        } + +        // Boolean. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Boolean& t) +        { +          check (t, true); +        } + +        // Integral types. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Byte& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedByte& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Short& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedShort& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Int& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedInt& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Long& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::UnsignedLong& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Integer& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::PositiveInteger& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NegativeInteger& t) +        { +          check (t, true); +        } + +        // Floats. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Float& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Double& t) +        { +          check (t, true); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Decimal& t) +        { +          check (t, true); +        } + +        // Strings. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::String& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NormalizedString& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Token& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameToken& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NameTokens& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Name& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::NCName& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Language& t) +        { +          check (t, false); +        } + + +        // Qualified name. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::QName& t) +        { +          check (t, false); +        } + + +        // ID/IDREF. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Id& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRef& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::IdRefs& t) +        { +          check (t, false); +        } + +        // URI. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::AnyURI& t) +        { +          check (t, false); +        } + +        // Binary. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Base64Binary& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::HexBinary& t) +        { +          check (t, false); +        } + + +        // Date/time. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Date& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::DateTime& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Duration& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Day& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Month& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::MonthDay& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Year& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::YearMonth& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Time& t) +        { +          check (t, false); +        } + +        // Entity. +        // +        virtual void +        traverse (SemanticGraph::Fundamental::Entity& t) +        { +          check (t, false); +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Entities& t) +        { +          check (t, false); +        } + +      private: +        TypeNameSet& poly_types_; +        bool& valid_; +      }; + +      struct GlobalElement: Traversal::Element +      { +        GlobalElement (TypeNameSet& poly_types, +                       bool& valid, +                       const WarningSet& disabled_warnings) +            : poly_types_ (poly_types), valid_ (valid), warning_ (true) +        { +          if (disabled_warnings.find ("all") != disabled_warnings.end () || +              disabled_warnings.find ("T005") != disabled_warnings.end ()) +            warning_ = false; +        } + +        virtual void +        traverse (Type& e) +        { +          using SemanticGraph::Schema; + +          if (!e.substitutes_p ()) +            return; + +          // If we are a substitution for some element, then mark +          // that element's type as polymorphic. +          // +          Type& r (e.substitutes ().root ()); +          SemanticGraph::Type& rt (r.type ()); +          SemanticGraph::Context& ctx (rt.context ()); + +          // We may need to override the previous value. +          // +          if (ctx.count ("polymorphic") && ctx.get<bool> ("polymorphic")) +            return; + +          // Built-in types that are mapped to fundamental types cannot +          // be declared polymorphic. +          // +          bool fund (false); +          IsFundamentalType test (fund); +          test.dispatch (rt); + +          if (fund) +          { +            wcerr << r.file () << ":" << r.line () << ":" << r.column () +                  << ": error: built-in type '" << rt.name () << "' " +                  << "is mapped to a fundamental C++ type and is expected " +                  << "to be polymorphic" << endl; + +            wcerr << e.file () << ":" << e.line () << ":" << e.column () +                  << ": info: because type '" << rt.name () << "' is " +                  << "used in a substitution group declared here" << endl; + +            valid_ = false; +            return; +          } + +          ctx.set ("polymorphic", true); + +          if (!warning_) +            return; + +          Schema& es (dynamic_cast<Schema&> (e.scope ().scope ())); +          Schema& rts (dynamic_cast<Schema&> (rt.scope ().scope ())); + +          // If the root type and this element are in different schemas +          // and the root type is not explicitly marked as polymorphic, +          // then issue a warning. +          // +          if (&es != &rts && !sources_p (es, rts) && !poly_types_.find (rt)) +          { +            wcerr << rt.file () << ":" << rt.line () << ":" << rt.column () +                  << ": warning T005: assuming type '" << rt.name () << "' " +                  << "is polymorphic" << endl; + +            wcerr << e.file () << ":" << e.line () << ":" << e.column () +                  << ": info: because type '" << rt.name () << "' is " +                  << "used in a substitution group declared here" << endl; + +            wcerr << rt.file () << ":" << rt.line () << ":" << rt.column () +                  << ": info: use --polymorphic-type to indicate this type " +                  << "is polymorphic when compiling schemas that " +                  << "reference it" << endl; +          } +        } + +      private: +        // Return true if root sources s. +        // +        bool +        sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) +        { +          using SemanticGraph::Schema; +          using SemanticGraph::Sources; + +          for (Schema::UsesIterator i (root.uses_begin ()); +               i != root.uses_end (); ++i) +          { +            if (i->is_a<Sources> ()) +            { +              if (&i->schema () == &s || sources_p (i->schema (), s)) +                return true; +            } +          } + +          return false; +        } + +      private: +        TypeNameSet& poly_types_; +        bool& valid_; +        bool warning_; +      }; + +      // Go into sourced/included/imported schemas while making sure +      // we don't process the same stuff more than once. +      // +      struct Uses: Traversal::Sources, +                   Traversal::Includes, +                   Traversal::Imports +      { +        Uses (char const* seen_key) +            : seen_key_ (seen_key) +        { +        } + +        virtual void +        traverse (SemanticGraph::Sources& sr) +        { +          SemanticGraph::Schema& s (sr.schema ()); + +          if (!s.context ().count (seen_key_)) +          { +            s.context ().set (seen_key_, true); +            Traversal::Sources::traverse (sr); +          } +        } + +        virtual void +        traverse (SemanticGraph::Includes& i) +        { +          SemanticGraph::Schema& s (i.schema ()); + +          if (!s.context ().count (seen_key_)) +          { +            s.context ().set (seen_key_, true); +            Traversal::Includes::traverse (i); +          } +        } + +        virtual void +        traverse (SemanticGraph::Imports& i) +        { +          SemanticGraph::Schema& s (i.schema ()); + +          if (!s.context ().count (seen_key_)) +          { +            s.context ().set (seen_key_, true); +            Traversal::Imports::traverse (i); +          } +        } + +      private: +        char const* seen_key_; +      }; + +      char const* pass_one_key = "cxx-tree-polymorphism-processor-seen-one"; +      char const* pass_two_key = "cxx-tree-polymorphism-processor-seen-two"; + +      bool +      process_impl (options const& ops, +                    SemanticGraph::Schema& tu, +                    SemanticGraph::Path const&, +                    const WarningSet& disabled_warnings) +      { +        bool valid (true); + +        // Prepare a set of polymorphic types. +        // + +        TypeNameSet poly_types (ops.polymorphic_type ().begin (), +                                ops.polymorphic_type ().end ()); + +        // Root schema in the file-per-type mode is just a bunch +        // of includes without a namespace. +        // +        SemanticGraph::Schema::NamesIterator i (tu.names_begin ()); + +        if (i != tu.names_end () && +            i->named ().name () == L"http://www.w3.org/2001/XMLSchema") +        { +          // XML Schema namespace. +          // +          Traversal::Schema schema; + +          Traversal::Names schema_names; +          Traversal::Namespace ns; +          Traversal::Names ns_names; +          FundType fund_type (poly_types, valid); + +          schema >> schema_names >> ns >> ns_names >> fund_type; + +          schema.dispatch (tu); +        } +        else +        { +          // First handle fundamental types. +          // +          { +            Traversal::Schema schema; +            Traversal::Implies implies; +            Traversal::Schema xs_schema; + +            schema >> implies >> xs_schema; + +            Traversal::Names xs_schema_names; +            Traversal::Namespace ns; +            Traversal::Names ns_names; +            FundType fund_type (poly_types, valid); + +            xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + +            schema.dispatch (tu); +          } + +          // Note that we check first if this schema has already been +          // processed which may happen in the file-per-type compilation +          // mode. +          // +          if (!tu.context ().count (pass_two_key)) +          { +            // Pass one - check substitution groups. +            // +            if (valid) +            { +              Traversal::Schema schema; +              Uses uses (pass_one_key); + +              schema >> uses >> schema; + +              Traversal::Names schema_names; +              Traversal::Namespace ns; +              Traversal::Names ns_names; +              GlobalElement element (poly_types, valid, disabled_warnings); + +              schema >> schema_names >> ns >> ns_names >> element; + +              // Some twisted schemas do recusive self-inclusion. +              // +              tu.context ().set (pass_one_key, true); + +              schema.dispatch (tu); +            } + +            // Pass two - process types. +            // +            if (valid) +            { +              Traversal::Schema schema; +              Uses uses (pass_two_key); + +              schema >> uses >> schema; + +              Traversal::Names schema_names; +              Traversal::Namespace ns; +              Traversal::Names ns_names; +              Type type (poly_types); + +              schema >> schema_names >> ns >> ns_names >> type; + +              // Some twisted schemas do recusive self-inclusion. +              // +              tu.context ().set (pass_two_key, true); + +              schema.dispatch (tu); +            } +          } +        } + +        return valid; +      } +    } + +    bool PolymorphismProcessor:: +    process (options const& ops, +             SemanticGraph::Schema& tu, +             SemanticGraph::Path const& file, +             const WarningSet& disabled_warnings) +    { +      return process_impl (ops, tu, file, disabled_warnings); +    } +  } +} diff --git a/xsd/cxx/tree/polymorphism-processor.hxx b/xsd/cxx/tree/polymorphism-processor.hxx new file mode 100644 index 0000000..88019a8 --- /dev/null +++ b/xsd/cxx/tree/polymorphism-processor.hxx @@ -0,0 +1,30 @@ +// file      : xsde/cxx/tree/polymorphism-processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_POLYMORPHISM_PROCESSOR_HXX +#define XSD_CXX_TREE_POLYMORPHISM_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph.hxx> + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> + +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ +  namespace Tree +  { +    class PolymorphismProcessor +    { +    public: +      bool +      process (options const&, +               XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file, +               const WarningSet& disabled_warnings); +    }; +  } +} + +#endif // XSD_CXX_TREE_POLYMORPHISM_PROCESSOR_HXX diff --git a/xsd/cxx/tree/serialization-header.cxx b/xsd/cxx/tree/serialization-header.cxx new file mode 100644 index 0000000..5434441 --- /dev/null +++ b/xsd/cxx/tree/serialization-header.cxx @@ -0,0 +1,579 @@ +// file      : xsd/cxx/tree/serialization-header.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/serialization-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          // operator<< (xercesc::DOMElement) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMElement&, " << +            "const " << name << "&);" +             << endl; + +          // operator<< (xercesc::DOMAttr) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMAttr&, " << +            "const " << name << "&);" +             << endl; + +          // operator<< (list_stream) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << list_stream_type << "&," << endl +             << "const " << name << "&);" +             << endl; + +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          // operator<< (xercesc::DOMElement) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMElement&, " << +            "const " << name << "&);" +             << endl; + +          // operator<< (xercesc::DOMAttr) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMAttr&, " << +            "const " << name << "&);" +             << endl; + +          // operator<< (list_stream) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << list_stream_type << "&," << endl +             << "const " << name << "&);" +             << endl; +        } +      }; + + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          // operator<< (xercesc::DOMElement) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMElement&, " << +            "const " << name << "&);" +             << endl; + +          // operator<< (xercesc::DOMAttr) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMAttr&, " << +            "const " << name << "&);" +             << endl; + +          // operator<< (list_stream) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << list_stream_type << "&," << endl +             << "const " << name << "&);" +             << endl; +        } +      }; + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (c, name) && !name) +            return; + +          // operator<< (xercesc::DOMElement) +          // +          os << inst_exp +             << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMElement&, " << +            "const " << name << "&);" +             << endl; + +          bool simple (true); +          { +            IsSimpleType t (simple); +            t.dispatch (c); +          } + +          if (simple) +          { +            // operator<< (xercesc::DOMAttr) +            // +            os << inst_exp +               << "void" << endl +               << "operator<< (" << xerces_ns << "::DOMAttr&, " << +              "const " << name << "&);" +               << endl; + +            // operator<< (list_stream) +            // +            os << inst_exp +               << "void" << endl +               << "operator<< (" << list_stream_type << "&," << endl +               << "const " << name << "&);" +               << endl; +          } +        } +      }; + +      struct ElementType: Traversal::Element, +                          GlobalElementBase, +                          Context +      { +        ElementType (Context& c) +            : GlobalElementBase (c), Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (doc_root_p (e)) +          { +            // operator<< (xercesc::DOMElement) +            // +            os << inst_exp +               << "void" << endl +               << "operator<< (" << xerces_ns << "::DOMElement&, " << +              "const " << ename (e) << "&);" +               << endl; +          } +        } +      }; + +      struct ElementFunction: Traversal::Element, +                              GlobalElementBase, +                              Context +      { +        ElementFunction (Context& c) +            : GlobalElementBase (c), Context (c) +        { +        } + + +        virtual void +        traverse (Type& e) +        { +          if (!doc_root_p (e)) +            return; + +          String const& name (eserializer (e)); +          String const& error_handler (error_handler_type); +          String const& namespace_infomap (namespace_infomap_type); + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name Serialization functions for the %" << +	       comment (e.name ()) << " document root." << endl; + +            if (e.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (e.annotation ()); +            } + +            os << " */" << endl +               << "//@{" << endl +               << endl; +          } + +          if (!doxygen) +          { +            os << "// Serialize to std::ostream." << endl +               << "//" << endl +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Serialize to a standard output stream." << endl +               << " *" << endl +               << " * @param os A standrad output stream." << endl +               << " * @param x An object model to serialize." << endl +               << " * @param m A namespace information map." << endl +               << " * @param e A character encoding to produce XML in." << endl +               << " * @param f Serialization flags." << endl +               << " *" << endl +               << " * This function uses exceptions to report " << +              "serialization errors." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << "void" << endl +             << name << " (::std::ostream& os," << endl +             << "const " << type_name (e) << "& x, " << endl +             << "const " << namespace_infomap << "& m = " << +            namespace_infomap << " ()," << endl +             << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl +             << flags_type << " f = 0);" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Serialize to a standard output stream with an " << +              "error handler." << endl +               << " *" << endl +               << " * @param os A standrad output stream." << endl +               << " * @param x An object model to serialize." << endl +               << " * @param eh An error handler." << endl +               << " * @param m A namespace information map." << endl +               << " * @param e A character encoding to produce XML in." << endl +               << " * @param f Serialization flags." << endl +               << " *" << endl +               << " * This function reports serialization errors by " << +              "calling the error" << endl +               << " * handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << "void" << endl +             << name << " (::std::ostream& os," << endl +             << "const " << type_name (e) << "& x, " << endl +             << error_handler << "& eh," << endl +             << "const " << namespace_infomap << "& m = "  << +            namespace_infomap << " ()," << endl +             << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl +             << flags_type << " f = 0);" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Serialize to a standard output stream with a " << +              "Xerces-C++ DOM" << endl +               << " * error handler." << endl +               << " *" << endl +               << " * @param os A standrad output stream." << endl +               << " * @param x An object model to serialize." << endl +               << " * @param eh A Xerces-C++ DOM error handler." << endl +               << " * @param m A namespace information map." << endl +               << " * @param e A character encoding to produce XML in." << endl +               << " * @param f Serialization flags." << endl +               << " *" << endl +               << " * This function reports serialization errors by " << +              "calling the error" << endl +               << " * handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << "void" << endl +             << name << " (::std::ostream& os," << endl +             << "const " << type_name (e) << "& x, " << endl +             << xerces_ns << "::DOMErrorHandler& eh," << endl +             << "const " << namespace_infomap << "& m = " << +            namespace_infomap << " ()," << endl +             << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl +             << flags_type << " f = 0);" +             << endl; + +          if (!doxygen) +          { +            os << "// Serialize to xercesc::XMLFormatTarget." << endl +               << "//" << endl +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Serialize to a Xerces-C++ XML format target." << endl +               << " *" << endl +               << " * @param ft A Xerces-C++ XML format target." << endl +               << " * @param x An object model to serialize." << endl +               << " * @param m A namespace information map." << endl +               << " * @param e A character encoding to produce XML in." << endl +               << " * @param f Serialization flags." << endl +               << " *" << endl +               << " * This function uses exceptions to report " << +              "serialization errors." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << "void" << endl +             << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl +             << "const " << type_name (e) << "& x, " << endl +             << "const " << namespace_infomap << "& m = " << +            namespace_infomap << " ()," << endl +             << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl +             << flags_type << " f = 0);" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Serialize to a Xerces-C++ XML format target " << +              "with an error" << endl +               << " * handler." << endl +               << " *" << endl +               << " * @param ft A Xerces-C++ XML format target." << endl +               << " * @param x An object model to serialize." << endl +               << " * @param eh An error handler." << endl +               << " * @param m A namespace information map." << endl +               << " * @param e A character encoding to produce XML in." << endl +               << " * @param f Serialization flags." << endl +               << " *" << endl +               << " * This function reports serialization errors by " << +              "calling the error" << endl +               << " * handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << "void" << endl +             << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl +             << "const " << type_name (e) << "& x, " << endl +             << error_handler << "& eh," << endl +             << "const " << namespace_infomap << "& m = " << +            namespace_infomap << " ()," << endl +             << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl +             << flags_type << " f = 0);" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Serialize to a Xerces-C++ XML format target " << +              "with a" << endl +               << " * Xerces-C++ DOM error handler." << endl +               << " *" << endl +               << " * @param ft A Xerces-C++ XML format target." << endl +               << " * @param x An object model to serialize." << endl +               << " * @param eh A Xerces-C++ DOM error handler." << endl +               << " * @param m A namespace information map." << endl +               << " * @param e A character encoding to produce XML in." << endl +               << " * @param f Serialization flags." << endl +               << " *" << endl +               << " * This function reports serialization errors by " << +              "calling the error" << endl +               << " * handler." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << "void" << endl +             << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl +             << "const " << type_name (e) << "& x, " << endl +             << xerces_ns << "::DOMErrorHandler& eh," << endl +             << "const " << namespace_infomap << "& m = " << +            namespace_infomap << " ()," << endl +             << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl +             << flags_type << " f = 0);" +             << endl; + +          if (!doxygen) +          { +            os << "// Serialize to an existing xercesc::DOMDocument." << endl +               << "//" << endl +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Serialize to an existing Xerces-C++ DOM document." << endl +               << " *" << endl +               << " * @param d A Xerces-C++ DOM document." << endl +               << " * @param x An object model to serialize." << endl +               << " * @param f Serialization flags." << endl +               << " *" << endl +               << " * Note that it is your responsibility to create the " << +              "DOM document" << endl +               << " * with the correct root element as well as set the " << +              "necessary" << endl +               << " * namespace mapping attributes." << endl +               << " */" << endl; +          } +          os << inst_exp +             << "void" << endl +             << name << " (" << xerces_ns << "::DOMDocument& d," << endl +             << "const " << type_name (e) << "& x," << endl +             << flags_type << " f = 0);" +             << endl; + +          if (!doxygen) +          { +            os << "// Serialize to a new xercesc::DOMDocument." << endl +               << "//" << endl +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Serialize to a new Xerces-C++ DOM document." << endl +               << " *" << endl +               << " * @param x An object model to serialize." << endl +               << " * @param m A namespace information map." << endl +               << " * @param f Serialization flags." << endl +               << " * @return A pointer to the new Xerces-C++ DOM document." << endl +               << " */" << endl; +          } + +          os << inst_exp +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument >" << endl +             << name << " (const " << type_name (e) << "& x, " << endl +             << "const " << namespace_infomap << "& m = " << +            namespace_infomap << " ()," << endl +             << flags_type << " f = 0);" +             << endl; + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } +        } + +      private: +        String +        type_name (Type& e) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (e.type ()); + +          return o.str (); +        } +      }; + +    } + +    void +    generate_serialization_header (Context& ctx) +    { +      bool elemen_type (ctx.options.generate_element_type ()); + +      if (!elemen_type) +        ctx.os << "#include <iosfwd>" << endl +               << endl +               << "#include <xercesc/dom/DOMDocument.hpp>" << endl +               << "#include <xercesc/dom/DOMErrorHandler.hpp>" << endl +               << "#include <xercesc/framework/XMLFormatter.hpp>" << endl +               << endl +               << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl +               << endl; + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names names_ns, names; + +      Namespace ns (ctx); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); +      ElementType element_type (ctx); +      ElementFunction element_function (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      if (elemen_type) +        names >> element_type; +      else +        names >> element_function; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/serialization-header.hxx b/xsd/cxx/tree/serialization-header.hxx new file mode 100644 index 0000000..08c58ab --- /dev/null +++ b/xsd/cxx/tree/serialization-header.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/serialization-header.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_SERIALIZATION_HEADER_HXX +#define XSD_CXX_TREE_SERIALIZATION_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_serialization_header (Context&); +  } +} + +#endif  // XSD_CXX_TREE_SERIALIZATION_HEADER_HXX diff --git a/xsd/cxx/tree/serialization-source.cxx b/xsd/cxx/tree/serialization-source.cxx new file mode 100644 index 0000000..08b81d6 --- /dev/null +++ b/xsd/cxx/tree/serialization-source.cxx @@ -0,0 +1,1499 @@ +// file      : xsd/cxx/tree/serialization-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/serialization-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      enum schema_type +      { +        st_other, +        st_double, +        st_decimal +      }; + +      enum schema_type +      schema_type (SemanticGraph::Type& t) +      { +        if (t.is_a<SemanticGraph::Fundamental::Double> ()) +          return st_double; +        else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) +          return st_decimal; +        else +          return st_other; +      } + + +      // +      // +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          SemanticGraph::Type& item_type (l.argumented ().type ()); +          String base (L"::xsd::cxx::tree::list< " + +                       item_type_name (item_type) + L", " + char_type); + +          if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) +            base += L", ::xsd::cxx::tree::schema_type::double_"; +          else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) +            base += L", ::xsd::cxx::tree::schema_type::decimal"; + +          base += L" >"; + +          // operator<< (xercesc::DOMElement) +          // +          os << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMElement& e, " << +            "const " << name << "& i)" +             << "{" +             << "e << static_cast< const " << base << "& > (i);" +             << "}"; + +          // operator<< (xercesc::DOMAttr) +          // +          os << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMAttr& a, " << +            "const " << name << "& i)" +             << "{" +             << "a << static_cast< const " << base << "& > (i);" +             << "}"; + +          // operator<< (list_stream) +          // +          os << "void" << endl +             << "operator<< (" << list_stream_type << "& l," << endl +             << "const " << name << "& i)" +             << "{" +             << "l << static_cast< const " << base << "& > (i);" +             << "}"; + +          // Register with type factory map. If this type is anonymous +          // but substitutes, then it will be registered as part of the +          // substitution registration. +          // +          if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (l)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::type_serializer_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +               << "_xsd_" << name << "_type_serializer_init (" << endl +               << strlit (l.name ()) << "," << endl +               << strlit (xml_ns_name (l)) << ");" +               << endl +               << endl; +          } +        } + +      private: +        String +        item_type_name (SemanticGraph::Type& t) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (t); + +          return o.str (); +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          String const& base (xs_string_type); + +          // operator<< (xercesc::DOMElement) +          // +          os << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMElement& e, " << +            "const " << name << "& i)" +             << "{" +             << "e << static_cast< const " << base << "& > (i);" +             << "}"; + +          // operator<< (xercesc::DOMAttr) +          // +          os << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMAttr& a, " << +            "const " << name << "& i)" +             << "{" +             << "a << static_cast< const " << base << "& > (i);" +             << "}"; + +          // operator<< (list_stream) +          // +          os << "void" << endl +             << "operator<< (" << list_stream_type << "& l," << endl +             << "const " << name << "& i)" +             << "{" +             << "l << static_cast< const " << base << "& > (i);" +             << "}"; + +          // Register with type factory map. If this type is anonymous +          // but substitutes, then it will be registered as part of the +          // substitution registration. +          // +          if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (u)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::type_serializer_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +               << "_xsd_" << name << "_type_serializer_init (" << endl +               << strlit (u.name ()) << "," << endl +               << strlit (xml_ns_name (u)) << ");" +               << endl +               << endl; +          } +        } +      }; + + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c), base_ (c) +        { +          inherits_base_ >> base_; +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          // operator<< (xercesc::DOMElement) +          // +          os << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMElement& e, " << +            "const " << name << "& i)" +             << "{" +             << "e << static_cast< const "; + +          inherits (e, inherits_base_); + +          os << "& > (i);" +             << "}"; + + +          // operator<< (xercesc::DOMAttr) +          // +          os << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMAttr& a, " << +            "const " << name << "& i)" +             << "{" +             << "a << static_cast< const "; + +          inherits (e, inherits_base_); + +          os << "& > (i);" +             << "}"; + + +          // operator<< (list_stream) +          // +          os << "void" << endl +             << "operator<< (" << list_stream_type << "& l," << endl +             << "const " << name << "& i)" +             << "{" +             << "l << static_cast< const "; + +          inherits (e, inherits_base_); + +          os << "& > (i);" +             << "}"; + + +          // Register with type factory map. If this type is anonymous +          // but substitutes, then it will be registered as part of the +          // substitution registration. +          // +          if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (e)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::type_serializer_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +               << "_xsd_" << name << "_type_serializer_init (" << endl +               << strlit (e.name ()) << "," << endl +               << strlit (xml_ns_name (e)) << ");" +               << endl +               << endl; +          } +        } + +      private: +        Traversal::Inherits inherits_base_; +        BaseTypeName base_; +      }; + +      struct Element: Traversal::Element, Context +      { +        Element (Context& c, String const& scope_) +            : Context (c), scope (scope_) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (skip (e)) +            return; + +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (e.scope ())); + +          bool ordered (ordered_p (c)); + +          String const& aname (eaname (e)); +          String ns (e.qualified_p () ? e.namespace_ ().name () : ""); +          String type (scope + L"::" + etype (e)); + +          // Check if we need to handle xsi:type and substitution groups. +          // If this element's type is anonymous then we don't need to do +          // anything. Note that if the type is anonymous then it can't be +          // derived from which makes it impossible to substitute or +          // dynamically-type with xsi:type. +          // +          SemanticGraph::Type& t (e.type ()); +          bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + +          os << "// " << comment (e.name ()) << endl +             << "//" << endl; + +          if (ordered) +            os << "case " << scope << "::" << +              e.context ().get<String> ("ordered-id-name") << ":" +               << "{"; + +          if (poly) +          { +            os << (ordered ? "" : "{") +               << "::xsd::cxx::tree::type_serializer_map< " << char_type +               << " >& tsm (" << endl +               << "::xsd::cxx::tree::type_serializer_map_instance< " << +              poly_plate << ", " << char_type << " > ());" +               << endl; +          } + +          if (max (e) != 1) +          { +            // sequence +            // +            // Always pass the sequence element reference to typeid() to +            // suppress the Clang's 'expression with side effects will be +            // evaluated despite being used as an operand to typeid' warning. +            // +            if (ordered) +              os << "const " << type << "& x (i." << aname << +                " ()[b->index]);" +                 << endl; +            else +              os << "for (" << scope << "::" << econst_iterator (e) << endl +                 << "b (i." << aname << " ().begin ()), " << +                "n (i." << aname << " ().end ());" << endl +                 << "b != n; ++b)" +                 << "{" +                 << "const " << type << "& x (*b);" << endl; + +            if (poly) +            { +              os << "if (typeid (" << type << ") == typeid (x))" +                 << "{" +                 << xerces_ns << "::DOMElement& s (" << endl +                 << "::xsd::cxx::xml::dom::create_element (" << endl +                 << strlit (e.name ()) << "," << endl +                 << (ns ? strlit (ns) + L",\n" : L"") +                 << "e));" +                 << endl +                 << "s << x;" +                 << "}" +                 << "else" << endl +                 << "tsm.serialize (" << endl +                 << strlit (e.name ()) << "," << endl +                 << strlit (ns) << "," << endl +                 << (e.global_p () ? "true" : "false") << ", " << +                (e.qualified_p () ? "true" : "false") << ", e, x);"; +            } +            else +            { +              os << xerces_ns << "::DOMElement& s (" << endl +                 << "::xsd::cxx::xml::dom::create_element (" << endl +                 << strlit (e.name ()) << "," << endl +                 << (ns ? strlit (ns) + L",\n" : L"") +                 << "e));" +                 << endl; + +              switch (schema_type (t)) +              { +              case st_other: +                { +                  os << "s << x;"; +                  break; +                } +              case st_double: +                { +                  os << "s << " << as_double_type << " (x);"; +                  break; +                } +              case st_decimal: +                { +                  os << "s << " << as_decimal_type << " (x);"; +                  break; +                } +              } +            } +          } +          else if (min (e) == 0) +          { +            // optional +            // +            if (!ordered) +              os << "if (i." << aname << " ())" +                 << "{"; + +            if (poly) +            { +              os << "const " << type << "& x (*i." << aname << " ());" +                 << "if (typeid (" << type << ") == typeid (x))" +                 << "{" +                 << xerces_ns << "::DOMElement& s (" << endl +                 << "::xsd::cxx::xml::dom::create_element (" << endl +                 << strlit (e.name ()) << "," << endl +                 << (ns ? strlit (ns) + L",\n" : L"") +                 << "e));" +                 << endl +                 << "s << x;" +                 << "}" +                 << "else" << endl +                 << "tsm.serialize (" << endl +                 << strlit (e.name ()) << "," << endl +                 << strlit (ns) << "," << endl +                 << (e.global_p () ? "true" : "false") << ", " << +                (e.qualified_p () ? "true" : "false") << ", e, x);"; +            } +            else +            { +              os << xerces_ns << "::DOMElement& s (" << endl +                 << "::xsd::cxx::xml::dom::create_element (" << endl +                 << strlit (e.name ()) << "," << endl +                 << (ns ? strlit (ns) + L",\n" : L"") +                 << "e));" +                 << endl; + +              switch (schema_type (t)) +              { +              case st_other: +                { +                  os << "s << *i." << aname << " ();"; +                  break; +                } +              case st_double: +                { +                  os << "s << " << as_double_type << "(*i." << aname << " ());"; +                  break; +                } +              case st_decimal: +                { +                  os << "s << " << as_decimal_type << "(*i." << aname << " ());"; +                  break; +                } +              } +            } +          } +          else +          { +            // one +            // +            if (poly) +            { +              os << "const " << type << "& x (i." << aname << " ());" +                 << "if (typeid (" << type << ") == typeid (x))" +                 << "{" +                 << xerces_ns << "::DOMElement& s (" << endl +                 << "::xsd::cxx::xml::dom::create_element (" << endl +                 << strlit (e.name ()) << "," << endl +                 << (ns ? strlit (ns) + L",\n" : L"") +                 << "e));" +                 << endl +                 << "s << x;" +                 << "}" +                 << "else" << endl +                 << "tsm.serialize (" << endl +                 << strlit (e.name ()) << "," << endl +                 << strlit (ns) << "," << endl +                 << (e.global_p () ? "true" : "false") << ", " << +                (e.qualified_p () ? "true" : "false") << ", e, x);"; +            } +            else +            { +              if (!ordered) +                os << "{"; + +              os << xerces_ns << "::DOMElement& s (" << endl +                 << "::xsd::cxx::xml::dom::create_element (" << endl +                 << strlit (e.name ()) << "," << endl +                 << (ns ? strlit (ns) + L",\n" : L"") +                 << "e));" +                 << endl; + +              switch (schema_type (t)) +              { +              case st_other: +                { +                  os << "s << i." << aname << " ();"; +                  break; +                } +              case st_double: +                { +                  os << "s << " << as_double_type << "(i." << aname << " ());"; +                  break; +                } +              case st_decimal: +                { +                  os << "s << " << as_decimal_type << "(i." << aname << " ());"; +                  break; +                } +              } +            } +          } + +          if (ordered) +          { +            // See comment for bool text (false); below. +            // +            if (mixed_p (c) && c.context ().get<size_t> ("ordered-start") != 1) +              os << "text = true;"; + +            os << "continue;" +               << "}"; +          } +          else +          { +            os << "}"; + +            if (poly && (max (e) != 1 || min (e) == 0)) +              os << "}"; // There is no extra block for poly one. +          } +        } + +      private: +        String scope; +      }; + +      struct Any: Traversal::Any, Context +      { +        Any (Context& c, String const& scope_) +            : Context (c), scope (scope_) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + +          bool ordered (ordered_p (c)); + +          String const& aname (eaname (a)); + +          os << "// " << ename (a) << endl +             << "//" << endl; + +          if (ordered) +            os << "case " << scope << "::" << +              a.context ().get<String> ("ordered-id-name") << ":"; + +          if (max (a) != 1) +          { +            // sequence +            // +            if (!ordered) +              os << "for (" << scope << "::" << econst_iterator (a) << endl +                 << "b (i." << aname << " ().begin ()), " << +                "n (i." << aname << " ().end ());" << endl +                 << "b != n; ++b)"; + +            os << "{" +               << "e.appendChild (" << endl +               << "e.getOwnerDocument ()->importNode (" << endl +               << "const_cast< " << xerces_ns << +              "::DOMElement* > (&(" << +              (ordered ? (L"i." + aname + L" ()[b->index]") : L"*b") << +              ")), true));"; +          } +          else if (min (a) == 0) +          { +            // optional +            // +            if (!ordered) +              os << "if (i." << aname << " ())"; + +            os << "{" +               << "e.appendChild (" << endl +               << "e.getOwnerDocument ()->importNode (" << endl +               << "const_cast< " << xerces_ns << "::DOMElement* > (&(*i." << +              aname << " ())), true));"; +          } +          else +          { +            // one +            // +            if (ordered) +              os << "{"; + +            os << "e.appendChild (" << endl +               << "e.getOwnerDocument ()->importNode (" << endl +               << "const_cast< " << xerces_ns << "::DOMElement* > (&(i." << +              aname << " ())), true));" +               << endl; +          } + +          if (ordered) +          { +            // See comment for bool text (false); below. +            // +            if (mixed_p (c) && c.context ().get<size_t> ("ordered-start") != 1) +              os << "text = true;"; + +            os << "continue;"; +          } + +          if (ordered || max (a) != 1 || min (a) == 0) +            os << "}"; +        } + +      private: +        String scope; +      }; + +      struct Attribute: Traversal::Attribute, Context +      { +        Attribute (Context& c, String const& scope_) +            : Context (c), scope (scope_) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& aname (eaname (a)); +          String ns (a.qualified_p () ? a.namespace_ ().name () : ""); + +          os << "// " << comment (a.name ()) << endl +             << "//" << endl; + +          if (a.optional_p () && !a.default_p ()) +          { +            os << "if (i." << aname << " ())" +               << "{" +               << xerces_ns << "::DOMAttr& a (" << endl +               << "::xsd::cxx::xml::dom::create_attribute (" << endl +               << strlit (a.name ()) << "," << endl +               << (ns ? strlit (ns) + L",\n" : L"") +               << "e));" +               << endl; + +            switch (schema_type (a.type ())) +            { +            case st_other: +              { +                os << "a << *i." << aname << " ();"; +                break; +              } +            case st_double: +              { +                os << "a << " << as_double_type << "(*i." << aname << " ());"; +                break; +              } +            case st_decimal: +              { +                os << "a << " << as_decimal_type << "(*i." << aname << " ());"; +                break; +              } +            } + +            os << "}"; +          } +          else +          { +            // Make sure we serialize required fixed attributes. +            // +            if (a.optional_p () && options.omit_default_attributes ()) +            { +              os << "if (i." << aname << " () != " << scope << +                "::" << edefault_value (a) << " ())"; +            } + +            os << "{" +               << xerces_ns << "::DOMAttr& a (" << endl +               << "::xsd::cxx::xml::dom::create_attribute (" << endl +               << strlit (a.name ()) << "," << endl +               << (ns ? strlit (ns) + L",\n" : L"") +               << "e));" +               << endl; + +            switch (schema_type (a.type ())) +            { +            case st_other: +              { +                os << "a << i." << aname << " ();"; +                break; +              } +            case st_double: +              { +                os << "a << " << as_double_type << "(i." << aname << " ());"; +                break; +              } +            case st_decimal: +              { +                os << "a << " << as_decimal_type << "(i." << aname << " ());"; +                break; +              } +            } + +            os << "}"; +          } +        } + +      private: +        String scope; +      }; + +      struct AnyAttribute: Traversal::AnyAttribute, Context +      { +        AnyAttribute (Context& c, String const& scope_) +            : Context (c), scope (scope_) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& aname (eaname (a)); + +          os << "// " << ename (a) << endl +             << "//" << endl; + +          os << "for (" << scope << "::" << econst_iterator (a) << endl +             << "b (i." << aname << " ().begin ()), " << +            "n (i." << aname << " ().end ());" << endl +             << "b != n; ++b)" +             << "{" +             << xerces_ns << "::DOMAttr* a (" << endl +             << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl +             << "e.getOwnerDocument ()->importNode (" << endl +             << "const_cast< " << xerces_ns << "::DOMAttr* > (&(*b)), true)));" +             << endl +             << "if (a->getLocalName () == 0)" << endl +             << "e.setAttributeNode (a);" +             << "else" << endl +             << "e.setAttributeNodeNS (a);" +             << "}"; +        } + +      private: +        String scope; +      }; + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), base_ (c) +        { +          inherits_ >> base_; +        } + +        virtual void +        traverse (Type& c) +        { +          SemanticGraph::Context& ctx (c.context ()); + +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (c, name) && !name) +            return; + +          // operator<< (xercesc::DOMElement) +          // +          os << "void" << endl +             << "operator<< (" << xerces_ns << "::DOMElement& e, " << +            "const " << name << "& i)" +             << "{"; + +          if (c.inherits_p ()) +          { +            os << "e << static_cast< const "; +            inherits (c, inherits_); +            os << "& > (i);" +               << endl; +          } +          else +            os << "e << static_cast< const " << any_type << "& > (i);" +               << endl; + +          // Serialize anyAttribute content first so that is gets +          // overriden by schema-defined attributes. +          // +          if (options.generate_wildcard ()) +          { +            AnyAttribute any_attribute (*this, name); +            Traversal::Names names (any_attribute); + +            Complex::names (c, names); +          } + +          { +            bool o (ordered_p (c)); +            size_t start (0), count (0); + +            if (o) +            { +              start = ctx.get<size_t> ("ordered-start"); +              count = ctx.get<size_t> ("ordered-count"); + +              if (start != count) +              { +                String const& ci (ctx.get<String> ("order-const-iterator")); +                String const& an (ctx.get<String> ("order-aname")); + +                // If we have mixed content and a base, then we have to +                // skip the text content until we serialize one of "our" +                // elements. +                // +                if (mixed_p (c) && start != 1) +                  os << "bool text (false);" +                     << endl; + +                os << "for (" << name << "::" << ci << endl +                   << "b (i." << an << " ().begin ()), n (i." << an << +                  " ().end ());" << endl +                   << "b != n; ++b)" +                   << "{" +                   << "switch (b->id)" +                   << "{"; +              } +            } + +            Traversal::Names names; +            Any any (*this, name); +            Element element (*this, name); + +            names >> element; + +            if (options.generate_wildcard ()) +              names >> any; + +            Complex::names (c, names); + +            if (o) +            { +              if (start != count) +              { +                if (mixed_p (c)) +                { +                  //@@ propagate mixed-ordered-id to derived + +                  os << "// text_content" << endl +                     << "//" << endl +                     << "case " << name << "::" << +                    ctx.get<String> ("mixed-ordered-id-name") << ":" +                     << "{"; + +                  // See the comment above. +                  // +                  if (start != 1) +                    os << "if (text)" << endl; + +                  os << "e.appendChild (" << endl +                     << "e.getOwnerDocument ()->createTextNode (" << endl +                     << "::xsd::cxx::xml::string (" << endl +                     << "i." << ctx.get<String> ("mixed-aname") << +                    " ()[b->index].c_str ()).c_str ()));"; + +                  // os << "e << i." << ctx.get<String> ("mixed-aname") << +                  //  " ()[b->index];"; + +                  os << "continue;" +                     << "}"; +                } + +                // Ignore content before our id range and stop serializing +                // if we see anything past. This handles inheritance. +                // +                os << "default:" +                   << "{"; + +                if (start != 1) +                  os << "if (b->id < " << start << "UL)" << endl +                     << "continue;"; + +                os << "break;" // Stop (see break below). +                   << "}"; + +                os << "}"      // switch +                   << "break;" // Unknown element past our elements. +                   << "}";     // for +              } +            } +          } + +          { +            Attribute attribute (*this, name); +            Traversal::Names names (attribute); +            Complex::names (c, names); +          } + +          os << "}"; + +          bool simple (true); +          { +            IsSimpleType t (simple); +            t.dispatch (c); +          } + +          if (simple) +          { +            bool hb (c.inherits_p ()); + +            // operator<< (xercesc::DOMAttr) +            // +            os << "void" << endl +               << "operator<< (" << xerces_ns << "::DOMAttr&" << +              (hb ? " a" : "") << ", " << +              "const " << name << "&" << (hb ? " i" : "") << ")" +               << "{"; + +            if (hb) +            { +              os << "a << static_cast< const "; + +              inherits (c, inherits_); + +              os << "& > (i);"; +            } + +            os << "}"; + + +            // operator<< (list_stream) +            // +            os << "void" << endl +               << "operator<< (" << list_stream_type << "&" << +              (hb ? " l" : "") << "," << endl +               << "const " << name << "&" << (hb ? " i" : "") << ")" +               << "{"; + +            if (hb) +            { +              os << "l << static_cast< const "; + +              inherits (c, inherits_); + +              os << "& > (i);"; +            } + +            os << "}"; +          } + +          // Register with type factory map. If this type is anonymous +          // but substitutes, then it will be registered as part of the +          // substitution registration. +          // +          if (polymorphic && +              polymorphic_p (c) && +              !c.abstract_p () && +              !anonymous_p (c)) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (c)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::type_serializer_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +               << "_xsd_" << name << "_type_serializer_init (" << endl +               << strlit (c.name ()) << "," << endl +               << strlit (xml_ns_name (c)) << ");" +               << endl +               << endl; +          } +        } + +      private: +        Traversal::Inherits inherits_; +        BaseTypeName base_; +      }; + + +      // Generate substitution group map entry. +      // +      struct GlobalElement: Traversal::Element, +                            GlobalElementBase, +                            Context +      { +        GlobalElement (Context& c) +            : GlobalElementBase (c), Context (c), type_name_ (c) +        { +          belongs_ >> type_name_; +        } + +        virtual void +        traverse (Type& e) +        { +          // Similar to parsing, we cannot just omit this element if it's +          // abstract because it may serve as a "link" between the root of the +          // substitution group and a non-abstract element that uses this +          // element as its root (see +          // element_serializer_map::find_substitution() for details). +          // +          if (polymorphic && e.substitutes_p ()) +          { +            SemanticGraph::Type& t (e.type ()); + +            // Check if this element is abstract. +            // +            bool abst; +            { +              SemanticGraph::Complex* tc; +              abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && +                tc->abstract_p (); +            } + +            Type& r (e.substitutes ().root ()); + +            String const& name (ename (e)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::element_serializer_initializer< " << +                poly_plate << ", " << char_type << ", "; + +            belongs (e, belongs_); + +            os << " >" << endl +               << "_xsd_" << name << "_element_serializer_init (" << endl +               << strlit (r.name ()) << "," << endl +               << strlit (r.namespace_ ().name ()) << "," << endl +               << strlit (e.name ()) << "," << endl +               << strlit (e.namespace_ ().name ()) << "," << endl; + +            if (abst) +              os << "0"; +            else +            { +              os << "&::xsd::cxx::tree::serializer_impl< "; +              belongs (e, belongs_); +              os << " >"; +            } + +            os << ");" +               << endl +               << endl; +          } +        } + +      private: +        Traversal::Belongs belongs_; +        MemberTypeName type_name_; + +      }; + +      struct ElementType: Traversal::Element, +                          GlobalElementBase, +                          Context +      { +        ElementType (Context& c) +            : GlobalElementBase (c), +              Context (c), +              element_map_ (c.options.generate_element_map ()) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (doc_root_p (e)) +          { +            String const& name (ename (e)); + +            // operator<< (xercesc::DOMElement) +            // +            os << "void" << endl +               << "operator<< (" << xerces_ns << "::DOMElement& e, " << +              "const " << name << "& i)" +               << "{" +               << "e << i." << eaname (e) << " ();" +               << "}"; + +            // Element map registration. +            // +            if (element_map_) +            { +              SemanticGraph::Context& ec (e.context ()); +              String const& aname (ec.get<String> ("element-name")); +              String const& ans (ec.get<String> ("element-ns")); + +              os << "static " << endl +                 << "const ::xsd::cxx::tree::serializer_init< " << +                name << ", " << char_type << ", " << any_type << " >" << endl +                 << "_xsd_" << name << "_serializer_init (" << +                name << "::" << aname << " (), " << +                name << "::" << ans << " ());" +                 << endl; +            } +          } +        } + +      private: +        bool element_map_; +      }; + +      struct ElementFunction: Traversal::Element, +                              GlobalElementBase, +                              Context +      { +        ElementFunction (Context& c) +            : GlobalElementBase (c), Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (!doc_root_p (e)) +            return; + +          String const& name (eserializer (e)); +          String ns (e.namespace_ ().name ()); +          String const& error_handler (error_handler_type); +          String const& namespace_infomap (namespace_infomap_type); + +          SemanticGraph::Type& type (e.type ()); + +          // Note that I am using fq-name in function calls because g++ gets +          // confused if the name is 'type'. (see tests/schema/anonymous) +          // + +          // Check if we need to handle xsi:type and substitution groups. +          // If this element's type is anonymous then we don't need to do +          // anything. +          // +          bool poly (polymorphic && +                        polymorphic_p (type) && +                        !anonymous_p (type)); + +          // To std::ostream. +          // +          os << "void" << endl +             << name << " (::std::ostream& o," << endl +             << "const " << type_name (e) << "& s," << endl +             << "const " << namespace_infomap << "& m," << endl +             << "const " << string_type << "& e," << endl +             << flags_type << " f)" +             << "{" +             << "::xsd::cxx::xml::auto_initializer i (" << endl +             << "(f & " << flags_type << "::dont_initialize) == 0);" +             << endl +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << fq_name (e, "serializer") << " (s, m, f));" +             << endl +             << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" +             << endl +             << "::xsd::cxx::xml::dom::ostream_format_target t (o);" +             << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" +             << "{" +             << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " << +            char_type << " > > ();" +             << "}" +             << "}"; + +          os << "void" << endl +             << name << " (::std::ostream& o," << endl +             << "const " << type_name (e) << "& s," << endl +             << error_handler << "& h," << endl +             << "const " << namespace_infomap << "& m," << endl +             << "const " << string_type << "& e," << endl +             << flags_type << " f)" +             << "{" +             << "::xsd::cxx::xml::auto_initializer i (" << endl +             << "(f & " << flags_type << "::dont_initialize) == 0);" +             << endl +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << fq_name (e, "serializer") << " (s, m, f));" +             << "::xsd::cxx::xml::dom::ostream_format_target t (o);" +             << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" +             << "{" +             << "throw ::xsd::cxx::tree::serialization< " << +            char_type << " > ();" +             << "}" +             << "}"; + +          os << "void" << endl +             << name << " (::std::ostream& o," << endl +             << "const " << type_name (e) << "& s," << endl +             << xerces_ns << "::DOMErrorHandler& h," << endl +             << "const " << namespace_infomap << "& m," << endl +             << "const " << string_type << "& e," << endl +             << flags_type << " f)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << fq_name (e, "serializer") << " (s, m, f));" +             << "::xsd::cxx::xml::dom::ostream_format_target t (o);" +             << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" +             << "{" +             << "throw ::xsd::cxx::tree::serialization< " << +            char_type << " > ();" +             << "}" +             << "}"; + +          // To XMLFormatTarget. +          // +          os << "void" << endl +             << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl +             << "const " << type_name (e) << "& s," << endl +             << "const " << namespace_infomap << "& m," << endl +             << "const " << string_type << "& e," << endl +             << flags_type << " f)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << fq_name (e, "serializer") << " (s, m, f));" +             << endl +             << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" +             << endl +             << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" +             << "{" +             << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " << +            char_type << " > > ();" +             << "}" +             << "}"; + +          os << "void" << endl +             << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl +             << "const " << type_name (e) << "& s," << endl +             << error_handler << "& h," << endl +             << "const " << namespace_infomap << "& m," << endl +             << "const " << string_type << "& e," << endl +             << flags_type << " f)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << fq_name (e, "serializer") << " (s, m, f));" +             << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" +             << "{" +             << "throw ::xsd::cxx::tree::serialization< " << +            char_type << " > ();" +             << "}" +             << "}"; + +          os << "void" << endl +             << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl +             << "const " << type_name (e) << "& s," << endl +             << xerces_ns << "::DOMErrorHandler& h," << endl +             << "const " << namespace_infomap << "& m," << endl +             << "const " << string_type << "& e," << endl +             << flags_type << " f)" +             << "{" +             << dom_auto_ptr << "< " << xerces_ns << +            "::DOMDocument > d (" << endl +             << fq_name (e, "serializer") << " (s, m, f));" +             << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" +             << "{" +             << "throw ::xsd::cxx::tree::serialization< " << +            char_type << " > ();" +             << "}" +             << "}"; + +          // To an existing DOM instance. +          // +          os << "void" << endl +             << name << " (" << xerces_ns << "::DOMDocument& d," << endl +             << "const " << type_name (e) << "& s," << endl +             << flags_type << ")" +             << "{" +             << xerces_ns << "::DOMElement& e (*d.getDocumentElement ());" +             << "const " << qname_type << " n (" << endl +             << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" +             << endl; + +          if (poly) +          { +            os << "if (typeid (" << type_name (e) << ") == typeid (s))" +               << "{"; +          } + +          os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl +             << "n.namespace_ () == " << strlit (ns) << ")" +             << "{"; + +          switch (schema_type (type)) +          { +          case st_other: +            { +              os << "e << s;"; +              break; +            } +          case st_double: +            { +              os << "e << " << as_double_type << "(s);"; +              break; +            } +          case st_decimal: +            { +              os << "e << " << as_decimal_type << "(s);"; +              break; +            } +          } + +          os << "}" +             << "else" +             << "{" +             << "throw ::xsd::cxx::tree::unexpected_element < " << +            char_type << " > (" << endl +             << "n.name ()," << endl +             << "n.namespace_ ()," << endl +             << strlit (e.name ()) << "," << endl +             << strlit (ns) << ");" +             << "}"; + +          if (poly) +          { +            os << "}" +               << "else" +               << "{" +               << "::xsd::cxx::tree::type_serializer_map_instance< " << +              poly_plate << ", " << char_type << " > ().serialize (" << endl +               << strlit (e.name ()) << "," << endl +               << strlit (e.namespace_().name ()) << "," << endl +               << "e, n, s);" +               << "}"; +          } + +          os << "}"; + + +          // To a new DOM instance. +          // +          os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument >" << endl +             << name << " (const " << type_name (e) << "& s," << endl +             << "const " << namespace_infomap << "& m," << endl +             << flags_type << " f)" +             << "{"; + +          if (poly) +          { +            os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument > d;" +               << endl +               << "if (typeid (" << type_name (e) << ") == typeid (s))" +               << "{" +               << "d = ::xsd::cxx::xml::dom::serialize< " << +              char_type << " > (" << endl +               << strlit (e.name ()) << "," << endl +               << strlit (ns) << "," << endl +               << "m, f);" +               << "}" +               << "else" +               << "{" +               << "d = ::xsd::cxx::tree::type_serializer_map_instance< " << +              poly_plate << ", " << char_type << " > ().serialize (" << endl +               << strlit (e.name ()) << "," << endl +               << strlit (e.namespace_().name ()) << "," << endl +               << "m, s, f);" +               << "}"; +          } +          else +          { +            os << dom_auto_ptr << "< " << xerces_ns << +              "::DOMDocument > d (" << endl +               << "::xsd::cxx::xml::dom::serialize< " << +              char_type << " > (" << endl +               << strlit (e.name ()) << "," << endl +               << strlit (ns) << "," << endl +               << "m, f));" +               << endl; +          } + +          os << fq_name (e, "serializer") << " (*d, s, f);" +             << "return d;" +             << "}"; + +        } + +      private: +        String +        type_name (Type& e) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (e.type ()); + +          return o.str (); +        } +      }; +    } + +    void +    generate_serialization_source (Context& ctx, size_t first, size_t last) +    { +      bool elemen_type (ctx.options.generate_element_type ()); + +      if (!elemen_type) +        ctx.os << "#include <ostream>" << endl +               << "#include <xsd/cxx/tree/error-handler.hxx>" << endl; + +      ctx.os << "#include <xsd/cxx/xml/dom/serialization-source.hxx>" << endl +             << endl; + +      if (ctx.polymorphic) +      { +        ctx.os << "#include <xsd/cxx/tree/type-serializer-map.hxx>" << endl +               << endl; + +        bool import_maps (ctx.options.import_maps ()); +        bool export_maps (ctx.options.export_maps ()); + +        if (import_maps || export_maps) +        { +          ctx.os << "#ifndef XSD_NO_EXPORT" << endl +                 << endl +                 << "namespace xsd" +                 << "{" +                 << "namespace cxx" +                 << "{" +                 << "namespace tree" +                 << "{" +                 << "#ifdef _MSC_VER" << endl; + +          if (export_maps) +            ctx.os << "template struct __declspec (dllexport) " << +              "type_serializer_plate< " << ctx.poly_plate << ", " << +              ctx.char_type << " >;"; + +          if (import_maps) +            ctx.os << "template struct __declspec (dllimport) " << +              "type_serializer_plate< " << ctx.poly_plate << ", " << +              ctx.char_type << " >;"; + +          ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl +                 << "template struct __attribute__ ((visibility(\"default\"))) " << +            "type_serializer_plate< " << ctx.poly_plate << ", " << +            ctx.char_type << " >;"; + +          ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl +                 << "template struct XSD_MAP_VISIBILITY " << +            "type_serializer_plate< " << ctx.poly_plate << ", " << +            ctx.char_type << " >;"; + +          ctx.os << "#endif" << endl +                 << "}"  // tree +                 << "}"  // cxx +                 << "}"  // xsd +                 << "#endif // XSD_NO_EXPORT" << endl +                 << endl; +        } + +        ctx.os << "namespace _xsd" +               << "{" +               << "static" << endl +               << "const ::xsd::cxx::tree::type_serializer_plate< " << +                ctx.poly_plate << ", " << ctx.char_type << " >" << endl +               << "type_serializer_plate_init;" +               << "}"; +      } + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names names_ns, names; + +      Namespace ns (ctx, first, last); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); +      GlobalElement element (ctx); +      ElementType element_type (ctx); +      ElementFunction element_function (ctx); + + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; +      names >> element; + +      if (elemen_type) +        names >> element_type; +      else +        names >> element_function; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/serialization-source.hxx b/xsd/cxx/tree/serialization-source.hxx new file mode 100644 index 0000000..75e57f3 --- /dev/null +++ b/xsd/cxx/tree/serialization-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/serialization-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_SERIALIZATION_SOURCE_HXX +#define XSD_CXX_TREE_SERIALIZATION_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_serialization_source (Context&, size_t first, size_t last); +  } +} + +#endif  // XSD_CXX_TREE_SERIALIZATION_SOURCE_HXX diff --git a/xsd/cxx/tree/stream-extraction-source.cxx b/xsd/cxx/tree/stream-extraction-source.cxx new file mode 100644 index 0000000..5a5ed66 --- /dev/null +++ b/xsd/cxx/tree/stream-extraction-source.cxx @@ -0,0 +1,864 @@ +// file      : xsd/cxx/tree/stream-extraction-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-extraction-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          SemanticGraph::Type& item_type (l.argumented ().type ()); +          String base (L"::xsd::cxx::tree::list< " + +                       item_type_name (item_type) + L", " + char_type); + +          if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) +            base += L", ::xsd::cxx::tree::schema_type::double_"; +          else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) +            base += L", ::xsd::cxx::tree::schema_type::decimal"; + +          base += L" >"; + +          size_t n (0); +          NarrowStrings const& st (options.generate_extraction ()); +          for (NarrowStrings::const_iterator i (st.begin ()); +               i != st.end (); ++i) +          { +            os << name << "::" << endl +               << name << " (" << istream_type << "< " << +              i->c_str () << " >& s," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << any_simple_type << " (s, f, c)," << endl +               << "  " << base <<  " (s, f, this)" +               << "{" +               << "}"; + +            // Register with type map. +            // +            if (polymorphic && +                polymorphic_p (l) && +                (!anonymous_p (l) || anonymous_substitutes_p (l))) +            { +              // Note that we are using the original type name. +              // +              String const& name (ename (l)); + +              os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_extraction_initializer< " << +                poly_plate << ", " << i->c_str () << ", " << char_type << +                ", " << name << " >" << endl +                 << "_xsd_" << name << "_stream_extraction_init_" << +                n++ << " (" << endl +                 << strlit (l.name ()) << "," << endl +                 << strlit (xml_ns_name (l)) << ");" +                 << endl; +            } +          } +        } + +      private: +        String +        item_type_name (SemanticGraph::Type& t) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (t); + +          return o.str (); +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          String const& base (xs_string_type); + +          size_t n (0); +          NarrowStrings const& st (options.generate_extraction ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            os << name << "::" << endl +               << name << " (" << istream_type << "< " << +              i->c_str () << " >& s," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << base << " (s, f, c)" +               << "{" +               << "}"; + +            // Register with type map. +            // +            if (polymorphic && +                polymorphic_p (u) && +                (!anonymous_p (u) || anonymous_substitutes_p (u))) +            { +              // Note that we are using the original type name. +              // +              String const& name (ename (u)); + +              os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_extraction_initializer< " << +                poly_plate << ", " << i->c_str () << ", " << char_type << +                ", " << name << " >" << endl +                 << "_xsd_" << name << "_stream_extraction_init_" << +                n++ << " (" << endl +                 << strlit (u.name ()) << "," << endl +                 << strlit (xml_ns_name (u)) << ");" +                 << endl; +            } +          } +        } +      }; + + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c), base_ (c) +        { +          inherits_base_ >> base_; +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (e); +          } + +          bool enum_based (false); +          if (string_based) +          { +            SemanticGraph::Enumeration* base_enum (0); +            IsEnumBasedType t (base_enum); +            t.dispatch (e); + +            enum_based = (base_enum != 0); +          } + +          String value; +          if (string_based) +            value = evalue (e); + +          size_t n (0); +          NarrowStrings const& st (options.generate_extraction ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            os << name << "::" << endl +               << name << " (" << istream_type << "< " << +              i->c_str () << " >& s," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": "; + +            inherits (e, inherits_base_); + +            if (string_based && !enum_based) +            { +              // Use copy c-tor to pass the flags and container. +              // +              os << " (" << endl; +              inherits (e, inherits_base_); +              os << " (_xsd_" << name << "_literals_[s.read_uint ()]), f, c)"; +            } +            else +              os << " (s, f, c)"; + +            os << "{"; + +            if (string_based) +              os << "_xsd_" << name << "_convert ();"; + +            os << "}"; + +            // Register with type map. +            // +            if (polymorphic && +                polymorphic_p (e) && +                (!anonymous_p (e) || anonymous_substitutes_p (e))) +            { +              // Note that we are using the original type name. +              // +              String const& name (ename (e)); + +              os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_extraction_initializer< " << +                poly_plate << ", " << i->c_str () << ", " << char_type << +                ", " << name << " >" << endl +                 << "_xsd_" << name << "_stream_extraction_init_" << +                n++ << " (" << endl +                 << strlit (e.name ()) << "," << endl +                 << strlit (xml_ns_name (e)) << ");" +                 << endl; +            } +          } +        } + +      private: +        Traversal::Inherits inherits_base_; +        BaseTypeName base_; +      }; + +      struct CtorMember: Traversal::Member, Context +      { +        CtorMember (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Member& m) +        { +          if (skip (m)) +            return; + +          os << "," << endl +             << "  " << emember (m) << " (this)"; +        } +      }; + +      struct CtorAny: Traversal::Any, +                      Traversal::AnyAttribute, +                      Context +      { +        CtorAny (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << member << " (this->" << dom_doc << " ())"; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << member << " (this->" << dom_doc << " ())"; +        } +      }; + +      struct Element: Traversal::Element, Context +      { +        Element (Context& c, String const& stream_) +            : Context (c), stream (stream_) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (skip (e)) +            return; + +          String const& member (emember (e)); + +          SemanticGraph::Type& t (e.type ()); +          String type (etype (e)); +          String tr (etraits (e)); // traits type name + +          bool fund (false); +          { +            IsFundamentalType traverser (fund); +            traverser.dispatch (t); +          } + +          // Figure out if we need to generate polymorphic code. If this +          // elemen's type is anonymous then we don't need to do anything. +          // Note that if the type is anonymous then it can't be derived +          // from which makes it impossible to substitute or dynamically- +          // type with xsi:type. +          // +          bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + +          // Check if this element is abstract. +          // +          bool abst (false); +          if (poly) +          { +            SemanticGraph::Complex* tc; +            abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && +              tc->abstract_p (); +          } + +          char const* r ( +            (poly || !fund) && std >= cxx_version::cxx11 +            ? "::std::move (r)" +            : "r"); + +          if (max (e) != 1) +          { +            // sequence +            // +            String container (econtainer (e)); + +            os << "{" +               << "::std::size_t n;" +               << "::xsd::cxx::tree::istream_common::as_size< " << +              "::std::size_t > as (n);" +               << "s >> as;" +               << "if (n > 0)" +               << "{" +               << container << "& c (this->" << member << ");" +               << "c.reserve (n);" +               << "while (n--)" +               << "{"; + +            if (poly) +            { +              os << auto_ptr << "< " << type << " > r;"; + +              if (!abst) +                os << "bool d;" +                   << "s >> d;" +                   << endl +                   << "if (!d)" << endl +                   << "r.reset (new " << type << " (s, f, this));" +                   << "else" +                   << "{"; + +              os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl +                 << "::xsd::cxx::tree::stream_extraction_map_instance< " << +                poly_plate << ", " << stream << ", " << char_type << +                " > ().extract (" << endl +                 << "s, f, this));" +                 << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" +                 << "if (r.get ())" << endl +                 << "tmp.release ();" +                 << "else" << endl +                 << "throw ::xsd::cxx::tree::not_derived< " << char_type << +                " > ();"; + +              if (!abst) +                os << "}"; +            } +            else if (fund) +            { +              os << type << " r;" +                 << "s >> r;"; +            } +            else +            { +              os << auto_ptr << "< " << type << " > r (" << endl +                 << tr << "::create (s, f, this));"; +            } + +            os << "c.push_back (" << r << ");" +               << "}" // while +               << "}" // if +               << "}"; +          } +          else if (min (e) == 0) +          { +            // optional +            // +            os << "{" +               << "bool p;" +               << "s >> p;" +               << "if (p)" +               << "{"; + +            if (poly) +            { +              os << auto_ptr << "< " << type << " > r;"; + +              if (!abst) +                os << "bool d;" +                   << "s >> d;" +                   << endl +                   << "if (!d)" << endl +                   << "r.reset (new " << type << " (s, f, this));" +                   << "else" +                   << "{"; + +              os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl +                 << "::xsd::cxx::tree::stream_extraction_map_instance< " << +                poly_plate << ", " << stream << ", " << char_type << +                " > ().extract (" << endl +                 << "s, f, this));" +                 << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" +                 << "if (r.get ())" << endl +                 << "tmp.release ();" +                 << "else" << endl +                 << "throw ::xsd::cxx::tree::not_derived< " << char_type << +                " > ();"; + +              if (!abst) +                os << "}"; +            } +            else if (fund) +            { +              os << type << " r;" +                 << "s >> r;"; +            } +            else +            { +              os << auto_ptr << "< " << type << " > r (" << endl +                 << tr << "::create (s, f, this));"; +            } + +            os << "this->" << member << ".set (" << r << ");" +               << "}" // if (p) +               << "}"; +          } +          else +          { +            // one +            // +            os << "{"; + +            if (poly) +            { +              os << auto_ptr << "< " << type << " > r;"; + +              if (!abst) +                os << "bool d;" +                   << "s >> d;" +                   << endl +                   << "if (!d)" << endl +                   << "r.reset (new " << type << " (s, f, this));" +                   << "else" +                   << "{"; + +              os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl +                 << "::xsd::cxx::tree::stream_extraction_map_instance< " << +                poly_plate << ", " << stream << ", " << char_type << +                " > ().extract (" << endl +                 << "s, f, this));" +                 << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" +                 << "if (r.get ())" << endl +                 << "tmp.release ();" +                 << "else" << endl +                 << "throw ::xsd::cxx::tree::not_derived< " << char_type << +                " > ();"; + +              if (!abst) +                os << "}"; +            } +            else if (fund) +            { +              os << type << " r;" +                 << "s >> r;"; +            } +            else +            { +              os << auto_ptr << "< " << type << " > r (" << endl +                 << tr << "::create (s, f, this));"; +            } + +            os << "this->" << member << ".set (" << r << ");" +               << "}"; +          } +        } + +      private: +        String stream; +      }; + +      struct Attribute: Traversal::Attribute, Context +      { +        Attribute (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& member (emember (a)); +          String type (etype (a)); +          String tr (etraits (a)); // traits type name + +          bool fund (false); +          { +            IsFundamentalType traverser (fund); +            traverser.dispatch (a.type ()); +          } + +          if (a.optional_p () && !a.default_p ()) +          { +            os << "{" +               << "bool p;" +               << "s >> p;" +               << "if (p)" +               << "{"; + +            if (fund) +            { +              os << type << " r;" +                 << "s >> r;" +                 << "this->" << member << ".set (r);"; +            } +            else +            { +              os << "this->" << member << ".set (" << tr << +                "::create (s, f, this));"; +            } + +            os << "}" // if (p) +               << "}"; +          } +          else +          { +            os << "{"; + +            if (fund) +            { +              os << type << " r;" +                 << "s >> r;" +                 << "this->" << member << ".set (r);"; +            } +            else +            { +              os << "this->" << member << ".set (" << tr << +                "::create (s, f, this));"; +            } + +            os << "}"; +          } +        } +      }; + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), base_ (c), ctor_any_ (c), ctor_member_ (c) +        { +          inherits_ >> base_; +          names_ctor_member_ >> ctor_member_; + +          if (options.generate_wildcard ()) +            names_ctor_member_ >> ctor_any_; +        } + +        virtual void +        traverse (Type& c) +        { +          SemanticGraph::Context& ctx (c.context ()); + +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (c, name) && !name) +            return; + +          bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); +          bool has_members (has<Traversal::Member> (c)); + +          bool facets (false); +          if (c.inherits_p ()) +          { +            // See if we have any facets that we need to handle. +            // +            using SemanticGraph::Restricts; +            using SemanticGraph::Fundamental::Decimal; + +            if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) +            { +              if (!r->facet_empty () && +                  (r->facet_find ("fractionDigits") != r->facet_end () || +                   r->facet_find ("totalDigits") != r->facet_end ()) && +                  ultimate_base (c).is_a<Decimal> ()) +                facets = true; +            } +          } + +          size_t n (0); +          NarrowStrings const& st (options.generate_extraction ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            os << name << "::" << endl +               << name << " (" << istream_type << "< " << +              i->c_str () << " >& s," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": "; + +            if (c.inherits_p ()) +              inherits (c, inherits_); +            else +              os << any_type; + +            os << " (s, f, c)"; + +            if (edom_document_member_p (c)) +            { +              os << "," << endl +                 << "  " << edom_document_member (c) << " (" << +                "::xsd::cxx::xml::dom::create_document< " << char_type << +                " > ())"; +            } + +            names (c, names_ctor_member_); + +            os << "{"; + +            if (facets) +              os << "this->_facet_table (_xsd_" << name << "_facet_table);" +                 << endl; + +            if (has_members) +              os << "this->" << unclash (name, "parse") << " (s, f);"; + +            os << "}"; + +            // Parse +            // +            if (ordered || has_members) +            { +              os << "void " << name << "::" << endl +                 << unclash (name, "parse") << " (" << +                istream_type << "< " << i->c_str () << " >& s," << endl +                 << flags_type << " f)" +                 << "{" +                 << "XSD_UNUSED (f);"; // Can be unused. + +              // Read the order sequence. +              // +              if (ordered) +              { +                String const& t (ctx.get<String> ("order-type")); +                String const& m (ctx.get<String> ("order-member")); + +                os << "{" +                   << "::std::size_t n;" +                   << "::xsd::cxx::tree::istream_common::as_size< " << +                  "::std::size_t > na (n);" +                   << "s >> na;" +                   << "if (n > 0)" +                   << "{" +                   << "this->" << m << ".reserve (n);" +                   << "while (n--)" +                   << "{" +                   << "::std::size_t id, in;" +                   << "::xsd::cxx::tree::istream_common::as_size< " << +                  "::std::size_t > ida (id), ina (in);" +                   << "s >> ida;" +                   << "s >> ina;" +                   << "this->" << m << ".push_back (" << t << " (id, in));" +                   << "}" // while +                   << "}" // if +                   << "}"; +              } + +              { +                Element element (*this, *i); +                Attribute attribute (*this); +                Traversal::Names names_; + +                names_ >> element; +                names_ >> attribute; + +                names (c, names_); +              } + +              os << "}"; +            } + + +            // Register with type map. +            // +            if (polymorphic && +                polymorphic_p (c) && +                !c.abstract_p () && +                (!anonymous_p (c) || anonymous_substitutes_p (c))) +            { +              // Note that we are using the original type name. +              // +              String const& name (ename (c)); + +              os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_extraction_initializer< " << +                poly_plate << ", " << i->c_str () << ", " << char_type << +                ", " << name << " >" << endl +                 << "_xsd_" << name << "_stream_extraction_init_" << +                n++ << " (" << endl +                 << strlit (c.name ()) << "," << endl +                 << strlit (xml_ns_name (c)) << ");" +                 << endl; +            } +          } +        } + +      private: +        Traversal::Inherits inherits_; +        BaseTypeName base_; + +        CtorAny ctor_any_; +        CtorMember ctor_member_; + +        Traversal::Names names_ctor_member_; +      }; +    } + +    void +    generate_stream_extraction_source (Context& ctx) +    { +      if (ctx.polymorphic) +      { +        NarrowStrings const& st (ctx.options.generate_extraction ()); + +        ctx.os << "#include <xsd/cxx/tree/stream-extraction-map.hxx>" << endl +               << endl; + +        bool import_maps (ctx.options.import_maps ()); +        bool export_maps (ctx.options.export_maps ()); + +        if (import_maps || export_maps) +        { +          ctx.os << "#ifndef XSD_NO_EXPORT" << endl +                 << endl +                 << "namespace xsd" +                 << "{" +                 << "namespace cxx" +                 << "{" +                 << "namespace tree" +                 << "{"; + +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream (*i); + +            ctx.os << "#ifdef _MSC_VER" << endl; + +            if (export_maps) +              ctx.os << "template struct __declspec (dllexport) " << +                "stream_extraction_plate< " << ctx.poly_plate << ", " << +                stream << ", " << ctx.char_type << " >;"; + +            if (import_maps) +              ctx.os << "template struct __declspec (dllimport) " << +                "stream_extraction_plate< " << ctx.poly_plate << ", " << +                stream << ", " << ctx.char_type << " >;"; + +            ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl +                   << "template struct __attribute__ ((visibility(\"default\"))) " << +              "stream_extraction_plate< " << ctx.poly_plate << ", " << +              stream << ", " << ctx.char_type << " >;" +                   << "#elif defined(XSD_MAP_VISIBILITY)" << endl +                   << "template struct XSD_MAP_VISIBILITY " << +              "stream_extraction_plate< " << ctx.poly_plate << ", " << +              stream << ", " << ctx.char_type << " >;" +                   << "#endif" << endl; +          } + +          ctx.os << "}"  // tree +                 << "}"  // cxx +                 << "}"  // xsd +                 << "#endif // XSD_NO_EXPORT" << endl +                 << endl; + +        } + +        ctx.os << "namespace _xsd" +               << "{"; + +        size_t n (0); +        for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +             ++i) +        { +          String stream (*i); + +          ctx.os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_extraction_plate< " << +            ctx.poly_plate << ", " << stream << ", " << ctx.char_type << +            " >" << endl +                 << "stream_extraction_plate_init_" << n++ << ";"; +        } + +        ctx.os << "}"; +      } + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names names_ns, names; + +      Namespace ns (ctx); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/stream-extraction-source.hxx b/xsd/cxx/tree/stream-extraction-source.hxx new file mode 100644 index 0000000..8b58491 --- /dev/null +++ b/xsd/cxx/tree/stream-extraction-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/stream-extraction-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_EXTRACTION_SOURCE_HXX +#define XSD_CXX_TREE_EXTRACTION_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_stream_extraction_source (Context&); +  } +} + +#endif  // XSD_CXX_TREE_EXTRACTION_SOURCE_HXX diff --git a/xsd/cxx/tree/stream-header.cxx b/xsd/cxx/tree/stream-header.cxx new file mode 100644 index 0000000..c8243c9 --- /dev/null +++ b/xsd/cxx/tree/stream-header.cxx @@ -0,0 +1,181 @@ +// file      : xsd/cxx/tree/stream-header.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          os << inst_exp +             << std_ostream_type << "&" << endl +             << "operator<< (" << std_ostream_type << "&, const " << +            name << "&);" +             << endl; +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          os << inst_exp +             << std_ostream_type << "&" << endl +             << "operator<< (" << std_ostream_type << "&, const " << +            name << "&);" +             << endl; +        } +      }; + + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (e); +          } + +          bool enum_based (false); +          if (string_based) +          { +            SemanticGraph::Enumeration* be (0); +            IsEnumBasedType t (be); +            t.dispatch (e); + +            enum_based = (be != 0); +          } + +          // If we are based on an enum then the value type is just an +          // alias and we don't need to generate this operator again. +          // +          if (string_based && !enum_based) +          { +            os << inst_exp +               << std_ostream_type << "&" << endl +               << "operator<< (" << std_ostream_type << "&, " << +              name << "::" << evalue (e) << ");" +               << endl; +          } + +          os << inst_exp +             << std_ostream_type << "&" << endl +             << "operator<< (" << std_ostream_type << "&, const " << +            name << "&);" +             << endl; +        } +      }; + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (c, name) && !name) +            return; + +          os << inst_exp +             << std_ostream_type << "&" << endl +             << "operator<< (" << std_ostream_type << "&, const " << +            name << "&);" +             << endl; +        } +      }; +    } + +    void +    generate_stream_header (Context& ctx) +    { +      String c (ctx.char_type); + +      ctx.os << "#include <iosfwd>" << endl +             << endl; + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names names_ns, names; + +      Namespace ns (ctx); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/stream-header.hxx b/xsd/cxx/tree/stream-header.hxx new file mode 100644 index 0000000..58481c2 --- /dev/null +++ b/xsd/cxx/tree/stream-header.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/stream-header.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_STREAM_HEADER_HXX +#define XSD_CXX_TREE_STREAM_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_stream_header (Context&); +  } +} + +#endif  // XSD_CXX_TREE_STREAM_HEADER_HXX diff --git a/xsd/cxx/tree/stream-insertion-header.cxx b/xsd/cxx/tree/stream-insertion-header.cxx new file mode 100644 index 0000000..9eb4bc4 --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-header.cxx @@ -0,0 +1,178 @@ +// file      : xsd/cxx/tree/stream-insertion-header.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-insertion-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          NarrowStrings const& st (options.generate_insertion ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream_type (ostream_type + L"< " + String (*i) + L" >"); + +            os << inst_exp +               << stream_type << "&" << endl +               << "operator<< (" << stream_type << "&," << endl +               << "const " << name << "&);" +               << endl; +          } +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          NarrowStrings const& st (options.generate_insertion ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream_type (ostream_type + L"< " + String (*i) + L" >"); + +            os << inst_exp +               << stream_type << "&" << endl +               << "operator<< (" << stream_type << "&," << endl +               << "const " << name << "&);" +               << endl; +          } +        } +      }; + + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          NarrowStrings const& st (options.generate_insertion ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream_type (ostream_type + L"< " + String (*i) + L" >"); + +            os << inst_exp +               << stream_type << "&" << endl +               << "operator<< (" << stream_type << "&," << endl +               << "const " << name << "&);" +               << endl; +          } +        } +      }; + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (c, name) && !name) +            return; + +          NarrowStrings const& st (options.generate_insertion ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream_type (ostream_type + L"< " + String (*i) + L" >"); + +            os << inst_exp +               << stream_type << "&" << endl +               << "operator<< (" << stream_type << "&," << endl +               << "const " << name << "&);" +               << endl; +          } +        } +      }; +    } + +    void +    generate_stream_insertion_header (Context& ctx) +    { +      String c (ctx.char_type); + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names names_ns, names; + +      Namespace ns (ctx); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/stream-insertion-header.hxx b/xsd/cxx/tree/stream-insertion-header.hxx new file mode 100644 index 0000000..597bea0 --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-header.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/stream-insertion-header.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_STREAM_INSERTION_HEADER_HXX +#define XSD_CXX_TREE_STREAM_INSERTION_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_stream_insertion_header (Context&); +  } +} + +#endif  // XSD_CXX_TREE_STREAM_INSERTION_HEADER_HXX diff --git a/xsd/cxx/tree/stream-insertion-source.cxx b/xsd/cxx/tree/stream-insertion-source.cxx new file mode 100644 index 0000000..08391ef --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-source.cxx @@ -0,0 +1,623 @@ +// file      : xsd/cxx/tree/stream-insertion-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-insertion-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          SemanticGraph::Type& item_type (l.argumented ().type ()); +          String base (L"::xsd::cxx::tree::list< " + +                       item_type_name (item_type) + L", " + char_type); + +          if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) +            base += L", ::xsd::cxx::tree::schema_type::double_"; +          else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) +            base += L", ::xsd::cxx::tree::schema_type::decimal"; + +          base += L" >"; + +          size_t n (0); +          NarrowStrings const& st (options.generate_insertion ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + +            os << stream_type << "&" << endl +               << "operator<< (" << stream_type << "& s," << endl +               << "const " << name << "& x)" +               << "{" +               << "return s << static_cast< const " << base << "& > (x);" +               << "}"; + +            // Register with type map. +            // +            if (polymorphic && +                polymorphic_p (l) && +                (!anonymous_p (l) || anonymous_substitutes_p (l))) +            { +              // Note that we are using the original type name. +              // +              String const& name (ename (l)); + +              os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_insertion_initializer< " << +                poly_plate << ", " << i->c_str () << ", " << char_type << +                ", " << name << " >" << endl +                 << "_xsd_" << name << "_stream_insertion_init_" << +                n++ << " (" << endl +                 << strlit (l.name ()) << "," << endl +                 << strlit (xml_ns_name (l)) << ");" +                 << endl; +            } +          } +        } + +      private: +        String +        item_type_name (SemanticGraph::Type& t) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (t); + +          return o.str (); +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          String const& base (xs_string_type); + +          size_t n (0); +          NarrowStrings const& st (options.generate_insertion ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + +            os << stream_type << "&" << endl +               << "operator<< (" << stream_type << "& s," << endl +               << "const " << name << "& x)" +               << "{" +               << "return s << static_cast< const " << base << "& > (x);" +               << "}"; + +            // Register with type map. +            // +            if (polymorphic && +                polymorphic_p (u) && +                (!anonymous_p (u) || anonymous_substitutes_p (u))) +            { +              // Note that we are using the original type name. +              // +              String const& name (ename (u)); + +              os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_insertion_initializer< " << +                poly_plate << ", " << i->c_str () << ", " << char_type << +                ", " << name << " >" << endl +                 << "_xsd_" << name << "_stream_insertion_init_" << +                n++ << " (" << endl +                 << strlit (u.name ()) << "," << endl +                 << strlit (xml_ns_name (u)) << ");" +                 << endl; +            } +          } +        } +      }; + + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c), base_ (c) +        { +          inherits_base_ >> base_; +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (e); +          } + +          bool enum_based (false); +          if (string_based) +          { +            SemanticGraph::Enumeration* base_enum (0); +            IsEnumBasedType t (base_enum); +            t.dispatch (e); + +            enum_based = (base_enum != 0); +          } + +          String value; +          if (string_based) +            value = evalue (e); + +          size_t n (0); +          NarrowStrings const& st (options.generate_insertion ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + +            os << stream_type << "&" << endl +               << "operator<< (" << stream_type << "& s," << endl +               << "const " << name << "& x)" +               << "{"; + +            if (!string_based || enum_based) +            { +              os << "return s << static_cast< const "; +              inherits (e, inherits_base_); +              os << "& > (x);"; +            } +            else +            { +              os << name << "::" << value << " v (x);" +                 << "return s << static_cast< unsigned int > (v);"; +            } + +            os << "}"; + +            // Register with type map. +            // +            if (polymorphic && +                polymorphic_p (e) && +                (!anonymous_p (e) || anonymous_substitutes_p (e))) +            { +              // Note that we are using the original type name. +              // +              String const& name (ename (e)); + +              os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_insertion_initializer< " << +                poly_plate << ", " << i->c_str () << ", " << char_type << +                ", " << name << " >" << endl +                 << "_xsd_" << name << "_stream_insertion_init_" << +                n++ << " (" << endl +                 << strlit (e.name ()) << "," << endl +                 << strlit (xml_ns_name (e)) << ");" +                 << endl; +            } +          } +        } + +      private: +        Traversal::Inherits inherits_base_; +        BaseTypeName base_; +      }; + +      struct Element: Traversal::Element, Context +      { +        Element (Context& c, String const& scope_, String const& stream_) +            : Context (c), scope (scope_), stream (stream_) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (skip (e)) return; + +          String const& aname (eaname (e)); +          SemanticGraph::Type& t (e.type ()); +          String type (scope + L"::" + etype (e)); + +          // Figure out if we need to generate polymorphic code. If this +          // elemen's type is anonymous then we don't need to do anything. +          // Note that if the type is anonymous then it can't be derived +          // from which makes it impossible to substitute or dynamically- +          // type with xsi:type. +          // +          bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + +          // Check if this element is abstract. +          // +          bool abst (false); +          if (poly) +          { +            SemanticGraph::Complex* tc; +            abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && +              tc->abstract_p (); +          } + +          if (max (e) != 1) +          { +            // sequence +            // +            os << "{" +               << "const " << scope << "::" << econtainer (e) << "& c (" << +              "x." << aname << " ());" +               << "s << ::xsd::cxx::tree::ostream_common::as_size< " << +              "::std::size_t > (c.size ());"; + +            os << "for (" << scope << "::" << econst_iterator (e) << endl +               << "i (c.begin ()), e (c.end ());" << endl +               << "i != e; ++i)" +               << "{"; + +            if (poly) +            { +              if (!abst) +                os << "bool d (typeid (" << type << ") != typeid (*i));" +                   << "s << d;" +                   << "if (!d)" << endl +                   << "s << *i;" +                   << "else" << endl; + +              os << "::xsd::cxx::tree::stream_insertion_map_instance< " << +                poly_plate << ", " << stream << ", " << char_type << +                " > ().insert (s, *i);"; +            } +            else +              os << "s << *i;"; + +            os << "}" // for +               << "}"; +          } +          else if (min (e) == 0) +          { +            // optional +            // +            os << "{" +               << "bool p (x." << aname << " ());" +               << "s << p;" +               << "if (p)"; + +            if (poly) +            { +              os << "{" +                 << "const " << type << "& i (*x." << aname << " ());"; + +              if (!abst) +                 os << "bool d (typeid (" << type << ") != typeid (i));" +                    << "s << d;" +                    << "if (!d)" << endl +                    << "s << i;" +                    << "else" << endl; + +              os << "::xsd::cxx::tree::stream_insertion_map_instance< " << +                poly_plate << ", " << stream << ", " << char_type << +                " > ().insert (s, i);" +                 << "}"; +            } +            else +              os << endl +                 << "s << *x." << aname << " ();"; + +            os << "}"; +          } +          else +          { +            // one +            // +            if (poly) +            { +              os << "{" +                 << "const " << type << "& i (x." << aname << " ());"; + +              if (!abst) +                os << "bool d (typeid (" << type << ") != typeid (i));" +                   << "s << d;" +                   << "if (!d)" << endl +                   << "s << i;" +                   << "else" << endl; + +              os << "::xsd::cxx::tree::stream_insertion_map_instance< " << +                poly_plate << ", " << stream << ", " << char_type << +                " > ().insert (s, i);" +                 << "}"; +            } +            else +              os << "s << x." << aname << " ();"; +          } +        } + +      private: +        String scope; +        String stream; +      }; + +      struct Attribute: Traversal::Attribute, Context +      { +        Attribute (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& aname (eaname (a)); + +          if (a.optional_p () && !a.default_p ()) +          { +            os << "{" +               << "bool p (x." << aname << " ());" +               << "s << p;" +               << "if (p)" << endl +               << "s << *x." << aname << " ();" +               << "}"; +          } +          else +          { +            os << "s << x." << aname << " ();"; +          } +        } +      }; + + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), base_ (c) +        { +          inherits_ >> base_; +        } + +        virtual void +        traverse (Type& c) +        { +          SemanticGraph::Context& ctx (c.context ()); + +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (c, name) && !name) +            return; + +          bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); +          bool has_body (ordered || +                         has<Traversal::Member> (c) || +                         c.inherits_p ()); + +          size_t n (0); +          NarrowStrings const& st (options.generate_insertion ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + +            os << stream_type << "&" << endl +               << "operator<< (" << stream_type << "& s," << endl +               << "const " << name << "&" << (has_body ? " x" : "") << ")" +               << "{"; + +            if (c.inherits_p ()) +            { +              os << "s << static_cast< const "; + +              inherits (c, inherits_); + +              os << "& > (x);"; +            } + +            // Write the order sequence. +            // +            if (ordered) +            { +              String const& ci (ctx.get<String> ("order-const-iterator")); +              String const& an (ctx.get<String> ("order-aname")); + +              os << "s << ::xsd::cxx::tree::ostream_common::as_size< " << +                "::std::size_t > (" << endl +                 << "x." << an << " ().size ());" +                 << endl +                 << "for (" << name << "::" << ci << endl +                 << "b (x." << an << " ().begin ()), n (x." << an << +                " ().end ());" << endl +                 << "b != n; ++b)" +                 << "{" +                 << "s << ::xsd::cxx::tree::ostream_common::as_size< " << +                "::std::size_t > (b->id);" +                 << "s << ::xsd::cxx::tree::ostream_common::as_size< " << +                "::std::size_t > (b->index);" +                 << "}"; +            } + +            { +              Traversal::Names names_member; +              Element element (*this, name, *i); +              Attribute attribute (*this); + +              names_member >> element; +              names_member >> attribute; + +              names (c, names_member); +            } + +            os << "return s;" +               << "}"; + + +            // Register with type map. +            // +            if (polymorphic && +                polymorphic_p (c) && +                !c.abstract_p () && +                (!anonymous_p (c) || anonymous_substitutes_p (c))) +            { +              // Note that we are using the original type name. +              // +              String const& name (ename (c)); + +              os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_insertion_initializer< " << +                poly_plate << ", " << i->c_str () << ", " << char_type << +                ", " << name << " >" << endl +                 << "_xsd_" << name << "_stream_insertion_init_" << +                n++ << " (" << endl +                 << strlit (c.name ()) << "," << endl +                 << strlit (xml_ns_name (c)) << ");" +                 << endl; +            } +          } +        } + +      private: +        Traversal::Inherits inherits_; +        BaseTypeName base_; +      }; +    } + +    void +    generate_stream_insertion_source (Context& ctx) +    { +      if (ctx.polymorphic) +      { +        NarrowStrings const& st (ctx.options.generate_insertion ()); + +        ctx.os << "#include <xsd/cxx/tree/stream-insertion-map.hxx>" << endl +               << endl; + +        bool import_maps (ctx.options.import_maps ()); +        bool export_maps (ctx.options.export_maps ()); + +        if (import_maps || export_maps) +        { +          ctx.os << "#ifndef XSD_NO_EXPORT" << endl +                 << endl +                 << "namespace xsd" +                 << "{" +                 << "namespace cxx" +                 << "{" +                 << "namespace tree" +                 << "{"; + +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            String stream (*i); + +            ctx.os << "#ifdef _MSC_VER" << endl; + +            if (export_maps) +              ctx.os << "template struct __declspec (dllexport) " << +                "stream_insertion_plate< " << ctx.poly_plate << ", " << +                stream << ", " << ctx.char_type << " >;"; + +            if (import_maps) +              ctx.os << "template struct __declspec (dllimport) " << +                "stream_insertion_plate< " << ctx.poly_plate << ", " << +                stream << ", " << ctx.char_type << " >;"; + +            ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl +                   << "template struct __attribute__ ((visibility(\"default\"))) " << +              "stream_insertion_plate< " << ctx.poly_plate << ", " << +              stream << ", " << ctx.char_type << " >;" +                   << "#elif defined(XSD_MAP_VISIBILITY)" << endl +                   << "template struct XSD_MAP_VISIBILITY " << +              "stream_insertion_plate< " << ctx.poly_plate << ", " << +              stream << ", " << ctx.char_type << " >;" +                   << "#endif" << endl; +          } + +          ctx.os << "}"  // tree +                 << "}"  // cxx +                 << "}"  // xsd +                 << "#endif // XSD_NO_EXPORT" << endl +                 << endl; +        } + +        ctx.os << "namespace _xsd" +               << "{"; + +        size_t n (0); +        for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +             ++i) +        { +          String stream (*i); + +          ctx.os << "static" << endl +                 << "const ::xsd::cxx::tree::stream_insertion_plate< " << +            ctx.poly_plate << ", " << stream << ", " << ctx.char_type << +            " >" << endl +                 << "stream_insertion_plate_init_" << n++ << ";"; +        } + +        ctx.os << "}"; +      } + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names names_ns, names; + +      Namespace ns (ctx); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/stream-insertion-source.hxx b/xsd/cxx/tree/stream-insertion-source.hxx new file mode 100644 index 0000000..ace8bf6 --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/stream-insertion-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_INSERTION_SOURCE_HXX +#define XSD_CXX_TREE_INSERTION_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_stream_insertion_source (Context&); +  } +} + +#endif  // XSD_CXX_TREE_INSERTION_SOURCE_HXX diff --git a/xsd/cxx/tree/stream-source.cxx b/xsd/cxx/tree/stream-source.cxx new file mode 100644 index 0000000..eeb3ca3 --- /dev/null +++ b/xsd/cxx/tree/stream-source.cxx @@ -0,0 +1,496 @@ +// file      : xsd/cxx/tree/stream-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          SemanticGraph::Type& item_type (l.argumented ().type ()); +          String base (L"::xsd::cxx::tree::list< " + +                       item_type_name (item_type) + L", " + char_type); + +          if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) +            base += L", ::xsd::cxx::tree::schema_type::double_"; +          else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) +            base += L", ::xsd::cxx::tree::schema_type::decimal"; + +          base += L" >"; + +          os << std_ostream_type << "&" << endl +             << "operator<< (" << std_ostream_type << "& o, " << +            "const " << name << "& i)" +             << "{" +             << "return o << static_cast< const " << base << "& > (i);" +             << "}"; + +          // Register with ostream map. +          // +          if (polymorphic && +              polymorphic_p (l) && +              (!anonymous_p (l) || anonymous_substitutes_p (l))) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (l)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::std_ostream_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +               << "_xsd_" << name << "_std_ostream_init;" +               << endl; +          } +        } + +      private: +        String +        item_type_name (SemanticGraph::Type& t) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (t); + +          return o.str (); +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          os << std_ostream_type << "&" << endl +             << "operator<< (" << std_ostream_type << "& o, " << +            "const " << name << "& i)" +             << "{" +             << "return o << static_cast< const " << xs_string_type << "& > (i);" +             << "}"; + +          // Register with ostream map. +          // +          if (polymorphic && +              polymorphic_p (u) && +              (!anonymous_p (u) || anonymous_substitutes_p (u))) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (u)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::std_ostream_initializer< " << +              poly_plate << ", " << char_type << ", " << name << " >" << endl +               << "_xsd_" << name << "_std_ostream_init;" +               << endl; +          } +        } +      }; + + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c), base_ (c) +        { +          inherits_base_ >> base_; +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (e); +          } + +          bool enum_based (false); +          if (string_based) +          { +            SemanticGraph::Enumeration* be (0); +            IsEnumBasedType t (be); +            t.dispatch (e); + +            enum_based = (be != 0); +          } + +          // If we are based on an enum then the value type is just an +          // alias and we don't need to generate this operator again. +          // +          if (string_based && !enum_based) +          { +            os << std_ostream_type << "&" << endl +               << "operator<< (" << std_ostream_type << "& o, " << +              name << "::" << evalue (e) << " i)" +               << "{" +               << "return o << " << name << "::_xsd_" << name << +              "_literals_[i];" +               << "}"; +          } + +          os << std_ostream_type << "&" << endl +             << "operator<< (" << std_ostream_type << "& o, " << +            "const " << name << "& i)" +             << "{" +             << "return o << static_cast< const "; + +          inherits (e, inherits_base_); + +          os << "& > (i);" +             << "}"; + +          // Register with ostream map. +          // +          if (polymorphic && +              polymorphic_p (e) && +              (!anonymous_p (e) || anonymous_substitutes_p (e))) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (e)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::std_ostream_initializer< " << +              poly_plate << ", " << char_type << ", " << name << " >" << endl +               << "_xsd_" << name << "_std_ostream_init;" +               << endl; +          } +        } + +      private: +        Traversal::Inherits inherits_base_; +        BaseTypeName base_; +      }; + +      struct Element: Traversal::Element, Context +      { +        Element (Context& c, String const& scope_) +            : Context (c), scope (scope_) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (skip (e)) +            return; + +          String const& aname (eaname (e)); + +          // Check if we need to handle xsi:type and substitution groups. +          // If this element's type is anonymous then we don't need to do +          // anything. Note that if the type is anonymous then it can't be +          // derived from which makes it impossible to substitute or +          // dynamically-type with xsi:type. +          // +          SemanticGraph::Type& t (e.type ()); +          bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + +          if (poly) +          { +            os << "{" +               << "::xsd::cxx::tree::std_ostream_map< " << char_type +               << " >& om (" << endl +               << "::xsd::cxx::tree::std_ostream_map_instance< " << +              poly_plate << ", " << char_type << " > ());" +               << endl; +          } + +          if (max (e) != 1) +          { +            // sequence +            // +            os << "for (" << scope << "::" << econst_iterator (e) << endl +               << "b (i." << aname << " ().begin ()), " << +              "e (i." << aname << " ().end ());" << endl +               << "b != e; ++b)" +               << "{" +               << "o << ::std::endl << " << strlit (e.name () + L": "); + +            if (!poly) +              os << " << *b;"; +            else +              os << ";" +                 << "om.insert (o, *b);"; + +            os << "}"; +          } +          else if (min (e) == 0) +          { +            // optional +            // + +            os << "if (i." << aname << " ())" +               << "{" +               << "o << ::std::endl << " << strlit (e.name () + L": "); + +            if (!poly) +              os << " << *i." << aname << " ();"; +            else +              os << ";" +                 << "om.insert (o, *i." << aname << " ());"; + +            os << "}"; +          } +          else +          { +            // one +            // +            os << "o << ::std::endl << " << strlit (e.name () + L": "); + +            if (!poly) +              os << " << i." << aname << " ();"; +            else +              os << ";" +                 << "om.insert (o, i." << aname << " ());"; +          } + +          if (poly) +            os << "}"; +        } + +      private: +        String scope; +      }; + +      struct Attribute: Traversal::Attribute, Context +      { +        Attribute (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& aname (eaname (a)); + +          if (a.optional_p () && !a.default_p ()) +          { +            os << "if (i." << aname << " ())" +               << "{" +               << "o << ::std::endl << " << strlit (a.name () + L": ") << +              " << *i." << aname << " ();" +               << "}"; +          } +          else +          { +            os << "o << ::std::endl << " << strlit (a.name () + L": ") << +              " << i." << aname << " ();"; +          } +        } +      }; + + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), base_ (c) +        { +          inherits_ >> base_; +        } + +        virtual void +        traverse (Type& c) +        { +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (c, name) && !name) +            return; + +          // +          // +          bool has_body (has<Traversal::Member> (c) || c.inherits_p ()); + +          os << std_ostream_type << "&" << endl +             << "operator<< (" << std_ostream_type << "& o, " << +            "const " << name << "&" << (has_body ? " i" : "") << ")" +             << "{"; + +          if (c.inherits_p ()) +          { +            os << "o << static_cast< const "; + +            inherits (c, inherits_); + +            os << "& > (i);" +               << endl; +          } + +          { +            Traversal::Names names_member; +            Element element (*this, name); +            Attribute attribute (*this); + +            names_member >> element; +            names_member >> attribute; + +            names (c, names_member); +          } + +          os << "return o;" +             << "}"; + +          // Register with ostream map. +          // +          if (polymorphic && +              polymorphic_p (c) && +              !c.abstract_p () && +              (!anonymous_p (c) || anonymous_substitutes_p (c))) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (c)); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::std_ostream_initializer< " << +              poly_plate << ", " << char_type << ", " << name << " >" << endl +               << "_xsd_" << name << "_std_ostream_init;" +               << endl; +          } +        } + +      private: +        Traversal::Inherits inherits_; +        BaseTypeName base_; +      }; +    } + +    void +    generate_stream_source (Context& ctx, size_t first, size_t last) +    { +      String c (ctx.char_type); + +      ctx.os << "#include <ostream>" << endl +             << endl; + +      if (ctx.polymorphic) +      { +        ctx.os << "#include <xsd/cxx/tree/std-ostream-map.hxx>" << endl +               << endl; + +        bool import_maps (ctx.options.import_maps ()); +        bool export_maps (ctx.options.export_maps ()); + +        if (import_maps || export_maps) +        { +          ctx.os << "#ifndef XSD_NO_EXPORT" << endl +                 << endl +                 << "namespace xsd" +                 << "{" +                 << "namespace cxx" +                 << "{" +                 << "namespace tree" +                 << "{" +                 << "#ifdef _MSC_VER" << endl; + +          if (export_maps) +            ctx.os << "template struct __declspec (dllexport) " << +              "std_ostream_plate< " << ctx.poly_plate << ", " << +              ctx.char_type << " >;"; + +          if (import_maps) +            ctx.os << "template struct __declspec (dllimport) " << +              "std_ostream_plate< " << ctx.poly_plate << ", " << +              ctx.char_type << " >;"; + +          ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl +                 << "template struct __attribute__ ((visibility(\"default\"))) " << +            "std_ostream_plate< " << ctx.poly_plate << ", " << ctx.char_type << +            " >;"; + +          ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl +                 << "template struct XSD_MAP_VISIBILITY " << +            "std_ostream_plate< " << ctx.poly_plate << ", " << ctx.char_type << +            " >;"; + +          ctx.os << "#endif" << endl +                 << "}"  // tree +                 << "}"  // cxx +                 << "}"  // xsd +                 << "#endif // XSD_NO_EXPORT" << endl +                 << endl; +        } + +        ctx.os << "namespace _xsd" +               << "{" +               << "static" << endl +               << "const ::xsd::cxx::tree::std_ostream_plate< " << +          ctx.poly_plate << ", " << ctx.char_type << " >" << endl +               << "std_ostream_plate_init;" +               << "}"; +      } + +      Traversal::Schema schema; + +      Sources sources; +      Traversal::Names names_ns, names; + +      Namespace ns (ctx, first, last); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/stream-source.hxx b/xsd/cxx/tree/stream-source.hxx new file mode 100644 index 0000000..b2b4d5d --- /dev/null +++ b/xsd/cxx/tree/stream-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/stream-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_STREAM_SOURCE_HXX +#define XSD_CXX_TREE_STREAM_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_stream_source (Context&, size_t first, size_t last); +  } +} + +#endif  // XSD_CXX_TREE_STREAM_SOURCE_HXX diff --git a/xsd/cxx/tree/tree-forward.cxx b/xsd/cxx/tree/tree-forward.cxx new file mode 100644 index 0000000..b715abe --- /dev/null +++ b/xsd/cxx/tree/tree-forward.cxx @@ -0,0 +1,325 @@ +// file      : xsd/cxx/tree/tree-forward.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/tree-forward.hxx> +#include <xsd/cxx/tree/fundamental-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String const& name (ename (l)); + +          if (String custom = custom_type (l)) +          { +            String new_name; +            renamed_type (l, new_name); + +            if (new_name) +              os << "class " << new_name << ";"; + +            if (custom == name) +              os << "class " << name << ";"; +            else +              os << "typedef " << custom << " " << name << ";"; +          } +          else +            os << "class " << name << ";"; +        } +      }; + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String const& name (ename (u)); + +          if (String custom = custom_type (u)) +          { +            String new_name; +            renamed_type (u, new_name); + +            if (new_name) +              os << "class " << new_name << ";"; + +            if (custom == name) +              os << "class " << name << ";"; +            else +              os << "typedef " << custom << " " << name << ";"; +          } +          else +            os << "class " << name << ";"; +        } +      }; + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          String const& name (ename (e)); + +          if (String custom = custom_type (e)) +          { +            String new_name; +            renamed_type (e, new_name); + +            if (new_name) +              os << "class " << new_name << ";"; + +            if (custom == name) +              os << "class " << name << ";"; +            else +              os << "typedef " << custom << " " << name << ";"; +          } +          else +            os << "class " << name << ";"; +        } +      }; + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          String const& name (ename (c)); + +          if (String custom = custom_type (c)) +          { +            String new_name; +            renamed_type (c, new_name); + +            if (new_name) +              os << "class " << new_name << ";"; + +            if (custom == name) +              os << "class " << name << ";"; +            else +              os << "typedef " << custom << " " << name << ";"; +          } +          else +            os << "class " << name << ";"; +        } +      }; +    } + +    void +    generate_forward (Context& ctx) +    { +      NarrowString xml_schema (ctx.options.extern_xml_schema ()); + +      // Inlcude or Emit fundamental types. +      // +      if (xml_schema) +      { +        String name (ctx.hxx_expr->replace (xml_schema)); + +        ctx.os << "#include " << ctx.process_include_path (name) << endl +               << endl; +      } +      else +      { +        if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") +        { +          ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << +            ".hxx>" << endl +                 << endl; +        } + +        ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl +               << "#include <xsd/cxx/tree/elements.hxx>" << endl +               << "#include <xsd/cxx/tree/types.hxx>" << endl +               << endl; + +        if (!ctx.options.suppress_parsing () || +            ctx.options.generate_serialization ()) +        { +          ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl +                 << endl; +        } + +        if (!ctx.options.suppress_parsing () || +            ctx.options.generate_serialization ()) +        { +          ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl +                 << endl; +        } + +        bool element_map (ctx.options.generate_element_map ()); + +        if (element_map) +          ctx.os << "#include <xsd/cxx/tree/element-map.hxx>" << endl +                 << endl; + +        // I need to include all the "optional" headers here (instead of +        // later in the individual generators for each feature because +        // those headers provide implementation for the fundamental types. +        // +        if (!ctx.options.suppress_parsing ()) +        { +          ctx.os << "#include <xsd/cxx/tree/parsing.hxx>" << endl; + +          Traversal::Schema schema, xsd; +          Traversal::Implies implies; +          Traversal::Names names; +          Traversal::Namespace ns; +          Traversal::Names ns_names; +          FundIncludes type (ctx, "parsing"); + +          schema >> implies >> xsd >> names >> ns >> ns_names >> type; + +          schema.dispatch (ctx.schema_root); + +          if (element_map) +            ctx.os << "#include <xsd/cxx/tree/parsing/element-map.txx>" << +              endl; + +          ctx.os << endl; +        } + +        if (ctx.options.generate_serialization ()) +        { +          ctx.os << "#include <xsd/cxx/xml/dom/serialization-header.hxx>" << endl +                 << "#include <xsd/cxx/tree/serialization.hxx>" << endl; + +          Traversal::Schema schema, xsd; +          Traversal::Implies implies; +          Traversal::Names names; +          Traversal::Namespace ns; +          Traversal::Names ns_names; +          FundIncludes type (ctx, "serialization"); + +          schema >> implies >> xsd >> names >> ns >> ns_names >> type; + +          schema.dispatch (ctx.schema_root); + +          if (element_map) +            ctx.os << "#include <xsd/cxx/tree/serialization/element-map.txx>" << +              endl; + +          ctx.os << endl; +        } + +        if (ctx.options.generate_ostream ()) +        { +          ctx.os << "#include <xsd/cxx/tree/std-ostream-operators.hxx>" << endl +                 << endl; +        } + +        NarrowStrings const& ist (ctx.options.generate_insertion ()); +        if (!ist.empty ()) +        { +          for (NarrowStrings::const_iterator i (ist.begin ()); i != ist.end (); +               ++i) +          { +            if (*i == "ACE_OutputCDR") +              ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-insertion.hxx>" +                     << endl; +            else if (*i == "XDR") +              ctx.os << "#include <xsd/cxx/tree/xdr-stream-insertion.hxx>" +                     << endl; +          } + +          ctx.os << "#include <xsd/cxx/tree/stream-insertion.hxx>" << endl +                 << endl; +        } + +        NarrowStrings const& est (ctx.options.generate_extraction ()); +        if (!est.empty ()) +        { +          for (NarrowStrings::const_iterator i (est.begin ()); i != est.end (); +               ++i) +          { +            if (*i == "ACE_InputCDR") +              ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-extraction.hxx>" +                     << endl; +            else if (*i == "XDR") +              ctx.os << "#include <xsd/cxx/tree/xdr-stream-extraction.hxx>" +                     << endl; +          } + +          ctx.os << "#include <xsd/cxx/tree/stream-extraction.hxx>" << endl +                 << endl; +        } + + +        Traversal::Schema schema, xsd; +        Traversal::Implies implies; +        Traversal::Names names; +        FundamentalNamespace ns (ctx); + +        schema >> implies >> xsd >> names >> ns; + +        schema.dispatch (ctx.schema_root); +      } + +      // First emit header includes. +      // +      if (ctx.options.generate_forward ()) +      { +        Traversal::Schema schema; +        Includes includes (ctx, Includes::forward); + +        schema >> includes; + +        schema.dispatch (ctx.schema_root); +      } + +      ctx.os << "// Forward declarations." << endl +             << "//" << endl; + +      Traversal::Schema schema; +      Sources sources; +      Traversal::Names names_ns, names; +      Namespace ns (ctx); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      schema.dispatch (ctx.schema_root); + +      ctx.os << endl; +    } +  } +} diff --git a/xsd/cxx/tree/tree-forward.hxx b/xsd/cxx/tree/tree-forward.hxx new file mode 100644 index 0000000..0610999 --- /dev/null +++ b/xsd/cxx/tree/tree-forward.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/tree-forward.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_TREE_FORWARD_HXX +#define XSD_CXX_TREE_TREE_FORWARD_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_forward (Context&); +  } +} + +#endif  // XSD_CXX_TREE_TREE_FORWARD_HXX diff --git a/xsd/cxx/tree/tree-header.cxx b/xsd/cxx/tree/tree-header.cxx new file mode 100644 index 0000000..99a9b17 --- /dev/null +++ b/xsd/cxx/tree/tree-header.cxx @@ -0,0 +1,4337 @@ +// file      : xsd/cxx/tree/tree-header.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/tree-header.hxx> +#include <xsd/cxx/tree/default-value.hxx> +#include <xsd/cxx/tree/fundamental-header.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      // List mapping. +      // +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief List class corresponding to the %" << +              comment (l.name ()) << endl +               << " * schema type." << endl +               << " *" << endl +               << " * This class has an interface of a standard C++ " << +              "sequence (e.g.," << endl +               << " * std::vector)." << endl; + +            if (l.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (l.annotation ()); +            } + +            os << " */" << endl; +          } + +          SemanticGraph::Type& item_type (l.argumented ().type ()); +          String item_name (item_type_name (item_type)); +          String base_type (L"::xsd::cxx::tree::list< " + item_name + L", " + +                            char_type); + +          if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) +            base_type += L", ::xsd::cxx::tree::schema_type::double_"; +          else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) +            base_type += L", ::xsd::cxx::tree::schema_type::decimal"; + +          base_type += L" >"; + +          os << "class " << type_exp << name << +            ": public " << any_simple_type << "," << endl +             << "  public " << base_type +             << "{" +             << "public:" << endl; + +          // c-tor () +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Default constructor." << endl +               << " *" << endl +               << " * Creates an empty list." << endl +               << " */" << endl; +          } +          os << name << " ();" +             << endl; + +          // c-tor (size_type, const X& x) +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Create a list with copies of the specified " << +               "element." << endl +               << " *" << endl +               << " * @param n A number of elements to copy." << endl +               << " * @param x An element to copy." << endl +               << " *" << endl +               << " * This constructor creates a list with @a n copies " << +              "of @a x." << endl +               << " */" << endl; +          } + +          String size_type (name != L"size_type" +                            ? String (L"size_type") +                            : base_type + L"::size_type"); + +          os << name << " (" << size_type << " n, const " << item_name << +            "& x);" +             << endl; + +          // c-tor (const I& begin, const I& end) +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Create a list from an iterator range." << endl +               << " *" << endl +               << " * @param begin An iterator pointing to the first " << +              "element." << endl +               << " * @param end An iterator pointing to the one past " << +              "the last element." << endl +               << " *" << endl +               << " * This constructor creates a list consisting of " << +              "copies of the" << endl +               << " * elements in the range [begin,end)." << endl +               << " */" << endl; +          } + +          String iter_type (unclash (name, "I")); + +          os << "template < typename " << iter_type << " >" << endl +             << name << " (const " << iter_type << "& begin, const " << +            iter_type << "& end)" << endl +             << ": " << base_type << " (begin, end, this)" +             << "{" +             << "}"; + +          // c-tor (istream&) +          // +          NarrowStrings const& st (options.generate_extraction ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a data " << +                "representation" << endl +                 << " * stream." << endl +                 << " *" << endl +                 << " * @param s A stream to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (" << istream_type << "< " << i->c_str () << +              " >& s," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; +          } + +          if (!options.suppress_parsing ()) +          { +            // c-tor (xercesc::DOMElement) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a DOM element." << endl +                 << " *" << endl +                 << " * @param e A DOM element to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << xerces_ns << "::DOMElement& e," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; + +            // c-tor (xercesc::DOMAttr) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a DOM attribute." << endl +                 << " *" << endl +                 << " * @param a A DOM attribute to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; + +            // c-tor (std::basic_string const&, xercesc::DOMElement) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a string fragment." << endl +                 << " *" << endl +                 << " * @param s A string fragment to extract the data from." << endl +                 << " * @param e A pointer to DOM element containing the " << +                "string fragment." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << string_type << "& s," << endl +               << "const " << xerces_ns << "::DOMElement* e," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; +          } + +          // copy c-tor () +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy constructor." << endl +               << " *" << endl +               << " * @param x An instance to make a copy of." << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @param c A pointer to the object that will contain " << +              "the copy." << endl +               << " *" << endl +               << " * For polymorphic object models use the @c _clone " << +              "function instead." << endl +               << " */" << endl; +          } + +          os << name << " (const " << name << "& x," << endl +             << flags_type << " f = 0," << endl +             << container << "* c = 0);" +             << endl; + +          os << "#ifdef XSD_CXX11" << endl +             << name << "&" << endl +             << "operator= (const " << name << "&) = default;" +             << "#endif" << endl +             << endl; + +          // clone +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy the instance polymorphically." << endl +               << " *" << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @param c A pointer to the object that will contain " << +              "the copy." << endl +               << " * @return A pointer to the dynamically allocated copy." << endl +               << " *" << endl +               << " * This function ensures that the dynamic type of the " << +              "instance is" << endl +               << " * used for copying and should be used for polymorphic " << +              "object" << endl +               << " * models instead of the copy constructor." << endl +               << " */" << endl; +          } + +          os << "virtual " << name << "*" << endl +             << "_clone (" << flags_type << " f = 0," << endl +             << container << "* c = 0) const;" +             << endl; + +          // d-tor +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Destructor." << endl +               << " */" << endl; +          } + +          os << "virtual " << endl +             << "~" << name << " ();"; + +          os << "};"; + +          // Comparison operators. +          // +          if (options.generate_comparison ()) +          { +            os << inst_exp +               << "bool" << endl +               << "operator== (const " << name << "&, const " << name << "&);" +               << endl; + +            os << inst_exp +               << "bool" << endl +               << "operator!= (const " << name << "&, const " << name << "&);" +               << endl +               << endl; +          } +        } + +      private: +        String +        item_type_name (SemanticGraph::Type& t) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (t); + +          return o.str (); +        } +      }; + + +      // Union mapping. +      // +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Union class corresponding to the %" << +              comment (u.name ()) << endl +               << " * schema type." << endl +               << " *" << endl +               << " * The mapping represents unions as strings." << endl; + +            if (u.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (u.annotation ()); +            } + +            os << " */" << endl; +          } + +          os << "class " << type_exp << name << +	    ": public " <<  xs_string_type +             << "{" +             << "public:" << endl +             << endl; + +          if (options.generate_default_ctor ()) +          { +            // c-tor () +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Default constructor." << endl +                 << " *" << endl +                 << " * Note that this constructor may leave the " << +                "instance in an" << endl +                 << " * invalid state." << endl +                 << " */" << endl; +            } + +            os << name << " ();" +               << endl; +          } + +          // c-tor (const char*) +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Create an instance from a C string." << endl +               << " *" << endl +               << " * @param v A string value." << endl +               << " */" << endl; +          } +          os << name << " (const " << char_type << "* v);" +             << endl; + +          // c-tor (string const&) +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Create an instance from a string." << endl +               << " *" << endl +               << " * @param v A string value." << endl +               << " */" << endl; +          } +          os << name << " (const " << string_type << "& v);" +             << endl; + +          // c-tor (istream&) +          // +          NarrowStrings const& st (options.generate_extraction ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a data " << +                "representation" << endl +                 << " * stream." << endl +                 << " *" << endl +                 << " * @param s A stream to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (" << istream_type << "< " << i->c_str () << +              " >& s," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; +          } + +          if (!options.suppress_parsing ()) +          { +            // c-tor (xercesc::DOMElement) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a DOM element." << endl +                 << " *" << endl +                 << " * @param e A DOM element to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << xerces_ns << "::DOMElement& e," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; + +            // c-tor (xercesc::DOMAttr) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a DOM attribute." << endl +                 << " *" << endl +                 << " * @param a A DOM attribute to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; + +            // c-tor (std::basic_string const&, xercesc::DOMElement) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a string fragment." << endl +                 << " *" << endl +                 << " * @param s A string fragment to extract the data from." << endl +                 << " * @param e A pointer to DOM element containing the " << +                "string fragment." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << string_type << "& s," << endl +               << "const " << xerces_ns << "::DOMElement* e," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; +          } + +          // copy c-tor () +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy constructor." << endl +               << " *" << endl +               << " * @param x An instance to make a copy of." << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @param c A pointer to the object that will contain " << +              "the copy." << endl +               << " *" << endl +               << " * For polymorphic object models use the @c _clone " << +              "function instead." << endl +               << " */" << endl; +          } + +          os << name << " (const " << name << "& x," << endl +             << flags_type << " f = 0," << endl +             << container << "* c = 0);" +             << endl; + +          os << "#ifdef XSD_CXX11" << endl +             << name << "&" << endl +             << "operator= (const " << name << "&) = default;" +             << "#endif" << endl +             << endl; + +          // clone +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy the instance polymorphically." << endl +               << " *" << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @param c A pointer to the object that will contain " << +              "the copy." << endl +               << " * @return A pointer to the dynamically allocated copy." << endl +               << " *" << endl +               << " * This function ensures that the dynamic type of the " << +              "instance is" << endl +               << " * used for copying and should be used for polymorphic " << +              "object" << endl +               << " * models instead of the copy constructor." << endl +               << " */" << endl; +          } + +          os << "virtual " << name << "*" << endl +             << "_clone (" << flags_type << " f = 0," << endl +             << container << "* c = 0) const;" +             << endl; + +          os << "};"; +        } +      }; + +      // Enum mapping. +      // +      struct Enumerator: Traversal::Enumerator, Context +      { +        Enumerator (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (doxygen && e.annotated_p ()) +          { +            os << "/**" << endl; +            write_annotation (e.annotation ()); +            os << " */" << endl; +          } + +          os << ename (e); +        } +      }; + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c), +              base_ (c), +              member_ (c), +              enumerator_ (c) +        { +          inherits_base_ >> base_; +          inherits_member_ >> member_; + +          names_ >> enumerator_; +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (e); +          } + +          bool enum_based (false); +          SemanticGraph::Enumeration* base_enum (0); + +          if (string_based) +          { +            IsEnumBasedType t (base_enum); +            t.dispatch (e); + +            if (base_enum != 0) +              enum_based = true; +          } + +          String value; +          if (string_based) +            value = evalue (e); + +          // Get to the ultimate base and see if is a fundamental type. +          // +          bool fund_based (false); +          SemanticGraph::Type& ult_base (ultimate_base (e)); +          { +            IsFundamentalType t (fund_based); +            t.dispatch (ult_base); +          } + +          // Count enumerators. +          // +          size_t enum_count (0); + +          for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ()); +               i != end; ++i) +            ++enum_count; + +          // +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Enumeration class corresponding to the %" << +              comment (e.name ()) << endl +               << " * schema type." << endl; + +            if (e.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (e.annotation ()); +            } + +            os << " */" << endl; +          } + +          os << "class " << type_exp << name << ": public "; + +          // Enumeration always has a base. +          // +          inherits (e, inherits_base_); + +          os << "{" +             << "public:" << endl; + +          if (string_based) +          { +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief Underlying enum type." << endl +                 << " */" << endl; +            } + +            if (enum_based) +            { +              os << "typedef "; + +              inherits (e, inherits_base_); + +              os << "::" << evalue (*base_enum) << " " << value << ";" +                 << endl; +            } +            else +            { +              os << "enum " << value +                 << "{"; + +              names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma); + +              os << "};"; +            } +          } + +          // default c-tor +          // +          bool list_based ( +            ult_base.is_a<SemanticGraph::List> () || +            ult_base.is_a<SemanticGraph::Fundamental::NameTokens> () || +            ult_base.is_a<SemanticGraph::Fundamental::IdRefs> () || +            ult_base.is_a<SemanticGraph::Fundamental::Entities> ()); + +          if (options.generate_default_ctor () || list_based) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Default constructor." << endl +                 << " *" << endl +                 << " * Note that this constructor may leave the " << +                "instance in an" << endl +                 << " * invalid state." << endl +                 << " */" << endl; +            } + +            os << name << " ();" +               << endl; +          } + +          // c-tor (value) +          // +          if (string_based) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from the " << +                "underlying enum value." << endl +                 << " *" << endl +                 << " * @param v A enum value." << endl +                 << " */" << endl; +            } + +            os << name << " (" << value << " v);" +               << endl; +          } + +          // c-tor (const char*) +          // +          if (string_based) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a C string." << endl +                 << " *" << endl +                 << " * @param v A string value." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << char_type << "* v);" +               << endl; +          } + +          // c-tor (const std::string&) +          // +          if (string_based) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a string." << endl +                 << " *" << endl +                 << " * @param v A string value." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << string_type << "& v);" +               << endl; +          } + +          // c-tor (fundamental) +          // +          if (fund_based) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a fundamental " << +                "type value." << endl +                 << " *" << endl +                 << " * @param v A fundamental type value." << endl +                 << " */" << endl; +            } + +            os << name << " ("; + +            member_.dispatch (ult_base); + +            os << " v);" +               << endl; +          } + +          // c-tor (base) +          // +          // If the ultimate is also our immediate base and it is a +          // fundamental type then this c-tor clashes with c-tor +          // (fundamental) above. +          // +          if (!fund_based || &ult_base != &e.inherits ().base ()) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from the " << +                "base value." << endl +                 << " *" << endl +                 << " * @param v A base value." << endl +                 << " */" << endl; +            } + +            os << name << " (const "; + +            inherits (e, inherits_member_); + +            os << "& v);" +               << endl; +          } + + +          // c-tor (istream&) +          // +          NarrowStrings const& st (options.generate_extraction ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a data " << +                "representation" << endl +                 << " * stream." << endl +                 << " *" << endl +                 << " * @param s A stream to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (" << istream_type << "< " << i->c_str () << +              " >& s," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; +          } + +          if (!options.suppress_parsing ()) +          { +            // c-tor (xercesc::DOMElement) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a DOM element." << endl +                 << " *" << endl +                 << " * @param e A DOM element to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << xerces_ns << "::DOMElement& e," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; + +            // c-tor (xercesc::DOMAttr) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a DOM attribute." << endl +                 << " *" << endl +                 << " * @param a A DOM attribute to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; + +            // c-tor (std::basic_string const&, xercesc::DOMElement) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a string fragment." << endl +                 << " *" << endl +                 << " * @param s A string fragment to extract the data from." << endl +                 << " * @param e A pointer to DOM element containing the " << +                "string fragment." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << string_type << "& s," << endl +               << "const " << xerces_ns << "::DOMElement* e," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; +          } + +          // copy c-tor +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy constructor." << endl +               << " *" << endl +               << " * @param x An instance to make a copy of." << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @param c A pointer to the object that will contain " << +              "the copy." << endl +               << " *" << endl +               << " * For polymorphic object models use the @c _clone " << +              "function instead." << endl +               << " */" << endl; +          } + +          os << name << " (const " << name << "& x," << endl +             << flags_type << " f = 0," << endl +             << container << "* c = 0);" +             << endl; + +          os << "#ifdef XSD_CXX11" << endl +             << name << "&" << endl +             << "operator= (const " << name << "&) = default;" +             << "#endif" << endl +             << endl; + +          // clone +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy the instance polymorphically." << endl +               << " *" << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @param c A pointer to the object that will contain " << +              "the copy." << endl +               << " * @return A pointer to the dynamically allocated copy." << endl +               << " *" << endl +               << " * This function ensures that the dynamic type of the " << +              "instance is" << endl +               << " * used for copying and should be used for polymorphic " << +              "object" << endl +               << " * models instead of the copy constructor." << endl +               << " */" << endl; +          } + +          os << "virtual " << name << "*" << endl +             << "_clone (" << flags_type << " f = 0," << endl +             << container << "* c = 0) const;" +             << endl; + +          // operator= (value) +          // +          if (string_based) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Assign the underlying enum value." << endl +                 << " *" << endl +                 << " * @param v A enum value." << endl +                 << " * @return A refernce to the instance." << endl +                 << " */" << endl; +            } + +            os << name << "&" << endl +               << "operator= (" << value << " v);" +               << endl; +          } + +          // operator value () +          // +          // Name lookup differences in various compilers make generation +          // of this operator outside of the class a really hard task. So +          // we are going to make it "always inline". +          // +          if (string_based) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Implicit conversion operator to the " << +                "underlying" << endl +                 << " * enum value." << endl +                 << " *" << endl +                 << " * @return A enum value." << endl +                 << " */" << endl; +            } + +            os << "virtual" << endl +               << "operator " << value << " () const" +               << "{" +               << "return _xsd_" << name << "_convert ();" +               << "}"; +          } + +          // +          // +          if (string_based) +          { +            if (doxygen) +              os << "//@cond" << endl +                 << endl; + +            os << "protected:" << endl +               << value << endl +               << "_xsd_" << name << "_convert () const;" +               << endl; + +            os << "public:" << endl; + +            if (enum_based) +            { +              // We are going to reuse our base's literals. +              // +              os << "static const " << char_type << "* const* " << +                "_xsd_" << name << "_literals_;"; +            } +            else +            { +              os << "static const " << char_type << "* const " << +                "_xsd_" << name << "_literals_[" << enum_count << "];"; +            } + +            os << "static const " << value << +              " _xsd_" << name << "_indexes_[" << enum_count << "];"; + +            if (doxygen) +              os << endl +                 << "//@endcond" << endl +                 << endl; +          } + +          os << "};"; +        } + +        virtual void +        comma (Type&) +        { +          os << "," << endl; +        } + +      private: +        Traversal::Inherits inherits_base_; +        BaseTypeName base_; + +        Traversal::Inherits inherits_member_; +        MemberTypeName member_; + +        Traversal::Names names_; +        Enumerator enumerator_; +      }; + + +      // +      // +      struct MemberFunction: Traversal::Member, Context +      { +        MemberFunction (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (skip (m)) +            return; + +          String const& aname (eaname (m)); +          String const& mname (emname (m)); +          String kind (m.is_a<SemanticGraph::Element> () +                       ? "element" : "attribute"); + +          bool fund (false); +          { +            IsFundamentalType t (fund); +            t.dispatch (m.type ()); +          } + +          bool def_attr (m.default_p () && +                         m.is_a<SemanticGraph::Attribute> ()); + +          if (max (m) != 1) +          { +            // sequence +            // +            String container (econtainer (m)); + +            // container const& +            // name () const; +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the element" << endl +                 << " * sequence." << endl +                 << " *" << endl +                 << " * @return A constant reference to the sequence " << +                "container." << endl +                 << " */" << endl; +            } + +            os << "const " << container << "&" << endl +               << aname << " () const;" +               << endl; + +            // container& +            // name (); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-write reference to the " << +                "element sequence." << endl +                 << " *" << endl +                 << " * @return A reference to the sequence container." << endl +                 << " */" << endl; +            } + +            os << container << "&" << endl +               << aname << " ();" +               << endl; + +            // void +            // name (container const&); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Copy elements from a given sequence." << endl +                 << " *" << endl +                 << " * @param s A sequence to copy elements from." << endl +                 << " *" << endl +                 << " * For each element in @a s this function " << +                "makes a copy and adds it " << endl +                 << " * to the sequence. Note that this operation " << +                "completely changes the " << endl +                 << " * sequence and all old elements will be lost." << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (const " << container << "& s);" +               << endl; +          } +          else if (min (m) == 0 && !def_attr) +          { +            // optional +            // +            String const& type (etype (m)); +            String container (econtainer (m)); + +            // container const& +            // name () const; +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the " << kind << endl +                 << " * container." << endl +                 << " *" << endl +                 << " * @return A constant reference to the optional " << +                "container." << endl +                 << " */" << endl; +            } + +            os << "const " << container << "&" << endl +               << aname << " () const;" +               << endl; + +            // container& +            // name (); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-write reference to the " << +                kind << " container." << endl +                 << " *" << endl +                 << " * @return A reference to the optional container." << endl +                 << " */" << endl; +            } + +            os << container << "&" << endl +               << aname << " ();" +               << endl; + +            // void +            // name (type const&); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Set the " << kind << " value." << endl +                 << " *" << endl +                 << " * @param x A new value to set." << endl +                 << " *" << endl +                 << " * This function makes a copy of its argument " << +                "and sets it as" << endl +                 << " * the new value of the " << kind << "." << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (const " << type << "& x);" +               << endl; + +            // void +            // name (container const&); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Set the " << kind << " value." << endl +                 << " *" << endl +                 << " * @param x An optional container with the new value " << +                "to set." << endl +                 << " *" << endl +                 << " * If the value is present in @a x then this function " << +                "makes a copy " << endl +                 << " * of this value and sets it as the new value of the " << +                kind << "." << endl +                 << " * Otherwise the " << kind << " container is set " << +                "the 'not present' state." << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (const " << container << "& x);" +               << endl; + +            // void +            // name (auto_ptr<type>); +            // +            if (!fund) +            { +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Set the " << kind << " value without " << +                  "copying." << endl +                   << " *" << endl +                   << " * @param p A new value to use." << endl +                   << " *" << endl +                   << " * This function will try to use the passed value " << +                  "directly instead" << endl +                   << " * of making a copy." << endl +                   << " */" << endl; +              } + +              os << "void" << endl +                 << mname << " (" << auto_ptr << "< " << type << " > p);" +                 << endl; +            } +          } +          else +          { +            // one +            // +            String const& type (etype (m)); + +            // type const& +            // name () const; +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the " << kind << "." << endl +                 << " *" << endl +                 << " * @return A constant reference to the " << kind << +                "." << endl +                 << " */" << endl; +            } + +            os << "const " << type << "&" << endl +               << aname << " () const;" +               << endl; + +            // Do not generate modifiers for fixed attributes. +            // +            if (!(def_attr && m.fixed_p ())) +            { +              // type& +              // name (); +              // +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Return a read-write reference to the " << +                  kind << "." << endl +                   << " *" << endl +                   << " * @return A reference to the " << kind << "." << endl +                   << " */" << endl; +              } + +              os << type << "&" << endl +                 << aname << " ();" +                 << endl; + +              // void +              // name (type const&); +              // +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Set the " << kind << " value." << endl +                   << " *" << endl +                   << " * @param x A new value to set." << endl +                   << " *" << endl +                   << " * This function makes a copy of its argument " << +                  "and sets it as" << endl +                   << " * the new value of the " << kind << "." << endl +                   << " */" << endl; +              } + +              os << "void" << endl +                 << mname << " (const " << type << "& x);" +                 << endl; + +              // void +              // name (auto_ptr<type>); +              // +              if (!fund) +              { +                if (doxygen) +                { +                  os << "/**" << endl +                     << " * @brief Set the " << kind << " value without " << +                    "copying." << endl +                     << " *" << endl +                     << " * @param p A new value to use." << endl +                     << " *" << endl +                     << " * This function will try to use the passed value " << +                    "directly" << endl +                     << " * instead of making a copy." << endl +                     << " */" << endl; +                } + +                os << "void" << endl +                   << mname << " (" << auto_ptr << "< " << type << " > p);" +                   << endl; + +              } + +              // auto_ptr<type> +              // detach_name (); +              // +              if (detach && !fund) +              { +                if (doxygen) +                { +                  os << "/**" << endl +                     << " * @brief Detach the " << kind << " value from " << +                    "the object model." << endl +                     << " *" << endl +                     << " * @return A pointer to the " << kind << " value." << endl +                     << " *" << endl +                     << " * Note that this function leaves the required " << +                    kind << " in " << endl +                     << " * the original object model uninitialized." << endl +                     << " */" << endl; +                } + +                os << auto_ptr << "< " << type << " >" << endl +                   << edname (m) << " ();" +                   << endl; +              } +            } +          } + +          // default_value +          // +          if (m.default_p ()) +          { +            bool simple (true); + +            if (m.is_a<SemanticGraph::Element> ()) +            { +              IsSimpleType test (simple); +              test.dispatch (m.type ()); +            } + +            if (simple) +            { +              bool lit (false); +              { +                IsLiteralValue test (lit); +                test.dispatch (m.type ()); +              } + +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Return the default value for the " << +                  kind << "." << endl +                   << " *" << endl; + +                if (lit) +                  os << " * @return The " << kind << "'s default value." << endl; +                else +                  os << " * @return A read-only (constant) reference to the " +                     << kind << "'s" << endl +                     << " * default value." << endl; + +                os << " */" << endl; +              } + +              if (lit) +                os << "static " << etype (m) << endl; +              else +                os << "static const " << etype (m) << "&" << endl; + +              os << edefault_value (m) << " ();" +                 << endl; +            } +          } +        } +      }; + +      struct AnyFunction: Traversal::Any, Context +      { +        AnyFunction (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& aname (eaname (a)); +          String const& mname (emname (a)); + +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + +          if (max (a) != 1) +          { +            // sequence +            // +            String container (econtainer (a)); + +            // container const& +            // name () const; +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the wildcard" << endl +                 << " * element sequence." << endl +                 << " *" << endl +                 << " * @return A constant reference to the sequence " << +                "container." << endl +                 << " */" << endl; +            } + +            os << "const " << container << "&" << endl +               << aname << " () const;" +               << endl; + +            // container& +            // name (); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-write reference to the " << +                "wildcard element" << endl +                 << " * sequence." << endl +                 << " *" << endl +                 << " * @return A reference to the sequence container." << endl +                 << " */" << endl; +            } + +            os << container << "&" << endl +               << aname << " ();" +               << endl; + +            // void +            // name (container const&); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Copy elements from a given sequence." << endl +                 << " *" << endl +                 << " * @param s A sequence to copy elements from." << endl +                 << " *" << endl +                 << " * For each element in @a s this function " << +                "makes a copy and adds" << endl +                 << " * it to the wildcard element sequence. Note that " << +                "this operation" << endl +                 << " * completely changes the sequence and all old " << +                "elements will be" << endl +                 << " * lost." << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (const " << container << "& s);" +               << endl; +          } +          else if (min (a) == 0) +          { +            // optional +            // +            String container (econtainer (a)); + +            // container const& +            // name () const; +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the wildcard" << endl +                 << " * element container." << endl +                 << " *" << endl +                 << " * @return A constant reference to the optional " << +                "container." << endl +                 << " */" << endl; +            } + +            os << "const " << container << "&" << endl +               << aname << " () const;" +               << endl; + +            // container& +            // name (); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-write reference to the " << +                "wildcard element" << endl +                 << " * container." << endl +                 << " *" << endl +                 << " * @return A reference to the optional container." << endl +                 << " */" << endl; +            } + +            os << container << "&" << endl +               << aname << " ();" +               << endl; + +            // void +            // name (type const&); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Set the wildcard content." << endl +                 << " *" << endl +                 << " * @param e A new element to set." << endl +                 << " *" << endl +                 << " * This function makes a copy of its argument " << +                "and sets it as" << endl +                 << " * the new wildcard content." << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (const " << xerces_ns << "::DOMElement& e);" +               << endl; + +            // void +            // name (type*); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Set the wildcard content without copying." << endl +                 << " *" << endl +                 << " * @param p A new element to use." << endl +                 << " *" << endl +                 << " * This function will use the passed element " << +                "directly instead" << endl +                 << " * of making a copy. For this to work the element " << +                "should belong" << endl +                 << " * to the DOM document associated with this instance." << endl +                 << " *" << endl +                 << " * @see " << edom_document (c) << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (" << xerces_ns << "::DOMElement* p);" +               << endl; + +            // void +            // name (container const&); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Set the wildcard content." << endl +                 << " *" << endl +                 << " * @param x An optional container with the new " << +                "element to set." << endl +                 << " *" << endl +                 << " * If the element is present in @a x then this function " << +                "makes a " << endl +                 << " * copy of this element and sets it as the new wildcard " << +                "content." << endl +                 << " * Otherwise the element container is set the 'not " << +                "present' state." << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (const " << container << "& x);" +               << endl; +          } +          else +          { +            // one +            // + +            // type const& +            // name () const; +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the wildcard" << endl +                 << " * element." << endl +                 << " *" << endl +                 << " * @return A constant reference to the DOM element." << endl +                 << " */" << endl; +            } + +            os << "const " << xerces_ns << "::DOMElement&" << endl +               << aname << " () const;" +               << endl; + +            // type& +            // name (); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-write reference to the " << +                "wildcard element." << endl +                 << " *" << endl +                 << " * @return A reference to the DOM element." << endl +                 << " */" << endl; +            } + +            os << xerces_ns << "::DOMElement&" << endl +               << aname << " ();" +               << endl; + +            // void +            // name (type const&); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Set the wildcard content." << endl +                 << " *" << endl +                 << " * @param e A new element to set." << endl +                 << " *" << endl +                 << " * This function makes a copy of its argument " << +                "and sets it as" << endl +                 << " * the new wildcard content." << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (const " << xerces_ns << "::DOMElement& e);" +               << endl; + +            // void +            // name (const*); +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Set the wildcard content without copying." << endl +                 << " *" << endl +                 << " * @param p A new element to use." << endl +                 << " *" << endl +                 << " * This function will use the passed element " << +                "directly instead" << endl +                 << " * of making a copy. For this to work the element " << +                "should belong" << endl +                 << " * to the DOM document associated with this instance." << endl +                 << " *" << endl +                 << " * @see " << edom_document (c) << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (" << xerces_ns << "::DOMElement* p);" +               << endl; +          } +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& aname (eaname (a)); +          String const& mname (emname (a)); + +          String container (econtainer (a)); + +          // container const& +          // name () const; +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return a read-only (constant) reference " << +              "to the" << endl +               << " * attribute set." << endl +               << " *" << endl +               << " * @return A constant reference to the set " << +              "container." << endl +               << " */" << endl; +          } + +          os << "const " << container << "&" << endl +             << aname << " () const;" +             << endl; + +          // container& +          // name (); +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return a read-write reference to the " << +              "attribute set." << endl +               << " *" << endl +               << " * @return A reference to the set container." << endl +               << " */" << endl; +          } + +          os << container << "&" << endl +             << aname << " ();" +             << endl; + +          // void +          // name (container const&); +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy attributes from a given set." << endl +               << " *" << endl +               << " * @param s A set to copy elements from." << endl +               << " *" << endl +               << " * For each attribute in @a s this function " << +              "makes a copy and adds" << endl +               << " * it to the set. Note that this operation " << +              "completely changes the " << endl +               << " * set and all old attributes will be lost." << endl +               << " */" << endl; +          } + +          os << "void" << endl +             << mname << " (const " << container << "& s);" +             << endl; +        } +      }; + +      // +      // +      struct Member: Traversal::Member, Context +      { +        Member (Context& c) +            : Context (c), +              type_name_ (c), +              member_function_ (c) +        { +          belongs_ >> type_name_; +        } + +        virtual void +        traverse (Type& m) +        { +          if (skip (m)) +            return; + +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (m.scope ())); + +          String const& type (etype (m)); +          bool el (m.is_a<SemanticGraph::Element> ()); + +          bool def_attr (m.default_p () && !el); + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name " << comment (m.name ()) << endl +               << " *" << endl +               << " * @brief Accessor and modifier functions for the %" << +              comment (m.name ()) << endl +               << " * "; + +            if (max (m) != 1) +            { +              os << "sequence element." << endl; +            } +            else if (min (m) == 0) +            { +              if (def_attr) +                os << "optional attribute with a default value." << endl; +              else +                os << "optional " << (el ? "element." : "attribute.") << endl; +            } +            else +            { +              os << "required " << (el ? "element." : "attribute.") << endl; +            } + +            if (m.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (m.annotation ()); +            } + +            os << " */" << endl +               << "//@{" << endl; +          } +          else +          { +            os << "// " << comment (m.name ()) << endl +               << "//" << endl; +          } + +          // Typedefs. +          // +          if (doxygen) +          { +            os << endl +               << "/**" << endl +               << " * @brief " << (el ? "Element" : "Attribute") << +              " type." << endl +               << " */" << endl; +          } + +          os << "typedef "; + +          belongs (m, belongs_); + +          os << " " << type << ";"; + +          if (max (m) != 1) +          { +            String const& container (econtainer (m)); +            bool isense (options.generate_intellisense ()); + +            // sequence +            // +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief Element sequence container type." << endl +                 << " */" << endl; +            } + +            os << "typedef ::xsd::cxx::tree::sequence< " << type << " > " << +              container << ";"; + +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief Element iterator type." << endl +                 << " */" << endl; +            } + +            // IntelliSense does not like aliases and fully-qualified +            // names here. +            // +            if (!isense) +              os << "typedef " << container << "::iterator " << +                eiterator (m) << ";"; +            else +              os << "typedef xsd::cxx::tree::sequence< " << type << +                " >::iterator " << eiterator (m) << ";"; + +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief Element constant iterator type." << endl +                 << " */" << endl; +            } + +            if (!isense) +              os << "typedef " << container << "::const_iterator " << +                econst_iterator (m) << ";"; +            else +              os << "typedef xsd::cxx::tree::sequence< " << type << +                " >::const_iterator " << econst_iterator (m) << ";"; + +          } +          else if (min (m) == 0 && !def_attr) +          { +            // optional +            // +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief " << (el ? "Element" : "Attribute") << +                " optional container type." << endl +                 << " */" << endl; +            } + +            os << "typedef ::xsd::cxx::tree::optional< " << type << " > " << +              econtainer (m) << ";"; +          } +          else +          { +            // one +            // +          } + +          if (doxygen) +          { +            os << endl +               << "/**" << endl +               << " * @brief " << (el ? "Element" : "Attribute") << +              " traits type." << endl +               << " */" << endl; +          } +          os << "typedef ::xsd::cxx::tree::traits< " << type << ", " << +            char_type; + +          SemanticGraph::Type& t (m.type ()); + +          if (t.is_a<SemanticGraph::Fundamental::Double> ()) +            os << ", ::xsd::cxx::tree::schema_type::double_"; +          else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) +            os << ", ::xsd::cxx::tree::schema_type::decimal"; + +          os << " > " << etraits (m) << ";" +             << endl; + + +          // Element id. +          // +          if (el && ordered_p (c)) +          { +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Element id used for capturing content " << +                "order." << endl +                 << " */" << endl; + +            SemanticGraph::Context& ctx (m.context ()); + +            os << "static const ::std::size_t " << +              ctx.get<String> ("ordered-id-name") << " = " << +              ctx.get<size_t> ("ordered-id") << "UL;" << endl; +          } + +          member_function_.traverse (m); + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } +        } + +      private: +        MemberTypeName type_name_; +        Traversal::Belongs belongs_; + +        MemberFunction member_function_; +      }; + + +      struct Any: Traversal::Any, +                  Traversal::AnyAttribute, +                  Context +      { +        Any (Context& c) +            : Context (c), any_function_ (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name " << ename (a) << endl +               << " *" << endl +               << " * @brief Accessor and modifier functions for the " << +              "any wildcard." << endl; + +            if (a.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (a.annotation ()); +            } + +            os << " */" << endl +               << "//@{" << endl; +          } +          else +          { +            os << "// " << ename (a) << endl +               << "//" << endl; +          } + +          // Typedefs. +          // +          if (max (a) != 1) +          { +            String const& container (econtainer (a)); + +            // sequence +            // +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief DOM element sequence container type." << endl +                 << " */" << endl; +            } + +            os << "typedef ::xsd::cxx::tree::element_sequence " << +              container << ";"; + +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief DOM element iterator type." << endl +                 << " */" << endl; +            } + +            os << "typedef " << container << "::iterator " << +              eiterator (a) << ";"; + +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief DOM element constant iterator type." << endl +                 << " */" << endl; +            } + +            os << "typedef " << container << "::const_iterator " << +              econst_iterator (a) << ";" +               << endl; + +          } +          else if (min (a) == 0) +          { +            // optional +            // +            if (doxygen) +            { +              os << endl +                 << "/**" << endl +                 << " * @brief DOM element optional container type." << endl +                 << " */" << endl; +            } + +            os << "typedef ::xsd::cxx::tree::element_optional " << +              econtainer (a) << ";" +               << endl; +          } +          else +          { +            // one +            // +            if (doxygen) +              os << endl; +          } + +          // Wildcard id. +          // +          if (ordered_p (c)) +          { +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Wildcard id used for capturing content " << +                "order." << endl +                 << " */" << endl; + +            SemanticGraph::Context& ctx (a.context ()); + +            os << "static const ::std::size_t " << +              ctx.get<String> ("ordered-id-name") << " = " << +              ctx.get<size_t> ("ordered-id") << "UL;" << endl; +          } + +          any_function_.traverse (a); + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& container (econtainer (a)); + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name " << ename (a) << endl +               << " *" << endl +               << " * @brief Accessor and modifier functions for the " << +              "anyAttribute" << endl +               << " * wildcard." << endl; + +            if (a.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (a.annotation ()); +            } + +            os << " */" << endl +               << "//@{" << endl; +          } +          else +          { +            os << "// " << ename (a) << endl +               << "//" << endl; +          } + +          if (doxygen) +          { +            os << endl +               << "/**" << endl +               << " * @brief DOM attribute set container type." << endl +               << " */" << endl; +          } + +          os << "typedef ::xsd::cxx::tree::attribute_set< " << char_type << +            " > " << container << ";"; + +          if (doxygen) +          { +            os << endl +               << "/**" << endl +               << " * @brief DOM attribute iterator type." << endl +               << " */" << endl; +          } + +          os << "typedef " << container << "::iterator " << +            eiterator (a) << ";"; + +          if (doxygen) +          { +            os << endl +               << "/**" << endl +               << " * @brief DOM attribute constant iterator type." << endl +               << " */" << endl; +          } + +          os << "typedef " << container << "::const_iterator " << +            econst_iterator (a) << ";" +             << endl; + +          any_function_.traverse (a); + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } +        } + +      private: +        AnyFunction any_function_; +      }; + +      struct DataMember: Traversal::Member, Context +      { +        DataMember (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (skip (m)) return; + +          String const& member (emember (m)); + +          bool def_attr (m.default_p () && +                            m.is_a<SemanticGraph::Attribute> ()); + +          if (max (m) != 1) +          { +            // sequence +            // +            os << econtainer (m) << " " << member << ";"; +          } +          else if (min (m) == 0 && !def_attr) +          { +            // optional +            // +            os << econtainer (m) << " " << member << ";"; +          } +          else +          { +            // one +            // +            os << "::xsd::cxx::tree::one< " << etype (m) << " > " << +              member << ";"; +          } + +          // default_value +          // +          if (m.default_p ()) +          { +            bool simple (true); + +            if (m.is_a<SemanticGraph::Element> ()) +            { +              IsSimpleType test (simple); +              test.dispatch (m.type ()); +            } + +            if (simple) +            { +              bool lit (false); +              { +                IsLiteralValue test (lit); +                test.dispatch (m.type ()); +              } + +              if (!lit) +              { +                os << "static const " << etype (m) << " " << +                  edefault_value_member (m) << ";"; +              } +            } +          } +        } +      }; + +      struct DataAny: Traversal::Any, +                      Traversal::AnyAttribute, +                      Context +      { +        DataAny (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& member (emember (a)); + +          if (max (a) != 1) +          { +            // sequence +            // +            os << econtainer (a) << " " << member << ";"; +          } +          else if (min (a) == 0) +          { +            // optional +            // +            os << econtainer (a) << " " << member << ";"; +          } +          else +          { +            // one +            // +            os << "::xsd::cxx::tree::element_one " << member << ";"; +          } +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          os << econtainer (a) << " " << emember (a) << ";"; +        } +      }; + + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), +              base_name_ (c), +              member_name_ (c), +              any_ (c), +              member_ (c), +              data_any_ (c), +              data_member_ (c) +        { +          inherits_base_ >> base_name_; +          inherits_member_ >> member_name_; + +          names_ >> member_; +          if (options.generate_wildcard ()) +            names_ >> any_; + +          names_data_ >> data_member_; +          if (options.generate_wildcard ()) +            names_data_ >> data_any_; +        } + +        virtual void +        traverse (Type& c) +        { +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          bool renamed (renamed_type (c, name)); +          if (renamed && !name) +            return; + +          SemanticGraph::Context& ctx (c.context ()); + +          bool has_members (has<Traversal::Member> (c)); + +          bool hae (has<Traversal::Any> (c)); +          bool haa (has<Traversal::AnyAttribute> (c)); + +          bool gen_wildcard (options.generate_wildcard ()); + +          bool mixed (mixed_p (c) && !ctx.count ("mixed-in-base")); +          bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); + +          bool simple (true); +          { +            IsSimpleType t (simple); +            t.dispatch (c); +          } + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (c); +          } + +          SemanticGraph::Enumeration* enum_base (0); +          { +            IsEnumBasedType t (enum_base); +            t.dispatch (c); +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Class corresponding to the %" << +	       comment (c.name ()) << " schema type." << endl; + +            if (c.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (c.annotation ()); +            } + +            os << " *" << endl +               << " * @nosubgrouping" << endl +               << " */" << endl; +          } + +          os << "class " << type_exp << name << ": public "; + +          if (c.inherits_p ()) +            inherits (c, inherits_base_); +          else +            os << any_type; + +          os << "{" +             << "public:" << endl; + +          // Members. +          // +          names (c, names_); + +          // Mixed content. +          // +          if (mixed) +          { +            String const& type (ctx.get<String> ("mixed-type")); +            String const& cont (ctx.get<String> ("mixed-container")); +            String const& iter (ctx.get<String> ("mixed-iterator")); +            String const& citer (ctx.get<String> ("mixed-const-iterator")); + +            if (doxygen) +              os << "/**" << endl +                 << " * @name " << comment ("text_content") << endl +                 << " *" << endl +                 << " * @brief Accessor and modifier functions for text " << +                "content." << endl +                 << " */" << endl +                 << "//@{" << endl; +            else +              os << "// text_content" << endl +                 << "//" << endl; + +            // Typedefs. +            // +            bool isense (options.generate_intellisense ()); + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Text content type." << endl +                 << " */" << endl; + +            os << "typedef " << xs_string_type << " " << type << ";"; + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Text content sequence container type." << endl +                 << " */" << endl; + +            os << "typedef ::xsd::cxx::tree::sequence< " << type << +              " > " << cont << ";"; + + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Text content iterator type." << endl +                 << " */" << endl; + +            // IntelliSense does not like aliases and fully-qualified +            // names here. +            // +            if (!isense) +              os << "typedef " << cont << "::iterator " << iter<< ";"; +            else +              os << "typedef ::xsd::cxx::tree::sequence< " << type << +                " >::iterator " << iter << ";"; + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Text content constant iterator type." << endl +                 << " */" << endl; + +            if (!isense) +              os << "typedef " << cont << "::const_iterator " << citer<< ";"; +            else +              os << "typedef ::xsd::cxx::tree::sequence< " << type << +                " >::const_iterator " << citer << ";"; + +            os << endl; + +            // Content id. +            // +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Text content id used for capturing content " << +                "order." << endl +                 << " */" << endl; + +            os << "static const ::std::size_t " << +              ctx.get<String> ("mixed-ordered-id-name") << " = " << +              ctx.get<size_t> ("mixed-ordered-id") << "UL;" << endl; + +            // Accessors and modifiers. +            // +            String const& aname (ctx.get<String> ("mixed-aname")); +            String const& mname (ctx.get<String> ("mixed-mname")); + +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the text" << endl +                 << " * content sequence." << endl +                 << " *" << endl +                 << " * @return A constant reference to the sequence " << +                "container." << endl +                 << " */" << endl; + +            os << "const " << cont << "&" << endl +               << aname << " () const;" +               << endl; + +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Return a read-write reference to the " << +                "text content" << endl +                 << " * sequence." << endl +                 << " *" << endl +                 << " * @return A reference to the sequence container." << endl +                 << " */" << endl; + +            os << cont << "&" << endl +               << aname << " ();" +               << endl; + +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Copy elements from a given sequence." << endl +                 << " *" << endl +                 << " * @param s A sequence to copy entries from." << endl +                 << " *" << endl +                 << " * For each element in @a s this function " << +                "add it to the sequence." << endl +                 << " * Note that this operation " << +                "completely changes the sequence and" << endl +                 << " * all old elements will be lost." << endl +                 << " */" << endl; + +            os << "void" << endl +               << mname << " (const " << cont << "& s);" +               << endl; + +            if (doxygen) +              os << "//@}" << endl +                 << endl; +          } + +          // dom_document accessors. +          // +          if (edom_document_member_p (c)) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the DOM" << endl +                 << " * document associated with this instance." << endl +                 << " *" << endl +                 << " * @return A constant reference to the DOM document." << endl +                 << " *" << endl +                 << " * The DOM document returned by this function is " << +                "used to store" << endl +                 << " * the raw XML content corresponding to wildcards." << endl +                 << " */" << endl; +            } +            else +              os << "// DOMDocument for wildcard content." << endl +                 << "//" << endl; + +            os << "const " << xerces_ns << "::DOMDocument&" << endl +               << edom_document (c) << " () const;" +               << endl; + +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Return a read-write reference to the DOM " << +                "document" << endl +                 << " * associated with this instance." << endl +                 << " *" << endl +                 << " * @return A reference to the DOM document." << endl +                 << " *" << endl +                 << " * The DOM document returned by this function is " << +                "used to store" << endl +                 << " * the raw XML content corresponding to wildcards." << endl +                 << " */" << endl; +            } +            os << xerces_ns << "::DOMDocument&" << endl +               << edom_document (c) << " ();" +               << endl; +          } + +          // Order container. +          // +          if (ordered) +          { +            String const& type (ctx.get<String> ("order-type")); +            String const& cont (ctx.get<String> ("order-container")); +            String const& iter (ctx.get<String> ("order-iterator")); +            String const& citer (ctx.get<String> ("order-const-iterator")); + +            String const ct (options.order_container_specified () +                             ? options.order_container () +                             : "::std::vector"); + +            if (doxygen) +              os << "/**" << endl +                 << " * @name " << comment ("content_order") << endl +                 << " *" << endl +                 << " * @brief Accessor and modifier functions for content " << +                "order." << endl +                 << " */" << endl +                 << "//@{" << endl; +            else +              os << "// content_order" << endl +                 << "//" << endl; + +            // Typedefs. +            // +            bool isense (options.generate_intellisense ()); + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Content order entry type." << endl +                 << " */" << endl; + +            os << "typedef " << ns_name (xs_ns ()) << "::" << +              xs_ns ().context ().get<String> ("content-order") << " " << +              type << ";"; + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Content order sequence container type." << endl +                 << " */" << endl; + +            os << "typedef " << ct << "< " << type << " > " << cont << ";"; + + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Content order iterator type." << endl +                 << " */" << endl; + +            // IntelliSense does not like aliases and fully-qualified +            // names here. +            // +            if (!isense) +              os << "typedef " << cont << "::iterator " << iter<< ";"; +            else +              os << "typedef " << ct << "< " << type << " >::iterator " << +                iter << ";"; + +            if (doxygen) +              os << endl +                 << "/**" << endl +                 << " * @brief Content order constant iterator type." << endl +                 << " */" << endl; + +            if (!isense) +              os << "typedef " << cont << "::const_iterator " << citer<< ";"; +            else +              os << "typedef " <<  ct << "< " << type << +                " >::const_iterator " << citer << ";"; + +            os << endl; + +            // Accessors and modifiers. +            // +            String const& aname (ctx.get<String> ("order-aname")); +            String const& mname (ctx.get<String> ("order-mname")); + +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Return a read-only (constant) reference " << +                "to the content" << endl +                 << " * order sequence." << endl +                 << " *" << endl +                 << " * @return A constant reference to the sequence " << +                "container." << endl +                 << " */" << endl; + +            os << "const " << cont << "&" << endl +               << aname << " () const;" +               << endl; + +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Return a read-write reference to the " << +                "content order" << endl +                 << " * sequence." << endl +                 << " *" << endl +                 << " * @return A reference to the sequence container." << endl +                 << " */" << endl; + +            os << cont << "&" << endl +               << aname << " ();" +               << endl; + +            if (doxygen) +              os << "/**" << endl +                 << " * @brief Copy elements from a given sequence." << endl +                 << " *" << endl +                 << " * @param s A sequence to copy entries from." << endl +                 << " *" << endl +                 << " * For each element in @a s this function " << +                "add it to the sequence." << endl +                 << " * Note that this operation " << +                "completely changes the sequence and" << endl +                 << " * all old elements will be lost." << endl +                 << " */" << endl; + +            os << "void" << endl +               << mname << " (const " << cont << "& s);" +               << endl; + +            if (doxygen) +              os << "//@}" << endl +                 << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name Constructors" << endl +               << " */" << endl +               << "//@{" << endl +               << endl; +          } +          else +          { +            os << "// Constructors." << endl +               << "//" << endl; +          } + +          bool generate_no_base_ctor (false); +          { +            GenerateWithoutBaseCtor t (generate_no_base_ctor); +            t.traverse (c); +          } + +          bool has_complex_non_op_args (false); +          bool has_poly_non_op_args (false); +          bool complex_poly_args_clash (true); +          { +            HasComplexPolyNonOptArgs t (*this, true, +                                        has_complex_non_op_args, +                                        has_poly_non_op_args, +                                        complex_poly_args_clash); +            t.traverse (c); +          } + +          // default c-tor +          // +          if (options.generate_default_ctor ()) +          { +            // c-tor (ultimate-base, all-non-optional-members) will become +            // default c-tor if our inheritance hierarchy has no required +            // members and no simple base. We can also collide with +            // c-tor (all-non-optional-members) if we have no required +            // members. +            // +            bool generate (false); +            { +              GenerateDefaultCtor t (*this, generate, generate_no_base_ctor); +              t.traverse (c); +            } + +            if (generate) +            { +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Default constructor." << endl +                   << " *" << endl +                   << " * Note that this constructor leaves required " << +                  "elements and" << endl +                   << " * attributes uninitialized." << endl +                   << " */" << endl; +              } + +              os << name << " ();" +                 << endl; +            } +          } + +          // c-tor (base, all-non-optional-members) +          // +          if (options.generate_from_base_ctor ()) +          { +            // c-tor (base, all-non-optional-members) will be equivalent to +            // c-tor (ultimate-base, all-non-optional-members) unless our +            // immediate base's hierarchy has some non-optional members. +            // We also need to generate this c-tor when one of the types +            // in our inheritance hierarchy was customized since the +            // customized version may not necessarily be convertible to +            // the base without loss of information. +            // +            bool generate (false); +            { +              GenerateFromBaseCtor t (*this, generate); +              t.traverse (c); +            } + +            if (generate) +            { +              bool has_complex_non_op_args (false); +              bool has_poly_non_op_args (false); +              bool complex_poly_args_clash (true); +              { +                HasComplexPolyNonOptArgs t (*this, false, +                                            has_complex_non_op_args, +                                            has_poly_non_op_args, +                                            complex_poly_args_clash); +                t.traverse (c); +              } + +              // +              // +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Create an instance from the immediate " +                  "base and" << endl +                   << " * initializers for required elements and " +                   << "attributes." << endl +                   << " */" << endl; +              } + +              os << name << " (const "; +              inherits (c, inherits_member_); +              os << "&"; +              { +                FromBaseCtorArg args (*this, CtorArgType::type, false); +                Traversal::Names args_names (args); +                names (c, args_names); +              } +              os << ");" +                 << endl; + +              // If we have any complex arguments in the previous c-tor +              // then also generate the auto_ptr version. +              // +              if (has_complex_non_op_args) +              { +                if (doxygen) +                { +                  os << "/**" << endl +                     << " * @brief Create an instance from the immediate " +                    "base and" << endl +                     << " * initializers for required elements and " +                     << "attributes" << endl +                     << " * (" << auto_ptr << " version)." << endl +                     << " *" << endl +                     << " * This constructor will try to use the passed " << +                    "values directly" << endl +                     << " * instead of making copies." << endl +                     << " */" << endl; +                } + +                os << name << " (const "; +                inherits (c, inherits_member_); +                os << "&"; +                { +                  FromBaseCtorArg args ( +                    *this, CtorArgType::complex_auto_ptr, false); +                  Traversal::Names args_names (args); +                  names (c, args_names); +                } +                os << ");" +                   << endl; +              } + +              // If we are generating polymorphic code then we also need to +              // provide auto_ptr version for every polymorphic type. +              // +              if (polymorphic && +                  has_poly_non_op_args && !complex_poly_args_clash) +              { +                if (doxygen) +                { +                  os << "/**" << endl +                     << " * @brief Create an instance from the immediate " +                    "base and" << endl +                     << " * initializers for required elements and " +                     << "attributes" << endl +                     << " * (" << auto_ptr << " version)." << endl +                     << " *" << endl +                     << " * This constructor will try to use the passed " << +                    "values directly" << endl +                     << " * instead of making copies." << endl +                     << " */" << endl; +                } + +                os << name << " (const "; +                inherits (c, inherits_member_); +                os << "&"; +                { +                  FromBaseCtorArg args ( +                    *this, CtorArgType::poly_auto_ptr, false); +                  Traversal::Names args_names (args); +                  names (c, args_names); +                } +                os << ");" +                   << endl; +              } +            } +          } + +          // c-tor (all-non-optional-members) +          // +          if (generate_no_base_ctor) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from initializers " << +                "for required " << endl +                 << " * elements and attributes." << endl +                 << " */" << endl; +            } + +            os << name << " ("; +            { +              CtorArgsWithoutBase ctor_args ( +                *this, CtorArgType::type, false, true); +              ctor_args.dispatch (c); +            } +            os << ");" +               << endl; + + +            // If we have any complex arguments in the previous c-tor +            // then also generate the auto_ptr version. One case where +            // this c-tor will be generated is restriction of anyType. +            // +            if (has_complex_non_op_args) +            { +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Create an instance from initializers " << +                  "for required " << endl +                   << " * elements and attributes (" << auto_ptr << +                  " version)." << endl +                   << " *" << endl +                   << " * This constructor will try to use the passed " << +                  "values directly" << endl +                   << " * instead of making copies." << endl +                   << " */" << endl; +              } + +              os << name << " ("; +              { +                CtorArgsWithoutBase ctor_args ( +                  *this, CtorArgType::complex_auto_ptr, false, true); +                ctor_args.dispatch (c); +              } +              os << ");" +                 << endl; +            } + +            // If we are generating polymorphic code then we also need to +            // provide auto_ptr version for every polymorphic type. +            // +            if (polymorphic && +                has_poly_non_op_args && !complex_poly_args_clash) +            { +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Create an instance from initializers " << +                  "for required " << endl +                   << " * elements and attributes (" << auto_ptr << +                  " version)." << endl +                   << " *" << endl +                   << " * This constructor will try to use the passed " << +                  "values directly" << endl +                   << " * instead of making copies." << endl +                   << " */" << endl; +              } + +              os << name << " ("; +              { +                CtorArgsWithoutBase ctor_args ( +                  *this, CtorArgType::poly_auto_ptr, false, true); +                ctor_args.dispatch (c); +              } +              os << ");" +                 << endl; +            } +          } + +          if (string_based) +          { +            // We might not have the value type if this enum is customized. +            // +            if (enum_base != 0 && enum_base->context ().count ("value")) +            { +              // c-tor (enum-value, all-non-optional-members) +              // +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Create an instance from the " << +                  "underlying enum value" << endl +                   << " * and initializers for required elements and " << +                  "attributes." << endl +                   << " */" << endl; +              } + +              os << name << " (" << fq_name (*enum_base) << "::" << +                evalue (*enum_base); + +              { +                CtorArgsWithoutBase ctor_args ( +                  *this, CtorArgType::type, false, false); +                ctor_args.dispatch (c); +              } + +              os << ");" +                 << endl; +            } + +            // c-tor (const char*, all-non-optional-members) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a C string and " << +                "initializers" << endl +                 << " * for required elements and attributes." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << char_type << "*"; + +            { +              CtorArgsWithoutBase ctor_args ( +                *this, CtorArgType::type, false, false); +              ctor_args.dispatch (c); +            } + +            os << ");" +               << endl; + +            // c-tor (const std::string&, all-non-optional-members) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a string and" << +                "initializers" << endl +                 << " * for required elements and attributes." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << string_type << "&"; + +            { +              CtorArgsWithoutBase ctor_args ( +                *this, CtorArgType::type, false, false); +              ctor_args.dispatch (c); +            } + +            os << ");" +               << endl; +          } + +          // c-tor (ultimate-base, all-non-optional-members) +          // + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Create an instance from the ultimate " +              "base and" << endl +               << " * initializers for required elements and " << +              "attributes." << endl +               << " */" << endl; +          } + +          os << name << " ("; + +          { +            CtorArgs ctor_args (*this, CtorArgType::type); +            ctor_args.dispatch (c); +          } + +          os << ");" +             << endl; + +          // If we have any complex arguments in the previous c-tor +          // then also generate the auto_ptr version. +          // +          if (has_complex_non_op_args) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from the ultimate " +                "base and" << endl +                 << " * initializers for required elements and " << +                "attributes" << endl +                 << " * (" << auto_ptr << " version)." << endl +                 << " *" << endl +                 << " * This constructor will try to use the passed " << +                "values directly" << endl +                 << " * instead of making copies." << endl +                 << " */" << endl; +            } + +            os << name << " ("; + +            { +              CtorArgs ctor_args (*this, CtorArgType::complex_auto_ptr); +              ctor_args.dispatch (c); +            } + +            os << ");" +               << endl; +          } + +          // If we are generating polymorphic code then we also need to +          // provide auto_ptr version for every polymorphic type. +          // +          if (polymorphic && has_poly_non_op_args && !complex_poly_args_clash) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from the ultimate " +                "base and" << endl +                 << " * initializers for required elements and " << +                "attributes" << endl +                 << " * (" << auto_ptr << " version)." << endl +                 << " *" << endl +                 << " * This constructor will try to use the passed " << +                "values directly" << endl +                 << " * instead of making copies." << endl +                 << " */" << endl; +            } + +            os << name << " ("; + +            { +              CtorArgs ctor_args (*this, CtorArgType::poly_auto_ptr); +              ctor_args.dispatch (c); +            } + +            os << ");" +               << endl; +          } + +          // c-tor (istream&) +          // +          NarrowStrings const& st (options.generate_extraction ()); +          for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +               ++i) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a data " << +                "representation" << endl +                 << " * stream." << endl +                 << " *" << endl +                 << " * @param s A stream to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (" << istream_type << "< " << i->c_str () << +              " >& s," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; +          } + + +          if (!options.suppress_parsing ()) +          { +            // c-tor (xercesc::DOMElement) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a DOM element." << endl +                 << " *" << endl +                 << " * @param e A DOM element to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " * @param c A pointer to the object that will " << +                "contain the new" << endl +                 << " * instance." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << xerces_ns << "::DOMElement& e," << endl +               << flags_type << " f = 0," << endl +               << container << "* c = 0);" +               << endl; + + +            if (simple) +            { +              // c-tor (xercesc::DOMAttr) +              // +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Create an instance from a DOM attribute." << endl +                   << " *" << endl +                   << " * @param a A DOM attribute to extract the data from." << endl +                   << " * @param f Flags to create the new instance with." << endl +                   << " * @param c A pointer to the object that will " << +                  "contain the new" << endl +                   << " * instance." << endl +                   << " */" << endl; +              } + +              os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl +                 << flags_type << " f = 0," << endl +                 << container << "* c = 0);" +                 << endl; + +              // c-tor (std::basic_string const&, xercesc::DOMElement) +              // +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Create an instance from a string fragment." << endl +                   << " *" << endl +                   << " * @param s A string fragment to extract the data from." << endl +                   << " * @param e A pointer to DOM element containing the " << +                  "string fragment." << endl +                   << " * @param f Flags to create the new instance with." << endl +                   << " * @param c A pointer to the object that will " << +                  "contain the new" << endl +                   << " * instance." << endl +                   << " */" << endl; +              } + +              os << name << " (const " << string_type << "& s," << endl +                 << "const " << xerces_ns << "::DOMElement* e," << endl +                 << flags_type << " f = 0," << endl +                 << container << "* c = 0);" +                 << endl; +            } +          } + +          // copy c-tor +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy constructor." << endl +               << " *" << endl +               << " * @param x An instance to make a copy of." << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @param c A pointer to the object that will contain " << +              "the copy." << endl +               << " *" << endl +               << " * For polymorphic object models use the @c _clone " << +              "function instead." << endl +               << " */" << endl; +          } + +          os << name << " (const " << name << "& x," << endl +             << flags_type << " f = 0," << endl +             << container << "* c = 0);" +             << endl; + +          // clone +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy the instance polymorphically." << endl +               << " *" << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @param c A pointer to the object that will contain " << +              "the copy." << endl +               << " * @return A pointer to the dynamically allocated copy." << endl +               << " *" << endl +               << " * This function ensures that the dynamic type of the " << +              "instance is" << endl +               << " * used for copying and should be used for polymorphic " << +              "object" << endl +               << " * models instead of the copy constructor." << endl +               << " */" << endl; +          } + +          os << "virtual " << name << "*" << endl +             << "_clone (" << flags_type << " f = 0," << endl +             << container << "* c = 0) const"; + +          // Make the _clone() function pure virtual if the type is +          // abstract or we are generating a polymorphic base for a +          // custom implementation (in which case the base must be +          // inherited from and _clone() overridden). +          // +          if (c.abstract_p () || +              (renamed && polymorphic && polymorphic_p (c))) +            os << " = 0"; + +          os << ";" +             << endl; + +          // operator= +          // +          bool priv (false); +          bool asop (true); + +          if (!simple) +          { +            if (options.suppress_assignment ()) +            { +              asop = false; + +              priv = true; +              os << "private:" << endl; + +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Disabled copy assignment operator." << endl +                   << " *" << endl +                   << " * @param x An instance to make a copy of." << endl +                   << " * @return A reference to itself." << endl +                   << " */" << endl; +              } + +              os << name << "&" << endl +                 << "operator= (const " << name << "& x);" +                 << endl; +            } +            else if (has_members || (gen_wildcard && (hae || haa))) +            { +              asop = false; + +              if (doxygen) +              { +                os << "/**" << endl +                   << " * @brief Copy assignment operator." << endl +                   << " *" << endl +                   << " * @param x An instance to make a copy of." << endl +                   << " * @return A reference to itself." << endl +                   << " *" << endl +                   << " * For polymorphic object models use the @c _clone " << +                  "function instead." << endl +                   << " */" << endl; +              } + +              os << name << "&" << endl +                 << "operator= (const " << name << "& x);" +                 << endl; +            } +          } + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } + +          if (priv) +            os << "public:" << endl; + +          if (asop) +          { +            os << "#ifdef XSD_CXX11" << endl +               << name << "&" << endl +               << "operator= (const " << name << "&) = default;" +               << "#endif" << endl +               << endl; +          } + +          // d-tor +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Destructor." << endl +               << " */" << endl; +          } + +          os << "virtual " << endl +             << "~" << name << " ();" +             << endl; + +          // Data members and implementation functions. +          // +          if (has_members || hae || (haa && gen_wildcard) || ordered || mixed) +          { +            os << "// Implementation." << endl +               << "//" << endl; + +            if (doxygen) +              os << endl +                 << "//@cond" << endl +                 << endl; + +            if (!options.suppress_parsing () && +                (has_members || hae || (haa && gen_wildcard) || mixed)) +            { +              // parse () +              // +              os << "protected:" << endl +                 << "void" << endl +                 << unclash (name, "parse") << " (" << +                parser_type << "&," << endl +                 << flags_type << ");" +                 << endl; +            } + +            os << "protected:" +               << endl; + +            // parse (istream) +            // +            if (has_members) +            { +              for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); +                   ++i) +              { +                os << "void" << endl +                   << unclash (name, "parse") << " (" << +                  istream_type << "< " << i->c_str () << " >&," << endl +                   << flags_type << ");" +                   << endl; +              } +            } + +            // DOM document. +            // +            if (edom_document_member_p (c)) +            { +              os << dom_auto_ptr << "< " << xerces_ns << +                "::DOMDocument > " << edom_document_member (c) << ";" +                 << endl; +            } + +            // Mixed text content. +            // +            if (mixed) +            { +              os << ctx.get<String> ("mixed-container") << " " << +                ctx.get<String> ("mixed-member") << ";" +                 << endl; +            } + +            // Order container. +            // +            if (ordered) +            { +              os << ctx.get<String> ("order-container") << " " << +                ctx.get<String> ("order-member") << ";" +                 << endl; +            } + +            // +            // +            names (c, names_data_); + +            if (doxygen) +              os << endl +                 << "//@endcond" << endl; +          } + +          os << "};"; + +          // Comparison operators. +          // +          if (options.generate_comparison () && +              (has_members || !c.inherits_p () || +               ((hae || haa) && gen_wildcard))) +          { +            os << inst_exp +               << "bool" << endl +               << "operator== (const " << name << "&, const " << name << "&);" +               << endl; + +            os << inst_exp +               << "bool" << endl +               << "operator!= (const " << name << "&, const " << name << "&);" +               << endl +               << endl; +          } +        } + +      private: +        Traversal::Inherits inherits_base_; +        BaseTypeName base_name_; + +        Traversal::Inherits inherits_member_; +        MemberTypeName member_name_; + +        Traversal::Names names_; +        Any any_; +        Member member_; + +        Traversal::Names names_data_; +        DataAny data_any_; +        DataMember data_member_; +      }; + + +      struct GlobalElement: Traversal::Element, +                            GlobalElementBase, +                            Context +      { +        GlobalElement (Context& c) +            : GlobalElementBase (c), Context (c), type_name_ (c) +        { +          belongs_ >> type_name_; +        } + +        virtual void +        traverse (Type& e) +        { +          if (!doc_root_p (e)) +            return; + +          SemanticGraph::Type& t (e.type ()); + +          bool fund (false); +          { +            IsFundamentalType test (fund); +            test.dispatch (t); +          } + +          bool simple (true); +          if (!fund) +          { +            IsSimpleType test (simple); +            test.dispatch (t); +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Class corresponding to the %" << +              comment (e.name ()) << " root element." << endl; + +            if (e.annotated_p ()) +            { +              os << " *" << endl; +              write_annotation (e.annotation ()); +            } + +            os << " *" << endl +               << " * @nosubgrouping" << endl +               << " */" << endl; +          } + +          String const& name (ename (e)); + +          os << "class " << type_exp << name << ": public " << element_type +             << "{" +             << "public:" << endl +             << endl; + +          String const& type (etype (e)); + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name Element value" << endl +               << " *" << endl +               << " * @brief Accessor and modifier functions for the " << +              "element value." << endl +               << " */" << endl +               << "//@{" << endl +               << endl; +          } +          else +          { +            os << "// Element value." << endl +               << "//" << endl; +          } + +          // Typedefs. +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Element value type." << endl +               << " */" << endl; +          } + +          os << "typedef "; + +          belongs (e, belongs_); + +          os << " " << type << ";"; + +          if (doxygen) +          { +            os << endl +               << "/**" << endl +               << " * @brief Element value traits type." << endl +               << " */" << endl; +          } + +          os << "typedef ::xsd::cxx::tree::traits< " << type << ", " << +            char_type; + +          if (t.is_a<SemanticGraph::Fundamental::Double> ()) +            os << ", ::xsd::cxx::tree::schema_type::double_"; +          else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) +            os << ", ::xsd::cxx::tree::schema_type::decimal"; + +          os << " > " << etraits (e) << ";" +             << endl; + +          // Accessors/modifiers. +          // +          String const& aname (eaname (e)); +          String const& mname (emname (e)); + +          // type const& +          // name () const; +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return a read-only (constant) reference " << +              "to the element" << endl +               << " * value." << endl +               << " *" << endl +               << " * @return A constant reference to the element value." << +              endl +               << " */" << endl; +          } + +          os << "const " << type << "&" << endl +             << aname << " () const;" +             << endl; + +          // type& +          // name (); +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return a read-write reference to the " << +              "element value." << endl +               << " *" << endl +               << " * @return A reference to the element value." << endl +               << " */" << endl; +          } + +          os << type << "&" << endl +             << aname << " ();" +             << endl; + +          // void +          // name (type const&); +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Set the element value." << endl +               << " *" << endl +               << " * @param x A new value to set." << endl +               << " *" << endl +               << " * This function makes a copy of its argument " << +              "and sets it as" << endl +               << " * the new value of the element." << endl +               << " */" << endl; +          } + +          os << "void" << endl +             << mname << " (const " << type << "& x);" +             << endl; + +          // void +          // name (auto_ptr<type>); +          // +          if (!fund) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Set the element value without " << +                "copying." << endl +                 << " *" << endl +                 << " * @param p A new value to use." << endl +                 << " *" << endl +                 << " * This function will try to use the passed value " << +                "directly" << endl +                 << " * instead of making a copy." << endl +                 << " */" << endl; +            } + +            os << "void" << endl +               << mname << " (" << auto_ptr << "< " << type << " > p);" +               << endl; +          } + +          // auto_ptr<type> +          // detach_name (); +          // +          if (detach && !fund) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Detach the element value from " << +                "the object." << endl +                 << " *" << endl +                 << " * @return A pointer to the element value." << endl +                 << " *" << endl +                 << " * Note that this function leaves the element " << +                "object uninitialized." << endl +                 << " */" << endl; +            } + +            os << auto_ptr << "< " << type << " >" << endl +               << edname (e) << " ();" +               << endl; +          } + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return a read-only (constant) pointer " << +              "to the element" << endl +               << " * value." << endl +               << " *" << endl +               << " * @return A constant pointer to the element value " << +              "or 0 if this" << endl +               << " * element is of a fundamental type." << endl +               << " */" << endl; +          } + +          os << "virtual const " << any_type << "*" << endl +             << "_value () const;" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return a pointer to the element value." << endl +               << " *" << endl +               << " * @return A pointer to the element value or 0 if this " << +              "element is" << endl +               << " * of a fundamental type." << endl +               << " */" << endl; +          } +          os << "virtual " << any_type << "*" << endl +             << "_value ();" +             << endl; + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } + +          // Constructor. +          // + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name Constructors" << endl +               << " */" << endl +               << "//@{" << endl +               << endl; +          } +          else +          { +            os << "// Constructors." << endl +               << "//" << endl; +          } + +          // default c-tor +          // +          if (options.generate_default_ctor ()) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Default constructor." << endl +                 << " *" << endl +                 << " * Note that this constructor leaves the element " << +                "value" << endl +                 << " * uninitialized." << endl +                 << " */" << endl; +            } + +            os << name << " ();" +               << endl; +          } + +          // c-tor (value) +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Create an instance from an initializer " << +              "for the element" << endl +               << " * value." << endl +               << " *" << endl +               << " * @param x Element value." << endl +               << " */" << endl; +          } + +          os << name << " (const " << type << "& x);" +             << endl; + + +          // If the element value is a complex type (has elements, +          // attributes, or wildcards) then also generate the auto_ptr +          // version. If we are generating polymorphic code then we +          // also need to provide auto_ptr version for simple types. +          // +          if (!simple || (polymorphic && polymorphic_p (t))) +          { +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from an initializer " << +                "for" << endl +                 << " * the element value (" << auto_ptr << +                " version)." << endl +                 << " *" << endl +                 << " * @param p Element value to use." << endl +                 << " *" << endl +                 << " * This constructor will try to use the passed " << +                "value directly" << endl +                 << " * instead of making a copy." << endl +                 << " */" << endl; +            } + +            os << name << " (" << auto_ptr << "< " << type << " > p);" +               << endl; +          } + +          if (!options.suppress_parsing ()) +          { +            // c-tor (xercesc::DOMElement) +            // +            if (doxygen) +            { +              os << "/**" << endl +                 << " * @brief Create an instance from a DOM element." << endl +                 << " *" << endl +                 << " * @param e A DOM element to extract the data from." << endl +                 << " * @param f Flags to create the new instance with." << endl +                 << " */" << endl; +            } + +            os << name << " (const " << xerces_ns << "::DOMElement& e, " << +              flags_type << " f = 0);" +               << endl; +          } + +          // copy c-tor +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy constructor." << endl +               << " *" << endl +               << " * @param x An instance to make a copy of." << endl +               << " * @param f Flags to create the copy with." << endl +               << " *" << endl +               << " * For polymorphic object models use the @c _clone " << +              "function instead." << endl +               << " */" << endl; +          } + +          os << name << " (const " << name << "& x, " << +            flags_type << " f = 0);" +             << endl; + +          os << "#ifdef XSD_CXX11" << endl +             << name << "&" << endl +             << "operator= (const " << name << "&) = default;" +             << "#endif" << endl +             << endl; + +          // _clone +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Copy the instance polymorphically." << endl +               << " *" << endl +               << " * @param f Flags to create the copy with." << endl +               << " * @return A pointer to the dynamically allocated copy." << endl +               << " *" << endl +               << " * This function ensures that the dynamic type of the " << +              "instance is" << endl +               << " * used for copying and should be used for polymorphic " << +              "object" << endl +               << " * models instead of the copy constructor." << endl +               << " */" << endl; +          } + +          os << "virtual " << name << "*" << endl +             << "_clone (" << flags_type << " f = 0) const;" +             << endl; + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } + +          // Element name and namespace accessors. +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @name Element name and namespace" << endl +               << " *" << endl +               << " * @brief Accessor functions for the element name " << +              "and namespace." << endl +               << " */" << endl +               << "//@{" << endl +               << endl; +          } +          else +          { +            os << "// Element name and namespace." << endl +               << "//" << endl; +          } + +          SemanticGraph::Context& ec (e.context ()); + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return the element name (static function)." << endl +               << " *" << endl +               << " * @return A read-only string reference containing " << +              "the element" << endl +               << " * name." << endl +               << " */" << endl; +          } +          os << "static const " << string_type << "&" << endl +             << ec.get<String> ("element-name") << " ();" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return the element namespace (static " << +              "function)." << endl +               << " *" << endl +               << " * @return A read-only string reference containing " << +              "the element" << endl +               << " * namespace." << endl +               << " */" << endl; +          } +          os << "static const " << string_type << "&" << endl +             << ec.get<String> ("element-ns") << " ();" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return the element name." << endl +               << " *" << endl +               << " * @return A read-only string reference containing " << +              "the element" << endl +               << " * name." << endl +               << " */" << endl; +          } +          os << "virtual const " << string_type << "&" << endl +             << "_name () const;" +             << endl; + +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Return the element namespace." << endl +               << " *" << endl +               << " * @return A read-only string reference containing " << +              "the element" << endl +               << " * namespace." << endl +               << " */" << endl; +          } +          os << "virtual const " << string_type << "&" << endl +             << "_namespace () const;" +             << endl; + +          if (doxygen) +          { +            os << "//@}" << endl +               << endl; +          } + +          // d-tor +          // +          if (doxygen) +          { +            os << "/**" << endl +               << " * @brief Destructor." << endl +               << " */" << endl; +          } + +          os << "virtual " << endl +             << "~" << name << " ();" +             << endl; + +          // Data member. +          // + +          if (doxygen) +            os << "//@cond" << endl +               << endl; + +          os << "protected:" << endl +             << "::xsd::cxx::tree::one< " << type << " > " << +            emember (e) << ";" +             << "static const " << string_type << " " << +            ec.get<String> ("element-name-member") << ";" +             << "static const " << string_type << " " << +            ec.get<String> ("element-ns-member") << ";"; + +          if (doxygen) +            os << endl +               << "//@endcond" << endl; + +          os << "};"; +        } + +      private: +        Traversal::Belongs belongs_; +        MemberTypeName type_name_; +      }; +    } + +    void +    generate_tree_header (Context& ctx) +    { +      if (ctx.generate_xml_schema) +      { +        if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") +        { +          ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << +            ".hxx>" << endl +                 << endl; +        } + +        ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl +               << "#include <xsd/cxx/tree/elements.hxx>" << endl +               << "#include <xsd/cxx/tree/types.hxx>" << endl +               << endl; + +        if (!ctx.options.suppress_parsing () || +            ctx.options.generate_serialization ()) +        { +          ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl +                 << endl; +        } + +        if (!ctx.options.suppress_parsing () || +            ctx.options.generate_serialization ()) +        { +          ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl +                 << endl; +        } + +        bool element_map (ctx.options.generate_element_map ()); + +        if (element_map) +          ctx.os << "#include <xsd/cxx/tree/element-map.hxx>" << endl +                 << endl; + +        // I need to include all the "optional" headers here (instead of +        // later in the individual generators for each feature because +        // those headers provide implementation for the fundamental types. +        // +        if (!ctx.options.suppress_parsing ()) +        { +          ctx.os << "#include <xsd/cxx/tree/parsing.hxx>" << endl; + +          Traversal::Schema schema; +          Traversal::Names names; +          Traversal::Namespace ns; +          Traversal::Names ns_names; +          FundIncludes type (ctx, "parsing"); + +          schema >> names >> ns >> ns_names >> type; + +          schema.dispatch (ctx.schema_root); + +          if (element_map) +            ctx.os << "#include <xsd/cxx/tree/parsing/element-map.txx>" << +              endl; + +          ctx.os << endl; +        } + +        if (ctx.options.generate_serialization ()) +        { +          ctx.os << "#include <xsd/cxx/xml/dom/serialization-header.hxx>" << endl +                 << "#include <xsd/cxx/tree/serialization.hxx>" << endl; + +          Traversal::Schema schema; +          Traversal::Names names; +          Traversal::Namespace ns; +          Traversal::Names ns_names; +          FundIncludes type (ctx, "serialization"); + +          schema >> names >> ns >> ns_names >> type; + +          schema.dispatch (ctx.schema_root); + +          if (element_map) +            ctx.os << "#include <xsd/cxx/tree/serialization/element-map.txx>" << +              endl; + +          ctx.os << endl; +        } + +        if (ctx.options.generate_ostream ()) +        { +          ctx.os << "#include <xsd/cxx/tree/std-ostream-operators.hxx>" << endl +                 << endl; +        } + +        NarrowStrings const& ist (ctx.options.generate_insertion ()); +        if (!ist.empty ()) +        { +          for (NarrowStrings::const_iterator i (ist.begin ()); i != ist.end (); +               ++i) +          { +            if (*i == "ACE_OutputCDR") +              ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-insertion.hxx>" +                     << endl; +            else if (*i == "XDR") +              ctx.os << "#include <xsd/cxx/tree/xdr-stream-insertion.hxx>" +                     << endl; +          } + +          ctx.os << "#include <xsd/cxx/tree/stream-insertion.hxx>" << endl +                 << endl; +        } + +        NarrowStrings const& est (ctx.options.generate_extraction ()); +        if (!est.empty ()) +        { +          for (NarrowStrings::const_iterator i (est.begin ()); i != est.end (); +               ++i) +          { +            if (*i == "ACE_InputCDR") +              ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-extraction.hxx>" +                     << endl; +            else if (*i == "XDR") +              ctx.os << "#include <xsd/cxx/tree/xdr-stream-extraction.hxx>" +                     << endl; +          } + +          ctx.os << "#include <xsd/cxx/tree/stream-extraction.hxx>" << endl +                 << endl; +        } + +        // Emit fundamental types. +        // +        { +          Traversal::Schema schema; +          Traversal::Names names; +          FundamentalNamespace ns (ctx); + +          schema >> names >> ns; + +          schema.dispatch (ctx.schema_root); +        } +      } +      else +      { +        bool inline_ (ctx.options.generate_inline ()); + +        ctx.os << "#include <memory>    // " << ctx.auto_ptr << endl +               << "#include <limits>    // std::numeric_limits" << endl +               << "#include <algorithm> // std::binary_search" << endl; + +        if (ctx.std >= cxx_version::cxx11) +          ctx.os << "#include <utility>   // std::move" << endl; + +        if (!ctx.options.ordered_type ().empty () || +            ctx.options.ordered_type_all ()) +        { +          ctx.os << "#include <cstddef>   // std::size_t" << endl; + +          if (!ctx.options.order_container_specified ()) +            ctx.os << "#include <vector>" << endl; +        } + +        ctx.os << endl; + +        if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") +        { +          ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << +            ".hxx>" << endl +                 << endl; +        } + +        ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl +               << "#include <xsd/cxx/tree/elements.hxx>" << endl +               << "#include <xsd/cxx/tree/containers.hxx>" << endl +               << "#include <xsd/cxx/tree/list.hxx>" << endl +               << endl; + +        if (!ctx.options.suppress_parsing ()) +        { +          ctx.os << "#include <xsd/cxx/xml/dom/parsing-header.hxx>" << endl +                 << endl; +        } + +        if (ctx.options.generate_wildcard ()) +        { +          if (ctx.options.suppress_parsing () || +              !ctx.options.generate_serialization ()) +            ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl; + +          ctx.os << "#include <xsd/cxx/tree/containers-wildcard.hxx>" << endl +                 << endl; +        } + +        if (!ctx.options.generate_extraction ().empty ()) +          ctx.os << "#include <xsd/cxx/tree/istream-fwd.hxx>" << endl +                 << endl; + +        // Emit header includes. +        // +        { +          if (inline_) +          { +            ctx.os << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl +                   << "#define XSD_DONT_INCLUDE_INLINE" << endl +                   << endl; +          } + +          Traversal::Schema schema; +          Includes includes (ctx, Includes::header); + +          schema >> includes; + +          schema.dispatch (ctx.schema_root); + +          if (inline_) +          { +            ctx.os << "#undef XSD_DONT_INCLUDE_INLINE" << endl +                   << "#else" << endl +                   << endl; + +            schema.dispatch (ctx.schema_root); + +            ctx.os << "#endif // XSD_DONT_INCLUDE_INLINE" << endl +                   << endl; +          } +        } + + +        { +          Traversal::Schema schema; + +          Sources sources; +          Traversal::Names names_ns, names; + +          DocumentedNamespace ns (ctx); + +          List list (ctx); +          Union union_ (ctx); +          Complex complex (ctx); +          Enumeration enumeration (ctx); +          GlobalElement element (ctx); + +          schema >> sources >> schema; +          schema >> names_ns >> ns >> names; + +          names >> list; +          names >> union_; +          names >> complex; +          names >> enumeration; + +          if (ctx.options.generate_element_type ()) +            names >> element; + +          schema.dispatch (ctx.schema_root); +        } + +        // Emit inline includes. +        // +        if (inline_) +        { +          ctx.os << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl +                 << endl; + +          Traversal::Schema schema; +          Includes ixx_includes (ctx, Includes::inline_); +          schema >> ixx_includes; + +          schema.dispatch (ctx.schema_root); + +          ctx.os << "#endif // XSD_DONT_INCLUDE_INLINE" << endl +                 << endl; +        } +      } +    } +  } +} diff --git a/xsd/cxx/tree/tree-header.hxx b/xsd/cxx/tree/tree-header.hxx new file mode 100644 index 0000000..d0e9ea6 --- /dev/null +++ b/xsd/cxx/tree/tree-header.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/tree-header.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_TREE_HEADER_HXX +#define XSD_CXX_TREE_TREE_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_tree_header (Context&); +  } +} + +#endif  // XSD_CXX_TREE_TREE_HEADER_HXX diff --git a/xsd/cxx/tree/tree-inline.cxx b/xsd/cxx/tree/tree-inline.cxx new file mode 100644 index 0000000..aa8b726 --- /dev/null +++ b/xsd/cxx/tree/tree-inline.cxx @@ -0,0 +1,1161 @@ +// file      : xsd/cxx/tree/tree-inline.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/tree-inline.hxx> +#include <xsd/cxx/tree/default-value.hxx> + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          SemanticGraph::Type& item_type (l.argumented ().type ()); +          String item_name (item_type_name (item_type)); +          String base_type (L"::xsd::cxx::tree::list< " + item_name + +                            L", " + char_type); + +          if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) +            base_type += L", ::xsd::cxx::tree::schema_type::double_"; +          else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) +            base_type += L", ::xsd::cxx::tree::schema_type::decimal"; + +          base_type += L" >"; + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // c-tor () +          // +          os << inl +             << name << "::" << endl +             << name << " ()" << endl +             << ": " << base_type << " (this)" +             << "{" +             << "}"; + +          // c-tor (size_type, const X& x) +          // +          String size_type (name != L"size_type" +                            ? String (L"size_type") +                            : base_type + L"::size_type"); + +          os << inl +             << name << "::" << endl +             << name << " (" << size_type << " n, const " << item_name << +            "& x)" << endl +             << ": " << base_type << " (n, x, this)" +             << "{" +             << "}"; + +          // copy c-tor () +          // +          os << inl +             << name << "::" << endl +             << name << " (const " << name << "& o," << endl +             << flags_type << " f," << endl +             << container << "* c)" << endl +             << ": " << any_simple_type << " (o, f, c)," << endl +             << "  " << base_type << " (o, f, this)" +             << "{" +             << "}"; + +          // Comparison operators. +          // +          if (options.generate_comparison ()) +          { +            os << inl +               << "bool" << endl +               << "operator== (const " << name << "& x, " << +              "const " << name << "& y)" +               << "{" +               << "const " << base_type << "& bx (x);" +               << "return bx == y;" +               << "}"; + +            os << inl +               << "bool" << endl +               << "operator!= (const " << name << "& x, " << +              "const " << name << "& y)" +               << "{" +               << "return !(x == y);" +               << "}"; +          } +        } + +      private: +        String +        item_type_name (SemanticGraph::Type& t) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (t); + +          return o.str (); +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          String const& base (xs_string_type); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          if (options.generate_default_ctor ()) +          { +            // c-tor () +            // +            os << inl +               << name << "::" << endl +               << name << " ()" << endl +               << ": " << base << " ()" +               << "{" +               << "}"; +          } + +          // c-tor (const char*) +          // +          os << inl +             << name << "::" << endl +             << name << " (const " << char_type << "* s)" << endl +             << ": " << base << " (s)" +             << "{" +             << "}"; + +          // c-tor (string const&) +          // +          os << inl +             << name << "::" << endl +             << name << " (const " << string_type << "& s)" << endl +             << ": " << base << " (s)" +             << "{" +             << "}"; + +          // copy c-tor () +          // +          os << inl +             << name << "::" << endl +             << name << " (const " << name << "& o," << endl +             << flags_type << " f," << endl +             << container << "* c)" << endl +             << ": " << base << " (o, f, c)" +             << "{" +             << "}"; +        } +      }; + +      // Enumeration +      // + +      // Generate a sequence of explicit c-tor calls until we reach +      // one of the fundamental string types that can be constructed +      // from char literals. +      // +      struct CtorCallSequence: Traversal::Complex, +                               Traversal::Fundamental::Type, +                               Context +      { +        CtorCallSequence (Context& c, String const& arg) +            : Context (c), arg_ (arg), base_type_name_ (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          // This type should be ultimately string based. +          // +          assert (c.inherits_p ()); + +          os << ename (c) << " (" << endl; + +          dispatch (c.inherits ().base ()); + +          os << ")"; +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Type& t) +        { +          base_type_name_.dispatch (t); + +          os << " (" << arg_ << ")"; +        } + +      private: +        String arg_; +        BaseTypeName base_type_name_; +      }; + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c), member_ (c) +        { +          inherits_member_ >> member_; +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (e); +          } + +          bool enum_based (false); +          if (string_based) +          { +            SemanticGraph::Enumeration* be (0); +            IsEnumBasedType t (be); +            t.dispatch (e); + +            enum_based = (be != 0); +          } + +          String value; +          if (string_based) +            value = evalue (e); + +          // Get to the ultimate base and see if is a fundamental type. +          // +          bool fund_based (false); +          SemanticGraph::Type& ult_base (ultimate_base (e)); +          { +            IsFundamentalType t (fund_based); +            t.dispatch (ult_base); +          } + +          // +          // +          String base; // base type name +          { +            std::wostringstream o; + +            BaseTypeName base_type (*this, o); +            Traversal::Inherits inherits_type (base_type); + +            inherits (e, inherits_type); +            base = o.str (); +          } + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // default c-tor +          // +          bool list_based ( +            ult_base.is_a<SemanticGraph::List> () || +            ult_base.is_a<SemanticGraph::Fundamental::NameTokens> () || +            ult_base.is_a<SemanticGraph::Fundamental::IdRefs> () || +            ult_base.is_a<SemanticGraph::Fundamental::Entities> ()); + +          if (options.generate_default_ctor () || list_based) +          { +            os << inl +               << name << "::" <<  endl +               << name << " ()" << endl +               << ": " << base << " ()" +               << "{" +               << "}"; +          } + +          // c-tor (value) +          // +          if (string_based) +          { +            os << inl +               << name << "::" <<  endl +               << name << " (" << value << " v)" << endl +               << ": "; + +            // If we are enum-based then we can just use the corresponding +            // base c-tor directly. Otherwise we will use the from-string +            // c-tor. +            // +            if (enum_based) +              os << base << " (v)"; +            else +            { +              CtorCallSequence t (*this, L"_xsd_" + name + L"_literals_[v]"); +              t.dispatch (e.inherits ().base ()); +            } + +            os << "{" +               << "}"; +          } + +          // c-tor (const char*) +          // +          if (string_based) +          { +            os << inl +               << name << "::" <<  endl +               << name << " (const " << char_type << "* v)" << endl +               << ": " << base << " (v)" +               << "{" +               << "}"; +          } + +          // c-tor (const std::string&) +          // +          if (string_based) +          { +            os << inl +               << name << "::" <<  endl +               << name << " (const " << string_type << "& v)" << endl +               << ": " << base << " (v)" +               << "{" +               << "}"; +          } + +          // c-tor (fundamental) +          // +          if (fund_based) +          { +            os << inl +               << name << "::" <<  endl +               << name << " ("; + +            member_.dispatch (ult_base); + +            os << " v)" +               << ": " << base << " (v)" +               << "{" +               << "}"; +          } + +          // c-tor (base) +          // +          // If the ultimate is also our immediate base and it is a +          // fundamental type then this c-tor clashes with c-tor +          // (fundamental) above. +          // +          if (!fund_based || &ult_base != &e.inherits ().base ()) +          { +            os << inl +               << name << "::" <<  endl +               << name << " (const "; + +          inherits (e, inherits_member_); + +          os << "& v)" << endl +             << ": " << base << " (v)" +             << "{" +             << "}"; +          } + +          // copy c-tor +          // +          os << inl +             << name << "::" <<  endl +             << name << " (const " << name << "& v," << endl +             << flags_type << " f," << endl +             << container << "* c)" << endl +             << ": " << base << " (v, f, c)" +             << "{" +             << "}"; + +          // operato= (value) +          // +          if (string_based) +          { +            os << inl +               << name << "& " << name << "::" << endl +               << "operator= (" << value << " v)" +               << "{" +               << "static_cast< " << base << "& > (*this) = "; + +            // If we are enum-based then we can just use the corresponding +            // base assignment directly. Otherwise we will use the from- +            // base assignment and a from-string base c-tor. +            // +            if (enum_based) +              os << "v"; +            else +            { +              os << endl; + +              CtorCallSequence t (*this, L"_xsd_" + name + L"_literals_[v]"); +              t.dispatch (e.inherits ().base ()); +            } + +            os << ";" +               << endl +               << "return *this;" +               << "}"; +          } + +          os << endl; +        } + +      private: +        Traversal::Inherits inherits_member_; +        MemberTypeName member_; +      }; + +      struct Member: Traversal::Member, Context +      { +        Member (Context& c, String const& scope) +            : Context (c), scope_ (scope), lit_value_ (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (skip (m)) +            return; + +          String const& aname (eaname (m)); +          String const& mname (emname (m)); +          String const& member (emember (m)); + +          bool fund (false); +          { +            IsFundamentalType t (fund); +            t.dispatch (m.type ()); +          } + +          bool def_attr (m.default_p () && +                            m.is_a<SemanticGraph::Attribute> ()); + +          if (max (m) != 1) +          { +            // sequence +            // +            String container (econtainer (m)); +            String q_container (scope_ + L"::" + container); + +            // container const& +            // name () const; +            // +            os << inl +               << "const " << q_container << "& " << scope_ << "::" << endl +               << aname << " () const" +               << "{" +               << "return this->" << member << ";" +               << "}"; + +            // container& +            // name (); +            // +            os << inl +               << q_container << "& " << scope_ << "::" << endl +               << aname << " ()" +               << "{" +               << "return this->" << member << ";" +               << "}"; + +            // void +            // name (container const&); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (const " << container << "& s)" +               << "{" +               << "this->" << member << " = s;" +               << "}"; +          } +          else if (min (m) == 0 && !def_attr) +          { +            // optional +            // +            String type (etype (m)); +            String container (econtainer (m)); +            String q_container (scope_ + L"::" + container); + +            // container const& +            // name () const; +            // +            os << inl +               << "const " << q_container << "& " << scope_ << "::" << endl +               << aname << " () const" +               << "{" +               << "return this->" << member << ";" +               << "}"; + +            // container& +            // name (); +            // +            os << inl +               << q_container << "& " << scope_ << "::" << endl +               << aname << " ()" +               << "{" +               << "return this->" << member << ";" +               << "}"; + +            // void +            // name (type const&); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (const " << type << "& x)" +               << "{" +               << "this->" << member << ".set (x);" +               << "}"; + +            // void +            // name (container const&); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (const " << container << "& x)" +               << "{" +               << "this->" << member << " = x;" +               << "}"; + +            // void +            // name (auto_ptr<type>); +            // +            if (!fund) +              os << inl +                 << "void " << scope_ << "::" << endl +                 << mname << " (" << auto_ptr << "< " << type << " > x)" +                 << "{" +                 << "this->" << member << ".set (" << +                (std >= cxx_version::cxx11 ? "std::move (x)" : "x") << ");" +                 << "}"; +          } +          else +          { +            // one +            // +            String type (etype (m)); +            String q_type (scope_ + L"::" + type); + +            // type const& +            // name () const; +            // +            os << inl +               << "const " << q_type << "& " << scope_ << "::" << endl +               << aname << " () const" +               << "{" +               << "return this->" << member << ".get ();" +               << "}"; + +            // Do not generate modifiers for fixed attributes. +            // +            if (!(def_attr && m.fixed_p ())) +            { +              // type& +              // name (); +              // +              os << inl +                 << q_type << "& " << scope_ << "::" << endl +                 << aname << " ()" +                 << "{" +                 << "return this->" << member << ".get ();" +                 << "}"; + +              // void +              // name (type const&); +              // +              os << inl +                 << "void " << scope_ << "::" << endl +                 << mname << " (const " << type << "& x)" +                 << "{" +                 << "this->" << member << ".set (x);" +                 << "}"; + +              // void +              // name (auto_ptr<type>); +              // +              if (!fund) +                os << inl +                   << "void " << scope_ << "::" << endl +                   << mname << " (" << auto_ptr << "< " << type << " > x)" +                   << "{" +                   << "this->" << member << ".set (" << +                  (std >= cxx_version::cxx11 ? "std::move (x)" : "x") << ");" +                   << "}"; + +              // auto_ptr<type> +              // detach_name (); +              // +              if (detach && !fund) +                os << inl +                   << auto_ptr << "< " << q_type << " > " << +                  scope_ << "::" << endl +                   << edname (m) << " ()" +                   << "{" +                   << "return this->" << member << ".detach ();" +                   << "}"; +            } +          } + + +          // default_value +          // +          if (m.default_p ()) +          { +            bool simple (true); + +            if (m.is_a<SemanticGraph::Element> ()) +            { +              IsSimpleType test (simple); +              test.dispatch (m.type ()); +            } + +            if (simple) +            { +              String lit (lit_value_.dispatch (m.type (), m.value ())); + +              os << inl; + +              if (lit) +                os << scope_ << "::" << etype (m) << " "; +              else +                os << "const " << scope_ << "::" << etype (m) << "& "; + +              os << scope_ << "::" << endl +                 << edefault_value (m) << " ()" +                 << "{"; + +              if (lit) +                os << "return " << etype (m) << " (" << lit << ");"; +              else +                os << "return " << edefault_value_member (m) << ";"; + +              os << "}"; +            } +          } +        } + +      private: +        String scope_; +        LiteralValue lit_value_; +      }; + +      struct Any: Traversal::Any, +                  Traversal::AnyAttribute, +                  Context +      { +        Any (Context& c, String const& scope) +            : Context (c), scope_ (scope) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& aname (eaname (a)); +          String const& mname (emname (a)); + +          String const& member (emember (a)); + +          if (max (a) != 1) +          { +            // sequence +            // +            String container (econtainer (a)); +            String q_container (scope_ + L"::" + container); + +            // container const& +            // name () const; +            // +            os << inl +               << "const " << q_container << "& " << scope_ << "::" << endl +               << aname << " () const" +               << "{" +               << "return this->" << member << ";" +               << "}"; + +            // container& +            // name (); +            // +            os << inl +               << q_container << "& " << scope_ << "::" << endl +               << aname << " ()" +               << "{" +               << "return this->" << member << ";" +               << "}"; + +            // void +            // name (container const&); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (const " << container << "& s)" +               << "{" +               << "this->" << member << " = s;" +               << "}"; +          } +          else if (min (a) == 0) +          { +            // optional +            // +            String container (econtainer (a)); +            String q_container (scope_ + L"::" + container); + +            // container const& +            // name () const; +            // +            os << inl +               << "const " << q_container << "& " << scope_ << "::" << endl +               << aname << " () const" +               << "{" +               << "return this->" << member << ";" +               << "}"; + +            // container& +            // name (); +            // +            os << inl +               << q_container << "& " << scope_ << "::" << endl +               << aname << " ()" +               << "{" +               << "return this->" << member << ";" +               << "}"; + +            // void +            // name (type const&); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (const " << xerces_ns << "::DOMElement& e)" +               << "{" +               << "this->" << member << ".set (e);" +               << "}"; + +            // void +            // name (type*); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (" << xerces_ns << "::DOMElement* e)" +               << "{" +               << "this->" << member << ".set (e);" +               << "}"; + +            // void +            // name (container const&); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (const " << container << "& x)" +               << "{" +               << "this->" << member << " = x;" +               << "}"; +          } +          else +          { +            // one +            // + +            // type const& +            // name () const; +            // +            os << inl +               << "const " << xerces_ns << "::DOMElement& " << +              scope_ << "::" << endl +               << aname << " () const" +               << "{" +               << "return this->" << member << ".get ();" +               << "}"; + +            // type& +            // name (); +            // +            os << inl +               << xerces_ns << "::DOMElement& " << scope_ << "::" << endl +               << aname << " ()" +               << "{" +               << "return this->" << member << ".get ();" +               << "}"; + +            // void +            // name (type const&); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (const " << xerces_ns << "::DOMElement& e)" +               << "{" +               << "this->" << member << ".set (e);" +               << "}"; + +            // void +            // name (type*); +            // +            os << inl +               << "void " << scope_ << "::" << endl +               << mname << " (" << xerces_ns << "::DOMElement* e)" +               << "{" +               << "this->" << member << ".set (e);" +               << "}"; +          } +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& aname (eaname (a)); +          String const& mname (emname (a)); + +          String const& member (emember (a)); +          String container (econtainer (a)); +          String q_container (scope_ + L"::" + container); + +          // container const& +          // name () const; +          // +          os << inl +             << "const " << q_container << "& " << scope_ << "::" << endl +             << aname << " () const" +             << "{" +             << "return this->" << member << ";" +             << "}"; + +          // container& +          // name (); +          // +          os << inl +             << q_container << "& " << scope_ << "::" << endl +             << aname << " ()" +             << "{" +             << "return this->" << member << ";" +             << "}"; + +          // void +          // name (container const&); +          // +          os << inl +             << "void " << scope_ << "::" << endl +             << mname << " (const " << container << "& s)" +             << "{" +             << "this->" << member << " = s;" +             << "}"; +        } + +      private: +        String scope_; +      }; + +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (c, name) && !name) +            return; + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // Generate accessors and modifiers. +          // +          Any any (*this, name); +          Member member (*this, name); +          Traversal::Names names; + +          if (options.generate_wildcard ()) +            names >> any; + +          names >> member; + +          Complex::names (c, names); + +          // Mixed text content. +          // +          if (mixed_p (c) && !c.context ().count ("mixed-in-base")) +          { +            SemanticGraph::Context& ctx (c.context ()); + +            String const& cont (ctx.get<String> ("mixed-container")); +            String const& memb (ctx.get<String> ("mixed-member")); + +            String const& aname (ctx.get<String> ("mixed-aname")); +            String const& mname (ctx.get<String> ("mixed-mname")); + +            os << inl +               << "const " << name << "::" << cont << "& " << +              name << "::" << endl +               << aname << " () const" +               << "{" +               << "return this->" << memb << ";" +               << "}"; + +            os << inl +               << name << "::" << cont << "& " << name << "::" << endl +               << aname << " ()" +               << "{" +               << "return this->" << memb << ";" +               << "}"; + +            os << inl +               << "void " << name << "::" << endl +               << mname << " (const " << cont << "& s)" +               << "{" +               << "this->" << memb << " = s;" +               << "}"; +          } + +          // dom_document accessors. +          // +          if (edom_document_member_p (c)) +          { +            os << inl +               << "const " << xerces_ns << "::DOMDocument& " << +              name << "::" << endl +               << edom_document (c) << " () const" +               << "{" +               << "return *this->" << edom_document_member (c) << ";" +               << "}"; + +            os << inl +               << xerces_ns << "::DOMDocument& " << name << "::" << endl +               << edom_document (c) << " ()" +               << "{" +               << "return *this->" << edom_document_member (c) << ";" +               << "}"; +          } + +          // Order container. +          // +          if (ordered_p (c) && !c.context ().count ("order-in-base")) +          { +            SemanticGraph::Context& ctx (c.context ()); + +            String const& cont (ctx.get<String> ("order-container")); +            String const& memb (ctx.get<String> ("order-member")); + +            String const& aname (ctx.get<String> ("order-aname")); +            String const& mname (ctx.get<String> ("order-mname")); + +            os << inl +               << "const " << name << "::" << cont << "& " << +              name << "::" << endl +               << aname << " () const" +               << "{" +               << "return this->" << memb << ";" +               << "}"; + +            os << inl +               << name << "::" << cont << "& " << name << "::" << endl +               << aname << " ()" +               << "{" +               << "return this->" << memb << ";" +               << "}"; + +            os << inl +               << "void " << name << "::" << endl +               << mname << " (const " << cont << "& s)" +               << "{" +               << "this->" << memb << " = s;" +               << "}"; +          } + +          os << endl; +        } +      }; + + +      struct GlobalElement: Traversal::Element, +                            GlobalElementBase, +                            Context +      { +        GlobalElement (Context& c) +            : GlobalElementBase (c), Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (!doc_root_p (e)) +            return; + +          bool fund (false); +          { +            IsFundamentalType test (fund); +            test.dispatch (e.type ()); +          } + +          String const& name (ename (e)); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // Accessors/modifiers. +          // +          String const& type (etype (e)); +          String const& aname (eaname (e)); +          String const& mname (emname (e)); +          String const& member (emember (e)); + +          // type const& +          // name () const; +          // +          os << inl +             << "const " << name << "::" << type << "& " << name << "::" << endl +             << aname << " () const" +             << "{" +             << "return this->" << member << ".get ();" +             << "}"; + +          // type& +          // name (); +          // +          os << inl +             << name << "::" << type << "& " << name << "::" << endl +             << aname << " ()" +             << "{" +             << "return this->" << member << ".get ();" +             << "}"; + +          // void +          // name (type const&); +          // +          os << inl +             << "void " << name << "::" << endl +             << mname << " (const " << type << "& x)" +             << "{" +             << "this->" << member << ".set (x);" +             << "}"; + +          // void +          // name (auto_ptr<type>); +          // +          if (!fund) +          { +            os << inl +               << "void " << name << "::" << endl +               << mname << " (" << auto_ptr  << "< " << type << " > x)" +               << "{" +               << "this->" << member << ".set (" << +              (std >= cxx_version::cxx11 ? "std::move (x)" : "x") << ");" +               << "}"; +          } + +          // auto_ptr<type> +          // detach_name (); +          // +          if (detach && !fund) +            os << inl +               << auto_ptr << "< " << name << "::" << type << " > " << +              name << "::" << endl +               << edname (e) << " ()" +               << "{" +               << "return this->" << member << ".detach ();" +               << "}"; +        } +      }; +    } + +    void +    generate_tree_inline (Context& ctx, size_t first, size_t last) +    { +      // Generate includes. +      // +      if (ctx.options.generate_inline ()) +      { +        Traversal::Schema schema; +        Includes includes (ctx, Includes::inline_); + +        schema >> includes; + +        schema.dispatch (ctx.schema_root); +      } +      else +      { +        // Emit "weak" header includes that are used in the file-per-type +        // compilation model. +        // +        Traversal::Schema schema; +        Includes includes (ctx, Includes::source); + +        schema >> includes; + +        schema.dispatch (ctx.schema_root); +      } + +      Traversal::Schema schema; +      Sources sources; +      Traversal::Names names_ns, names; +      Namespace ns (ctx, first, last); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); +      GlobalElement element (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; + +      if (ctx.options.generate_element_type ()) +        names >> element; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/tree-inline.hxx b/xsd/cxx/tree/tree-inline.hxx new file mode 100644 index 0000000..dad4c24 --- /dev/null +++ b/xsd/cxx/tree/tree-inline.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/tree-inline.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_TREE_INLINE_HXX +#define XSD_CXX_TREE_TREE_INLINE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_tree_inline (Context&, size_t first, size_t last); +  } +} + +#endif  // XSD_CXX_TREE_TREE_INLINE_HXX diff --git a/xsd/cxx/tree/tree-source.cxx b/xsd/cxx/tree/tree-source.cxx new file mode 100644 index 0000000..89419af --- /dev/null +++ b/xsd/cxx/tree/tree-source.cxx @@ -0,0 +1,3912 @@ +// file      : xsd/cxx/tree/tree-source.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <map> +#include <list> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/tree-source.hxx> +#include <xsd/cxx/tree/default-value.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      struct List: Traversal::List, Context +      { +        List (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& l) +        { +          String name (ename (l)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (l, name) && !name) +            return; + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          if (!options.suppress_parsing ()) +          { +            SemanticGraph::Type& item_type (l.argumented ().type ()); +            String base (L"::xsd::cxx::tree::list< " + +                         item_type_name (item_type) + L", " + char_type); + +            if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) +              base += L", ::xsd::cxx::tree::schema_type::double_"; +            else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) +              base += L", ::xsd::cxx::tree::schema_type::decimal"; + +            base += L" >"; + +            // c-tor (xercesc::DOMElement) +            // +            os << name << "::" << endl +               << name << " (const " << xerces_ns << "::DOMElement& e," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << any_simple_type << " (e, f, c)," << endl +               << "  " << base << " (e, f, this)" +               << "{" +               << "}"; + +            // c-tor (xercesc::DOMAttr) +            // +            os << name << "::" << endl +               << name << " (const " << xerces_ns << "::DOMAttr& a," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << any_simple_type << " (a, f, c)," << endl +               << "  " << base << " (a, f, this)" +               << "{" +               << "}"; + +            // c-tor (string const&, xercesc::DOMElement) +            // +            os << name << "::" << endl +               << name << " (const " << string_type << "& s," << endl +               << "const " << xerces_ns << "::DOMElement* e," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << any_simple_type << " (s, e, f, c)," << endl +               << "  " << base << " (s, e, f, this)" +               << "{" +               << "}"; +          } + +          // _clone +          // +          os << name << "* " << name << "::" << endl +             << "_clone (" << flags_type << " f," << endl +             << container << "* c) const" +             << "{" +             << "return new class " << name << " (*this, f, c);" +             << "}"; + +          // d-tor +          // +          os << name << "::" << endl +             << "~" << name << " ()" +             << "{" +             << "}"; + +          // Register with type factory map. +          // +          if (polymorphic && polymorphic_p (l)) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (l)); + +            // If this type is anonymous but substitutes, then it will +            // be registered as part of the substitution registration. +            // +            if (!anonymous_p (l) && !options.suppress_parsing ()) +            { +              os << "static" << endl +                 << "const ::xsd::cxx::tree::type_factory_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +                 << "_xsd_" << name << "_type_factory_init (" << endl +                 << strlit (l.name ()) << "," << endl +                 << strlit (xml_ns_name (l)) << ");" +                 << endl; +            } + +            if ((!anonymous_p (l) || anonymous_substitutes_p (l)) && +                options.generate_comparison ()) +            { +              os << "static" << endl +                 << "const ::xsd::cxx::tree::comparison_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +                 << "_xsd_" << name << "_comparison_init;" +                 << endl; +            } +          } +        } + +      private: +        String +        item_type_name (SemanticGraph::Type& t) +        { +          std::wostringstream o; + +          MemberTypeName type (*this, o); +          type.dispatch (t); + +          return o.str (); +        } +      }; + + +      struct Union: Traversal::Union, Context +      { +        Union (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& u) +        { +          String name (ename (u)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (u, name) && !name) +            return; + +          String const& base (xs_string_type); + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          if (!options.suppress_parsing ()) +          { +            // c-tor (xercesc::DOMElement) +            // +            os << name << "::" << endl +               << name << " (const " << xerces_ns << "::DOMElement& e," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << base << " (e, f, c)" +               << "{" +               << "}"; + +            // c-tor (xercesc::DOMAttr) +            // +            os << name << "::" << endl +               << name << " (const " << xerces_ns << "::DOMAttr& a," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << base << " (a, f, c)" +               << "{" +               << "}"; + +            // c-tor (string const&, xercesc::DOMElement) +            // +            os << name << "::" << endl +               << name << " (const " << string_type << "& s," << endl +               << "const " << xerces_ns << "::DOMElement* e," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << base << " (s, e, f, c)" +               << "{" +               << "}"; +          } + +          // _clone +          // +          os << name << "* " << name << "::" << endl +             << "_clone (" << flags_type << " f," << endl +             << container << "* c) const" +             << "{" +             << "return new class " << name << " (*this, f, c);" +             << "}"; + +          // Register with type factory map. +          // +          if (polymorphic && polymorphic_p (u)) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (u)); + +            // If this type is anonymous but substitutes, then it will +            // be registered as part of the substitution registration. +            // +            if (!anonymous_p (u) && !options.suppress_parsing ()) +            { +              os << "static" << endl +                 << "const ::xsd::cxx::tree::type_factory_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +                 << "_xsd_" << name << "_type_factory_init (" << endl +                 << strlit (u.name ()) << "," << endl +                 << strlit (xml_ns_name (u)) << ");" +                 << endl; +            } + +            if ((!anonymous_p (u) || anonymous_substitutes_p (u)) && +                options.generate_comparison ()) +            { +              os << "static" << endl +                 << "const ::xsd::cxx::tree::comparison_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +                 << "_xsd_" << name << "_comparison_init;" +                 << endl; +            } +          } +        } +      }; + + +      // Enumeration mapping. +      // + +      struct EnumeratorLiteral: Traversal::Enumerator, Context +      { +        EnumeratorLiteral (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          os << strlit (e.name ()); +        } +      }; + + +      // +      // +      struct LiteralInfo +      { +        LiteralInfo (String const& value, String const& name) +            : value_ (value), name_ (name) +        { +        } + +        String value_; +        String name_; +      }; + +      bool +      operator< (LiteralInfo const& x, LiteralInfo const& y) +      { +        return x.value_ < y.value_; +      } + +      typedef list<LiteralInfo> LiteralInfoList; + + +      // Populate LiteralInfoList +      // +      struct EnumeratorLiteralInfo: Traversal::Enumerator, Context + +      { +        EnumeratorLiteralInfo (Context& c, LiteralInfoList& list) +            : Context (c), list_ (list) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          list_.push_back (LiteralInfo (e.name (), ename (e))); +        } + +      private: +        LiteralInfoList& list_; +      }; + + +      struct Enumeration: Traversal::Enumeration, Context +      { +        Enumeration (Context& c) +            : Context (c), enumerator_literal_ (c) +        { +          names_enumerator_literal_ >> enumerator_literal_; +        } + +        virtual void +        traverse (Type& e) +        { +          String name (ename (e)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          if (renamed_type (e, name) && !name) +            return; + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (e); +          } + +          SemanticGraph::Enumeration* be (0); +          bool enum_based (false); +          if (string_based) +          { +            IsEnumBasedType t (be); +            t.dispatch (e); + +            enum_based = (be != 0); +          } + +          String value; +          if (string_based) +            value = evalue (e); + +          size_t enum_count (0); + +          for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ()); +               i != end; ++i) +            ++enum_count; + +          String base; // base type name +          { +            std::wostringstream o; + +            BaseTypeName base_type (*this, o); +            Traversal::Inherits inherits_type (base_type); + +            inherits (e, inherits_type); +            base = o.str (); +          } + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          if (!options.suppress_parsing ()) +          { +            // c-tor (xercesc::DOMElement) +            // +            os << name << "::" << endl +               << name << " (const " << xerces_ns << "::DOMElement& e," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << base << " (e, f, c)" +               << "{"; + +            if (string_based) +              os << "_xsd_" << name << "_convert ();"; + +            os << "}"; + + +            // c-tor (xercesc::DOMAttr) +            // +            os << name << "::" << endl +               << name << " (const " << xerces_ns << "::DOMAttr& a," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << base << " (a, f, c)" +               << "{"; + +            if (string_based) +            { +              os << "_xsd_" << name << "_convert ();"; +            } + +            os << "}"; + + +            // c-tor (string const&, xercesc::DOMElement) +            // +            os << name << "::" << endl +               << name << " (const " << string_type << "& s," << endl +               << "const " << xerces_ns << "::DOMElement* e," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << base << " (s, e, f, c)" +               << "{"; + +            if (string_based) +            { +              os << "_xsd_" << name << "_convert ();"; +            } + +            os << "}"; +          } + +          // _clone +          // +          os << name << "* " << name << "::" << endl +             << "_clone (" << flags_type << " f," << endl +             << container << "* c) const" +             << "{" +             << "return new class " << name << " (*this, f, c);" +             << "}"; + +          // convert +          // +          // @@ TODO: expected list +          // +          if (string_based) +          { +            String i_name (L"_xsd_" + name + L"_indexes_"); + +            os << name << "::" << value << " " << +              name << "::" << endl +               << "_xsd_" << name << "_convert () const" +               << "{" +               << "::xsd::cxx::tree::enum_comparator< " << char_type << +              " > c (_xsd_" << name << "_literals_);" +               << "const " << value << "* i (::std::lower_bound (" << endl +               << i_name << "," << endl +               << i_name << " + " << enum_count << "," << endl +               << "*this," << endl +               << "c));" +               << endl +               << "if (i == " << i_name << " + " << enum_count << " || " << +              "_xsd_" << name << "_literals_[*i] != *this)" +               << "{" +               << "throw ::xsd::cxx::tree::unexpected_enumerator < " << +              char_type << " > (*this);" +               << "}" +               << "return *i;" +               << "}"; +          } + +          // literals and indexes +          // +          if (string_based) +          { +            if (enum_based) +            { +              os << "const " << char_type << "* const* " << name << "::" << endl +                 << "_xsd_" << name << "_literals_ = " << +                fq_name (*be) << "::_xsd_" << ename (*be) << "_literals_;" +                 << endl; +            } +            else +            { +              os << "const " << char_type << "* const " << name << "::" << endl +                 << "_xsd_" << name << "_literals_[" << enum_count << "] =" +                 << "{"; + +              names<Enumeration> ( +                e, names_enumerator_literal_, 0, 0, 0, &Enumeration::comma); + +              os << "};"; +            } + + +            LiteralInfoList l; +            { +              EnumeratorLiteralInfo enumerator (*this, l); +              Traversal::Names names_enumerator (enumerator); +              names (e, names_enumerator); +            } + +            l.sort (); + +            os << "const " << name << "::" << value << " " << +              name << "::" << endl +               << "_xsd_" << name << "_indexes_[" << enum_count << "] =" +               << "{"; + +            String fq_name (ns_scope + L"::" + name); + +            for (LiteralInfoList::iterator +                   b (l.begin ()), i (b), end (l.end ()); i != end; ++i) +            { +              if (i != b) +                os << "," << endl; + +              os << fq_name << "::" << i->name_; +            } + +            os << "};"; +          } + +          // Register with type factory map. +          // +          if (polymorphic && polymorphic_p (e)) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (e)); + +            // If this type is anonymous but substitutes, then it will +            // be registered as part of the substitution registration. +            // +            if (!anonymous_p (e) && !options.suppress_parsing ()) +            { +              os << "static" << endl +                 << "const ::xsd::cxx::tree::type_factory_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +                 << "_xsd_" << name << "_type_factory_init (" << endl +                 << strlit (e.name ()) << "," << endl +                 << strlit (xml_ns_name (e)) << ");" +                 << endl; +            } + +            if ((!anonymous_p (e) || anonymous_substitutes_p (e)) && +                options.generate_comparison ()) +            { +              os << "static" << endl +                 << "const ::xsd::cxx::tree::comparison_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +                 << "_xsd_" << name << "_comparison_init;" +                 << endl; +            } +          } +        } + +        virtual void +        comma (Type&) +        { +          os << "," << endl; +        } + +      private: +        Traversal::Names names_enumerator_literal_; +        EnumeratorLiteral enumerator_literal_; + +      }; + +      // +      // +      struct Member: Traversal::Member, Context +      { +        Member (Context& c, String const& scope) +            : Context (c), scope_ (scope), init_value_ (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +	  if (skip (m)) +            return; + +          // default_value +          // +          if (m.default_p ()) +          { +            SemanticGraph::Type& t (m.type ()); +            bool simple (true); + +            if (m.is_a<SemanticGraph::Element> ()) +            { +              IsSimpleType test (simple); +              test.dispatch (t); +            } + +            if (simple) +            { +              bool lit (false); +              { +                IsLiteralValue test (lit); +                test.dispatch (t); +              } + +              if (!lit) +              { +                InitKind::Kind kind (InitKind::simple); +                { +                  InitKind test (kind); +                  test.dispatch (t); +                } + +                String const& member (edefault_value_member (m)); + +                String init_name; + +                switch (kind) +                { +                case InitKind::data: +                  { +                    init_name = escape (L"_xsd_" + scope_ + member + L"data"); +                    init_value_.data (init_name); +                    init_value_.dispatch (t, m.value ()); +                    break; +                  } +                case InitKind::function: +                  { +                    init_name = escape (L"_xsd_" + scope_ + member + L"init"); + +                    os << "static " << scope_ << "::" << etype (m) << endl +                       << init_name << " ()" +                       << "{" +                       << scope_ << "::" << etype (m) << " r;" +                       << endl; + +                    init_value_.dispatch (t, m.value ()); + +                    os << "return r;" +                       << "};"; +                    break; +                  } +                case InitKind::simple: +                  break; +                } + +                os << "const " << scope_ << "::" << etype (m) << " " << +                  scope_ << "::" << member << " (" << endl; + +                switch (kind) +                { +                case InitKind::data: +                  { +                    // Second dispatch. +                    // +                    init_value_.dispatch (t, m.value ()); +                    break; +                  } +                case InitKind::function: +                  { +                    os << init_name << " ()"; +                    break; +                  } +                case InitKind::simple: +                  { +                    init_value_.dispatch (t, m.value ()); +                    break; +                  } +                } + +                os << ");" +                   << endl; +              } +            } +          } +        } + +      private: +        String scope_; +        InitValue init_value_; +      }; + + +      struct Element: Traversal::Element, Context +      { +        Element (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (skip (e)) +            return; + +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (e.scope ())); + +          String const& member (emember (e)); + +          String tr (etraits (e)); // traits type name +          String type (etype (e)); + +          SemanticGraph::Type& t (e.type ()); + +          bool fund (false); +          { +            IsFundamentalType traverser (fund); +            traverser.dispatch (t); +          } + +          // Check if we need to handle xsi:type and substitution groups. +          // If this element's type is anonymous then we don't need to do +          // anything. Note that if the type is anonymous then it can't be +          // derived from which makes it impossible to substitute or +          // dynamically-type with xsi:type. +          // +          bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + +          os << "// " << comment (e.name ()) << endl +             << "//" << endl; + +          if (poly) +          { +            os << "{" +               << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl +               << "::xsd::cxx::tree::type_factory_map_instance< " << +              poly_plate << ", " << char_type << " > ().create (" << endl +               << strlit (e.name ()) << "," << endl +               << (e.qualified_p () +                   ? strlit (e.namespace_ ().name ()) +                   : L + String ("\"\"")) << "," << endl; + +            SemanticGraph::Complex* tc; +            if ((tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && +                tc->abstract_p ()) +              os << "0,"; +            else +              os << "&::xsd::cxx::tree::factory_impl< " << type << " >,"; + +            os << endl +               << (e.global_p () ? "true" : "false") << ", " << +              (e.qualified_p () ? "true" : "false") << ", " << +              "i, n, f, this));" +               << endl +               << "if (tmp.get () != 0)" +               << "{"; +          } +          else +          { +            if (e.qualified_p () && e.namespace_ ().name ()) +            { +              os << "if (n.name () == " << strlit (e.name ()) << " && " << +                "n.namespace_ () == " << strlit (e.namespace_ ().name ()) << ")" +                 << "{"; +            } +            else +            { +              os << "if (n.name () == " << strlit (e.name ()) << " && " << +                "n.namespace_ ().empty ())" +                 << "{"; +            } + +            if (!fund) +            { +              os << auto_ptr << "< " << type << " > r (" << endl +                 << tr << "::create (i, f"; + +              if (t.is_a<SemanticGraph::AnyType> () && +                  options.generate_any_type ()) +                os << " | " << flags_type << "::extract_content"; + +              os << ", this));" +                 << endl; +            } +          } + + +          // Checks. Disabled at the moment since they make it impossible to +          // parse valid instances where the same element is used in both +          // base and derived types. See the cxx/tree/name-clash/inheritance +          // test for details. +          // +          // +          if (max (e) != 1) +          { +            // sequence +            // +          } +          else if (min (e) == 0) +          { +            // optional +            // +            os << "if (!this->" << member << ")" +               << "{"; +          } +          else +          { +            // one +            // +            os << "if (!" << member << ".present ())" +               << "{"; +          } + + +          if (poly || !fund) +          { +            if (poly) +            { +              // Cast to static type. +              // +              os << auto_ptr << "< " << type << " > r (" << endl +                 << "dynamic_cast< " << type << "* > (tmp.get ()));" +                 << endl +                 << "if (r.get ())" << endl +                 << "tmp.release ();" +                 << "else" << endl +                 << "throw ::xsd::cxx::tree::not_derived< " << char_type << +                " > ();" +                 << endl; +            } + +            char const* r (std >= cxx_version::cxx11 ? "::std::move (r)" : "r"); + +            if (max (e) != 1) +            { +              // sequence +              // +              os << "this->" << member << ".push_back (" << r << ");"; +            } +            else if (min (e) == 0) +            { +              // optional +              // +              os << "this->" << member << ".set (" << r << ");"; +            } +            else +            { +              // one +              // +              os << "this->" << member << ".set (" << r << ");"; +            } +          } +          else +          { +            if (max (e) != 1) +            { +              // sequence +              // +              os << "this->" << member << ".push_back (" << tr << +                "::create (i, f, this));"; +            } +            else if (min (e) == 0) +            { +              // optional +              // +              os << "this->" << member << ".set (" << tr << +                "::create (i, f, this));"; +            } +            else +            { +              // one +              // +              os << "this->" << member << ".set (" << tr << +                "::create (i, f, this));"; +            } +          } + +          // Capture order. +          // +          if (ordered_p (c)) +          { +            SemanticGraph::Context& ctx (c.context ()); + +            String const& t (ctx.get<String> ("order-type")); +            String const& m (ctx.get<String> ("order-member")); + +            os << "this->" << m << ".push_back (" << endl +               << t << " (" << +              e.context ().get<String> ("ordered-id-name"); + +            // sequence +            // +            if (max (e) != 1) +              os << ", " << "this->" << member << ".size () - 1"; + +            os << "));"; +          } + +          os << "continue;"; + +          // End of check block. +          // +          if (max (e) != 1) +          { +            // sequence +            // +          } +          else if (min (e) == 0) +          { +            // optional +            // +            os << "}"; +          } +          else +          { +            // one +            // +            os << "}"; +          } + +          os << "}"; // if block + +          if (poly) +            os << "}"; +        } +      }; + +      struct ElementTest: Traversal::Element, Context +      { +        ElementTest (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& e) +        { +          if (skip (e)) +            return; + +          if (max (e) == 1 && min (e) == 1) +          { +            // one +            // +            os << "if (!" << emember (e) << ".present ())" +               << "{" +               << "throw ::xsd::cxx::tree::expected_element< " << +              char_type << " > (" << endl +               << strlit (e.name ()) << "," << endl +               << (e.qualified_p () +                   ? strlit (e.namespace_ ().name ()) +                   : L + String ("\"\"")) << ");" +               << "}"; +          } +        } +      }; + +      struct Any: Traversal::Any, Context +      { +        Any (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& member (emember (a)); + +          SemanticGraph::Complex& c ( +            dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + +          String const& ns (a.definition_namespace ().name ()); +          String const& dom_doc (edom_document (c)); + +          os << "// " << ename (a) << endl +             << "//" << endl +             << "if ("; + +          for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), +                 e (a.namespace_end ()); i != e;) +          { +            if (*i == L"##any") +            { +              os << "true"; +            } +            else if (*i == L"##other") +            { +              if (ns) +              { +                // Note that here I assume that ##other does not include +                // unqualified names in a schema with target namespace. +                // This is not what the spec says but that seems to be +                // the consensus. +                // +                os << "(!n.namespace_ ().empty () && " << +                  "n.namespace_ () != " << strlit (ns) << ")"; +              } +              else +                os << "!n.namespace_ ().empty ()"; +            } +            else if (*i == L"##local") +            { +              os << "n.namespace_ ().empty ()"; +            } +            else if (*i == L"##targetNamespace") +            { +              os << "n.namespace_ () == " << strlit (ns); +            } +            else +            { +              os << "n.namespace_ () == " << strlit (*i); +            } + +            if (++i != e) +              os << " ||" << endl; +          } + +          os << ")" +             << "{"; + + +          // Checks. +          // +          // +          if (max (a) != 1) +          { +            // sequence +            // +          } +          else if (min (a) == 0) +          { +            // optional +            // +            os << "if (!this->" << member << ")" +               << "{"; +          } +          else +          { +            // one +            // +            os << "if (!" << member << ".present ())" +               << "{"; +          } + +          os << xerces_ns << "::DOMElement* r (" << endl +             << "static_cast< " << xerces_ns << "::DOMElement* > (" << endl +             << "this->" << dom_doc << " ().importNode (" << endl +             << "const_cast< " << xerces_ns << "::DOMElement* > (&i), true)));"; + +          if (max (a) != 1) +          { +            // sequence +            // +            os << "this->" << member << ".push_back (r);"; +          } +          else if (min (a) == 0) +          { +            // optional +            // +            os << "this->" << member << ".set (r);"; +          } +          else +          { +            // one +            // +            os << "this->" << member << ".set (r);"; +          } + +          // Capture order. +          // +          if (ordered_p (c)) +          { +            SemanticGraph::Context& ctx (c.context ()); + +            String const& t (ctx.get<String> ("order-type")); +            String const& m (ctx.get<String> ("order-member")); + +            os << "this->" << m << ".push_back (" << endl +               << t << " (" << +              a.context ().get<String> ("ordered-id-name") << ", "; + +            if (max (a) != 1) +              // sequence +              // +              os << "this->" << member << ".size () - 1"; +            else +              // optional & one +              // +              os << "0"; + +            os << "));"; +          } + +          os << "continue;"; + +          // End of check block. +          // +          if (max (a) != 1) +          { +            // sequence +            // +          } +          else if (min (a) == 0) +          { +            // optional +            // +            os << "}"; +          } +          else +          { +            // one +            // +            os << "}"; +          } + +          os << "}"; // if block +        } +      }; + +      struct AnyTest: Traversal::Any, Context +      { +        AnyTest (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          if (max (a) == 1 && min (a) == 1) +          { +            // one +            // +            os << "if (!" << emember (a) << ".present ())" +               << "{" +               << "throw ::xsd::cxx::tree::expected_element< " << +              char_type << " > (" << endl +               << L << "\"*\"," << endl +               << strlit (*a.namespace_begin ()) << ");" +               << "}"; +          } +        } +      }; + +      struct Attribute: Traversal::Attribute, Context +      { +        Attribute (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& member (emember (a)); + +          String const& tr (etraits (a)); // traits type name + +          if (a.qualified_p () && a.namespace_ ().name ()) +          { +            os << "if (n.name () == " << strlit (a.name ()) << " && " << +              "n.namespace_ () == " << strlit (a.namespace_ ().name ()) << ")" +               << "{"; +          } +          else +          { +            os << "if (n.name () == " << strlit (a.name ()) << " && " << +              "n.namespace_ ().empty ())" +               << "{"; +          } + +          os << "this->" << member << ".set (" << tr << +            "::create (i, f, this));"; + +          os << "continue;" +             << "}"; + +        } +      }; + +      struct AnyAttribute: Traversal::AnyAttribute, Context +      { +        AnyAttribute (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& member (emember (a)); + +          String const& ns (a.definition_namespace ().name ()); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "// " << ename (a) << endl +             << "//" << endl +             << "if ("; + +          // Note that we need to filter out namespaces for xmlns and +          // xsi. +          // +          for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), +                 e (a.namespace_end ()); i != e;) +          { +            if (*i == L"##any") +            { +              os << "(n.namespace_ () != " << +                "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << +                " > () &&" << endl +                 << "n.namespace_ () != " << +                "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << +                " > ())"; +            } +            else if (*i == L"##other") +            { +              if (ns) +              { +                // Note that here I assume that ##other does not include +                // unqualified names in a schema with target namespace. +                // This is not what the spec says but that seems to be +                // the consensus. +                // +                os << "(!n.namespace_ ().empty () &&" << endl +                   << "n.namespace_ () != " << strlit (ns) << " &&" <<endl +                   << "n.namespace_ () != " << +                  "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << +                  " > () &&" << endl +                   << "n.namespace_ () != " << +                  "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << +                  " > ())"; +              } +              else +                os << "(!n.namespace_ ().empty () &&" << endl +                   << "n.namespace_ () != " << +                  "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << +                  " > () &&" << endl +                   << "n.namespace_ () != " << +                  "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << +                  " > ())"; +            } +            else if (*i == L"##local") +            { +              os << "n.namespace_ ().empty ()"; +            } +            else if (*i == L"##targetNamespace") +            { +              os << "n.namespace_ () == " << strlit (ns); +            } +            else +            { +              os << "n.namespace_ () == " << strlit (*i); +            } + +            if (++i != e) +              os << " ||" << endl; +          } + +          os << ")" +             << "{" +             << xerces_ns << "::DOMAttr* r (" << endl +             << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl +             << "this->" << dom_doc << " ().importNode (" << endl +             << "const_cast< " << xerces_ns << "::DOMAttr* > (&i), true)));" +             << "this->" << member << " .insert (r);" +             << "continue;" +             << "}"; +        } +      }; + + +      struct AttributeTest: Traversal::Attribute, Context +      { +        AttributeTest (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& a) +        { +          String const& member (emember (a)); + +          if (!a.optional_p () || a.default_p ()) +          { +            os << "if (!" << member << ".present ())" +               << "{"; + +            if (a.default_p ()) +            { +              os << "this->" << member << ".set (" << +                edefault_value (a) << " ());"; +            } +            else +              os << "throw ::xsd::cxx::tree::expected_attribute< " << +                char_type << " > (" << endl +                 << strlit (a.name ()) << "," << endl +                 << (a.qualified_p () +                     ? strlit (a.namespace_ ().name ()) +                     : L + String ("\"\"")) << ");"; + +            os << "}"; +          } +        } +      }; + + +      // +      // +      struct CtorBase: Traversal::Complex, +                       Traversal::Enumeration, +                       Traversal::Type, +                       Context +      { +        // If base_arg is empty then no base argument is generated. +        // +        CtorBase (Context& c, CtorArgType at, String const& base_arg) +            : Context (c), args_ (c, at, base_arg) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type&) +        { +          if (args_.base_arg_) +            os << args_.base_arg_; +        } + +        virtual void +        traverse (SemanticGraph::Enumeration&) +        { +          if (args_.base_arg_) +            os << args_.base_arg_; +        } + +        void +        traverse (SemanticGraph::Complex& c) +        { +          args_.traverse (c); +        } + +      private: +        // No need to traverse AnyAttribute since it is always mapped +        // to a sequence. +        // +        struct Args: Traversal::Complex, +                     Traversal::Enumeration, +                     Traversal::Type, +                     Traversal::Any, +                     Traversal::Element, +                     Traversal::Attribute, +                     Context +        { +          Args (Context& c, CtorArgType at, String const& base_arg) +              : Context (c), +                arg_type_ (at), base_arg_ (base_arg), first_ (true) +          { +            *this >> inherits_ >> *this; +            *this >> names_ >> *this; +          } + +          virtual void +          traverse (SemanticGraph::Type&) +          { +            if (base_arg_) +              os << comma () << base_arg_; +          } + +          virtual void +          traverse (SemanticGraph::Enumeration&) +          { +            if (base_arg_) +              os << comma () << base_arg_; +          } + +          virtual void +          traverse (SemanticGraph::Any& a) +          { +            if (!options.generate_wildcard ()) +              return; + +            if (min (a) == 1 && max (a) == 1) +            { +              // one +              // +              os << comma () << ename (a); +            } +          } + +          virtual void +          traverse (SemanticGraph::Element& e) +          { +            if (!skip (e) && min (e) == 1 && max (e) == 1) +            { +              // one +              // +              bool move (false); + +              if (std >= cxx_version::cxx11) +              { +                switch (arg_type_) +                { +                case CtorArgType::complex_auto_ptr: +                  { +                    bool simple (true); +                    IsSimpleType t (simple); +                    t.dispatch (e.type ()); +                    move = !simple; +                    break; +                  } +                case CtorArgType::poly_auto_ptr: +                  { +                    move = polymorphic && polymorphic_p (e.type ()); +                    break; +                  } +                case CtorArgType::type: +                  break; +                } +              } + +              os << comma () << (move ? "std::move (" : "") << ename (e) << +                (move ? ")" : ""); +            } +          } + +          virtual void +          traverse (SemanticGraph::Attribute& a) +          { +            // Note that we are not including attributes with default +            // or required fixed values here. +            // +            if (min (a) == 1 && !a.fixed_p ()) +            { +              // one +              // +              os << comma () << ename (a); +            } +          } + +          using Complex::traverse; + +        private: +          String +          comma () +          { +            bool tmp (first_); +            first_ = false; +            return tmp ? "" : ",\n"; +          } + +        public: +          CtorArgType arg_type_; +          String base_arg_; + +        private: +          bool first_; + +          Traversal::Inherits inherits_; +          Traversal::Names names_; +        }; + +        Args args_; +      }; + + +      struct CtorMember: Traversal::Element, +                         Traversal::Attribute, +                         Context +      { +        CtorMember (Context& c, CtorArgType at) +            : Context (c), arg_type_ (at) +        { +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          if (skip (e)) +            return; + +          String const& member (emember (e)); + +          if (max (e) != 1) +          { +            // sequence +            // +            os << "," << endl +               << "  " << member << " (this)"; +          } +          else if (min (e) == 0) +          { +            // optional +            // +            os << "," << endl +               << "  " << member << " (this)"; +          } +          else +          { +            // one +            // +            bool move (false); + +            if (std >= cxx_version::cxx11) +            { +              switch (arg_type_) +              { +              case CtorArgType::complex_auto_ptr: +                { +                  bool simple (true); +                  IsSimpleType t (simple); +                  t.dispatch (e.type ()); +                  move = !simple; +                  break; +                } +              case CtorArgType::poly_auto_ptr: +                { +                  move = polymorphic && polymorphic_p (e.type ()); +                  break; +                } +              case CtorArgType::type: +                break; +              } +            } + +            os << "," << endl +               << "  " << member << " (" << (move ? "std::move (" : "") << +              ename (e) << (move ? ")" : "") << ", this)"; +          } +        } + +        virtual void +        traverse (SemanticGraph::Attribute& a) +        { +          String const& member (emember (a)); + +          bool def (a.default_p ()); + +          if (min (a) == 0 && !def) +          { +            // optional +            // +            os << "," << endl +               << "  " << member << " (this)"; +          } +          else +          { +            // one +            // + +            if (def) +            { +              // This is an attribute with default or fixed value. We are +              // going to initialize it to its default value. +              // +              os << "," << endl +                 << "  " << member << " (" << +                edefault_value (a) << " (), this)"; +            } +            else +            { +              os << "," << endl +                 << "  " << member << " (" << ename (a) << ", this)"; +            } +          } +        } + +      private: +        CtorArgType arg_type_; +      }; + +      struct CtorAny: Traversal::Any, +                      Traversal::AnyAttribute, +                      Context +      { +        CtorAny (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          if (max (a) != 1) +          { +            // sequence +            // +            os << "," << endl +               << "  " << member << " (this->" << dom_doc << " ())"; +          } +          else if (min (a) == 0) +          { +            // optional +            // +            os << "," << endl +               << "  " << member << " (this->" << dom_doc << " ())"; +          } +          else +          { +            // one +            // +            os << "," << endl +               << "  " << member << " (" << ename (a) << ", this->" << +              dom_doc << " ())"; +          } +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << emember (a) << " (this->" << dom_doc << " ())"; +        } +      }; + + +      struct CopyMember: Traversal::Member, Context +      { +        CopyMember (Context& c, String const& arg_name_) +            : Context (c), arg_name (arg_name_) +        { +        } + +        virtual void +        traverse (SemanticGraph::Member& m) +        { +          if (skip (m)) +            return; + +          String const& member (emember (m)); + +          os << "," << endl +             << "  " << member << " (" << +            arg_name << "." << member << ", f, this)"; +        } + +      private: +        String arg_name; +      }; + +      struct CopyAny: Traversal::Any, +                      Traversal::AnyAttribute, +                      Context +      { +        CopyAny (Context& c, String const& arg_name_) +            : Context (c), arg_name (arg_name_) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << member << " (" << +            arg_name << "." << member << ", this->" << dom_doc << " ())"; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << member << " (" << +            arg_name << "." << member << ", this->" << dom_doc << " ())"; +        } + +      private: +        String arg_name; +      }; + +      struct AssignMember: Traversal::Member, Context +      { +        AssignMember (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Member& m) +        { +          if (skip (m)) +            return; + +          String const& member (emember (m)); +          os << "this->" << member << " = x." << member << ";"; +        } +      }; + +      struct AssignAny: Traversal::Any, +                        Traversal::AnyAttribute, +                        Context +      { +        AssignAny (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& member (emember (a)); +          os << "this->" << member << " = x." << member << ";"; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& member (emember (a)); +          os << "this->" << member << " = x." << member << ";"; +        } +      }; + + +      // Element parsing c-tor initializers. +      // +      struct ElementCtorMember: Traversal::Member, Context +      { +        ElementCtorMember (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& m) +        { +          if (skip (m)) +            return; + +          String const& member (emember (m)); + +          os << "," << endl +             << "  " << member << " (this)"; +        } +      }; + +      struct ElementCtorAny: Traversal::Any, +                             Traversal::AnyAttribute, +                             Context +      { +        ElementCtorAny (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << member << " (this->" << dom_doc << " ())"; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << member << " (this->" << dom_doc << " ())"; +        } +      }; + + +      // Default c-tor member initializer. +      // +      struct DefaultCtorMemberInit: Traversal::Element, +                                    Traversal::Attribute, +                                    Context +      { +        DefaultCtorMemberInit (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          if (skip (e)) +            return; + +          String const& member (emember (e)); + +          os << "," << endl +             << "  " << member << " (this)"; +        } + +        virtual void +        traverse (SemanticGraph::Attribute& a) +        { +          String const& member (emember (a)); + +          if (a.default_p ()) +          { +            // This is an attribute with default or fixed value. We are +            // going to initialize it to its default value. +            // +            os << "," << endl +               << "  " << member << " (" << +              edefault_value (a) << " (), this)"; +          } +          else +            os << "," << endl +               << "  " << member << " (this)"; +        } +      }; + +      struct DefaultCtorAnyInit: Traversal::Any, +                                 Traversal::AnyAttribute, +                                 Context +      { +        DefaultCtorAnyInit (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << member << " (this->" << dom_doc << " ())"; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& member (emember (a)); +          String const& dom_doc ( +            edom_document ( +              dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + +          os << "," << endl +             << "  " << member << " (this->" << dom_doc << " ())"; +        } +      }; + +      // Test whether the base has comparison operators. +      // +      struct HasComparisonOperator: Traversal::Fundamental::Type, +                                    Traversal::List, +                                    Traversal::Union, +                                    Traversal::Complex, +                                    Traversal::Enumeration, +                                    Traversal::Member, +                                    Traversal::Any, +                                    Traversal::AnyAttribute, +                                    Context +      { +        // generate should initially be false. +        // +        HasComparisonOperator (Context& c, bool& generate) +            : Context (c), generate_ (generate) +        { +          *this >> inherits_ >> *this; +          *this >> names_ >> *this; +        } + +        virtual void +        traverse (SemanticGraph::Fundamental::Type&) +        { +          // All built-in types are comparable. +          generate_ = true; +        } + +        virtual void +        traverse (SemanticGraph::List&) +        { +          generate_ = true; +        } + +        virtual void +        traverse (SemanticGraph::Union&) +        { +          generate_ = true; +        } + +        virtual void +        traverse (SemanticGraph::Enumeration& e) +        { +          Traversal::Enumeration::inherits (e); +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          Complex::names (c); + +          if (!generate_) +            Complex::inherits (c); +        } + +        virtual void +        traverse (SemanticGraph::Member& m) +        { +          if (!skip (m)) +            generate_ = true; +        } + +        virtual void +        traverse (SemanticGraph::Any&) +        { +          if (options.generate_wildcard ()) +            generate_ = true; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute&) +        { +          if (options.generate_wildcard ()) +            generate_ = true; +        } + +      private: +        bool& generate_; + +        Traversal::Inherits inherits_; +        Traversal::Names names_; +      }; + +      // +      // +      struct MemberComparison: Traversal::Element, +                               Traversal::Attribute, +                               Context +      { +        MemberComparison (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          if (skip (e)) +            return; + +          String const& aname (eaname (e)); + +          // Check if we need to handle xsi:type and substitution groups. +          // If this element's type is anonymous then we don't need to do +          // anything. Note that if the type is anonymous then it can't be +          // derived from which makes it impossible to substitute or +          // dynamically-type with xsi:type. +          // +          SemanticGraph::Type& t (e.type ()); +          bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + +          if (!poly) +          { +            os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl +               << "return false;" +               << endl; +          } +          else +          { +            os << "{" +               << "::xsd::cxx::tree::comparison_map< " << char_type +               << " >& cm (" << endl +               << "::xsd::cxx::tree::comparison_map_instance< " << +              poly_plate << ", " << char_type << " > ());" +               << endl; + +            if (max (e) != 1) +            { +              // sequence +              // +              String const& scope (ename (e.scope ())); + +              os << scope << "::" << econtainer (e) << +                " a (x." << aname << " ()), b (y." << aname << " ());" +                 << endl; + +              os << "if (a.size () != b.size ())" << endl +                 << "return false;" +                 << endl; + +              os << "for (" << scope << "::" << econst_iterator (e) << endl +                 << "ai (a.begin ()), bi (b.begin ()), " << +                "ae (a.end ()), be (b.end ());" << endl +                 << "ai != ae; ++ai, ++bi)" +                 << "{" +                 << "if (!cm.compare (*ai, *bi))" << endl +                 << "return false;" +                 << "}"; +            } +            else if (min (e) == 0) +            { +              // optional +              // +              String const& scope (ename (e.scope ())); + +              os << scope << "::" << econtainer (e) << +                " a (x." << aname << " ()), b (y." << aname << " ());" +                 << endl; + +              os << "if (!a || !b)" +                 << "{" +                 << "if (a.present () != b.present ())" << endl +                 << "return false;" +                 << "}" +                 << "else" +                 << "{" +                 << "if (!cm.compare (*a, *b))" << endl +                 << "return false;" +                 << "}"; +            } +            else +            { +              // one +              // +              os << "if (!cm.compare (x." << aname << " (), y." << +                aname << " ()))" << endl +                 << "return false;"; +            } + +            os << "}"; +          } +        } + +        virtual void +        traverse (SemanticGraph::Attribute& a) +        { +          String const& aname (eaname (a)); + +          os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl +             << "return false;" +             << endl; +        } +      }; + +      struct AnyComparison: Traversal::Any, +                            Traversal::AnyAttribute, +                            Context +      { +        AnyComparison (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          String const& aname (eaname (a)); + +          if (max (a) == 1 && min (a) == 1) +            os << "if (!x." << aname << " ().isEqualNode (&y." << +              aname << " ()))"; +          else +            os << "if (!(x." << aname << " () == y." << aname << " ()))"; + +          os << endl +             << "return false;" +             << endl; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute& a) +        { +          String const& aname (eaname (a)); + +          os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl +             << "return false;" +             << endl; +        } +      }; + +      // Check whether a type has a parse() function (i.e., has any +      // members, recursively). +      // +      struct HasParseFunction: Traversal::Complex, +                               Traversal::Element, +                               Traversal::Any, +                               Traversal::Attribute, +                               Traversal::AnyAttribute, +                               Context +      { +        HasParseFunction (Context& c, bool& has_el, bool& has_at) +            : Context (c), has_el_ (has_el), has_at_ (has_at) +        { +          *this >> names_ >> *this; +          *this >> inherits_ >> *this; +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          if (mixed_p (c) && !c.context ().count ("mixed-in-base")) +            has_el_ = true; + +          names (c); + +          if (!(has_el_ && has_at_)) +            inherits (c); +        } + +        virtual void +        traverse (SemanticGraph::Element&) +        { +          has_el_ = true; +        } + +        virtual void +        traverse (SemanticGraph::Any&) +        { +          has_el_ = true; +        } + +        virtual void +        traverse (SemanticGraph::Attribute&) +        { +          has_at_ = true; +        } + +        virtual void +        traverse (SemanticGraph::AnyAttribute&) +        { +          if (options.generate_wildcard ()) +            has_at_ = true; +        } + +      private: +        bool& has_el_; +        bool& has_at_; + +        Traversal::Names names_; +        Traversal::Inherits inherits_; +      }; + +      // +      // +      struct FacetArray: Traversal::Complex, Context +      { +        FacetArray (Context& c) +            : Context (c) +        { +        } + +        virtual void +        traverse (Type& c) +        { +          Facets f; +          FacetCollector col (f); +          col.traverse (c); + +          for (Facets::const_iterator i (f.begin ()); i != f.end (); ++i) +          { +            if (i->first == L"fractionDigits") +              os << "{::xsd::cxx::tree::facet::fraction_digits, " << +                i->second << "UL}," << endl; +            else if (i->first == L"totalDigits") +              os << "{::xsd::cxx::tree::facet::total_digits, " << +                i->second << "UL}," << endl; +          } +        } + +      private: +        typedef map<String, String> Facets; + +        struct FacetCollector: Traversal::Complex +        { +          FacetCollector (Facets& facets) +              : facets_ (facets) +          { +            *this >> inherits_ >> *this; +          } + +          virtual void +          traverse (Type& c) +          { +            if (c.inherits_p ()) +            { +              // First collect our base so that we can override its +              // facets. +              // +              inherits (c); + +              using SemanticGraph::Restricts; + +              if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) +              { +                if (!r->facet_empty ()) +                { +                  Restricts::FacetIterator i (r->facet_find ("totalDigits")); + +                  if (i != r->facet_end ()) +                    facets_[i->first] = i->second; + +                  i = r->facet_find ("fractionDigits"); + +                  if (i != r->facet_end ()) +                    facets_[i->first] = i->second; +                } +              } +            } +          } + +        private: +          Traversal::Inherits inherits_; +          Facets& facets_; +        }; +      }; + +      // +      // +      struct Complex: Traversal::Complex, Context +      { +        Complex (Context& c) +            : Context (c), +              member_name_ (c), +              any_ (c), +              element_ (c), +              any_test_ (c), +              element_test_ (c), +              attribute_ (c), +              attribute_test_ (c), +              any_attribute_ (c), +              default_ctor_any_init_ (c), +              default_ctor_member_init_ (c), +              ctor_any_ (c), +              ctor_member_ (c, CtorArgType::type), +              element_ctor_any_ (c), +              element_ctor_member_ (c), +              assign_any_ (c), +              assign_member_ (c), +              comparison_any_ (c), +              comparison_member_ (c), +              facet_array_ (c) +        { +          bool gen_wildcard (options.generate_wildcard ()); + +          inherits_member_ >> member_name_; + +          names_element_ >> element_; +          if (gen_wildcard) +            names_element_ >> any_; + +          names_element_test_ >> element_test_; +          if (gen_wildcard) +            names_element_test_ >> any_test_; + +          names_attribute_ >> attribute_; +          names_attribute_test_ >> attribute_test_; +          names_any_attribute_ >> any_attribute_; + +          default_ctor_init_names_ >> default_ctor_member_init_; +          if (gen_wildcard) +            default_ctor_init_names_ >> default_ctor_any_init_; + +          ctor_names_ >> ctor_member_; +          if (gen_wildcard) +            ctor_names_ >> ctor_any_; + +          element_ctor_names_ >> element_ctor_member_; +          if (gen_wildcard) +            element_ctor_names_ >> element_ctor_any_; + +          assign_names_ >> assign_member_; +          if (gen_wildcard) +            assign_names_ >> assign_any_; + +          comparison_names_ >> comparison_member_; +          if (gen_wildcard) +            comparison_names_ >> comparison_any_; +        } + + +        virtual void +        traverse (Type& c) +        { +          bool gen_wildcard (options.generate_wildcard ()); + +          String name (ename (c)); + +          // If renamed name is empty then we do not need to generate +          // anything for this type. +          // +          bool renamed (renamed_type (c, name)); +          if (renamed && !name) +            return; + +          SemanticGraph::Context& ctx (c.context ()); + +          bool mixed (mixed_p (c) && !ctx.count ("mixed-in-base")); +          bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); + +          bool string_based (false); +          { +            IsStringBasedType t (string_based); +            t.dispatch (c); +          } + +          SemanticGraph::Enumeration* enum_base (0); +          { +            IsEnumBasedType t (enum_base); +            t.dispatch (c); +          } + +          bool facets (false); +          String base; // base type name +          if (c.inherits_p ()) +          { +            // Get base name. +            // +            std::wostringstream o; + +            BaseTypeName base_type (*this, o); +            Traversal::Inherits inherits_type (base_type); + +            // Cannot use inherits_none here because need the +            // result in a string. +            // +            inherits (c, inherits_type); + +            base = o.str (); + +            // See if we have any facets that we need to handle. +            // +            using SemanticGraph::Restricts; +            using SemanticGraph::Fundamental::Decimal; + +            if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) +            { +              if (!r->facet_empty () && +                  (r->facet_find ("fractionDigits") != r->facet_end () || +                   r->facet_find ("totalDigits") != r->facet_end ()) && +                  ultimate_base (c).is_a<Decimal> ()) +                facets = true; +            } +          } +          else +            base = any_type; + +          os << "// " << name << endl +             << "//" << endl +             << endl; + +          // +          // +          { +            Member member (*this, name); +            Traversal::Names names_member (member); +            names (c, names_member); +          } + +          // facets +          // +          if (facets) +          { +            os << "static const ::xsd::cxx::tree::facet _xsd_" << name << +              "_facet_table[] = " +               << "{"; + +            facet_array_.traverse (c); + +            os << "{::xsd::cxx::tree::facet::none, 0UL}" +               << "};"; +          } + +          // c-tors +          // +          bool generate_no_base_ctor (false); +          { +            GenerateWithoutBaseCtor t (generate_no_base_ctor); +            t.traverse (c); +          } + +          bool has_complex_non_op_args (false); +          bool has_poly_non_op_args (false); +          bool complex_poly_args_clash (true); +          { +            HasComplexPolyNonOptArgs t (*this, true, +                                        has_complex_non_op_args, +                                        has_poly_non_op_args, +                                        complex_poly_args_clash); +            t.traverse (c); +          } + +          // default c-tor +          // +          if (options.generate_default_ctor ()) +          { +            bool generate (false); +            { +              GenerateDefaultCtor t (*this, generate, generate_no_base_ctor); +              t.traverse (c); +            } + +            if (generate) +            { +              os << name << "::" << endl +                 << name << " ()" << endl +                 << ": " << base << " ()"; + +              if (edom_document_member_p (c)) +              { +                os << "," << endl +                   << "  " << edom_document_member (c) << " (" << +                  "::xsd::cxx::xml::dom::create_document< " << char_type << +                  " > ())"; +              } + +              if (mixed) +              { +                os << "," << endl +                   << "  " << ctx.get<String> ("mixed-member") << " (this)"; +              } + +              names (c, default_ctor_init_names_); + +              os << "{"; +              if (facets) +                os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +              os << "}"; +            } +          } + +          // c-tor (base, all-non-optional-members) +          // +          if (options.generate_from_base_ctor ()) +          { +            bool generate (false); +            { +              GenerateFromBaseCtor t (*this, generate); +              t.traverse (c); +            } + +            if (generate) +            { +              bool has_complex_non_op_args (false); +              bool has_poly_non_op_args (false); +              bool complex_poly_args_clash (true); +              { +                HasComplexPolyNonOptArgs t (*this, false, +                                            has_complex_non_op_args, +                                            has_poly_non_op_args, +                                            complex_poly_args_clash); +                t.traverse (c); +              } + +              String base_arg ( +                L"_xsd_" + ename (c.inherits ().base ()) + L"_base"); + +              os << name << "::" << endl +                 << name << " (const "; +              inherits (c, inherits_member_); +              os << "& " << base_arg; +              { +                FromBaseCtorArg args (*this, CtorArgType::type, true); +                Traversal::Names args_names (args); +                names (c, args_names); +              } +              os << ")" << endl +                 << ": " << base << " (" << base_arg << ")"; + +              if (edom_document_member_p (c)) +              { +                os << "," << endl +                   << "  " << edom_document_member (c) << " (" << +                  "::xsd::cxx::xml::dom::create_document< " << char_type << +                  " > ())"; +              } + +              if (mixed) +              { +                os << "," << endl +                   << "  " << ctx.get<String> ("mixed-member") << " (this)"; +              } + +              names (c, ctor_names_); + +              os << "{"; +              if (facets) +                os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +              os << "}"; + +              // If we have any complex arguments in the previous c-tor +              // then also generate the auto_ptr version. +              // +              if (has_complex_non_op_args) +              { +                CtorArgType const at (CtorArgType::complex_auto_ptr); + +                os << name << "::" << endl +                   << name << " (const "; +                inherits (c, inherits_member_); +                os << "& " << base_arg; +                { +                  FromBaseCtorArg args (*this, at, true); +                  Traversal::Names args_names (args); +                  names (c, args_names); +                } +                os << ")" << endl +                   << ": " << base << " (" << base_arg << ")"; + +                if (edom_document_member_p (c)) +                { +                  os << "," << endl +                     << "  " << edom_document_member (c) << " (" << +                    "::xsd::cxx::xml::dom::create_document< " << char_type << +                    " > ())"; +                } + +                if (mixed) +                { +                  os << "," << endl +                     << "  " << ctx.get<String> ("mixed-member") << " (this)"; +                } + +                { +                  CtorMember t (*this, at); +                  Traversal::Names n (t); + +                  if (gen_wildcard) +                    n >> ctor_any_; + +                  names (c, n); +                } + +                os << "{"; +                if (facets) +                  os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +                os << "}"; +              } + +              // If we are generating polymorphic code then we also need to +              // provide auto_ptr version for every polymorphic type. +              // +              if (polymorphic && +                  has_poly_non_op_args && !complex_poly_args_clash) +              { +                CtorArgType const at (CtorArgType::poly_auto_ptr); + +                os << name << "::" << endl +                   << name << " (const "; +                inherits (c, inherits_member_); +                os << "& " << base_arg; +                { +                  FromBaseCtorArg args (*this, at, true); +                  Traversal::Names args_names (args); +                  names (c, args_names); +                } +                os << ")" << endl +                   << ": " << base << " (" << base_arg << ")"; + +                if (edom_document_member_p (c)) +                { +                  os << "," << endl +                     << "  " << edom_document_member (c) << " (" << +                    "::xsd::cxx::xml::dom::create_document< " << char_type << +                    " > ())"; +                } + +                if (mixed) +                { +                  os << "," << endl +                     << "  " << ctx.get<String> ("mixed-member") << " (this)"; +                } + +                { +                  CtorMember t (*this, at); +                  Traversal::Names n (t); + +                  if (gen_wildcard) +                    n >> ctor_any_; + +                  names (c, n); +                } + +                os << "{"; +                if (facets) +                  os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +                os << "}"; +              } +            } +          } + +          // c-tor (all-non-optional-members) +          // +          if (generate_no_base_ctor) +          { +            CtorArgType const at (CtorArgType::type); + +            os << name << "::" << endl +               << name << " ("; +            { +              CtorArgsWithoutBase ctor_args (*this, at, true, true); +              ctor_args.dispatch (c); +            } +            os << ")" << endl +               << ": " << base << " ("; +            { +              CtorBase base (*this, at, ""); +              Traversal::Inherits inherits_base (base); + +              inherits (c, inherits_base); +            } +            os << ")"; + +            if (edom_document_member_p (c)) +            { +              os << "," << endl +                 << "  " << edom_document_member (c) << " (" << +                "::xsd::cxx::xml::dom::create_document< " << char_type << +                " > ())"; +            } + +            if (mixed) +            { +              os << "," << endl +                 << "  " << ctx.get<String> ("mixed-member") << " (this)"; +            } + +            names (c, ctor_names_); + +            os << "{"; +            if (facets) +              os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +            os << "}"; + +            // If we have any complex arguments in the previous c-tor +            // then also generate the auto_ptr version. One case where +            // this c-tor will be generated is restriction of anyType. +            // +            if (has_complex_non_op_args) +            { +              CtorArgType const at (CtorArgType::complex_auto_ptr); + +              os << name << "::" << endl +                 << name << " ("; +              { +                CtorArgsWithoutBase ctor_args (*this, at, true, true); +                ctor_args.dispatch (c); +              } +              os << ")" << endl +                 << ": " << base << " ("; +              { +                CtorBase base (*this, at, ""); +                Traversal::Inherits inherits_base (base); + +                inherits (c, inherits_base); +              } +              os << ")"; + +              if (edom_document_member_p (c)) +              { +                os << "," << endl +                   << "  " << edom_document_member (c) << " (" << +                  "::xsd::cxx::xml::dom::create_document< " << char_type << +                  " > ())"; +              } + +              if (mixed) +              { +                os << "," << endl +                   << "  " << ctx.get<String> ("mixed-member") << " (this)"; +              } + +              { +                CtorMember t (*this, at); +                Traversal::Names n (t); + +                if (gen_wildcard) +                  n >> ctor_any_; + +                names (c, n); +              } + +              os << "{"; +              if (facets) +                os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +              os << "}"; +            } + +            // If we are generating polymorphic code then we also need to +            // provide auto_ptr version for every polymorphic type. +            // +            if (polymorphic && +                has_poly_non_op_args && !complex_poly_args_clash) +            { +              CtorArgType const at (CtorArgType::poly_auto_ptr); + +              os << name << "::" << endl +                 << name << " ("; +              { +                CtorArgsWithoutBase ctor_args (*this, at, true, true); +                ctor_args.dispatch (c); +              } +              os << ")" << endl +                 << ": " << base << " ("; +              { +                CtorBase base (*this, at, ""); +                Traversal::Inherits inherits_base (base); + +                inherits (c, inherits_base); +              } +              os << ")"; + +              if (edom_document_member_p (c)) +              { +                os << "," << endl +                   << "  " << edom_document_member (c) << " (" << +                  "::xsd::cxx::xml::dom::create_document< " << char_type << +                  " > ())"; +              } + +              if (mixed) +              { +                os << "," << endl +                   << "  " << ctx.get<String> ("mixed-member") << " (this)"; +              } + +              { +                CtorMember t (*this, at); +                Traversal::Names n (t); + +                if (gen_wildcard) +                  n >> ctor_any_; + +                names (c, n); +              } + +              os << "{"; +              if (facets) +                os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +              os << "}"; +            } +          } + +          if (string_based) +          { +            // We might not have the value type if this enum is customized. +            // +            if (enum_base != 0 && enum_base->context ().count ("value")) +            { +              // c-tor (enum-value, all-non-optional-members) +              // +              CtorArgType const at (CtorArgType::type); +              String base_arg (L"_xsd_" + ename (*enum_base) + L"_base"); + +              os << name << "::" << endl +                 << name << " (" << fq_name (*enum_base) << "::" << +                evalue (*enum_base) << " " << base_arg; + +              { +                CtorArgsWithoutBase ctor_args (*this, at, true, false); +                ctor_args.dispatch (c); +              } + +              os << ")" << endl +                 << ": " << base << " ("; + +              { +                CtorBase base (*this, at, base_arg); +                Traversal::Inherits inherits_base (base); + +                inherits (c, inherits_base); +              } + +              os << ")"; + +              if (edom_document_member_p (c)) +              { +                os << "," << endl +                   << "  " << edom_document_member (c) << " (" << +                  "::xsd::cxx::xml::dom::create_document< " << char_type << +                  " > ())"; +              } + +              // Cannot be mixed. + +              names (c, ctor_names_); + +              os << "{"; +              if (facets) +                os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +              os << "}"; +            } + +            CtorArgType const at (CtorArgType::type); +            String base_arg (L"_xsd_" + ename (ultimate_base (c)) + L"_base"); + +            // c-tor (const char*, all-non-optional-members) +            // +            os << name << "::" << endl +               << name << " (const " << char_type << "* " << base_arg; + +            { +              CtorArgsWithoutBase ctor_args (*this, at, true, false); +              ctor_args.dispatch (c); +            } + +            os << ")" << endl +               << ": " << base << " ("; + +            { +              CtorBase base (*this, at, base_arg); +              Traversal::Inherits inherits_base (base); + +              inherits (c, inherits_base); +            } + +            os << ")"; + +            if (edom_document_member_p (c)) +            { +              os << "," << endl +                 << "  " << edom_document_member (c) << " (" << +                "::xsd::cxx::xml::dom::create_document< " << char_type << +                " > ())"; +            } + +            // Cannot be mixed. + +            names (c, ctor_names_); + +            os << "{"; +            if (facets) +              os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +            os << "}"; + + +            // c-tor (const std::string&, all-non-optional-members) +            // +            os << name << "::" << endl +               << name << " (const " << string_type << "& " << base_arg; + +            { +              CtorArgsWithoutBase ctor_args (*this, at, true, false); +              ctor_args.dispatch (c); +            } + +            os << ")" << endl +               << ": " << base << " ("; + +            { +              CtorBase base (*this, at, base_arg); +              Traversal::Inherits inherits_base (base); + +              inherits (c, inherits_base); +            } + +            os << ")"; + +            if (edom_document_member_p (c)) +            { +              os << "," << endl +                 << "  " << edom_document_member (c) << " (" << +                "::xsd::cxx::xml::dom::create_document< " << char_type << +                " > ())"; +            } + +            // Cannot be mixed. + +            names (c, ctor_names_); + +            os << "{"; +            if (facets) +              os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +            os << "}"; +          } + +          // c-tor (ultimate-base, all-non-optional-members) +          // +          { +            CtorArgType const at (CtorArgType::type); + +            os << name << "::" << endl +               << name << " ("; + +            String base_arg; + +            { +              CtorArgs ctor_args (*this, at, base_arg); +              ctor_args.dispatch (c); +            } + +            os << ")" << endl +               << ": " << base << " ("; + +            { +              CtorBase base (*this, at, base_arg); +              Traversal::Inherits inherits_base (base); + +              inherits (c, inherits_base); +            } + +            os << ")"; + +            if (edom_document_member_p (c)) +            { +              os << "," << endl +                 << "  " << edom_document_member (c) << " (" << +                "::xsd::cxx::xml::dom::create_document< " << char_type << +                " > ())"; +            } + +            if (mixed) +            { +              os << "," << endl +                 << "  " << ctx.get<String> ("mixed-member") << " (this)"; +            } + +            names (c, ctor_names_); + +            os << "{"; +            if (facets) +              os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +            os << "}"; +          } + +          // If we have any complex arguments in the previous c-tor +          // then also generate the auto_ptr version. +          // +          if (has_complex_non_op_args) +          { +            CtorArgType const at (CtorArgType::complex_auto_ptr); +            String base_arg; + +            os << name << "::" << endl +               << name << " ("; + +            { +              CtorArgs ctor_args (*this, at, base_arg); +              ctor_args.dispatch (c); +            } + +            os << ")" << endl +               << ": " << base << " ("; + +            { +              CtorBase base (*this, at, base_arg); +              Traversal::Inherits inherits_base (base); + +              inherits (c, inherits_base); +            } + +            os << ")"; + +            if (edom_document_member_p (c)) +            { +              os << "," << endl +                 << "  " << edom_document_member (c) << " (" << +                "::xsd::cxx::xml::dom::create_document< " << char_type << +                " > ())"; +            } + +            if (mixed) +            { +              os << "," << endl +                 << "  " << ctx.get<String> ("mixed-member") << " (this)"; +            } + +            { +              CtorMember t (*this, at); +              Traversal::Names n (t); + +              if (gen_wildcard) +                n >> ctor_any_; + +              names (c, n); +            } + +            os << "{"; +            if (facets) +              os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +            os << "}"; +          } + +          // If we are generating polymorphic code then we also need to +          // provide auto_ptr version for every polymorphic type. +          // +          if (polymorphic && +              has_poly_non_op_args && !complex_poly_args_clash) +          { +            CtorArgType const at (CtorArgType::poly_auto_ptr); +            String base_arg; + +            os << name << "::" << endl +               << name << " ("; + +            { +              CtorArgs ctor_args (*this, at, base_arg); +              ctor_args.dispatch (c); +            } + +            os << ")" << endl +               << ": " << base << " ("; + +            { +              CtorBase base (*this, at, base_arg); +              Traversal::Inherits inherits_base (base); + +              inherits (c, inherits_base); +            } + +            os << ")"; + +            if (edom_document_member_p (c)) +            { +              os << "," << endl +                 << "  " << edom_document_member (c) << " (" << +                "::xsd::cxx::xml::dom::create_document< " << char_type << +                " > ())"; +            } + +            if (mixed) +            { +              os << "," << endl +                 << "  " << ctx.get<String> ("mixed-member") << " (this)"; +            } + +            { +              CtorMember t (*this, at); +              Traversal::Names n (t); + +              if (gen_wildcard) +                n >> ctor_any_; + +              names (c, n); +            } + +            os << "{"; +            if (facets) +              os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +            os << "}"; +          } + + +          // copy c-tor +          // + +          os << name << "::" << endl +             << name << " (const " << name << "& x," << endl +             << flags_type << " f," << endl +             << container << "* c)" << endl +             << ": " << base << " (x, f, c)"; + +          if (edom_document_member_p (c)) +          { +            os << "," << endl +               << "  " << edom_document_member (c) << " (" << +              "::xsd::cxx::xml::dom::create_document< " << char_type << +              " > ())"; +          } + +          if (mixed) +          { +            String const& m (ctx.get<String> ("mixed-member")); +            os << "," << endl +               << "  " << m << " (x." << m << ", f, this)"; +          } + +          if (ordered) +          { +            String const& m (ctx.get<String> ("order-member")); +            os << "," << endl +               << "  " << m << " (x." << m << ")"; +          } + +          { +            CopyAny copy_any (*this, "x"); +            CopyMember copy_member (*this, "x"); +            Traversal::Names names; + +            names >> copy_member; + +            if (gen_wildcard) +              names >> copy_any; + +            Complex::names (c, names); +          } + +          os << "{"; +          if (facets) +            os << "this->_facet_table (_xsd_" << name << "_facet_table);"; +          os << "}"; + +          // +          // +          bool he (has<Traversal::Element> (c)); +          bool hae (has<Traversal::Any> (c)); + +          bool ha (has<Traversal::Attribute> (c)); +          bool haa (has<Traversal::AnyAttribute> (c)); + +          // +          // +          if (!options.suppress_parsing ()) +          { +            // c-tor (xercesc::DOMElement) +            // +            os << name << "::" << endl +               << name << " (const " << xerces_ns << "::DOMElement& e," << endl +               << flags_type << " f," << endl +               << container << "* c)" << endl +               << ": " << base << " (e, f"; + +            if (he || ha || hae || (haa && gen_wildcard) || mixed) +              os << " | " << flags_type << "::base"; + +            os << ", c)"; + +            if (edom_document_member_p (c)) +            { +              os << "," << endl +                 << "  " << edom_document_member (c) << " (" << +                "::xsd::cxx::xml::dom::create_document< " << char_type << +                " > ())"; +            } + +            if (mixed) +            { +              os << "," << endl +                 << "  " << ctx.get<String> ("mixed-member") << " (this)"; +            } + +            names (c, element_ctor_names_); + +            os << "{"; + +            if (facets) +              os << "this->_facet_table (_xsd_" << name << "_facet_table);" +                 << endl; + +            bool base_has_el (false), base_has_at (false); + +            // We are only interested in this information if we are +            // generating our own parse(). +            // +            if (he || ha || hae || (haa && gen_wildcard) || mixed) +            { +              if (c.inherits_p ()) +              { +                HasParseFunction test (*this, base_has_el, base_has_at); +                test.dispatch (c.inherits ().base ()); +              } +            } + +            //@@ Throw if p is not exhausted at the end. +            // +            if (he || ha || hae || (haa && gen_wildcard) || mixed) +              os << "if ((f & " << flags_type << "::base) == 0)" +                 << "{" +                 << parser_type << " p (e, " << +                (he || hae || base_has_el || mixed_p (c) ? "true, " : "false, ") << +                (mixed_p (c) ? "true, " : "false, ") << +                (ha || (haa && gen_wildcard) || base_has_at ? "true" : "false") +                 << ");" +                 << "this->" << unclash (name, "parse") << " (p, f);" +                 << "}"; + +            os << "}"; + +            bool simple (true); +            { +              IsSimpleType t (simple); +              t.dispatch (c); +            } + +            if (simple) +            { +              // c-tor (xercesc::DOMAttr) +              // +              os << name << "::" << endl +                 << name << " (const " << xerces_ns << "::DOMAttr& a," << endl +                 << flags_type << " f," << endl +                 << container << "* c)" << endl +                 << ": " << base << " (a, f, c)" +                 << "{"; + +              if (facets) +                os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + +              os << "}"; + +              // c-tor (string const&, xercesc::DOMElement) +              // +              os << name << "::" << endl +                 << name << " (const " << string_type << "& s," << endl +                 << "const " << xerces_ns << "::DOMElement* e," << endl +                 << flags_type << " f," << endl +                 << container << "* c)" << endl +                 << ": " << base << " (s, e, f, c)" +                 << "{"; + +              if (facets) +                os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + +              os << "}"; +            } + +            if (he || ha || hae || (haa && gen_wildcard) || mixed) +            { +              os << "void " << name << "::" << endl +                 << unclash (name, "parse") << " (" << +                parser_type << "& p," << endl +                 << flags_type << +                (he || ha || base_has_el || base_has_at ? " f" : "") << ")" +                 << "{"; + +              // Allow the base to parse its part. +              // +              if (base_has_el || base_has_at) +                os << "this->" << base << "::parse (p, f);" +                   << endl; + +              if (he || hae || mixed_p (c)) +              { +                bool m (mixed_p (c)); + +                os << "for (; p.more_content (); p.next_content (" << +                  (m ? "true" : "false") << "))" +                   << "{"; + +                if (m) +                { +                  String const& ma (ctx.get<String> ("mixed-aname")); +                  String const& mi (ctx.get<String> ("mixed-ordered-id-name")); +                  String const& oa (ctx.get<String> ("order-aname")); +                  String const& ot (ctx.get<String> ("order-type")); + +                  os << "if (p.cur_is_text ())" +                     << "{" +                     << "const " << xerces_ns << "::DOMText& t (" << +                    "p.cur_text ());" +                     << "this->" << ma << " ().push_back (" << endl +                     << "::xsd::cxx::xml::transcode< " << char_type << " > (" << +                    "t.getData (), t.getLength ()));" +                     << "this->" << oa << " ().push_back (" << endl +                     << ot << " (" << mi << "," << endl +                     << "this->" << ma << " ().size () - 1));" +                     << "continue;" +                     << "}"; +                } + +                if (he || hae) +                { +                  os << "const " << xerces_ns << "::DOMElement& i (" << +                    "p.cur_element ());" +                     << "const " << qname_type << " n (" << endl +                     << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" +                     << endl; + +                  names (c, names_element_); +                } + +                os << "break;" +                   << "}"; + +                // Make sure all non-optional elements are set. +                // +                names (c, names_element_test_); +              } + +              if (ha || (haa && gen_wildcard)) +              { +                if (base_has_at) +                  os << "p.reset_attributes ();" +                     << endl; + +                os << "while (p.more_attributes ())" +                   << "{" +                   << "const " << xerces_ns << "::DOMAttr& i (" << +                  "p.next_attribute ());" +                   << "const " << qname_type << " n (" << endl +                   << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" +                   << endl; + +                names (c, names_attribute_); + +                // Generate anyAttribute code after all the attributes. +                // +                if (gen_wildcard) +                  names (c, names_any_attribute_); + + +                // os << "{"  // else block +                // @@ +                // This doesn't play well with inheritance because we +                // don't expect base's attributes. Also there are other +                // "special" attributes such as xmlns, etc. +                // +                // << "throw ::xsd::cxx::tree::unexpected_attribute ... " +                // << "}"; + +                os << "}"; // while loop + +                // Make sure all non-optional attributes are set. +                // +                names (c, names_attribute_test_); +              } + +              os << "}"; +            } +          } + +          // _clone +          // +          if (!(c.abstract_p () || +                (renamed && polymorphic && polymorphic_p (c)))) +            os << name << "* " << name << "::" << endl +               << "_clone (" << flags_type << " f," << endl +               << container << "* c) const" +               << "{" +               << "return new class " << name << " (*this, f, c);" +               << "}"; + +          // operator= +          // +          if (!options.suppress_assignment () && +              (he || ha || (gen_wildcard && (hae || haa)))) +          { +            os << name << "& " << name << "::" << endl +               << "operator= (const " << name << "& x)" +               << "{" +               << "if (this != &x)" +               << "{" +               << "static_cast< " << base << "& > (*this) = x;"; + +            // Note that here we don't assign the DOMDocument that is +            // used to hold wildcard fragments. Each document has its +            // own copy. + +            // Mixed text content. +            // +            if (mixed) +            { +              String const& m (ctx.get<String> ("mixed-member")); +              os << "this->" << m << " = x." << m << ";"; +            } + +            // Order container. +            // +            if (ordered) +            { +              String const& m (ctx.get<String> ("order-member")); +              os << "this->" << m << " = x." << m << ";"; +            } + +            names (c, assign_names_); + +            os << "}" +               << "return *this;" +               << "}"; +          } + +          // d-tor +          // +          os << name << "::" << endl +             << "~" << name << " ()" +             << "{" +             << "}"; + +          // Register with type factory map. +          // +          if (polymorphic && polymorphic_p (c) && !c.abstract_p ()) +          { +            // Note that we are using the original type name. +            // +            String const& name (ename (c)); + +            // If this type is anonymous but substitutes, then it will +            // be registered as part of the substitution registration. +            // +            if (!anonymous_p (c) && !options.suppress_parsing ()) +            { +              os << "static" << endl +                 << "const ::xsd::cxx::tree::type_factory_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +                 << "_xsd_" << name << "_type_factory_init (" << endl +                 << strlit (c.name ()) << "," << endl +                 << strlit (xml_ns_name (c)) << ");" +                 << endl; +            } + +            if ((!anonymous_p (c) || anonymous_substitutes_p (c)) && +                options.generate_comparison ()) +            { +              os << "static" << endl +                 << "const ::xsd::cxx::tree::comparison_initializer< " << +                poly_plate << ", " << char_type << ", " << name << " >" << endl +                 << "_xsd_" << name << "_comparison_init;" +                 << endl; +            } +          } + +          // Comparison operators. +          // +          if (options.generate_comparison () && +              (he || ha || mixed || ordered || !c.inherits_p () || +               ((hae || haa) && gen_wildcard))) +          { +            bool base_comp (false); + +            if (c.inherits_p ()) +            { +              HasComparisonOperator test (*this, base_comp); +              test.dispatch (c.inherits ().base ()); +            } + +            bool has_body (he || ha || ordered || mixed || base_comp || +                           ((hae || haa) && gen_wildcard)); + +            os << "bool" << endl +               << "operator== (const " << name << "&" << +              (has_body ? " x" : "") << ", " << +              "const " << name << "&" << (has_body ? " y" : "") << ")" +               << "{"; + +            if (base_comp) +              os << "if (!(static_cast< const " << base << "& > (x) ==" << endl +                 << "static_cast< const " << base << "& > (y)))" << endl +                 << "return false;" +                 << endl; + +            { +              Complex::names (c, comparison_names_); +            } + +            if (mixed) +            { +              String const& an (ctx.get<String> ("mixed-aname")); +              os << "if (!(x." << an << " () == y." << an << " ()))" << endl +                 << "return false;" +                 << endl; +            } + +            if (ordered) +            { +              String const& an (ctx.get<String> ("order-aname")); +              os << "if (!(x." << an << " () == y." << an << " ()))" << endl +                 << "return false;" +                 << endl; +            } + +            os << "return true;" +               << "}"; + +            os << "bool" << endl +               << "operator!= (const " << name << "& x, " << +              "const " << name << "& y)" +               << "{" +               << "return !(x == y);" +               << "}"; +          } +        } + +      private: +        Traversal::Inherits inherits_member_; +        MemberTypeName member_name_; + +        Traversal::Names names_element_; +        Traversal::Names names_element_test_; + +        Traversal::Names names_attribute_; +        Traversal::Names names_any_attribute_; +        Traversal::Names names_attribute_test_; + +        Any any_; +        Element element_; + +        AnyTest any_test_; +        ElementTest element_test_; + +        Attribute attribute_; +        AttributeTest attribute_test_; + +        AnyAttribute any_attribute_; + +        DefaultCtorAnyInit default_ctor_any_init_; +        DefaultCtorMemberInit default_ctor_member_init_; +        Traversal::Names default_ctor_init_names_; + +        CtorAny ctor_any_; +        CtorMember ctor_member_; +        Traversal::Names ctor_names_; + +        ElementCtorAny element_ctor_any_; +        ElementCtorMember element_ctor_member_; +        Traversal::Names element_ctor_names_; + +        AssignAny assign_any_; +        AssignMember assign_member_; +        Traversal::Names assign_names_; + +        AnyComparison comparison_any_; +        MemberComparison comparison_member_; +        Traversal::Names comparison_names_; + +        FacetArray facet_array_; +      }; + + +      // Generate element types and substitution group map entries. +      // +      struct GlobalElement: Traversal::Element, +                            GlobalElementBase, +                            Context +      { +        GlobalElement (Context& c) +            : GlobalElementBase (c), +              Context (c), +              element_type_ (c.options.generate_element_type ()), +              element_map_ (c.options.generate_element_map ()), +              type_name_ (c) +        { +          belongs_ >> type_name_; +        } + +        virtual void +        traverse (Type& e) +        { +          SemanticGraph::Type& t (e.type ()); + +          // Check if this element is abstract. +          // +          bool abst; +          { +            SemanticGraph::Complex* tc; +            abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && +              tc->abstract_p (); +          } + +          if (!abst && element_type_ && doc_root_p (e)) +          { +            bool fund (false); +            { +              IsFundamentalType test (fund); +              test.dispatch (t); +            } + +            bool simple (true); +            if (!fund) +            { +              IsSimpleType test (simple); +              test.dispatch (t); +            } + +            String const& name (ename (e)); +            String const& type (etype (e)); +            String const& member (emember (e)); + +            os << "// " << name << endl +               << "//" << endl +               << endl; + +            // Virtual accessors. +            // +            os << "const " << any_type << "* " << name << "::" << endl +               << "_value () const" +               << "{"; + +            if (fund) +              os << "return 0;"; +            else +              os << "return &this->" << member << ".get ();"; + +            os << "}"; + +            os << any_type << "* " << name << "::" << endl +               << "_value ()" +               << "{"; + +            if (fund) +              os << "return 0;"; +            else +              os << "return &this->" << member << ".get ();"; + +            os << "}"; + +            // default c-tor +            // +            if (options.generate_default_ctor ()) +            { +              os << name << "::" << endl +                 << name << " ()" << endl +                 << ": " << member << " (0)" +                 << "{" +                 << "}"; +            } + +            // c-tor (value) +            // +            os << name << "::" << endl +               << name << " (const " << type << "& x)" << endl +               << ": " << member << " (x, 0)" +               << "{" +               << "}"; + + +            // c-tor (auto_ptr<value>) +            // +            if (!simple || (polymorphic && polymorphic_p (t))) +            { +              os << name << "::" << endl +                 << name << " (" << auto_ptr << "< " << type << " > p)" << endl +                 << ": " << member << " (" << +                (std >= cxx_version::cxx11 ? "::std::move (p)" : "p") << ", 0)" +                 << "{" +                 << "}"; +            } + +            // c-tor (xercesc::DOMElement) +            // +            SemanticGraph::Context& ec (e.context ()); +            String const& name_member (ec.get<String> ("element-name-member")); +            String const& ns_member (ec.get<String> ("element-ns-member")); + +            bool parsing (!options.suppress_parsing ()); +            if (parsing) +            { +              String const& tr (etraits (e)); + +              os << name << "::" << endl +                 << name << " (const " << xerces_ns << "::DOMElement& e, " << +                flags_type << " f)" << endl +                 << ": " << member << " (0)" +                 << "{" +                 << "const " << qname_type << " n (" << endl +                 << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" +                 << endl +                 << "if (n.name () == " << name_member << " && " << +                "n.namespace_ () == " << ns_member << ")" << endl +                 << "this->" << member << ".set (" << tr << +                "::create (e, f, 0));" +                 << "else" << endl +                 << "throw ::xsd::cxx::tree::unexpected_element < " << +                char_type << " > (" << endl +                 << "n.name (), n.namespace_ ()," << endl +                 << name_member << ", " << ns_member << ");" +                 << "}"; +            } + +            // copy c-tor +            // +            os << name << "::" << endl +               << name << " (const " << name << "& x, " << +              flags_type << " f)" << endl +               << ": " << element_type << " ()," << endl +               << "  " << member << " (x." << member << ", f, 0)" +               << "{" +               << "}"; + +            // _clone +            // +            os << name << "* " << name << "::" << endl +               << "_clone (" << flags_type << " f) const" +               << "{" +               << "return new class " << name << " (*this, f);" +               << "}"; + +            // Element name and namespace accessors. +            // +            String const& aname (ec.get<String> ("element-name")); +            String const& ans (ec.get<String> ("element-ns")); + +            os << "const " << string_type << "& " << name << "::" << endl +               << aname << " ()" +               << "{" +               << "return " << name_member << ";" +               << "}"; + +            os << "const " << string_type << "& " << name << "::" << endl +               << ans << " ()" +               << "{" +               << "return " << ns_member << ";" +               << "}"; + +            os << "const " << string_type << "& " << name << "::" << endl +               << "_name () const" +               << "{" +               << "return " << name_member << ";" +               << "}"; + +            os << "const " << string_type << "& " << name << "::" << endl +               << "_namespace () const" +               << "{" +               << "return " << ns_member << ";" +               << "}"; + +            os << "const " << string_type << " " << name << "::" << endl +               << name_member << " (" << strlit (e.name ()) << ");" +               << endl +               << "const " << string_type << " " << name << "::" << endl +               << ns_member << " (" << strlit (e.namespace_ ().name ()) << ");" +               << endl; + +            // d-tor +            // +            os << name << "::" << endl +               << "~" << name << " ()" +               << "{" +               << "}"; + +            // Element map registration. +            // +            if (element_map_ && parsing) +            { +              os << "static " << endl +                 << "const ::xsd::cxx::tree::parser_init< " << name << ", " << +                char_type << ", " << any_type << " >" << endl +                 << "_xsd_" << name << "_parser_init (" << +                name << "::" << aname << " (), " << +                name << "::" << ans << " ());" +                 << endl; +            } +          } + +          // Note that we cannot just omit this element if it's abstract +          // because it may serve as a "link" between the root of the +          // substitution group and a non-abstract element that uses this +          // element as its root (see element_factory_map::find_substitution() +          // for details). +          // +          if (polymorphic && e.substitutes_p () && !options.suppress_parsing ()) +          { +            String const& name (ename (e)); +            Type& r (e.substitutes ().root ()); + +            os << "static" << endl +               << "const ::xsd::cxx::tree::element_factory_initializer< " << +              poly_plate << ", " << char_type << " >" << endl +               << "_xsd_" << name << "_element_factory_init (" << endl +               << strlit (r.name ()) << "," << endl +               << strlit (r.namespace_ ().name ()) << "," << endl +               << strlit (e.name ()) << "," << endl +               << strlit (e.namespace_ ().name ()) << "," << endl; + +            if (abst) +              os << "0"; +            else +            { +              os << "&::xsd::cxx::tree::factory_impl< "; +              belongs (e, belongs_); +              os << " >"; +            } + +            os << ");" +               << endl +               << endl; +          } +        } + +      private: +        bool element_type_; +        bool element_map_; +        Traversal::Belongs belongs_; +        MemberTypeName type_name_; +      }; +    } + +    void +    generate_tree_source (Context& ctx, size_t first, size_t last) +    { +      if (ctx.options.generate_wildcard ()) +      { +        ctx.os << "#include <xsd/cxx/xml/dom/wildcard-source.hxx>" << endl +               << endl; +      } + +      if (!ctx.options.suppress_parsing ()) +        ctx.os << "#include <xsd/cxx/xml/dom/parsing-source.hxx>" << endl +               << endl; + +      if (ctx.polymorphic) +      { +        bool parsing (!ctx.options.suppress_parsing ()); +        bool comparison (ctx.options.generate_comparison ()); + +        if (parsing) +          ctx.os << "#include <xsd/cxx/tree/type-factory-map.hxx>" << endl +                 << endl; + +        if (comparison) +          ctx.os << "#include <xsd/cxx/tree/comparison-map.hxx>" << endl +                 << endl; + +        if (parsing || comparison) +        { +          bool import_maps (ctx.options.import_maps ()); +          bool export_maps (ctx.options.export_maps ()); + +          if (import_maps || export_maps) +          { +            ctx.os << "#ifndef XSD_NO_EXPORT" << endl +                   << endl +                   << "namespace xsd" +                   << "{" +                   << "namespace cxx" +                   << "{" +                   << "namespace tree" +                   << "{" +                   << "#ifdef _MSC_VER" << endl; + +            if (parsing && export_maps) +              ctx.os << "template struct __declspec (dllexport) " << +                "type_factory_plate< " << ctx.poly_plate << ", " << +                ctx.char_type << " >;"; + +            if (parsing && import_maps) +              ctx.os << "template struct __declspec (dllimport) " << +                "type_factory_plate< " << ctx.poly_plate << ", " << +                ctx.char_type << " >;"; + +            if (comparison && export_maps) +              ctx.os << "template struct __declspec (dllexport) " << +                "comparison_plate< " << ctx.poly_plate << ", " << +                ctx.char_type << " >;"; + +            if (comparison && import_maps) +              ctx.os << "template struct __declspec (dllimport) " << +                "comparison_plate< " << ctx.poly_plate << ", " << +                ctx.char_type << " >;"; + +            ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl; + +            if (parsing) +              ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << +                "type_factory_plate< " << ctx.poly_plate << ", " << +                ctx.char_type << " >;"; + +            if (comparison) +              ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << +                "comparison_plate< " << ctx.poly_plate << ", " << +                ctx.char_type << " >;"; + +            ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl; + +            if (parsing) +              ctx.os << "template struct XSD_MAP_VISIBILITY " << +                "type_factory_plate< " << ctx.poly_plate << ", " << +                ctx.char_type << " >;"; + +            if (comparison) +              ctx.os << "template struct XSD_MAP_VISIBILITY " << +                "comparison_plate< " << ctx.poly_plate << ", " << +                ctx.char_type << " >;"; + +            ctx.os << "#endif" << endl +                   << "}"  // tree +                   << "}"  // cxx +                   << "}"  // xsd +                   << "#endif // XSD_NO_EXPORT" << endl +                   << endl; +          } + +          ctx.os << "namespace _xsd" +                 << "{"; + +          if (parsing) +            ctx.os << "static" << endl +                   << "const ::xsd::cxx::tree::type_factory_plate< " << +              ctx.poly_plate << ", " << ctx.char_type << " >" << endl +                   << "type_factory_plate_init;" +                   << endl; + +          if (comparison) +            ctx.os << "static" << endl +                   << "const ::xsd::cxx::tree::comparison_plate< " << +              ctx.poly_plate << ", " << ctx.char_type << " >" << endl +                   << "comparison_plate_init;" +                   << endl; + +          ctx.os << "}"; +        } +      } + +      Traversal::Schema schema; +      Sources sources; +      Traversal::Names names_ns, names; +      Namespace ns (ctx, first, last); + +      List list (ctx); +      Union union_ (ctx); +      Complex complex (ctx); +      Enumeration enumeration (ctx); +      GlobalElement element (ctx); + +      schema >> sources >> schema; +      schema >> names_ns >> ns >> names; + +      names >> list; +      names >> union_; +      names >> complex; +      names >> enumeration; +      names >> element; + +      schema.dispatch (ctx.schema_root); +    } +  } +} diff --git a/xsd/cxx/tree/tree-source.hxx b/xsd/cxx/tree/tree-source.hxx new file mode 100644 index 0000000..66dcff7 --- /dev/null +++ b/xsd/cxx/tree/tree-source.hxx @@ -0,0 +1,18 @@ +// file      : xsd/cxx/tree/tree-source.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_TREE_SOURCE_HXX +#define XSD_CXX_TREE_TREE_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ +  namespace Tree +  { +    void +    generate_tree_source (Context&, size_t first, size_t last); +  } +} + +#endif  // XSD_CXX_TREE_TREE_SOURCE_HXX diff --git a/xsd/cxx/tree/validator.cxx b/xsd/cxx/tree/validator.cxx new file mode 100644 index 0000000..9785560 --- /dev/null +++ b/xsd/cxx/tree/validator.cxx @@ -0,0 +1,676 @@ +// file      : xsd/cxx/tree/validator.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <iostream> + +#include <xsd/cxx/tree/validator.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/elements.hxx> + +using namespace std; + +namespace CXX +{ +  namespace Tree +  { +    namespace +    { +      class ValidationContext: public Context +      { +      public: +        ValidationContext (SemanticGraph::Schema& root, +                           SemanticGraph::Path const& path, +                           Tree::options const& ops, +                           const WarningSet& disabled_warnings, +                           Counts const& counts, +                           bool generate_xml_schema, +                           bool& valid_) +            : Context (std::wcerr, +                       root, +                       path, +                       ops, +                       counts, +                       generate_xml_schema, +                       0, +                       0, +                       0, +                       0), +              disabled_warnings_ (disabled_warnings), +              disabled_warnings_all_ (false), +              valid (valid_), +              subst_group_warning_issued (subst_group_warning_issued_), +              subst_group_warning_issued_ (false) +        { +          if (disabled_warnings_.find ("all") != disabled_warnings_.end ()) +            disabled_warnings_all_ = true; +        } + +      public: +        bool +        is_disabled (char const* w) +        { +          return disabled_warnings_all_ || +            disabled_warnings_.find (w) != disabled_warnings_.end (); +        } + +      public: +        String +        xpath (SemanticGraph::Nameable& n) +        { +          if (n.is_a<SemanticGraph::Namespace> ()) +            return L"<namespace-level>"; // There is a bug if you see this. + +          if (n.named_p ()) +          { +            SemanticGraph::Scope& scope (n.scope ()); + +            if (scope.is_a<SemanticGraph::Namespace> ()) +              return n.name (); + +            return xpath (scope) + L"/" + n.name (); +          } +          else +          { +            return L"(anonymous type for " + +              n.context ().get<String> ("instance-name") + L")"; +          } +        } + +      protected: +        ValidationContext (ValidationContext& c) +            :  Context (c), +               disabled_warnings_ (c.disabled_warnings_), +               disabled_warnings_all_ (c.disabled_warnings_all_), +               valid (c.valid), +               subst_group_warning_issued (c.subst_group_warning_issued) +        { +        } + +      protected: +        const WarningSet& disabled_warnings_; +        bool disabled_warnings_all_; + +        bool& valid; + +        bool& subst_group_warning_issued; +        bool subst_group_warning_issued_; +      }; + + +      // +      // +      struct Any: Traversal::Any, ValidationContext +      { +        Any (ValidationContext& c) +            : ValidationContext (c) +        { +        } + +        struct Element: Traversal::Element, ValidationContext +        { +          Element (ValidationContext& c, SemanticGraph::Any& any) +              : ValidationContext (c), +                any_ (any), +                ns_ (any.definition_namespace ().name ()) +          { +          } + +          virtual void +          traverse (SemanticGraph::Element& e) +          { +	    if (skip (e)) +              return; + +            using SemanticGraph::Any; + +            bool q (e.qualified_p ()); +            String ns (q ? e.namespace_ ().name () : ""); + +            for (Any::NamespaceIterator i (any_.namespace_begin ()); +                 i != any_.namespace_end (); ++i) +            { +              bool failed (false); + +              if (*i == L"##any") +              { +                failed = true; +              } +              else if (*i == L"##other") +              { +                if (ns_) +                { +                  // Note that here I assume that ##other does not +                  // include names without target namespace. This +                  // is not what the spec says but that seems to be +                  // the consensus. +                  // +                  failed = q && ns != ns_; +                } +                else +                { +                  // No target namespace. +                  // +                  failed = q && ns != L""; +                } +              } +              else if (*i == L"##local") +              { +                failed = !q || ns == L""; +              } +              else if (*i == L"##targetNamespace") +              { +                failed = (q && ns_ == ns) || (!q && ns_ == L""); +              } +              else +              { +                failed = q && *i == ns; +              } + +              if (failed) +              { +                Any& a (any_); + +                os << a.file () << ":" << a.line () << ":" << a.column () +                   << ": warning T001: namespace '" << *i << "' allows for " +                   << "element '" << e.name () << "'" << endl; + +                os << a.file () << ":" << a.line () << ":" << a.column () +                   << ": warning T001: generated code may not associate element '" +                   << e.name () << "' correctly if it appears in place of " +                   << "this wildcard" << endl; + +                os << e.file () << ":" << e.line () << ":" << e.column () +                   << ": info: element '" << e.name () << "' is defined " +                   << "here" << endl; +              } +            } +          } + +        private: +          SemanticGraph::Any& any_; +          String ns_; +        }; + +        struct Complex: Traversal::Complex +        { +          Complex () +              : up_ (true), down_ (true) +          { +          } + +          virtual void +          post (Type& c) +          { +            // Go down the inheritance hierarchy. +            // +            if (down_) +            { +              bool up = up_; +              up_ = false; + +              if (c.inherits_p ()) +                dispatch (c.inherits ().base ()); + +              up_ = up; +            } + +            // Go up the inheritance hierarchy. +            // +            if (up_) +            { +              bool down = down_; +              down_ = false; + +              for (Type::BegetsIterator i (c.begets_begin ()); +                   i != c.begets_end (); ++i) +              { +                dispatch (i->derived ()); +              } + +              down_ = down; +            } +          } + +        private: +          bool up_, down_; +        }; + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          using SemanticGraph::Compositor; + +          // Find our complex type. +          // +          Compositor* c (&a.contained_particle ().compositor ()); + +          while(!c->contained_compositor_p ()) +            c = &c->contained_particle ().compositor (); + +          SemanticGraph::Complex& type ( +            dynamic_cast<SemanticGraph::Complex&> ( +              c->contained_compositor ().container ())); + +          Complex complex; +          Traversal::Names names; +          Element element (*this, a); + +          complex >> names >> element; + +          complex.dispatch (type); +        } +      }; + + +      // +      // +      struct Traverser: Traversal::Schema, +                        Traversal::Complex, +                        Traversal::Type, +                        Traversal::Element, +                        ValidationContext +      { +        using Schema::traverse; + +        Traverser (ValidationContext& c) +            : ValidationContext (c), any_ (c) +        { +          *this >> sources_ >> *this; +          *this >> schema_names_ >> ns_ >> names_; + +          names_ >> *this >> names_; + +          // Any +          // +          if (!is_disabled ("T001")) +          { +            *this >> contains_compositor_ >> compositor_ >> contains_particle_; +            contains_particle_ >> compositor_; +            contains_particle_ >> any_; +          } +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          using SemanticGraph::Schema; + +          traverse (static_cast<SemanticGraph::Type&> (c)); + +          if (c.inherits_p ()) +          { +            SemanticGraph::Type& t (c.inherits ().base ()); + +            if (t.named_p () && +                types_.find ( +                  t.scope ().name () + L"#" + t.name ()) == types_.end ()) +            { +              // Don't worry about types that are in included/imported +              // schemas. +              // +              Schema& s (dynamic_cast<Schema&> (t.scope ().scope ())); + +              if (&s == &schema_root || sources_p (schema_root, s)) +              { +                valid = false; + +                os << c.file () << ":" << c.line () << ":" << c.column () +                   << ": error: type '" << xpath (c) << "' inherits from " +                   << "yet undefined type '" << xpath (t) << "'" << endl; + +                os << t.file () << ":" << t.line () << ":" << t.column () +                   << ": info: '" << xpath (t) << "' is defined here" +                   << endl; + +                os << c.file () << ":" << c.line () << ":" << c.column () +                   << ": info: inheritance from a yet-undefined type is " +                   << "not supported" << endl; + +                os << c.file () << ":" << c.line () << ":" << c.column () +                   << ": info: re-arrange your schema and try again" +                   << endl; +              } +            } +          } + +          Complex::traverse (c); +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          // This is also used to traverse Complex. +          // +          if (t.named_p ()) +          { +            types_.insert (t.scope ().name () + L"#" + t.name ()); +          } +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          if (is_disabled ("T002")) +            return; + +          // Note that there is no test for generate_p since we want +          // to catch cases when things are not being generated but +          // most likely should have been. +          // +          if (e.substitutes_p () && !polymorphic && +              !subst_group_warning_issued) +          { +            subst_group_warning_issued = true; + +            os << e.file () << ":" << e.line () << ":" << e.column () +               << ": warning T002: substitution groups are used but " +               << "--generate-polymorphic was not specified" << endl; + +            os << e.file () << ":" << e.line () << ":" << e.column () +               << ": info: generated code may not be able to handle " +               << "some conforming instances" << endl; +          } +        } + +        // Return true if root sources s. +        // +        bool +        sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) +        { +          using SemanticGraph::Schema; +          using SemanticGraph::Sources; + +          for (Schema::UsesIterator i (root.uses_begin ()); +               i != root.uses_end (); ++i) +          { +            if (i->is_a<Sources> ()) +            { +              if (&i->schema () == &s || sources_p (i->schema (), s)) +                return true; +            } +          } + +          return false; +        } + +      private: +        set<String> types_; + +        Sources sources_; + +        Traversal::Names schema_names_; +        Traversal::Namespace ns_; + +        Traversal::Names names_; + +        // Any. +        // +        Any any_; +        Traversal::Compositor compositor_; +        Traversal::ContainsParticle contains_particle_; +        Traversal::ContainsCompositor contains_compositor_; +      }; + + +      struct AnonymousType: Traversal::Schema, +                            Traversal::Complex, +                            Traversal::Element, +                            Traversal::Attribute, +                            ValidationContext +      { +        using Schema::traverse; +        using Complex::traverse; + +        AnonymousType (ValidationContext& c) +            : ValidationContext (c), +              anonymous_error_issued_ (false) +        { +          *this >> sources_ >> *this; +          *this >> schema_names_ >> ns_ >> names_ >> *this; +          *this >> names_; +        } + +        bool +        traverse_common (SemanticGraph::Member& m) +        { +          SemanticGraph::Type& t (m.type ()); + +          if (!t.named_p () +              && !t.is_a<SemanticGraph::Fundamental::IdRef> () +              && !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +          { +            if (!anonymous_error_issued_) +            { +              valid = false; +              anonymous_error_issued_ = true; + +              wcerr << t.file () +                    << ": error: anonymous types detected" +                    << endl; + +              wcerr << t.file () +                    << ": info: " +                    << "anonymous types are not supported in this mapping" +                    << endl; + +              wcerr << t.file () +                    << ": info: consider explicitly naming these types or " +                    << "remove the --preserve-anonymous option to " +                    << "automatically name them" +                    << endl; + +              if (!options.show_anonymous ()) +                wcerr << t.file () +                      << ": info: use --show-anonymous option to see these " +                      << "types" << endl; +            } + +            return true; +          } + +          return false; +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +	  if (skip (e)) return; + +          if (traverse_common (e)) +          { +            if (options.show_anonymous ()) +            { +              wcerr << e.file () << ":" << e.line () << ":" << e.column () +                    << ": error: element '" << xpath (e) << "' " +                    << "is of anonymous type" << endl; +            } +          } +          else +            Traversal::Element::traverse (e); +        } + +        virtual void +        traverse (SemanticGraph::Attribute& a) +        { +          if (traverse_common (a)) +          { +            if (options.show_anonymous ()) +            { +              wcerr << a.file () << ":" << a.line () << ":" << a.column () +                    << ": error: attribute '" << xpath (a) << "' " +                    << "is of anonymous type" << endl; +            } +          } +          else +            Traversal::Attribute::traverse (a); +        } + +      private: +        bool anonymous_error_issued_; + +        set<String> types_; + +        Sources sources_; + +        Traversal::Names schema_names_; +        Traversal::Namespace ns_; + +        Traversal::Names names_; +      }; +    } + +    bool Validator:: +    validate (options const& ops, +              SemanticGraph::Schema& schema, +              SemanticGraph::Path const& path, +              const WarningSet& disabled_warnings, +              Counts const& counts) +    { +      bool valid (true); +      ValidationContext ctx ( +        schema, path, ops, disabled_warnings, counts, false, valid); + +      // +      // +      bool import_maps (ops.import_maps ()); +      bool export_maps (ops.export_maps ()); + +      if (import_maps && export_maps) +      { +        wcerr << "error: --import-maps and --export-maps are " +              << "mutually exclusive" << endl; + +        return false; +      } + +      if (import_maps && !ctx.polymorphic) +      { +        wcerr << "error: --import-maps can only be specified together with " +              << "--generate-polymorphic" << endl; + +        return false; +      } + +      if (export_maps && !ctx.polymorphic) +      { +        wcerr << "error: --export-maps can only be specified together " << +          "with --generate-polymorphic" << endl; + +        return false; +      } + +      // +      // +      if (ops.char_type () != "char" && +          ops.char_type () != "wchar_t" && +          !ctx.is_disabled ("T003")) +      { +        wcerr << "warning T003: unknown base character type '" << +          ops.char_type ().c_str () << "'" << endl; +      } + +      // +      // +      NarrowString tn (ops.type_naming ()); + +      if (tn != "knr" && tn != "ucc" && tn != "java") +      { +        wcerr << "error: unknown type naming style specified: '" << +          tn.c_str () << "'" << endl; + +        return false; +      } + +      NarrowString fn (ops.function_naming ()); + +      if (fn != "knr" && fn != "lcc" && fn != "ucc" && fn != "java") +      { +        wcerr << "error: unknown function naming style specified: '" << +          fn.c_str () << "'" << endl; + +        return false; +      } + +      // +      // +      bool element_type (ops.generate_element_type ()); +      bool par (!ops.suppress_parsing ()); +      bool ser (ops.generate_serialization ()); + +      if (ops.generate_element_map ()) +      { +        if (!element_type) +        { +          wcerr << "error: --generate-element-map can only be specified " << +            "together with --generate-element-type" << endl; + +          return false; +        } + +        if (!(par || ser)) +        { +          wcerr << "error: --generate-element-map is specified but " << +            "neither parsing nor serialization code is generated" << endl; + +          return false; +        } +      } + +      // Issue a warning if there are more than one global element +      // and we are generating parsing/serialization functions or +      // element types for all of them by default. +      // + +      if (counts.global_elements > 1 && +          (element_type || par || ser) && +          !ops.root_element_first () && +          !ops.root_element_last () && +          !ops.root_element_all () && +          !ops.root_element_none () && +          ops.root_element ().empty () && +          !ctx.is_disabled ("T004")) +      { +        wcerr << schema.file () << ": warning T004: generating "; + +        if (element_type) +          wcerr << "element types"; +        else +        { +          wcerr << (par ? "parsing " : "") << +            (ser ? (par ? "and serialization " : "serialization ") : "") << +            "functions"; +        } +        wcerr << " for " << counts.global_elements << " global elements" << +          endl; + +        wcerr << schema.file () << ": info: use --root-element-* options " +              << "to specify document root(s)" << endl; +      } + + +      // Test for anonymout types. +      // +      { +        AnonymousType traverser (ctx); +        traverser.dispatch (schema); +      } + +      // Test the rest. +      // +      if (valid) +      { +        Traverser traverser (ctx); +        traverser.dispatch (schema); +      } + +      return valid; + +      // T005 is used in polymorphism-processor.cxx. +      // +    } +  } +} diff --git a/xsd/cxx/tree/validator.hxx b/xsd/cxx/tree/validator.hxx new file mode 100644 index 0000000..23f3f04 --- /dev/null +++ b/xsd/cxx/tree/validator.hxx @@ -0,0 +1,29 @@ +// file      : xsd/cxx/tree/validator.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_VALIDATOR_HXX +#define XSD_CXX_TREE_VALIDATOR_HXX + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/options.hxx> + +#include <xsd/xsd.hxx> + +namespace CXX +{ +  namespace Tree +  { +    class Validator +    { +    public: +      bool +      validate (options const&, +                SemanticGraph::Schema&, +                SemanticGraph::Path const& tu, +                const WarningSet& disabled_warnings, +                Counts const& counts); +    }; +  } +} + +#endif  // XSD_CXX_TREE_VALIDATOR_HXX diff --git a/xsd/elements.hxx b/xsd/elements.hxx new file mode 100644 index 0000000..d3dd659 --- /dev/null +++ b/xsd/elements.hxx @@ -0,0 +1,125 @@ +// file      : xsd/elements.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_ELEMENTS_HXX +#define XSD_ELEMENTS_HXX + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/types.hxx> + +namespace SemanticGraph = XSDFrontend::SemanticGraph; +namespace Traversal = XSDFrontend::Traversal; + +// Anonymous feedback via belongs edge. +// +struct AnonymousBase : Traversal::Element, Traversal::Attribute +{ +  AnonymousBase (Traversal::NodeDispatcher& d1) +      : complex_ (&d1, 0) +  { +    edge_traverser (belongs_); +    belongs_.node_traverser (complex_); +  } + +  AnonymousBase (Traversal::NodeDispatcher& d1, Traversal::NodeDispatcher& d2) +      : complex_ (&d1, &d2) +  { +    edge_traverser (belongs_); +    belongs_.node_traverser (complex_); +  } + +  // Hooks. +  // +public: +  virtual void +  member_pre (SemanticGraph::Member&) +  { +  } + +  virtual void +  member_post (SemanticGraph::Member&) +  { +  } + +  /* +    virtual void +    type_pre (SemanticGraph::Type& t) +    { +    } + +    virtual void +    type_post (SemanticGraph::Type& t) +    { +    } +  */ + +public: + +  virtual void +  traverse (SemanticGraph::Element& e) +  { +    SemanticGraph::Type& t (e.type ()); + +    if (!t.named_p () && !t.context ().count ("seen")) +    { +      t.context ().set ("seen", true); + +      member_pre (e); + +      Element::belongs (e, belongs_); + +      member_post (e); + +      t.context ().remove ("seen"); +    } +  } + +  virtual void +  traverse (SemanticGraph::Attribute& a) +  { +    SemanticGraph::Type& t (a.type ()); + +    if (!t.named_p () && !t.context ().count ("seen")) +    { +      t.context ().set ("seen", true); + +      member_pre (a); + +      Attribute::belongs (a, belongs_); + +      member_post (a); + +      t.context ().remove ("seen"); +    } +  } + +private: +  struct Complex : Traversal::Complex +  { +    Complex (Traversal::NodeDispatcher* d1, Traversal::NodeDispatcher* d2) +        : d1_ (d1), d2_ (d2) +    { +    } + +    virtual void +    traverse (SemanticGraph::Complex& c) +    { +      if (d1_) +        d1_->dispatch (c); + +      if (d2_) +        d2_->dispatch (c); +    } + +  private: +    Traversal::NodeDispatcher* d1_; +    Traversal::NodeDispatcher* d2_; + +  } complex_; + +  Traversal::Belongs belongs_; +}; + +#endif // XSD_ELEMENTS_HXX diff --git a/xsd/options-parser.hxx b/xsd/options-parser.hxx new file mode 100644 index 0000000..afcdf80 --- /dev/null +++ b/xsd/options-parser.hxx @@ -0,0 +1,29 @@ +// file      : xsd/options-parser.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_OPTIONS_PARSER_HXX +#define XSD_OPTIONS_PARSER_HXX + +#include <xsd/types.hxx> +#include <xsd/options.hxx> + +namespace cli +{ +  template <> +  struct parser<NarrowString> +  { +    static void +    parse (NarrowString& x, bool& xs, scanner& s) +    { +      xs = true; +      const char* o (s.next ()); + +      if (s.more ()) +        x = s.next (); +      else +        throw missing_value (o); +    } +  }; +} + +#endif // XSD_OPTIONS_PARSER_HXX diff --git a/xsd/options.cli b/xsd/options.cli new file mode 100644 index 0000000..3153be9 --- /dev/null +++ b/xsd/options.cli @@ -0,0 +1,322 @@ +// file      : xsd/options.cli +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include <cstddef>; // std::size_t +include <cstdint>; // std::uint64_t + +include <xsd/types.hxx>; // NarrowString, NarrowStrings + +class help_options +{ +  std::uint64_t --build2-metadata; // Leave undocumented/hidden. + +  // These are all documented elsewhere. +  // +  bool --help; +  bool --version; +  bool --proprietary-license; +}; + +class options = 0 +{ +  NarrowStrings --disable-warning +  { +    "<warn>", +    "Disable printing warning with id <warn>. If \cb{all} is specified for +     the warning id then all warnings are disabled." +  }; + +  // The following option is "fake" in that it is actually handled by +  // argv_file_scanner. We have it here to get the documentation. +  // +  std::string --options-file +  { +    "<file>", +    "Read additional options from <file>. Each option should appearing on a +     separate line optionally followed by space and an option value. Empty +     lines and lines starting with \cb{#} are ignored. Option values can +     be enclosed in double (\cb{\"}) or single (\cb{'}) quotes  to preserve +     leading and trailing whitespaces as well as to specify empty values. +     If the value itself contains trailing or leading quotes, enclose it +     with an extra pair of quotes, for example \cb{'\"x\"'}. Non-leading +     and non-trailing quotes are interpreted as being part of the option +     value. + +     The semantics of providing options in a file is equivalent to providing +     the same set of options in the same order on the command line at the +     point where the \cb{--options-file} option is specified except that +     the shell escaping and quoting is not required. You can repeat this +     option to specify more than one options file." +  }; + +  // SLOC/license options. +  // +  bool --show-sloc +  { +    "Show the number of generated physical source lines of code (SLOC)." +  }; + +  std::size_t --sloc-limit +  { +    "<num>", +    "Check that the number of generated physical source lines of code (SLOC) +     does not exceed <num>." +  }; + +  bool --proprietary-license +  { +    "Indicate that the generated code is licensed under a proprietary +     license instead of the GPL." +  }; + +  NarrowString --custom-literals +  { +    "<file>", +    "Load custom XML string to C++ literal mappings from <file>. This +     mechanism can be useful if you are using a custom character encoding +     and some of the strings in your schemas, for example element/attribute +     names or enumeration values, contain non-ASCII characters. In this +     case you will need to provide a custom mapping to C++ literals for +     such strings. The format of this file is specified in the +     \cb{custom-literals.xsd} XML Schema file that can be found in the +     documentation directory." +  }; + +  // Anonymous type morphing. +  // +  bool --preserve-anonymous +  { +    "Preserve anonymous types. By default anonymous types are automatically +     named with names derived from the enclosing elements/attributes. Because +     mappings implemented by this compiler require all types to be named, +     this option is only useful if you want to make sure your schemas don't +     have anonymous types." +  }; + +  bool --show-anonymous +  { +    "Show elements and attributes that are of anonymous types. This option +     only makes sense together with the \cb{--preserve-anonymous} option." +  }; + +  NarrowStrings --anonymous-regex +  { +    "<regex>", +    "Add <regex> to the list of regular expressions used to derive names for +     anonymous types from the enclosing attributes/elements. <regex> is a +     Perl-like regular expression in the form +     \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. +     Any character can be used as a delimiter instead of '\cb{/}'. Escaping of +     the delimiter character in \ci{pattern} or \ci{replacement} is not +     supported. + +     All the regular expressions are pushed into a stack with the last +     specified expression considered first. The first match that succeeds is +     used. Regular expressions are applied to a string in the form + +     \c{\i{filename} \i{namespace} \i{xpath}} + +     For instance: + +     \cb{hello.xsd http://example.com/hello element} + +     \cb{hello.xsd http://example.com/hello type/element} + +     As an example, the following expression makes all the derived names +     start with capital letters. This could be useful when your naming +     convention requires type names to start with capital letters: + +     \cb{%.* .* (.+/)*(.+)%\\u$2%} + +     See also the REGEX AND SHELL QUOTING section below." +  }; + +  bool --anonymous-regex-trace +  { +    "Trace the process of applying regular expressions specified with the +     \cb{--anonymous-regex} option. Use this option to find out why your +     regular expressions don't do what you expected them to do." +  }; + +  bool --morph-anonymous; // Deprecated and therefore undocumented. + +  // Location options. +  // +  NarrowStrings --location-map +  { +    "<ol>=<nl>", +    "Map the original schema location <ol> that is specified in the XML +     Schema include or import elements to new schema location <nl>. Repeat +     this option to map more than one schema location. For example, the +     following option maps the \cb{http://example.com/foo.xsd} URL to the +     \cb{foo.xsd} local file. + +     \cb{--location-map http://example.com/foo.xsd=foo.xsd}" +  }; + +  NarrowStrings --location-regex +  { +    "<regex>", +    "Add <regex> to the list of regular expressions used to map schema +     locations that are specified in the XML Schema include or import +     elements. <regex> is a Perl-like regular expression in the form +     \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. Any character can +     be used as a delimiter instead of '\cb{/}'. Escaping of the delimiter +     character in \ci{pattern} or \ci{replacement} is not supported. All +     the regular expressions are pushed into a stack with the last specified +     expression considered first. The first match that succeeds is used. + +     For example, the following expression maps URL locations in the form +     \cb{http://example.com/foo/bar.xsd} to local files in the form +     \cb{bar.xsd}: + +     \cb{%http://.+/(.+)%$1%} + +     See also the REGEX AND SHELL QUOTING section below." +  }; + +  bool --location-regex-trace +  { +    "Trace the process of applying regular expressions specified with the +     \cb{--location-regex} option. Use this option to find out why your +     regular expressions don't do what you expected them to do." +  }; + +  // File-per-type option. +  // +  bool --file-per-type +  { +    "Generate a separate set of C++ files for each type defined in XML +     Schema. Note that in this mode you only need to compile the root +     schema(s) and the code will be generated for all included and +     imported schemas. This compilation mode is primarily useful when +     some of your schemas cannot be compiled separately or have cyclic +     dependencies which involve type inheritance. Other options related +     to this mode are: \cb{--type-file-regex}, \cb{--schema-file-regex}, +     \cb{--fat-type-file}, and \cb{--file-list}." +  }; + +  NarrowStrings --type-file-regex +  { +    "<regex>", +    "Add <regex> to the list of regular expressions used to translate type +     names to file names when the \cb{--file-per-type} option is specified. +     <regex> is a Perl-like regular expression in the form +     \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. Any character can be +     used as a delimiter instead of '\cb{/}'. Escaping of the delimiter +     character in \ci{pattern} or \ci{replacement} is not supported. All +     the regular expressions are pushed into a stack with the last specified +     expression considered first. The first match that succeeds is used. +     Regular expressions are applied to a string in the form + +     \c{\i{namespace} \i{type-name}} + +     For example, the following expression maps type \cb{foo} that is +     defined in the \cb{http://example.com/bar} namespace to file name +     \cb{bar-foo}: + +     \cb{%http://example.com/(.+) (.+)%$1-$2%} + +     See also the REGEX AND SHELL QUOTING section below." +  }; + +  bool --type-file-regex-trace +  { +    "Trace the process of applying regular expressions specified with the +     \cb{--type-file-regex} option. Use this option to find out why your +     regular expressions don't do what you expected them to do." +  }; + +  NarrowStrings --schema-file-regex +  { +    "<regex>", +    "Add <regex> to the list of regular expressions used to translate schema +     file names when the \cb{--file-per-type} option is specified. <regex> is +     a Perl-like regular expression in the form +     \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. Any character can be used +     as a delimiter instead of '\cb{/}'. Escaping of the delimiter character in +     \ci{pattern} or \ci{replacement} is not supported. All the regular +     expressions are pushed into a stack with the last specified expression +     considered first. The first match that succeeds is used. Regular +     Expressions are applied to the absolute filesystem path of a schema file +     and the result, including the directory part, if any, is used to derive +     the \cb{#include} directive paths as well as the generated C++ file +     paths. This option, along with \cb{--type-file-regex} are primarily +     useful to place the generated files into subdirectories or to resolve +     file name conflicts. + +     For example, the following expression maps schema files in the +     \cb{foo/1.0.0/} subdirectory to the files in the \cb{foo/} subdirectory. +     As a result, the \cb{#include} directive paths for such schemas will be +     in the \cb{foo/schema.hxx} form and the generated C++ files will be +     placed into the \cb{foo/} subdirectory: + +     \cb{%.*/foo/1.0.0/(.+)%foo/$1%} + +     See also the REGEX AND SHELL QUOTING section below." +  }; + +  bool --schema-file-regex-trace +  { +    "Trace the process of applying regular expressions specified with the +     \cb{--schema-file-regex} option. Use this option to find out why your +     regular expressions don't do what you expected them to do." +  }; + +  bool --fat-type-file +  { +    "Generate code corresponding to global elements into type files instead +     of schema files when the \cb{--type-file-regex} option is specified. +     This option is primarily useful when trying to minimize the amount of +     object code that is linked to an executable by packaging compiled +     generated code into a static (archive) library." +  }; + +  // File list options. +  // +  NarrowString --file-list +  { +    "<file>", +    "Write a list of generated C++ files to <file> or to \cb{stdout} if +     <file> is \cb{-}. This option is primarily useful in the file-per-type +     compilation mode (\cb{--file-per-type}) to create a list of generated +     C++ files, for example, as a makefile fragment." +  }; + +  bool --file-list-only +  { +    "Only write the list of C++ files that would be generated without +     actually generating them. This option only makes sense together with +     \cb{--file-list}." +  } + +  NarrowString --file-list-prologue +  { +    "<text>", +    "Insert <text> at the beginning of the file list. As a convenience, all +     occurrences of the \cb{\\n} character sequence in <text> are replaced +     with new lines. This option can, for example, be used to assign the +     generated file list to a makefile variable." +  }; + +  NarrowString --file-list-epilogue +  { +    "<text>", +    "Insert <text> at the end of the file list. As a convenience, all +     occurrences of the \cb{\\n} character sequence in <text> are replaced +     with new lines." +  }; + +  NarrowString --file-list-delim = "\n" +  { +    "<text>", +    "Delimit file names written to the file list with <text> instead of new +     lines. As a convenience, all occurrences of the \cb{\\n} character +     sequence in <text> are replaced with new lines." +  }; + +  // Undocumented. +  // +  bool --disable-multi-import; +  bool --disable-full-check; +}; diff --git a/xsd/pregenerated/xsd/cxx/options.cxx b/xsd/pregenerated/xsd/cxx/options.cxx new file mode 100644 index 0000000..9eea3a9 --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/options.cxx @@ -0,0 +1,739 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <xsd/options-parser.hxx> +// +// End prologue. + +#include <xsd/cxx/options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +namespace cli +{ +  template <typename X> +  struct parser +  { +    static void +    parse (X& x, bool& xs, scanner& s) +    { +      using namespace std; + +      const char* o (s.next ()); +      if (s.more ()) +      { +        string v (s.next ()); +        istringstream is (v); +        if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) +          throw invalid_value (o, v); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <> +  struct parser<bool> +  { +    static void +    parse (bool& x, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        const char* v (s.next ()); + +        if (std::strcmp (v, "1")    == 0 || +            std::strcmp (v, "true") == 0 || +            std::strcmp (v, "TRUE") == 0 || +            std::strcmp (v, "True") == 0) +          x = true; +        else if (std::strcmp (v, "0")     == 0 || +                 std::strcmp (v, "false") == 0 || +                 std::strcmp (v, "FALSE") == 0 || +                 std::strcmp (v, "False") == 0) +          x = false; +        else +          throw invalid_value (o, v); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <> +  struct parser<std::string> +  { +    static void +    parse (std::string& x, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +        x = s.next (); +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename X> +  struct parser<std::pair<X, std::size_t> > +  { +    static void +    parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) +    { +      x.second = s.position (); +      parser<X>::parse (x.first, xs, s); +    } +  }; + +  template <typename X> +  struct parser<std::vector<X> > +  { +    static void +    parse (std::vector<X>& c, bool& xs, scanner& s) +    { +      X x; +      bool dummy; +      parser<X>::parse (x, dummy, s); +      c.push_back (x); +      xs = true; +    } +  }; + +  template <typename X, typename C> +  struct parser<std::set<X, C> > +  { +    static void +    parse (std::set<X, C>& c, bool& xs, scanner& s) +    { +      X x; +      bool dummy; +      parser<X>::parse (x, dummy, s); +      c.insert (x); +      xs = true; +    } +  }; + +  template <typename K, typename V, typename C> +  struct parser<std::map<K, V, C> > +  { +    static void +    parse (std::map<K, V, C>& m, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        std::size_t pos (s.position ()); +        std::string ov (s.next ()); +        std::string::size_type p = ov.find ('='); + +        K k = K (); +        V v = V (); +        std::string kstr (ov, 0, p); +        std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + +        int ac (2); +        char* av[] = +        { +          const_cast<char*> (o), +          0 +        }; + +        bool dummy; +        if (!kstr.empty ()) +        { +          av[1] = const_cast<char*> (kstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<K>::parse (k, dummy, s); +        } + +        if (!vstr.empty ()) +        { +          av[1] = const_cast<char*> (vstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<V>::parse (v, dummy, s); +        } + +        m[k] = v; +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename K, typename V, typename C> +  struct parser<std::multimap<K, V, C> > +  { +    static void +    parse (std::multimap<K, V, C>& m, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        std::size_t pos (s.position ()); +        std::string ov (s.next ()); +        std::string::size_type p = ov.find ('='); + +        K k = K (); +        V v = V (); +        std::string kstr (ov, 0, p); +        std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + +        int ac (2); +        char* av[] = +        { +          const_cast<char*> (o), +          0 +        }; + +        bool dummy; +        if (!kstr.empty ()) +        { +          av[1] = const_cast<char*> (kstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<K>::parse (k, dummy, s); +        } + +        if (!vstr.empty ()) +        { +          av[1] = const_cast<char*> (vstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<V>::parse (v, dummy, s); +        } + +        m.insert (typename std::multimap<K, V, C>::value_type (k, v)); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename X, typename T, T X::*M> +  void +  thunk (X& x, scanner& s) +  { +    parser<T>::parse (x.*M, s); +  } + +  template <typename X, bool X::*M> +  void +  thunk (X& x, scanner& s) +  { +    s.next (); +    x.*M = true; +  } + +  template <typename X, typename T, T X::*M, bool X::*S> +  void +  thunk (X& x, scanner& s) +  { +    parser<T>::parse (x.*M, x.*S, s); +  } +} + +#include <map> + +namespace CXX +{ +  // options +  // + +  options:: +  options () +  : std_ (cxx_version::cxx11), +    std_specified_ (false), +    char_type_ ("char"), +    char_type_specified_ (false), +    char_encoding_ (), +    char_encoding_specified_ (false), +    output_dir_ (), +    output_dir_specified_ (false), +    generate_inline_ (), +    generate_xml_schema_ (), +    extern_xml_schema_ (), +    extern_xml_schema_specified_ (false), +    namespace_map_ (), +    namespace_map_specified_ (false), +    namespace_regex_ (), +    namespace_regex_specified_ (false), +    namespace_regex_trace_ (), +    reserved_name_ (), +    reserved_name_specified_ (false), +    include_with_brackets_ (), +    include_prefix_ (), +    include_prefix_specified_ (false), +    include_regex_ (), +    include_regex_specified_ (false), +    include_regex_trace_ (), +    guard_prefix_ (), +    guard_prefix_specified_ (false), +    hxx_suffix_ (".hxx"), +    hxx_suffix_specified_ (false), +    ixx_suffix_ (".ixx"), +    ixx_suffix_specified_ (false), +    cxx_suffix_ (".cxx"), +    cxx_suffix_specified_ (false), +    fwd_suffix_ ("-fwd.hxx"), +    fwd_suffix_specified_ (false), +    hxx_regex_ (), +    hxx_regex_specified_ (false), +    ixx_regex_ (), +    ixx_regex_specified_ (false), +    cxx_regex_ (), +    cxx_regex_specified_ (false), +    fwd_regex_ (), +    fwd_regex_specified_ (false), +    hxx_prologue_ (), +    hxx_prologue_specified_ (false), +    ixx_prologue_ (), +    ixx_prologue_specified_ (false), +    cxx_prologue_ (), +    cxx_prologue_specified_ (false), +    fwd_prologue_ (), +    fwd_prologue_specified_ (false), +    prologue_ (), +    prologue_specified_ (false), +    hxx_epilogue_ (), +    hxx_epilogue_specified_ (false), +    ixx_epilogue_ (), +    ixx_epilogue_specified_ (false), +    cxx_epilogue_ (), +    cxx_epilogue_specified_ (false), +    fwd_epilogue_ (), +    fwd_epilogue_specified_ (false), +    epilogue_ (), +    epilogue_specified_ (false), +    hxx_prologue_file_ (), +    hxx_prologue_file_specified_ (false), +    ixx_prologue_file_ (), +    ixx_prologue_file_specified_ (false), +    cxx_prologue_file_ (), +    cxx_prologue_file_specified_ (false), +    fwd_prologue_file_ (), +    fwd_prologue_file_specified_ (false), +    prologue_file_ (), +    prologue_file_specified_ (false), +    hxx_epilogue_file_ (), +    hxx_epilogue_file_specified_ (false), +    ixx_epilogue_file_ (), +    ixx_epilogue_file_specified_ (false), +    cxx_epilogue_file_ (), +    cxx_epilogue_file_specified_ (false), +    fwd_epilogue_file_ (), +    fwd_epilogue_file_specified_ (false), +    epilogue_file_ (), +    epilogue_file_specified_ (false), +    export_symbol_ (), +    export_symbol_specified_ (false), +    export_xml_schema_ (), +    export_maps_ (), +    import_maps_ (), +    generate_dep_ (), +    generate_dep_only_ (), +    dep_phony_ (), +    dep_target_ (), +    dep_target_specified_ (false), +    dep_suffix_ (".d"), +    dep_suffix_specified_ (false), +    dep_file_ (), +    dep_file_specified_ (false), +    dep_regex_ (), +    dep_regex_specified_ (false) +  { +  } + +  ::cli::usage_para options:: +  print_usage (::std::wostream& os, ::cli::usage_para p) +  { +    CLI_POTENTIALLY_UNUSED (os); + +    if (p == ::cli::usage_para::text) +      os << ::std::endl; + +    os << "--std <version>              Specify the C++ standard that the generated code" << ::std::endl +       << "                             should conform to." << ::std::endl; + +    os << "--char-type <type>           Generate code using the provided character <type>" << ::std::endl +       << "                             instead of the default char." << ::std::endl; + +    os << "--char-encoding <enc>        Specify the character encoding that should be used" << ::std::endl +       << "                             in the generated code." << ::std::endl; + +    os << "--output-dir <dir>           Write generated files to <dir> instead of the" << ::std::endl +       << "                             current directory." << ::std::endl; + +    os << "--generate-inline            Generate simple functions inline." << ::std::endl; + +    os << "--generate-xml-schema        Generate a C++ header file as if the schema being" << ::std::endl +       << "                             compiled defines the XML Schema namespace." << ::std::endl; + +    os << "--extern-xml-schema <file>   Include a header file derived from <file> instead" << ::std::endl +       << "                             of generating the XML Schema namespace mapping" << ::std::endl +       << "                             inline." << ::std::endl; + +    os << "--namespace-map <xns>=<cns>  Map XML Schema namespace <xns> to C++ namespace" << ::std::endl +       << "                             <cns>." << ::std::endl; + +    os << "--namespace-regex <regex>    Add <regex> to the list of regular expressions" << ::std::endl +       << "                             used to translate XML Schema namespace names to" << ::std::endl +       << "                             C++ namespace names." << ::std::endl; + +    os << "--namespace-regex-trace      Trace the process of applying regular expressions" << ::std::endl +       << "                             specified with the --namespace-regex option." << ::std::endl; + +    os << "--reserved-name <n>[=<r>]    Add name <n> to the list of names that should not" << ::std::endl +       << "                             be used as identifiers." << ::std::endl; + +    os << "--include-with-brackets      Use angle brackets (<>) instead of quotes (\"\") in" << ::std::endl +       << "                             generated #include directives." << ::std::endl; + +    os << "--include-prefix <prefix>    Add <prefix> to generated #include directive" << ::std::endl +       << "                             paths." << ::std::endl; + +    os << "--include-regex <regex>      Add <regex> to the list of regular expressions" << ::std::endl +       << "                             used to transform #include directive paths." << ::std::endl; + +    os << "--include-regex-trace        Trace the process of applying regular expressions" << ::std::endl +       << "                             specified with the --include-regex option." << ::std::endl; + +    os << "--guard-prefix <prefix>      Add <prefix> to generated header inclusion guards." << ::std::endl; + +    os << "--hxx-suffix <suffix>        Use the provided <suffix> instead of the default" << ::std::endl +       << "                             .hxx to construct the name of the header file." << ::std::endl; + +    os << "--ixx-suffix <suffix>        Use the provided <suffix> instead of the default" << ::std::endl +       << "                             .ixx to construct the name of the inline file." << ::std::endl; + +    os << "--cxx-suffix <suffix>        Use the provided <suffix> instead of the default" << ::std::endl +       << "                             .cxx to construct the name of the source file." << ::std::endl; + +    os << "--fwd-suffix <suffix>        Use the provided <suffix> instead of the default" << ::std::endl +       << "                             -fwd.hxx to construct the name of the forward" << ::std::endl +       << "                             declaration file." << ::std::endl; + +    os << "--hxx-regex <regex>          Use the provided expression to construct the name" << ::std::endl +       << "                             of the header file." << ::std::endl; + +    os << "--ixx-regex <regex>          Use the provided expression to construct the name" << ::std::endl +       << "                             of the inline file." << ::std::endl; + +    os << "--cxx-regex <regex>          Use the provided expression to construct the name" << ::std::endl +       << "                             of the source file." << ::std::endl; + +    os << "--fwd-regex <regex>          Use the provided expression to construct the name" << ::std::endl +       << "                             of the forward declaration file." << ::std::endl; + +    os << "--hxx-prologue <text>        Insert <text> at the beginning of the header file." << ::std::endl; + +    os << "--ixx-prologue <text>        Insert <text> at the beginning of the inline file." << ::std::endl; + +    os << "--cxx-prologue <text>        Insert <text> at the beginning of the source file." << ::std::endl; + +    os << "--fwd-prologue <text>        Insert <text> at the beginning of the forward" << ::std::endl +       << "                             declaration file." << ::std::endl; + +    os << "--prologue <text>            Insert <text> at the beginning of each generated" << ::std::endl +       << "                             file for which there is no file-specific prologue." << ::std::endl; + +    os << "--hxx-epilogue <text>        Insert <text> at the end of the header file." << ::std::endl; + +    os << "--ixx-epilogue <text>        Insert <text> at the end of the inline file." << ::std::endl; + +    os << "--cxx-epilogue <text>        Insert <text> at the end of the source file." << ::std::endl; + +    os << "--fwd-epilogue <text>        Insert <text> at the end of the forward" << ::std::endl +       << "                             declaration file." << ::std::endl; + +    os << "--epilogue <text>            Insert <text> at the end of each generated file" << ::std::endl +       << "                             for which there is no file-specific epilogue." << ::std::endl; + +    os << "--hxx-prologue-file <file>   Insert the content of the <file> at the beginning" << ::std::endl +       << "                             of the header file." << ::std::endl; + +    os << "--ixx-prologue-file <file>   Insert the content of the <file> at the beginning" << ::std::endl +       << "                             of the inline file." << ::std::endl; + +    os << "--cxx-prologue-file <file>   Insert the content of the <file> at the beginning" << ::std::endl +       << "                             of the source file." << ::std::endl; + +    os << "--fwd-prologue-file <file>   Insert the content of the <file> at the beginning" << ::std::endl +       << "                             of the forward declaration file." << ::std::endl; + +    os << "--prologue-file <file>       Insert the content of the <file> at the beginning" << ::std::endl +       << "                             of each generated file for which there is no" << ::std::endl +       << "                             file-specific prologue file." << ::std::endl; + +    os << "--hxx-epilogue-file <file>   Insert the content of the <file> at the end of the" << ::std::endl +       << "                             header file." << ::std::endl; + +    os << "--ixx-epilogue-file <file>   Insert the content of the <file> at the end of the" << ::std::endl +       << "                             inline file." << ::std::endl; + +    os << "--cxx-epilogue-file <file>   Insert the content of the <file> at the end of the" << ::std::endl +       << "                             source file." << ::std::endl; + +    os << "--fwd-epilogue-file <file>   Insert the content of the <file> at the end of the" << ::std::endl +       << "                             forward declaration file." << ::std::endl; + +    os << "--epilogue-file <file>       Insert the content of the <file> at the end of" << ::std::endl +       << "                             each generated file for which there is no" << ::std::endl +       << "                             file-specific epilogue file." << ::std::endl; + +    os << "--export-symbol <symbol>     Insert <symbol> in places where DLL export/import" << ::std::endl +       << "                             control statements" << ::std::endl +       << "                             (__declspec(dllexport/dllimport)) are necessary." << ::std::endl; + +    os << "--export-xml-schema          Export/import types in the XML Schema namespace" << ::std::endl +       << "                             using the export symbol provided with the" << ::std::endl +       << "                             --export-symbol option." << ::std::endl; + +    os << "--export-maps                Export polymorphism support maps from a Win32 DLL" << ::std::endl +       << "                             into which this generated code is placed." << ::std::endl; + +    os << "--import-maps                Import polymorphism support maps to a Win32 DLL or" << ::std::endl +       << "                             executable into which this generated code is" << ::std::endl +       << "                             linked." << ::std::endl; + +    os << "--generate-dep               Generate make dependency information." << ::std::endl; + +    os << "--generate-dep-only          Generate make dependency information only." << ::std::endl; + +    os << "--dep-phony                  Generate phony targets for included/imported" << ::std::endl +       << "                             schema files, causing each to depend on nothing." << ::std::endl; + +    os << "--dep-target <target>        Change the target of the dependency rule." << ::std::endl; + +    os << "--dep-suffix <suffix>        Use <suffix> instead of the default .d to" << ::std::endl +       << "                             construct the name of the dependency file." << ::std::endl; + +    os << "--dep-file <path>            Use <path> as the generated dependency file path" << ::std::endl +       << "                             instead of deriving it from the input file name." << ::std::endl; + +    os << "--dep-regex <regex>          Use the provided expression to construct the name" << ::std::endl +       << "                             of the dependency file." << ::std::endl; + +    p = ::cli::usage_para::option; + +    return p; +  } + +  typedef +  std::map<std::string, void (*) (options&, ::cli::scanner&)> +  _cli_options_map; + +  static _cli_options_map _cli_options_map_; + +  struct _cli_options_map_init +  { +    _cli_options_map_init () +    { +      _cli_options_map_["--std"] = +      &::cli::thunk< options, cxx_version, &options::std_, +        &options::std_specified_ >; +      _cli_options_map_["--char-type"] = +      &::cli::thunk< options, NarrowString, &options::char_type_, +        &options::char_type_specified_ >; +      _cli_options_map_["--char-encoding"] = +      &::cli::thunk< options, NarrowString, &options::char_encoding_, +        &options::char_encoding_specified_ >; +      _cli_options_map_["--output-dir"] = +      &::cli::thunk< options, NarrowString, &options::output_dir_, +        &options::output_dir_specified_ >; +      _cli_options_map_["--generate-inline"] = +      &::cli::thunk< options, &options::generate_inline_ >; +      _cli_options_map_["--generate-xml-schema"] = +      &::cli::thunk< options, &options::generate_xml_schema_ >; +      _cli_options_map_["--extern-xml-schema"] = +      &::cli::thunk< options, NarrowString, &options::extern_xml_schema_, +        &options::extern_xml_schema_specified_ >; +      _cli_options_map_["--namespace-map"] = +      &::cli::thunk< options, NarrowStrings, &options::namespace_map_, +        &options::namespace_map_specified_ >; +      _cli_options_map_["--namespace-regex"] = +      &::cli::thunk< options, NarrowStrings, &options::namespace_regex_, +        &options::namespace_regex_specified_ >; +      _cli_options_map_["--namespace-regex-trace"] = +      &::cli::thunk< options, &options::namespace_regex_trace_ >; +      _cli_options_map_["--reserved-name"] = +      &::cli::thunk< options, NarrowStrings, &options::reserved_name_, +        &options::reserved_name_specified_ >; +      _cli_options_map_["--include-with-brackets"] = +      &::cli::thunk< options, &options::include_with_brackets_ >; +      _cli_options_map_["--include-prefix"] = +      &::cli::thunk< options, NarrowString, &options::include_prefix_, +        &options::include_prefix_specified_ >; +      _cli_options_map_["--include-regex"] = +      &::cli::thunk< options, NarrowStrings, &options::include_regex_, +        &options::include_regex_specified_ >; +      _cli_options_map_["--include-regex-trace"] = +      &::cli::thunk< options, &options::include_regex_trace_ >; +      _cli_options_map_["--guard-prefix"] = +      &::cli::thunk< options, NarrowString, &options::guard_prefix_, +        &options::guard_prefix_specified_ >; +      _cli_options_map_["--hxx-suffix"] = +      &::cli::thunk< options, NarrowString, &options::hxx_suffix_, +        &options::hxx_suffix_specified_ >; +      _cli_options_map_["--ixx-suffix"] = +      &::cli::thunk< options, NarrowString, &options::ixx_suffix_, +        &options::ixx_suffix_specified_ >; +      _cli_options_map_["--cxx-suffix"] = +      &::cli::thunk< options, NarrowString, &options::cxx_suffix_, +        &options::cxx_suffix_specified_ >; +      _cli_options_map_["--fwd-suffix"] = +      &::cli::thunk< options, NarrowString, &options::fwd_suffix_, +        &options::fwd_suffix_specified_ >; +      _cli_options_map_["--hxx-regex"] = +      &::cli::thunk< options, NarrowString, &options::hxx_regex_, +        &options::hxx_regex_specified_ >; +      _cli_options_map_["--ixx-regex"] = +      &::cli::thunk< options, NarrowString, &options::ixx_regex_, +        &options::ixx_regex_specified_ >; +      _cli_options_map_["--cxx-regex"] = +      &::cli::thunk< options, NarrowString, &options::cxx_regex_, +        &options::cxx_regex_specified_ >; +      _cli_options_map_["--fwd-regex"] = +      &::cli::thunk< options, NarrowString, &options::fwd_regex_, +        &options::fwd_regex_specified_ >; +      _cli_options_map_["--hxx-prologue"] = +      &::cli::thunk< options, NarrowStrings, &options::hxx_prologue_, +        &options::hxx_prologue_specified_ >; +      _cli_options_map_["--ixx-prologue"] = +      &::cli::thunk< options, NarrowStrings, &options::ixx_prologue_, +        &options::ixx_prologue_specified_ >; +      _cli_options_map_["--cxx-prologue"] = +      &::cli::thunk< options, NarrowStrings, &options::cxx_prologue_, +        &options::cxx_prologue_specified_ >; +      _cli_options_map_["--fwd-prologue"] = +      &::cli::thunk< options, NarrowStrings, &options::fwd_prologue_, +        &options::fwd_prologue_specified_ >; +      _cli_options_map_["--prologue"] = +      &::cli::thunk< options, NarrowStrings, &options::prologue_, +        &options::prologue_specified_ >; +      _cli_options_map_["--hxx-epilogue"] = +      &::cli::thunk< options, NarrowStrings, &options::hxx_epilogue_, +        &options::hxx_epilogue_specified_ >; +      _cli_options_map_["--ixx-epilogue"] = +      &::cli::thunk< options, NarrowStrings, &options::ixx_epilogue_, +        &options::ixx_epilogue_specified_ >; +      _cli_options_map_["--cxx-epilogue"] = +      &::cli::thunk< options, NarrowStrings, &options::cxx_epilogue_, +        &options::cxx_epilogue_specified_ >; +      _cli_options_map_["--fwd-epilogue"] = +      &::cli::thunk< options, NarrowStrings, &options::fwd_epilogue_, +        &options::fwd_epilogue_specified_ >; +      _cli_options_map_["--epilogue"] = +      &::cli::thunk< options, NarrowStrings, &options::epilogue_, +        &options::epilogue_specified_ >; +      _cli_options_map_["--hxx-prologue-file"] = +      &::cli::thunk< options, NarrowString, &options::hxx_prologue_file_, +        &options::hxx_prologue_file_specified_ >; +      _cli_options_map_["--ixx-prologue-file"] = +      &::cli::thunk< options, NarrowString, &options::ixx_prologue_file_, +        &options::ixx_prologue_file_specified_ >; +      _cli_options_map_["--cxx-prologue-file"] = +      &::cli::thunk< options, NarrowString, &options::cxx_prologue_file_, +        &options::cxx_prologue_file_specified_ >; +      _cli_options_map_["--fwd-prologue-file"] = +      &::cli::thunk< options, NarrowString, &options::fwd_prologue_file_, +        &options::fwd_prologue_file_specified_ >; +      _cli_options_map_["--prologue-file"] = +      &::cli::thunk< options, NarrowString, &options::prologue_file_, +        &options::prologue_file_specified_ >; +      _cli_options_map_["--hxx-epilogue-file"] = +      &::cli::thunk< options, NarrowString, &options::hxx_epilogue_file_, +        &options::hxx_epilogue_file_specified_ >; +      _cli_options_map_["--ixx-epilogue-file"] = +      &::cli::thunk< options, NarrowString, &options::ixx_epilogue_file_, +        &options::ixx_epilogue_file_specified_ >; +      _cli_options_map_["--cxx-epilogue-file"] = +      &::cli::thunk< options, NarrowString, &options::cxx_epilogue_file_, +        &options::cxx_epilogue_file_specified_ >; +      _cli_options_map_["--fwd-epilogue-file"] = +      &::cli::thunk< options, NarrowString, &options::fwd_epilogue_file_, +        &options::fwd_epilogue_file_specified_ >; +      _cli_options_map_["--epilogue-file"] = +      &::cli::thunk< options, NarrowString, &options::epilogue_file_, +        &options::epilogue_file_specified_ >; +      _cli_options_map_["--export-symbol"] = +      &::cli::thunk< options, NarrowString, &options::export_symbol_, +        &options::export_symbol_specified_ >; +      _cli_options_map_["--export-xml-schema"] = +      &::cli::thunk< options, &options::export_xml_schema_ >; +      _cli_options_map_["--export-maps"] = +      &::cli::thunk< options, &options::export_maps_ >; +      _cli_options_map_["--import-maps"] = +      &::cli::thunk< options, &options::import_maps_ >; +      _cli_options_map_["--generate-dep"] = +      &::cli::thunk< options, &options::generate_dep_ >; +      _cli_options_map_["--generate-dep-only"] = +      &::cli::thunk< options, &options::generate_dep_only_ >; +      _cli_options_map_["--dep-phony"] = +      &::cli::thunk< options, &options::dep_phony_ >; +      _cli_options_map_["--dep-target"] = +      &::cli::thunk< options, NarrowStrings, &options::dep_target_, +        &options::dep_target_specified_ >; +      _cli_options_map_["--dep-suffix"] = +      &::cli::thunk< options, NarrowString, &options::dep_suffix_, +        &options::dep_suffix_specified_ >; +      _cli_options_map_["--dep-file"] = +      &::cli::thunk< options, NarrowString, &options::dep_file_, +        &options::dep_file_specified_ >; +      _cli_options_map_["--dep-regex"] = +      &::cli::thunk< options, NarrowString, &options::dep_regex_, +        &options::dep_regex_specified_ >; +    } +  }; + +  static _cli_options_map_init _cli_options_map_init_; + +  bool options:: +  _parse (const char* o, ::cli::scanner& s) +  { +    _cli_options_map::const_iterator i (_cli_options_map_.find (o)); + +    if (i != _cli_options_map_.end ()) +    { +      (*(i->second)) (*this, s); +      return true; +    } + +    // options base +    // +    if (::options::_parse (o, s)) +      return true; + +    return false; +  } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/xsd/pregenerated/xsd/cxx/options.hxx b/xsd/pregenerated/xsd/cxx/options.hxx new file mode 100644 index 0000000..085aa4c --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/options.hxx @@ -0,0 +1,451 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef XSD_CXX_OPTIONS_HXX +#define XSD_CXX_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <cstddef> + +#include <xsd/types.hxx> + +#include <xsd/cxx/option-types.hxx> + +#include <xsd/options.hxx> + +namespace CXX +{ +  class options: public ::options +  { +    public: +    // Option accessors. +    // +    const cxx_version& +    std () const; + +    bool +    std_specified () const; + +    const NarrowString& +    char_type () const; + +    bool +    char_type_specified () const; + +    const NarrowString& +    char_encoding () const; + +    bool +    char_encoding_specified () const; + +    const NarrowString& +    output_dir () const; + +    bool +    output_dir_specified () const; + +    const bool& +    generate_inline () const; + +    const bool& +    generate_xml_schema () const; + +    const NarrowString& +    extern_xml_schema () const; + +    bool +    extern_xml_schema_specified () const; + +    const NarrowStrings& +    namespace_map () const; + +    bool +    namespace_map_specified () const; + +    const NarrowStrings& +    namespace_regex () const; + +    bool +    namespace_regex_specified () const; + +    const bool& +    namespace_regex_trace () const; + +    const NarrowStrings& +    reserved_name () const; + +    bool +    reserved_name_specified () const; + +    const bool& +    include_with_brackets () const; + +    const NarrowString& +    include_prefix () const; + +    bool +    include_prefix_specified () const; + +    const NarrowStrings& +    include_regex () const; + +    bool +    include_regex_specified () const; + +    const bool& +    include_regex_trace () const; + +    const NarrowString& +    guard_prefix () const; + +    bool +    guard_prefix_specified () const; + +    const NarrowString& +    hxx_suffix () const; + +    bool +    hxx_suffix_specified () const; + +    const NarrowString& +    ixx_suffix () const; + +    bool +    ixx_suffix_specified () const; + +    const NarrowString& +    cxx_suffix () const; + +    bool +    cxx_suffix_specified () const; + +    const NarrowString& +    fwd_suffix () const; + +    bool +    fwd_suffix_specified () const; + +    const NarrowString& +    hxx_regex () const; + +    bool +    hxx_regex_specified () const; + +    const NarrowString& +    ixx_regex () const; + +    bool +    ixx_regex_specified () const; + +    const NarrowString& +    cxx_regex () const; + +    bool +    cxx_regex_specified () const; + +    const NarrowString& +    fwd_regex () const; + +    bool +    fwd_regex_specified () const; + +    const NarrowStrings& +    hxx_prologue () const; + +    bool +    hxx_prologue_specified () const; + +    const NarrowStrings& +    ixx_prologue () const; + +    bool +    ixx_prologue_specified () const; + +    const NarrowStrings& +    cxx_prologue () const; + +    bool +    cxx_prologue_specified () const; + +    const NarrowStrings& +    fwd_prologue () const; + +    bool +    fwd_prologue_specified () const; + +    const NarrowStrings& +    prologue () const; + +    bool +    prologue_specified () const; + +    const NarrowStrings& +    hxx_epilogue () const; + +    bool +    hxx_epilogue_specified () const; + +    const NarrowStrings& +    ixx_epilogue () const; + +    bool +    ixx_epilogue_specified () const; + +    const NarrowStrings& +    cxx_epilogue () const; + +    bool +    cxx_epilogue_specified () const; + +    const NarrowStrings& +    fwd_epilogue () const; + +    bool +    fwd_epilogue_specified () const; + +    const NarrowStrings& +    epilogue () const; + +    bool +    epilogue_specified () const; + +    const NarrowString& +    hxx_prologue_file () const; + +    bool +    hxx_prologue_file_specified () const; + +    const NarrowString& +    ixx_prologue_file () const; + +    bool +    ixx_prologue_file_specified () const; + +    const NarrowString& +    cxx_prologue_file () const; + +    bool +    cxx_prologue_file_specified () const; + +    const NarrowString& +    fwd_prologue_file () const; + +    bool +    fwd_prologue_file_specified () const; + +    const NarrowString& +    prologue_file () const; + +    bool +    prologue_file_specified () const; + +    const NarrowString& +    hxx_epilogue_file () const; + +    bool +    hxx_epilogue_file_specified () const; + +    const NarrowString& +    ixx_epilogue_file () const; + +    bool +    ixx_epilogue_file_specified () const; + +    const NarrowString& +    cxx_epilogue_file () const; + +    bool +    cxx_epilogue_file_specified () const; + +    const NarrowString& +    fwd_epilogue_file () const; + +    bool +    fwd_epilogue_file_specified () const; + +    const NarrowString& +    epilogue_file () const; + +    bool +    epilogue_file_specified () const; + +    const NarrowString& +    export_symbol () const; + +    bool +    export_symbol_specified () const; + +    const bool& +    export_xml_schema () const; + +    const bool& +    export_maps () const; + +    const bool& +    import_maps () const; + +    const bool& +    generate_dep () const; + +    const bool& +    generate_dep_only () const; + +    const bool& +    dep_phony () const; + +    const NarrowStrings& +    dep_target () const; + +    bool +    dep_target_specified () const; + +    const NarrowString& +    dep_suffix () const; + +    bool +    dep_suffix_specified () const; + +    const NarrowString& +    dep_file () const; + +    bool +    dep_file_specified () const; + +    const NarrowString& +    dep_regex () const; + +    bool +    dep_regex_specified () const; + +    // Print usage information. +    // +    static ::cli::usage_para +    print_usage (::std::wostream&, +                 ::cli::usage_para = ::cli::usage_para::none); + +    // Implementation details. +    // +    protected: +    options (); + +    bool +    _parse (const char*, ::cli::scanner&); + +    public: +    cxx_version std_; +    bool std_specified_; +    NarrowString char_type_; +    bool char_type_specified_; +    NarrowString char_encoding_; +    bool char_encoding_specified_; +    NarrowString output_dir_; +    bool output_dir_specified_; +    bool generate_inline_; +    bool generate_xml_schema_; +    NarrowString extern_xml_schema_; +    bool extern_xml_schema_specified_; +    NarrowStrings namespace_map_; +    bool namespace_map_specified_; +    NarrowStrings namespace_regex_; +    bool namespace_regex_specified_; +    bool namespace_regex_trace_; +    NarrowStrings reserved_name_; +    bool reserved_name_specified_; +    bool include_with_brackets_; +    NarrowString include_prefix_; +    bool include_prefix_specified_; +    NarrowStrings include_regex_; +    bool include_regex_specified_; +    bool include_regex_trace_; +    NarrowString guard_prefix_; +    bool guard_prefix_specified_; +    NarrowString hxx_suffix_; +    bool hxx_suffix_specified_; +    NarrowString ixx_suffix_; +    bool ixx_suffix_specified_; +    NarrowString cxx_suffix_; +    bool cxx_suffix_specified_; +    NarrowString fwd_suffix_; +    bool fwd_suffix_specified_; +    NarrowString hxx_regex_; +    bool hxx_regex_specified_; +    NarrowString ixx_regex_; +    bool ixx_regex_specified_; +    NarrowString cxx_regex_; +    bool cxx_regex_specified_; +    NarrowString fwd_regex_; +    bool fwd_regex_specified_; +    NarrowStrings hxx_prologue_; +    bool hxx_prologue_specified_; +    NarrowStrings ixx_prologue_; +    bool ixx_prologue_specified_; +    NarrowStrings cxx_prologue_; +    bool cxx_prologue_specified_; +    NarrowStrings fwd_prologue_; +    bool fwd_prologue_specified_; +    NarrowStrings prologue_; +    bool prologue_specified_; +    NarrowStrings hxx_epilogue_; +    bool hxx_epilogue_specified_; +    NarrowStrings ixx_epilogue_; +    bool ixx_epilogue_specified_; +    NarrowStrings cxx_epilogue_; +    bool cxx_epilogue_specified_; +    NarrowStrings fwd_epilogue_; +    bool fwd_epilogue_specified_; +    NarrowStrings epilogue_; +    bool epilogue_specified_; +    NarrowString hxx_prologue_file_; +    bool hxx_prologue_file_specified_; +    NarrowString ixx_prologue_file_; +    bool ixx_prologue_file_specified_; +    NarrowString cxx_prologue_file_; +    bool cxx_prologue_file_specified_; +    NarrowString fwd_prologue_file_; +    bool fwd_prologue_file_specified_; +    NarrowString prologue_file_; +    bool prologue_file_specified_; +    NarrowString hxx_epilogue_file_; +    bool hxx_epilogue_file_specified_; +    NarrowString ixx_epilogue_file_; +    bool ixx_epilogue_file_specified_; +    NarrowString cxx_epilogue_file_; +    bool cxx_epilogue_file_specified_; +    NarrowString fwd_epilogue_file_; +    bool fwd_epilogue_file_specified_; +    NarrowString epilogue_file_; +    bool epilogue_file_specified_; +    NarrowString export_symbol_; +    bool export_symbol_specified_; +    bool export_xml_schema_; +    bool export_maps_; +    bool import_maps_; +    bool generate_dep_; +    bool generate_dep_only_; +    bool dep_phony_; +    NarrowStrings dep_target_; +    bool dep_target_specified_; +    NarrowString dep_suffix_; +    bool dep_suffix_specified_; +    NarrowString dep_file_; +    bool dep_file_specified_; +    NarrowString dep_regex_; +    bool dep_regex_specified_; +  }; +} + +#include <xsd/cxx/options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // XSD_CXX_OPTIONS_HXX diff --git a/xsd/pregenerated/xsd/cxx/options.ixx b/xsd/pregenerated/xsd/cxx/options.ixx new file mode 100644 index 0000000..8266e31 --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/options.ixx @@ -0,0 +1,615 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace CXX +{ +  // options +  // + +  inline const cxx_version& options:: +  std () const +  { +    return this->std_; +  } + +  inline bool options:: +  std_specified () const +  { +    return this->std_specified_; +  } + +  inline const NarrowString& options:: +  char_type () const +  { +    return this->char_type_; +  } + +  inline bool options:: +  char_type_specified () const +  { +    return this->char_type_specified_; +  } + +  inline const NarrowString& options:: +  char_encoding () const +  { +    return this->char_encoding_; +  } + +  inline bool options:: +  char_encoding_specified () const +  { +    return this->char_encoding_specified_; +  } + +  inline const NarrowString& options:: +  output_dir () const +  { +    return this->output_dir_; +  } + +  inline bool options:: +  output_dir_specified () const +  { +    return this->output_dir_specified_; +  } + +  inline const bool& options:: +  generate_inline () const +  { +    return this->generate_inline_; +  } + +  inline const bool& options:: +  generate_xml_schema () const +  { +    return this->generate_xml_schema_; +  } + +  inline const NarrowString& options:: +  extern_xml_schema () const +  { +    return this->extern_xml_schema_; +  } + +  inline bool options:: +  extern_xml_schema_specified () const +  { +    return this->extern_xml_schema_specified_; +  } + +  inline const NarrowStrings& options:: +  namespace_map () const +  { +    return this->namespace_map_; +  } + +  inline bool options:: +  namespace_map_specified () const +  { +    return this->namespace_map_specified_; +  } + +  inline const NarrowStrings& options:: +  namespace_regex () const +  { +    return this->namespace_regex_; +  } + +  inline bool options:: +  namespace_regex_specified () const +  { +    return this->namespace_regex_specified_; +  } + +  inline const bool& options:: +  namespace_regex_trace () const +  { +    return this->namespace_regex_trace_; +  } + +  inline const NarrowStrings& options:: +  reserved_name () const +  { +    return this->reserved_name_; +  } + +  inline bool options:: +  reserved_name_specified () const +  { +    return this->reserved_name_specified_; +  } + +  inline const bool& options:: +  include_with_brackets () const +  { +    return this->include_with_brackets_; +  } + +  inline const NarrowString& options:: +  include_prefix () const +  { +    return this->include_prefix_; +  } + +  inline bool options:: +  include_prefix_specified () const +  { +    return this->include_prefix_specified_; +  } + +  inline const NarrowStrings& options:: +  include_regex () const +  { +    return this->include_regex_; +  } + +  inline bool options:: +  include_regex_specified () const +  { +    return this->include_regex_specified_; +  } + +  inline const bool& options:: +  include_regex_trace () const +  { +    return this->include_regex_trace_; +  } + +  inline const NarrowString& options:: +  guard_prefix () const +  { +    return this->guard_prefix_; +  } + +  inline bool options:: +  guard_prefix_specified () const +  { +    return this->guard_prefix_specified_; +  } + +  inline const NarrowString& options:: +  hxx_suffix () const +  { +    return this->hxx_suffix_; +  } + +  inline bool options:: +  hxx_suffix_specified () const +  { +    return this->hxx_suffix_specified_; +  } + +  inline const NarrowString& options:: +  ixx_suffix () const +  { +    return this->ixx_suffix_; +  } + +  inline bool options:: +  ixx_suffix_specified () const +  { +    return this->ixx_suffix_specified_; +  } + +  inline const NarrowString& options:: +  cxx_suffix () const +  { +    return this->cxx_suffix_; +  } + +  inline bool options:: +  cxx_suffix_specified () const +  { +    return this->cxx_suffix_specified_; +  } + +  inline const NarrowString& options:: +  fwd_suffix () const +  { +    return this->fwd_suffix_; +  } + +  inline bool options:: +  fwd_suffix_specified () const +  { +    return this->fwd_suffix_specified_; +  } + +  inline const NarrowString& options:: +  hxx_regex () const +  { +    return this->hxx_regex_; +  } + +  inline bool options:: +  hxx_regex_specified () const +  { +    return this->hxx_regex_specified_; +  } + +  inline const NarrowString& options:: +  ixx_regex () const +  { +    return this->ixx_regex_; +  } + +  inline bool options:: +  ixx_regex_specified () const +  { +    return this->ixx_regex_specified_; +  } + +  inline const NarrowString& options:: +  cxx_regex () const +  { +    return this->cxx_regex_; +  } + +  inline bool options:: +  cxx_regex_specified () const +  { +    return this->cxx_regex_specified_; +  } + +  inline const NarrowString& options:: +  fwd_regex () const +  { +    return this->fwd_regex_; +  } + +  inline bool options:: +  fwd_regex_specified () const +  { +    return this->fwd_regex_specified_; +  } + +  inline const NarrowStrings& options:: +  hxx_prologue () const +  { +    return this->hxx_prologue_; +  } + +  inline bool options:: +  hxx_prologue_specified () const +  { +    return this->hxx_prologue_specified_; +  } + +  inline const NarrowStrings& options:: +  ixx_prologue () const +  { +    return this->ixx_prologue_; +  } + +  inline bool options:: +  ixx_prologue_specified () const +  { +    return this->ixx_prologue_specified_; +  } + +  inline const NarrowStrings& options:: +  cxx_prologue () const +  { +    return this->cxx_prologue_; +  } + +  inline bool options:: +  cxx_prologue_specified () const +  { +    return this->cxx_prologue_specified_; +  } + +  inline const NarrowStrings& options:: +  fwd_prologue () const +  { +    return this->fwd_prologue_; +  } + +  inline bool options:: +  fwd_prologue_specified () const +  { +    return this->fwd_prologue_specified_; +  } + +  inline const NarrowStrings& options:: +  prologue () const +  { +    return this->prologue_; +  } + +  inline bool options:: +  prologue_specified () const +  { +    return this->prologue_specified_; +  } + +  inline const NarrowStrings& options:: +  hxx_epilogue () const +  { +    return this->hxx_epilogue_; +  } + +  inline bool options:: +  hxx_epilogue_specified () const +  { +    return this->hxx_epilogue_specified_; +  } + +  inline const NarrowStrings& options:: +  ixx_epilogue () const +  { +    return this->ixx_epilogue_; +  } + +  inline bool options:: +  ixx_epilogue_specified () const +  { +    return this->ixx_epilogue_specified_; +  } + +  inline const NarrowStrings& options:: +  cxx_epilogue () const +  { +    return this->cxx_epilogue_; +  } + +  inline bool options:: +  cxx_epilogue_specified () const +  { +    return this->cxx_epilogue_specified_; +  } + +  inline const NarrowStrings& options:: +  fwd_epilogue () const +  { +    return this->fwd_epilogue_; +  } + +  inline bool options:: +  fwd_epilogue_specified () const +  { +    return this->fwd_epilogue_specified_; +  } + +  inline const NarrowStrings& options:: +  epilogue () const +  { +    return this->epilogue_; +  } + +  inline bool options:: +  epilogue_specified () const +  { +    return this->epilogue_specified_; +  } + +  inline const NarrowString& options:: +  hxx_prologue_file () const +  { +    return this->hxx_prologue_file_; +  } + +  inline bool options:: +  hxx_prologue_file_specified () const +  { +    return this->hxx_prologue_file_specified_; +  } + +  inline const NarrowString& options:: +  ixx_prologue_file () const +  { +    return this->ixx_prologue_file_; +  } + +  inline bool options:: +  ixx_prologue_file_specified () const +  { +    return this->ixx_prologue_file_specified_; +  } + +  inline const NarrowString& options:: +  cxx_prologue_file () const +  { +    return this->cxx_prologue_file_; +  } + +  inline bool options:: +  cxx_prologue_file_specified () const +  { +    return this->cxx_prologue_file_specified_; +  } + +  inline const NarrowString& options:: +  fwd_prologue_file () const +  { +    return this->fwd_prologue_file_; +  } + +  inline bool options:: +  fwd_prologue_file_specified () const +  { +    return this->fwd_prologue_file_specified_; +  } + +  inline const NarrowString& options:: +  prologue_file () const +  { +    return this->prologue_file_; +  } + +  inline bool options:: +  prologue_file_specified () const +  { +    return this->prologue_file_specified_; +  } + +  inline const NarrowString& options:: +  hxx_epilogue_file () const +  { +    return this->hxx_epilogue_file_; +  } + +  inline bool options:: +  hxx_epilogue_file_specified () const +  { +    return this->hxx_epilogue_file_specified_; +  } + +  inline const NarrowString& options:: +  ixx_epilogue_file () const +  { +    return this->ixx_epilogue_file_; +  } + +  inline bool options:: +  ixx_epilogue_file_specified () const +  { +    return this->ixx_epilogue_file_specified_; +  } + +  inline const NarrowString& options:: +  cxx_epilogue_file () const +  { +    return this->cxx_epilogue_file_; +  } + +  inline bool options:: +  cxx_epilogue_file_specified () const +  { +    return this->cxx_epilogue_file_specified_; +  } + +  inline const NarrowString& options:: +  fwd_epilogue_file () const +  { +    return this->fwd_epilogue_file_; +  } + +  inline bool options:: +  fwd_epilogue_file_specified () const +  { +    return this->fwd_epilogue_file_specified_; +  } + +  inline const NarrowString& options:: +  epilogue_file () const +  { +    return this->epilogue_file_; +  } + +  inline bool options:: +  epilogue_file_specified () const +  { +    return this->epilogue_file_specified_; +  } + +  inline const NarrowString& options:: +  export_symbol () const +  { +    return this->export_symbol_; +  } + +  inline bool options:: +  export_symbol_specified () const +  { +    return this->export_symbol_specified_; +  } + +  inline const bool& options:: +  export_xml_schema () const +  { +    return this->export_xml_schema_; +  } + +  inline const bool& options:: +  export_maps () const +  { +    return this->export_maps_; +  } + +  inline const bool& options:: +  import_maps () const +  { +    return this->import_maps_; +  } + +  inline const bool& options:: +  generate_dep () const +  { +    return this->generate_dep_; +  } + +  inline const bool& options:: +  generate_dep_only () const +  { +    return this->generate_dep_only_; +  } + +  inline const bool& options:: +  dep_phony () const +  { +    return this->dep_phony_; +  } + +  inline const NarrowStrings& options:: +  dep_target () const +  { +    return this->dep_target_; +  } + +  inline bool options:: +  dep_target_specified () const +  { +    return this->dep_target_specified_; +  } + +  inline const NarrowString& options:: +  dep_suffix () const +  { +    return this->dep_suffix_; +  } + +  inline bool options:: +  dep_suffix_specified () const +  { +    return this->dep_suffix_specified_; +  } + +  inline const NarrowString& options:: +  dep_file () const +  { +    return this->dep_file_; +  } + +  inline bool options:: +  dep_file_specified () const +  { +    return this->dep_file_specified_; +  } + +  inline const NarrowString& options:: +  dep_regex () const +  { +    return this->dep_regex_; +  } + +  inline bool options:: +  dep_regex_specified () const +  { +    return this->dep_regex_specified_; +  } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/xsd/pregenerated/xsd/cxx/parser/options.cxx b/xsd/pregenerated/xsd/cxx/parser/options.cxx new file mode 100644 index 0000000..60667ac --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/parser/options.cxx @@ -0,0 +1,776 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <xsd/options-parser.hxx> +// +// End prologue. + +#include <xsd/cxx/parser/options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +namespace cli +{ +  template <typename X> +  struct parser +  { +    static void +    parse (X& x, bool& xs, scanner& s) +    { +      using namespace std; + +      const char* o (s.next ()); +      if (s.more ()) +      { +        string v (s.next ()); +        istringstream is (v); +        if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) +          throw invalid_value (o, v); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <> +  struct parser<bool> +  { +    static void +    parse (bool& x, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        const char* v (s.next ()); + +        if (std::strcmp (v, "1")    == 0 || +            std::strcmp (v, "true") == 0 || +            std::strcmp (v, "TRUE") == 0 || +            std::strcmp (v, "True") == 0) +          x = true; +        else if (std::strcmp (v, "0")     == 0 || +                 std::strcmp (v, "false") == 0 || +                 std::strcmp (v, "FALSE") == 0 || +                 std::strcmp (v, "False") == 0) +          x = false; +        else +          throw invalid_value (o, v); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <> +  struct parser<std::string> +  { +    static void +    parse (std::string& x, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +        x = s.next (); +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename X> +  struct parser<std::pair<X, std::size_t> > +  { +    static void +    parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) +    { +      x.second = s.position (); +      parser<X>::parse (x.first, xs, s); +    } +  }; + +  template <typename X> +  struct parser<std::vector<X> > +  { +    static void +    parse (std::vector<X>& c, bool& xs, scanner& s) +    { +      X x; +      bool dummy; +      parser<X>::parse (x, dummy, s); +      c.push_back (x); +      xs = true; +    } +  }; + +  template <typename X, typename C> +  struct parser<std::set<X, C> > +  { +    static void +    parse (std::set<X, C>& c, bool& xs, scanner& s) +    { +      X x; +      bool dummy; +      parser<X>::parse (x, dummy, s); +      c.insert (x); +      xs = true; +    } +  }; + +  template <typename K, typename V, typename C> +  struct parser<std::map<K, V, C> > +  { +    static void +    parse (std::map<K, V, C>& m, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        std::size_t pos (s.position ()); +        std::string ov (s.next ()); +        std::string::size_type p = ov.find ('='); + +        K k = K (); +        V v = V (); +        std::string kstr (ov, 0, p); +        std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + +        int ac (2); +        char* av[] = +        { +          const_cast<char*> (o), +          0 +        }; + +        bool dummy; +        if (!kstr.empty ()) +        { +          av[1] = const_cast<char*> (kstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<K>::parse (k, dummy, s); +        } + +        if (!vstr.empty ()) +        { +          av[1] = const_cast<char*> (vstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<V>::parse (v, dummy, s); +        } + +        m[k] = v; +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename K, typename V, typename C> +  struct parser<std::multimap<K, V, C> > +  { +    static void +    parse (std::multimap<K, V, C>& m, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        std::size_t pos (s.position ()); +        std::string ov (s.next ()); +        std::string::size_type p = ov.find ('='); + +        K k = K (); +        V v = V (); +        std::string kstr (ov, 0, p); +        std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + +        int ac (2); +        char* av[] = +        { +          const_cast<char*> (o), +          0 +        }; + +        bool dummy; +        if (!kstr.empty ()) +        { +          av[1] = const_cast<char*> (kstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<K>::parse (k, dummy, s); +        } + +        if (!vstr.empty ()) +        { +          av[1] = const_cast<char*> (vstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<V>::parse (v, dummy, s); +        } + +        m.insert (typename std::multimap<K, V, C>::value_type (k, v)); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename X, typename T, T X::*M> +  void +  thunk (X& x, scanner& s) +  { +    parser<T>::parse (x.*M, s); +  } + +  template <typename X, bool X::*M> +  void +  thunk (X& x, scanner& s) +  { +    s.next (); +    x.*M = true; +  } + +  template <typename X, typename T, T X::*M, bool X::*S> +  void +  thunk (X& x, scanner& s) +  { +    parser<T>::parse (x.*M, x.*S, s); +  } +} + +#include <map> + +namespace CXX +{ +  namespace Parser +  { +    // options +    // + +    options:: +    options () +    : type_map_ (), +      type_map_specified_ (false), +      xml_parser_ ("xerces"), +      xml_parser_specified_ (false), +      generate_validation_ (), +      suppress_validation_ (), +      generate_polymorphic_ (), +      generate_noop_impl_ (), +      generate_print_impl_ (), +      generate_test_driver_ (), +      force_overwrite_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_ (), +      root_element_specified_ (false), +      skel_type_suffix_ ("_pskel"), +      skel_type_suffix_specified_ (false), +      skel_file_suffix_ ("-pskel"), +      skel_file_suffix_specified_ (false), +      impl_type_suffix_ ("_pimpl"), +      impl_type_suffix_specified_ (false), +      impl_file_suffix_ ("-pimpl"), +      impl_file_suffix_specified_ (false) +    { +    } + +    options:: +    options (int& argc, +             char** argv, +             bool erase, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : type_map_ (), +      type_map_specified_ (false), +      xml_parser_ ("xerces"), +      xml_parser_specified_ (false), +      generate_validation_ (), +      suppress_validation_ (), +      generate_polymorphic_ (), +      generate_noop_impl_ (), +      generate_print_impl_ (), +      generate_test_driver_ (), +      force_overwrite_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_ (), +      root_element_specified_ (false), +      skel_type_suffix_ ("_pskel"), +      skel_type_suffix_specified_ (false), +      skel_file_suffix_ ("-pskel"), +      skel_file_suffix_specified_ (false), +      impl_type_suffix_ ("_pimpl"), +      impl_type_suffix_specified_ (false), +      impl_file_suffix_ ("-pimpl"), +      impl_file_suffix_specified_ (false) +    { +      ::cli::argv_scanner s (argc, argv, erase); +      _parse (s, opt, arg); +    } + +    options:: +    options (int start, +             int& argc, +             char** argv, +             bool erase, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : type_map_ (), +      type_map_specified_ (false), +      xml_parser_ ("xerces"), +      xml_parser_specified_ (false), +      generate_validation_ (), +      suppress_validation_ (), +      generate_polymorphic_ (), +      generate_noop_impl_ (), +      generate_print_impl_ (), +      generate_test_driver_ (), +      force_overwrite_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_ (), +      root_element_specified_ (false), +      skel_type_suffix_ ("_pskel"), +      skel_type_suffix_specified_ (false), +      skel_file_suffix_ ("-pskel"), +      skel_file_suffix_specified_ (false), +      impl_type_suffix_ ("_pimpl"), +      impl_type_suffix_specified_ (false), +      impl_file_suffix_ ("-pimpl"), +      impl_file_suffix_specified_ (false) +    { +      ::cli::argv_scanner s (start, argc, argv, erase); +      _parse (s, opt, arg); +    } + +    options:: +    options (int& argc, +             char** argv, +             int& end, +             bool erase, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : type_map_ (), +      type_map_specified_ (false), +      xml_parser_ ("xerces"), +      xml_parser_specified_ (false), +      generate_validation_ (), +      suppress_validation_ (), +      generate_polymorphic_ (), +      generate_noop_impl_ (), +      generate_print_impl_ (), +      generate_test_driver_ (), +      force_overwrite_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_ (), +      root_element_specified_ (false), +      skel_type_suffix_ ("_pskel"), +      skel_type_suffix_specified_ (false), +      skel_file_suffix_ ("-pskel"), +      skel_file_suffix_specified_ (false), +      impl_type_suffix_ ("_pimpl"), +      impl_type_suffix_specified_ (false), +      impl_file_suffix_ ("-pimpl"), +      impl_file_suffix_specified_ (false) +    { +      ::cli::argv_scanner s (argc, argv, erase); +      _parse (s, opt, arg); +      end = s.end (); +    } + +    options:: +    options (int start, +             int& argc, +             char** argv, +             int& end, +             bool erase, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : type_map_ (), +      type_map_specified_ (false), +      xml_parser_ ("xerces"), +      xml_parser_specified_ (false), +      generate_validation_ (), +      suppress_validation_ (), +      generate_polymorphic_ (), +      generate_noop_impl_ (), +      generate_print_impl_ (), +      generate_test_driver_ (), +      force_overwrite_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_ (), +      root_element_specified_ (false), +      skel_type_suffix_ ("_pskel"), +      skel_type_suffix_specified_ (false), +      skel_file_suffix_ ("-pskel"), +      skel_file_suffix_specified_ (false), +      impl_type_suffix_ ("_pimpl"), +      impl_type_suffix_specified_ (false), +      impl_file_suffix_ ("-pimpl"), +      impl_file_suffix_specified_ (false) +    { +      ::cli::argv_scanner s (start, argc, argv, erase); +      _parse (s, opt, arg); +      end = s.end (); +    } + +    options:: +    options (::cli::scanner& s, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : type_map_ (), +      type_map_specified_ (false), +      xml_parser_ ("xerces"), +      xml_parser_specified_ (false), +      generate_validation_ (), +      suppress_validation_ (), +      generate_polymorphic_ (), +      generate_noop_impl_ (), +      generate_print_impl_ (), +      generate_test_driver_ (), +      force_overwrite_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_ (), +      root_element_specified_ (false), +      skel_type_suffix_ ("_pskel"), +      skel_type_suffix_specified_ (false), +      skel_file_suffix_ ("-pskel"), +      skel_file_suffix_specified_ (false), +      impl_type_suffix_ ("_pimpl"), +      impl_type_suffix_specified_ (false), +      impl_file_suffix_ ("-pimpl"), +      impl_file_suffix_specified_ (false) +    { +      _parse (s, opt, arg); +    } + +    ::cli::usage_para options:: +    print_usage (::std::wostream& os, ::cli::usage_para p) +    { +      CLI_POTENTIALLY_UNUSED (os); + +      if (p == ::cli::usage_para::text) +        os << ::std::endl; + +      os << "--type-map <mapfile>         Read XML Schema to C++ type mapping information" << ::std::endl +         << "                             from <mapfile>." << ::std::endl; + +      os << "--xml-parser <parser>        Use <parser> as the underlying XML parser." << ::std::endl; + +      os << "--generate-validation        Generate validation code." << ::std::endl; + +      os << "--suppress-validation        Suppress the generation of validation code." << ::std::endl; + +      os << "--generate-polymorphic       Generate polymorphism-aware code." << ::std::endl; + +      os << "--generate-noop-impl         Generate a sample parser implementation that does" << ::std::endl +         << "                             nothing (no operation)." << ::std::endl; + +      os << "--generate-print-impl        Generate a sample parser implementation that" << ::std::endl +         << "                             prints the XML data to STDOUT." << ::std::endl; + +      os << "--generate-test-driver       Generate a test driver for the sample parser" << ::std::endl +         << "                             implementation." << ::std::endl; + +      os << "--force-overwrite            Force overwriting of the existing implementation" << ::std::endl +         << "                             and test driver files." << ::std::endl; + +      os << "--root-element-first         Indicate that the first global element is the" << ::std::endl +         << "                             document root." << ::std::endl; + +      os << "--root-element-last          Indicate that the last global element is the" << ::std::endl +         << "                             document root." << ::std::endl; + +      os << "--root-element <element>     Indicate that <element> is the document root." << ::std::endl; + +      os << "--skel-type-suffix <suffix>  Use the provided <suffix> instead of the default" << ::std::endl +         << "                             _pskel to construct the names of the generated" << ::std::endl +         << "                             parser skeletons." << ::std::endl; + +      os << "--skel-file-suffix <suffix>  Use the provided <suffix> instead of the default" << ::std::endl +         << "                             -pskel to construct the names of the generated" << ::std::endl +         << "                             parser skeleton files." << ::std::endl; + +      os << "--impl-type-suffix <suffix>  Use the provided <suffix> instead of the default" << ::std::endl +         << "                             _pimpl to construct the names of the parser" << ::std::endl +         << "                             implementations for the built-in XML Schema types" << ::std::endl +         << "                             as well as sample parser implementations." << ::std::endl; + +      os << "--impl-file-suffix <suffix>  Use the provided <suffix> instead of the default" << ::std::endl +         << "                             -pimpl to construct the names of the generated" << ::std::endl +         << "                             sample parser implementation files." << ::std::endl; + +      p = ::cli::usage_para::option; + +      return p; +    } + +    typedef +    std::map<std::string, void (*) (options&, ::cli::scanner&)> +    _cli_options_map; + +    static _cli_options_map _cli_options_map_; + +    struct _cli_options_map_init +    { +      _cli_options_map_init () +      { +        _cli_options_map_["--type-map"] = +        &::cli::thunk< options, NarrowStrings, &options::type_map_, +          &options::type_map_specified_ >; +        _cli_options_map_["--xml-parser"] = +        &::cli::thunk< options, NarrowString, &options::xml_parser_, +          &options::xml_parser_specified_ >; +        _cli_options_map_["--generate-validation"] = +        &::cli::thunk< options, &options::generate_validation_ >; +        _cli_options_map_["--suppress-validation"] = +        &::cli::thunk< options, &options::suppress_validation_ >; +        _cli_options_map_["--generate-polymorphic"] = +        &::cli::thunk< options, &options::generate_polymorphic_ >; +        _cli_options_map_["--generate-noop-impl"] = +        &::cli::thunk< options, &options::generate_noop_impl_ >; +        _cli_options_map_["--generate-print-impl"] = +        &::cli::thunk< options, &options::generate_print_impl_ >; +        _cli_options_map_["--generate-test-driver"] = +        &::cli::thunk< options, &options::generate_test_driver_ >; +        _cli_options_map_["--force-overwrite"] = +        &::cli::thunk< options, &options::force_overwrite_ >; +        _cli_options_map_["--root-element-first"] = +        &::cli::thunk< options, &options::root_element_first_ >; +        _cli_options_map_["--root-element-last"] = +        &::cli::thunk< options, &options::root_element_last_ >; +        _cli_options_map_["--root-element"] = +        &::cli::thunk< options, NarrowString, &options::root_element_, +          &options::root_element_specified_ >; +        _cli_options_map_["--skel-type-suffix"] = +        &::cli::thunk< options, NarrowString, &options::skel_type_suffix_, +          &options::skel_type_suffix_specified_ >; +        _cli_options_map_["--skel-file-suffix"] = +        &::cli::thunk< options, NarrowString, &options::skel_file_suffix_, +          &options::skel_file_suffix_specified_ >; +        _cli_options_map_["--impl-type-suffix"] = +        &::cli::thunk< options, NarrowString, &options::impl_type_suffix_, +          &options::impl_type_suffix_specified_ >; +        _cli_options_map_["--impl-file-suffix"] = +        &::cli::thunk< options, NarrowString, &options::impl_file_suffix_, +          &options::impl_file_suffix_specified_ >; +      } +    }; + +    static _cli_options_map_init _cli_options_map_init_; + +    bool options:: +    _parse (const char* o, ::cli::scanner& s) +    { +      _cli_options_map::const_iterator i (_cli_options_map_.find (o)); + +      if (i != _cli_options_map_.end ()) +      { +        (*(i->second)) (*this, s); +        return true; +      } + +      // options base +      // +      if (::CXX::options::_parse (o, s)) +        return true; + +      return false; +    } + +    bool options:: +    _parse (::cli::scanner& s, +            ::cli::unknown_mode opt_mode, +            ::cli::unknown_mode arg_mode) +    { +      // Can't skip combined flags (--no-combined-flags). +      // +      assert (opt_mode != ::cli::unknown_mode::skip); + +      bool r = false; +      bool opt = true; + +      while (s.more ()) +      { +        const char* o = s.peek (); + +        if (std::strcmp (o, "--") == 0) +        { +          opt = false; +          s.skip (); +          r = true; +          continue; +        } + +        if (opt) +        { +          if (_parse (o, s)) +          { +            r = true; +            continue; +          } + +          if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') +          { +            // Handle combined option values. +            // +            std::string co; +            if (const char* v = std::strchr (o, '=')) +            { +              co.assign (o, 0, v - o); +              ++v; + +              int ac (2); +              char* av[] = +              { +                const_cast<char*> (co.c_str ()), +                const_cast<char*> (v) +              }; + +              ::cli::argv_scanner ns (0, ac, av); + +              if (_parse (co.c_str (), ns)) +              { +                // Parsed the option but not its value? +                // +                if (ns.end () != 2) +                  throw ::cli::invalid_value (co, v); + +                s.next (); +                r = true; +                continue; +              } +              else +              { +                // Set the unknown option and fall through. +                // +                o = co.c_str (); +              } +            } + +            // Handle combined flags. +            // +            char cf[3]; +            { +              const char* p = o + 1; +              for (; *p != '\0'; ++p) +              { +                if (!((*p >= 'a' && *p <= 'z') || +                      (*p >= 'A' && *p <= 'Z') || +                      (*p >= '0' && *p <= '9'))) +                  break; +              } + +              if (*p == '\0') +              { +                for (p = o + 1; *p != '\0'; ++p) +                { +                  std::strcpy (cf, "-"); +                  cf[1] = *p; +                  cf[2] = '\0'; + +                  int ac (1); +                  char* av[] = +                  { +                    cf +                  }; + +                  ::cli::argv_scanner ns (0, ac, av); + +                  if (!_parse (cf, ns)) +                    break; +                } + +                if (*p == '\0') +                { +                  // All handled. +                  // +                  s.next (); +                  r = true; +                  continue; +                } +                else +                { +                  // Set the unknown option and fall through. +                  // +                  o = cf; +                } +              } +            } + +            switch (opt_mode) +            { +              case ::cli::unknown_mode::skip: +              { +                s.skip (); +                r = true; +                continue; +              } +              case ::cli::unknown_mode::stop: +              { +                break; +              } +              case ::cli::unknown_mode::fail: +              { +                throw ::cli::unknown_option (o); +              } +            } + +            break; +          } +        } + +        switch (arg_mode) +        { +          case ::cli::unknown_mode::skip: +          { +            s.skip (); +            r = true; +            continue; +          } +          case ::cli::unknown_mode::stop: +          { +            break; +          } +          case ::cli::unknown_mode::fail: +          { +            throw ::cli::unknown_argument (o); +          } +        } + +        break; +      } + +      return r; +    } +  } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/xsd/pregenerated/xsd/cxx/parser/options.hxx b/xsd/pregenerated/xsd/cxx/parser/options.hxx new file mode 100644 index 0000000..03b67fd --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/parser/options.hxx @@ -0,0 +1,186 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef XSD_CXX_PARSER_OPTIONS_HXX +#define XSD_CXX_PARSER_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <cstddef> + +#include <xsd/types.hxx> + +#include <xsd/cxx/options.hxx> + +namespace CXX +{ +  namespace Parser +  { +    class options: public ::CXX::options +    { +      public: +      options (); + +      options (int& argc, +               char** argv, +               bool erase = false, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      options (int start, +               int& argc, +               char** argv, +               bool erase = false, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      options (int& argc, +               char** argv, +               int& end, +               bool erase = false, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      options (int start, +               int& argc, +               char** argv, +               int& end, +               bool erase = false, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      options (::cli::scanner&, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      // Option accessors. +      // +      const NarrowStrings& +      type_map () const; + +      bool +      type_map_specified () const; + +      const NarrowString& +      xml_parser () const; + +      bool +      xml_parser_specified () const; + +      const bool& +      generate_validation () const; + +      const bool& +      suppress_validation () const; + +      const bool& +      generate_polymorphic () const; + +      const bool& +      generate_noop_impl () const; + +      const bool& +      generate_print_impl () const; + +      const bool& +      generate_test_driver () const; + +      const bool& +      force_overwrite () const; + +      const bool& +      root_element_first () const; + +      const bool& +      root_element_last () const; + +      const NarrowString& +      root_element () const; + +      bool +      root_element_specified () const; + +      const NarrowString& +      skel_type_suffix () const; + +      bool +      skel_type_suffix_specified () const; + +      const NarrowString& +      skel_file_suffix () const; + +      bool +      skel_file_suffix_specified () const; + +      const NarrowString& +      impl_type_suffix () const; + +      bool +      impl_type_suffix_specified () const; + +      const NarrowString& +      impl_file_suffix () const; + +      bool +      impl_file_suffix_specified () const; + +      // Print usage information. +      // +      static ::cli::usage_para +      print_usage (::std::wostream&, +                   ::cli::usage_para = ::cli::usage_para::none); + +      // Implementation details. +      // +      protected: +      bool +      _parse (const char*, ::cli::scanner&); + +      private: +      bool +      _parse (::cli::scanner&, +              ::cli::unknown_mode option, +              ::cli::unknown_mode argument); + +      public: +      NarrowStrings type_map_; +      bool type_map_specified_; +      NarrowString xml_parser_; +      bool xml_parser_specified_; +      bool generate_validation_; +      bool suppress_validation_; +      bool generate_polymorphic_; +      bool generate_noop_impl_; +      bool generate_print_impl_; +      bool generate_test_driver_; +      bool force_overwrite_; +      bool root_element_first_; +      bool root_element_last_; +      NarrowString root_element_; +      bool root_element_specified_; +      NarrowString skel_type_suffix_; +      bool skel_type_suffix_specified_; +      NarrowString skel_file_suffix_; +      bool skel_file_suffix_specified_; +      NarrowString impl_type_suffix_; +      bool impl_type_suffix_specified_; +      NarrowString impl_file_suffix_; +      bool impl_file_suffix_specified_; +    }; +  } +} + +#include <xsd/cxx/parser/options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // XSD_CXX_PARSER_OPTIONS_HXX diff --git a/xsd/pregenerated/xsd/cxx/parser/options.ixx b/xsd/pregenerated/xsd/cxx/parser/options.ixx new file mode 100644 index 0000000..64c00c5 --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/parser/options.ixx @@ -0,0 +1,162 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace CXX +{ +  namespace Parser +  { +    // options +    // + +    inline const NarrowStrings& options:: +    type_map () const +    { +      return this->type_map_; +    } + +    inline bool options:: +    type_map_specified () const +    { +      return this->type_map_specified_; +    } + +    inline const NarrowString& options:: +    xml_parser () const +    { +      return this->xml_parser_; +    } + +    inline bool options:: +    xml_parser_specified () const +    { +      return this->xml_parser_specified_; +    } + +    inline const bool& options:: +    generate_validation () const +    { +      return this->generate_validation_; +    } + +    inline const bool& options:: +    suppress_validation () const +    { +      return this->suppress_validation_; +    } + +    inline const bool& options:: +    generate_polymorphic () const +    { +      return this->generate_polymorphic_; +    } + +    inline const bool& options:: +    generate_noop_impl () const +    { +      return this->generate_noop_impl_; +    } + +    inline const bool& options:: +    generate_print_impl () const +    { +      return this->generate_print_impl_; +    } + +    inline const bool& options:: +    generate_test_driver () const +    { +      return this->generate_test_driver_; +    } + +    inline const bool& options:: +    force_overwrite () const +    { +      return this->force_overwrite_; +    } + +    inline const bool& options:: +    root_element_first () const +    { +      return this->root_element_first_; +    } + +    inline const bool& options:: +    root_element_last () const +    { +      return this->root_element_last_; +    } + +    inline const NarrowString& options:: +    root_element () const +    { +      return this->root_element_; +    } + +    inline bool options:: +    root_element_specified () const +    { +      return this->root_element_specified_; +    } + +    inline const NarrowString& options:: +    skel_type_suffix () const +    { +      return this->skel_type_suffix_; +    } + +    inline bool options:: +    skel_type_suffix_specified () const +    { +      return this->skel_type_suffix_specified_; +    } + +    inline const NarrowString& options:: +    skel_file_suffix () const +    { +      return this->skel_file_suffix_; +    } + +    inline bool options:: +    skel_file_suffix_specified () const +    { +      return this->skel_file_suffix_specified_; +    } + +    inline const NarrowString& options:: +    impl_type_suffix () const +    { +      return this->impl_type_suffix_; +    } + +    inline bool options:: +    impl_type_suffix_specified () const +    { +      return this->impl_type_suffix_specified_; +    } + +    inline const NarrowString& options:: +    impl_file_suffix () const +    { +      return this->impl_file_suffix_; +    } + +    inline bool options:: +    impl_file_suffix_specified () const +    { +      return this->impl_file_suffix_specified_; +    } +  } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/xsd/pregenerated/xsd/cxx/tree/options.cxx b/xsd/pregenerated/xsd/cxx/tree/options.cxx new file mode 100644 index 0000000..17214c1 --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/tree/options.cxx @@ -0,0 +1,1343 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <xsd/options-parser.hxx> +// +// End prologue. + +#include <xsd/cxx/tree/options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +namespace cli +{ +  template <typename X> +  struct parser +  { +    static void +    parse (X& x, bool& xs, scanner& s) +    { +      using namespace std; + +      const char* o (s.next ()); +      if (s.more ()) +      { +        string v (s.next ()); +        istringstream is (v); +        if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) +          throw invalid_value (o, v); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <> +  struct parser<bool> +  { +    static void +    parse (bool& x, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        const char* v (s.next ()); + +        if (std::strcmp (v, "1")    == 0 || +            std::strcmp (v, "true") == 0 || +            std::strcmp (v, "TRUE") == 0 || +            std::strcmp (v, "True") == 0) +          x = true; +        else if (std::strcmp (v, "0")     == 0 || +                 std::strcmp (v, "false") == 0 || +                 std::strcmp (v, "FALSE") == 0 || +                 std::strcmp (v, "False") == 0) +          x = false; +        else +          throw invalid_value (o, v); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <> +  struct parser<std::string> +  { +    static void +    parse (std::string& x, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +        x = s.next (); +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename X> +  struct parser<std::pair<X, std::size_t> > +  { +    static void +    parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) +    { +      x.second = s.position (); +      parser<X>::parse (x.first, xs, s); +    } +  }; + +  template <typename X> +  struct parser<std::vector<X> > +  { +    static void +    parse (std::vector<X>& c, bool& xs, scanner& s) +    { +      X x; +      bool dummy; +      parser<X>::parse (x, dummy, s); +      c.push_back (x); +      xs = true; +    } +  }; + +  template <typename X, typename C> +  struct parser<std::set<X, C> > +  { +    static void +    parse (std::set<X, C>& c, bool& xs, scanner& s) +    { +      X x; +      bool dummy; +      parser<X>::parse (x, dummy, s); +      c.insert (x); +      xs = true; +    } +  }; + +  template <typename K, typename V, typename C> +  struct parser<std::map<K, V, C> > +  { +    static void +    parse (std::map<K, V, C>& m, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        std::size_t pos (s.position ()); +        std::string ov (s.next ()); +        std::string::size_type p = ov.find ('='); + +        K k = K (); +        V v = V (); +        std::string kstr (ov, 0, p); +        std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + +        int ac (2); +        char* av[] = +        { +          const_cast<char*> (o), +          0 +        }; + +        bool dummy; +        if (!kstr.empty ()) +        { +          av[1] = const_cast<char*> (kstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<K>::parse (k, dummy, s); +        } + +        if (!vstr.empty ()) +        { +          av[1] = const_cast<char*> (vstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<V>::parse (v, dummy, s); +        } + +        m[k] = v; +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename K, typename V, typename C> +  struct parser<std::multimap<K, V, C> > +  { +    static void +    parse (std::multimap<K, V, C>& m, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        std::size_t pos (s.position ()); +        std::string ov (s.next ()); +        std::string::size_type p = ov.find ('='); + +        K k = K (); +        V v = V (); +        std::string kstr (ov, 0, p); +        std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + +        int ac (2); +        char* av[] = +        { +          const_cast<char*> (o), +          0 +        }; + +        bool dummy; +        if (!kstr.empty ()) +        { +          av[1] = const_cast<char*> (kstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<K>::parse (k, dummy, s); +        } + +        if (!vstr.empty ()) +        { +          av[1] = const_cast<char*> (vstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<V>::parse (v, dummy, s); +        } + +        m.insert (typename std::multimap<K, V, C>::value_type (k, v)); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename X, typename T, T X::*M> +  void +  thunk (X& x, scanner& s) +  { +    parser<T>::parse (x.*M, s); +  } + +  template <typename X, bool X::*M> +  void +  thunk (X& x, scanner& s) +  { +    s.next (); +    x.*M = true; +  } + +  template <typename X, typename T, T X::*M, bool X::*S> +  void +  thunk (X& x, scanner& s) +  { +    parser<T>::parse (x.*M, x.*S, s); +  } +} + +#include <map> + +namespace CXX +{ +  namespace Tree +  { +    // options +    // + +    options:: +    options () +    : generate_polymorphic_ (), +      polymorphic_type_ (), +      polymorphic_type_specified_ (false), +      polymorphic_type_all_ (), +      polymorphic_plate_ (0), +      polymorphic_plate_specified_ (false), +      ordered_type_ (), +      ordered_type_specified_ (false), +      ordered_type_derived_ (), +      ordered_type_mixed_ (), +      ordered_type_all_ (), +      order_container_ (), +      order_container_specified_ (false), +      generate_serialization_ (), +      generate_ostream_ (), +      generate_doxygen_ (), +      generate_comparison_ (), +      generate_default_ctor_ (), +      generate_from_base_ctor_ (), +      suppress_assignment_ (), +      generate_detach_ (), +      generate_wildcard_ (), +      generate_any_type_ (), +      generate_insertion_ (), +      generate_insertion_specified_ (false), +      generate_extraction_ (), +      generate_extraction_specified_ (false), +      generate_forward_ (), +      suppress_parsing_ (), +      generate_element_type_ (), +      generate_element_map_ (), +      generate_intellisense_ (), +      omit_default_attributes_ (), +      type_naming_ ("knr"), +      type_naming_specified_ (false), +      function_naming_ ("knr"), +      function_naming_specified_ (false), +      type_regex_ (), +      type_regex_specified_ (false), +      accessor_regex_ (), +      accessor_regex_specified_ (false), +      one_accessor_regex_ (), +      one_accessor_regex_specified_ (false), +      opt_accessor_regex_ (), +      opt_accessor_regex_specified_ (false), +      seq_accessor_regex_ (), +      seq_accessor_regex_specified_ (false), +      modifier_regex_ (), +      modifier_regex_specified_ (false), +      one_modifier_regex_ (), +      one_modifier_regex_specified_ (false), +      opt_modifier_regex_ (), +      opt_modifier_regex_specified_ (false), +      seq_modifier_regex_ (), +      seq_modifier_regex_specified_ (false), +      parser_regex_ (), +      parser_regex_specified_ (false), +      serializer_regex_ (), +      serializer_regex_specified_ (false), +      const_regex_ (), +      const_regex_specified_ (false), +      enumerator_regex_ (), +      enumerator_regex_specified_ (false), +      element_type_regex_ (), +      element_type_regex_specified_ (false), +      name_regex_trace_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_all_ (), +      root_element_none_ (), +      root_element_ (), +      root_element_specified_ (false), +      custom_type_ (), +      custom_type_specified_ (false), +      custom_type_regex_ (), +      custom_type_regex_specified_ (false), +      parts_ (1), +      parts_specified_ (false), +      parts_suffix_ ("-"), +      parts_suffix_specified_ (false) +    { +    } + +    options:: +    options (int& argc, +             char** argv, +             bool erase, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : generate_polymorphic_ (), +      polymorphic_type_ (), +      polymorphic_type_specified_ (false), +      polymorphic_type_all_ (), +      polymorphic_plate_ (0), +      polymorphic_plate_specified_ (false), +      ordered_type_ (), +      ordered_type_specified_ (false), +      ordered_type_derived_ (), +      ordered_type_mixed_ (), +      ordered_type_all_ (), +      order_container_ (), +      order_container_specified_ (false), +      generate_serialization_ (), +      generate_ostream_ (), +      generate_doxygen_ (), +      generate_comparison_ (), +      generate_default_ctor_ (), +      generate_from_base_ctor_ (), +      suppress_assignment_ (), +      generate_detach_ (), +      generate_wildcard_ (), +      generate_any_type_ (), +      generate_insertion_ (), +      generate_insertion_specified_ (false), +      generate_extraction_ (), +      generate_extraction_specified_ (false), +      generate_forward_ (), +      suppress_parsing_ (), +      generate_element_type_ (), +      generate_element_map_ (), +      generate_intellisense_ (), +      omit_default_attributes_ (), +      type_naming_ ("knr"), +      type_naming_specified_ (false), +      function_naming_ ("knr"), +      function_naming_specified_ (false), +      type_regex_ (), +      type_regex_specified_ (false), +      accessor_regex_ (), +      accessor_regex_specified_ (false), +      one_accessor_regex_ (), +      one_accessor_regex_specified_ (false), +      opt_accessor_regex_ (), +      opt_accessor_regex_specified_ (false), +      seq_accessor_regex_ (), +      seq_accessor_regex_specified_ (false), +      modifier_regex_ (), +      modifier_regex_specified_ (false), +      one_modifier_regex_ (), +      one_modifier_regex_specified_ (false), +      opt_modifier_regex_ (), +      opt_modifier_regex_specified_ (false), +      seq_modifier_regex_ (), +      seq_modifier_regex_specified_ (false), +      parser_regex_ (), +      parser_regex_specified_ (false), +      serializer_regex_ (), +      serializer_regex_specified_ (false), +      const_regex_ (), +      const_regex_specified_ (false), +      enumerator_regex_ (), +      enumerator_regex_specified_ (false), +      element_type_regex_ (), +      element_type_regex_specified_ (false), +      name_regex_trace_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_all_ (), +      root_element_none_ (), +      root_element_ (), +      root_element_specified_ (false), +      custom_type_ (), +      custom_type_specified_ (false), +      custom_type_regex_ (), +      custom_type_regex_specified_ (false), +      parts_ (1), +      parts_specified_ (false), +      parts_suffix_ ("-"), +      parts_suffix_specified_ (false) +    { +      ::cli::argv_scanner s (argc, argv, erase); +      _parse (s, opt, arg); +    } + +    options:: +    options (int start, +             int& argc, +             char** argv, +             bool erase, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : generate_polymorphic_ (), +      polymorphic_type_ (), +      polymorphic_type_specified_ (false), +      polymorphic_type_all_ (), +      polymorphic_plate_ (0), +      polymorphic_plate_specified_ (false), +      ordered_type_ (), +      ordered_type_specified_ (false), +      ordered_type_derived_ (), +      ordered_type_mixed_ (), +      ordered_type_all_ (), +      order_container_ (), +      order_container_specified_ (false), +      generate_serialization_ (), +      generate_ostream_ (), +      generate_doxygen_ (), +      generate_comparison_ (), +      generate_default_ctor_ (), +      generate_from_base_ctor_ (), +      suppress_assignment_ (), +      generate_detach_ (), +      generate_wildcard_ (), +      generate_any_type_ (), +      generate_insertion_ (), +      generate_insertion_specified_ (false), +      generate_extraction_ (), +      generate_extraction_specified_ (false), +      generate_forward_ (), +      suppress_parsing_ (), +      generate_element_type_ (), +      generate_element_map_ (), +      generate_intellisense_ (), +      omit_default_attributes_ (), +      type_naming_ ("knr"), +      type_naming_specified_ (false), +      function_naming_ ("knr"), +      function_naming_specified_ (false), +      type_regex_ (), +      type_regex_specified_ (false), +      accessor_regex_ (), +      accessor_regex_specified_ (false), +      one_accessor_regex_ (), +      one_accessor_regex_specified_ (false), +      opt_accessor_regex_ (), +      opt_accessor_regex_specified_ (false), +      seq_accessor_regex_ (), +      seq_accessor_regex_specified_ (false), +      modifier_regex_ (), +      modifier_regex_specified_ (false), +      one_modifier_regex_ (), +      one_modifier_regex_specified_ (false), +      opt_modifier_regex_ (), +      opt_modifier_regex_specified_ (false), +      seq_modifier_regex_ (), +      seq_modifier_regex_specified_ (false), +      parser_regex_ (), +      parser_regex_specified_ (false), +      serializer_regex_ (), +      serializer_regex_specified_ (false), +      const_regex_ (), +      const_regex_specified_ (false), +      enumerator_regex_ (), +      enumerator_regex_specified_ (false), +      element_type_regex_ (), +      element_type_regex_specified_ (false), +      name_regex_trace_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_all_ (), +      root_element_none_ (), +      root_element_ (), +      root_element_specified_ (false), +      custom_type_ (), +      custom_type_specified_ (false), +      custom_type_regex_ (), +      custom_type_regex_specified_ (false), +      parts_ (1), +      parts_specified_ (false), +      parts_suffix_ ("-"), +      parts_suffix_specified_ (false) +    { +      ::cli::argv_scanner s (start, argc, argv, erase); +      _parse (s, opt, arg); +    } + +    options:: +    options (int& argc, +             char** argv, +             int& end, +             bool erase, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : generate_polymorphic_ (), +      polymorphic_type_ (), +      polymorphic_type_specified_ (false), +      polymorphic_type_all_ (), +      polymorphic_plate_ (0), +      polymorphic_plate_specified_ (false), +      ordered_type_ (), +      ordered_type_specified_ (false), +      ordered_type_derived_ (), +      ordered_type_mixed_ (), +      ordered_type_all_ (), +      order_container_ (), +      order_container_specified_ (false), +      generate_serialization_ (), +      generate_ostream_ (), +      generate_doxygen_ (), +      generate_comparison_ (), +      generate_default_ctor_ (), +      generate_from_base_ctor_ (), +      suppress_assignment_ (), +      generate_detach_ (), +      generate_wildcard_ (), +      generate_any_type_ (), +      generate_insertion_ (), +      generate_insertion_specified_ (false), +      generate_extraction_ (), +      generate_extraction_specified_ (false), +      generate_forward_ (), +      suppress_parsing_ (), +      generate_element_type_ (), +      generate_element_map_ (), +      generate_intellisense_ (), +      omit_default_attributes_ (), +      type_naming_ ("knr"), +      type_naming_specified_ (false), +      function_naming_ ("knr"), +      function_naming_specified_ (false), +      type_regex_ (), +      type_regex_specified_ (false), +      accessor_regex_ (), +      accessor_regex_specified_ (false), +      one_accessor_regex_ (), +      one_accessor_regex_specified_ (false), +      opt_accessor_regex_ (), +      opt_accessor_regex_specified_ (false), +      seq_accessor_regex_ (), +      seq_accessor_regex_specified_ (false), +      modifier_regex_ (), +      modifier_regex_specified_ (false), +      one_modifier_regex_ (), +      one_modifier_regex_specified_ (false), +      opt_modifier_regex_ (), +      opt_modifier_regex_specified_ (false), +      seq_modifier_regex_ (), +      seq_modifier_regex_specified_ (false), +      parser_regex_ (), +      parser_regex_specified_ (false), +      serializer_regex_ (), +      serializer_regex_specified_ (false), +      const_regex_ (), +      const_regex_specified_ (false), +      enumerator_regex_ (), +      enumerator_regex_specified_ (false), +      element_type_regex_ (), +      element_type_regex_specified_ (false), +      name_regex_trace_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_all_ (), +      root_element_none_ (), +      root_element_ (), +      root_element_specified_ (false), +      custom_type_ (), +      custom_type_specified_ (false), +      custom_type_regex_ (), +      custom_type_regex_specified_ (false), +      parts_ (1), +      parts_specified_ (false), +      parts_suffix_ ("-"), +      parts_suffix_specified_ (false) +    { +      ::cli::argv_scanner s (argc, argv, erase); +      _parse (s, opt, arg); +      end = s.end (); +    } + +    options:: +    options (int start, +             int& argc, +             char** argv, +             int& end, +             bool erase, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : generate_polymorphic_ (), +      polymorphic_type_ (), +      polymorphic_type_specified_ (false), +      polymorphic_type_all_ (), +      polymorphic_plate_ (0), +      polymorphic_plate_specified_ (false), +      ordered_type_ (), +      ordered_type_specified_ (false), +      ordered_type_derived_ (), +      ordered_type_mixed_ (), +      ordered_type_all_ (), +      order_container_ (), +      order_container_specified_ (false), +      generate_serialization_ (), +      generate_ostream_ (), +      generate_doxygen_ (), +      generate_comparison_ (), +      generate_default_ctor_ (), +      generate_from_base_ctor_ (), +      suppress_assignment_ (), +      generate_detach_ (), +      generate_wildcard_ (), +      generate_any_type_ (), +      generate_insertion_ (), +      generate_insertion_specified_ (false), +      generate_extraction_ (), +      generate_extraction_specified_ (false), +      generate_forward_ (), +      suppress_parsing_ (), +      generate_element_type_ (), +      generate_element_map_ (), +      generate_intellisense_ (), +      omit_default_attributes_ (), +      type_naming_ ("knr"), +      type_naming_specified_ (false), +      function_naming_ ("knr"), +      function_naming_specified_ (false), +      type_regex_ (), +      type_regex_specified_ (false), +      accessor_regex_ (), +      accessor_regex_specified_ (false), +      one_accessor_regex_ (), +      one_accessor_regex_specified_ (false), +      opt_accessor_regex_ (), +      opt_accessor_regex_specified_ (false), +      seq_accessor_regex_ (), +      seq_accessor_regex_specified_ (false), +      modifier_regex_ (), +      modifier_regex_specified_ (false), +      one_modifier_regex_ (), +      one_modifier_regex_specified_ (false), +      opt_modifier_regex_ (), +      opt_modifier_regex_specified_ (false), +      seq_modifier_regex_ (), +      seq_modifier_regex_specified_ (false), +      parser_regex_ (), +      parser_regex_specified_ (false), +      serializer_regex_ (), +      serializer_regex_specified_ (false), +      const_regex_ (), +      const_regex_specified_ (false), +      enumerator_regex_ (), +      enumerator_regex_specified_ (false), +      element_type_regex_ (), +      element_type_regex_specified_ (false), +      name_regex_trace_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_all_ (), +      root_element_none_ (), +      root_element_ (), +      root_element_specified_ (false), +      custom_type_ (), +      custom_type_specified_ (false), +      custom_type_regex_ (), +      custom_type_regex_specified_ (false), +      parts_ (1), +      parts_specified_ (false), +      parts_suffix_ ("-"), +      parts_suffix_specified_ (false) +    { +      ::cli::argv_scanner s (start, argc, argv, erase); +      _parse (s, opt, arg); +      end = s.end (); +    } + +    options:: +    options (::cli::scanner& s, +             ::cli::unknown_mode opt, +             ::cli::unknown_mode arg) +    : generate_polymorphic_ (), +      polymorphic_type_ (), +      polymorphic_type_specified_ (false), +      polymorphic_type_all_ (), +      polymorphic_plate_ (0), +      polymorphic_plate_specified_ (false), +      ordered_type_ (), +      ordered_type_specified_ (false), +      ordered_type_derived_ (), +      ordered_type_mixed_ (), +      ordered_type_all_ (), +      order_container_ (), +      order_container_specified_ (false), +      generate_serialization_ (), +      generate_ostream_ (), +      generate_doxygen_ (), +      generate_comparison_ (), +      generate_default_ctor_ (), +      generate_from_base_ctor_ (), +      suppress_assignment_ (), +      generate_detach_ (), +      generate_wildcard_ (), +      generate_any_type_ (), +      generate_insertion_ (), +      generate_insertion_specified_ (false), +      generate_extraction_ (), +      generate_extraction_specified_ (false), +      generate_forward_ (), +      suppress_parsing_ (), +      generate_element_type_ (), +      generate_element_map_ (), +      generate_intellisense_ (), +      omit_default_attributes_ (), +      type_naming_ ("knr"), +      type_naming_specified_ (false), +      function_naming_ ("knr"), +      function_naming_specified_ (false), +      type_regex_ (), +      type_regex_specified_ (false), +      accessor_regex_ (), +      accessor_regex_specified_ (false), +      one_accessor_regex_ (), +      one_accessor_regex_specified_ (false), +      opt_accessor_regex_ (), +      opt_accessor_regex_specified_ (false), +      seq_accessor_regex_ (), +      seq_accessor_regex_specified_ (false), +      modifier_regex_ (), +      modifier_regex_specified_ (false), +      one_modifier_regex_ (), +      one_modifier_regex_specified_ (false), +      opt_modifier_regex_ (), +      opt_modifier_regex_specified_ (false), +      seq_modifier_regex_ (), +      seq_modifier_regex_specified_ (false), +      parser_regex_ (), +      parser_regex_specified_ (false), +      serializer_regex_ (), +      serializer_regex_specified_ (false), +      const_regex_ (), +      const_regex_specified_ (false), +      enumerator_regex_ (), +      enumerator_regex_specified_ (false), +      element_type_regex_ (), +      element_type_regex_specified_ (false), +      name_regex_trace_ (), +      root_element_first_ (), +      root_element_last_ (), +      root_element_all_ (), +      root_element_none_ (), +      root_element_ (), +      root_element_specified_ (false), +      custom_type_ (), +      custom_type_specified_ (false), +      custom_type_regex_ (), +      custom_type_regex_specified_ (false), +      parts_ (1), +      parts_specified_ (false), +      parts_suffix_ ("-"), +      parts_suffix_specified_ (false) +    { +      _parse (s, opt, arg); +    } + +    ::cli::usage_para options:: +    print_usage (::std::wostream& os, ::cli::usage_para p) +    { +      CLI_POTENTIALLY_UNUSED (os); + +      if (p == ::cli::usage_para::text) +        os << ::std::endl; + +      os << "--generate-polymorphic       Generate polymorphism-aware code." << ::std::endl; + +      os << "--polymorphic-type <type>    Indicate that <type> is a root of a polymorphic" << ::std::endl +         << "                             type hierarchy." << ::std::endl; + +      os << "--polymorphic-type-all       Indicate that all types should be treated as" << ::std::endl +         << "                             polymorphic." << ::std::endl; + +      os << "--polymorphic-plate <num>    Specify the polymorphic map plate the generated" << ::std::endl +         << "                             code should register on." << ::std::endl; + +      os << "--ordered-type <type>        Indicate that element order in <type> is" << ::std::endl +         << "                             significant." << ::std::endl; + +      os << "--ordered-type-derived       Automatically treat types derived from ordered" << ::std::endl +         << "                             bases as also ordered." << ::std::endl; + +      os << "--ordered-type-mixed         Automatically treat complex types with mixed" << ::std::endl +         << "                             content as ordered." << ::std::endl; + +      os << "--ordered-type-all           Indicate that element order in all types is" << ::std::endl +         << "                             significant." << ::std::endl; + +      os << "--order-container <type>     Specify a custom class template that should be" << ::std::endl +         << "                             used as a container for the content order in" << ::std::endl +         << "                             ordered types instead of the default std::vector." << ::std::endl; + +      os << "--generate-serialization     Generate serialization functions." << ::std::endl; + +      os << "--generate-ostream           Generate ostream insertion operators (operator<<)" << ::std::endl +         << "                             for generated types." << ::std::endl; + +      os << "--generate-doxygen           Generate documentation comments suitable for" << ::std::endl +         << "                             extraction by the Doxygen documentation system." << ::std::endl; + +      os << "--generate-comparison        Generate comparison operators (operator== and" << ::std::endl +         << "                             operator!=) for complex types." << ::std::endl; + +      os << "--generate-default-ctor      Generate default constructors even for types that" << ::std::endl +         << "                             have required members." << ::std::endl; + +      os << "--generate-from-base-ctor    Generate constructors that expect an instance of a" << ::std::endl +         << "                             base type followed by all required members." << ::std::endl; + +      os << "--suppress-assignment        Suppress the generation of copy assignment" << ::std::endl +         << "                             operators for complex types." << ::std::endl; + +      os << "--generate-detach            Generate detach functions for required elements" << ::std::endl +         << "                             and attributes." << ::std::endl; + +      os << "--generate-wildcard          Generate accessors and modifiers as well as" << ::std::endl +         << "                             parsing and serialization code for XML Schema" << ::std::endl +         << "                             wildcards (any and anyAttribute)." << ::std::endl; + +      os << "--generate-any-type          Extract and store content of the XML Schema" << ::std::endl +         << "                             anyType type as a DOM fragment." << ::std::endl; + +      os << "--generate-insertion <os>    Generate data representation stream insertion" << ::std::endl +         << "                             operators for the <os> output stream type." << ::std::endl; + +      os << "--generate-extraction <is>   Generate data representation stream extraction" << ::std::endl +         << "                             constructors for the <is> input stream type." << ::std::endl; + +      os << "--generate-forward           Generate a separate header file with forward" << ::std::endl +         << "                             declarations for the types being generated." << ::std::endl; + +      os << "--suppress-parsing           Suppress the generation of the parsing functions" << ::std::endl +         << "                             and constructors." << ::std::endl; + +      os << "--generate-element-type      Generate types instead of parsing and" << ::std::endl +         << "                             serialization functions for root elements." << ::std::endl; + +      os << "--generate-element-map       Generate a root element map that allows uniform" << ::std::endl +         << "                             parsing and serialization of multiple root" << ::std::endl +         << "                             elements." << ::std::endl; + +      os << "--generate-intellisense      Generate workarounds for IntelliSense bugs in" << ::std::endl +         << "                             Visual Studio 2005 (8.0)." << ::std::endl; + +      os << "--omit-default-attributes    Omit attributes with default and fixed values from" << ::std::endl +         << "                             serialized XML documents." << ::std::endl; + +      os << "--type-naming <style>        Specify the type naming convention that should be" << ::std::endl +         << "                             used in the generated code." << ::std::endl; + +      os << "--function-naming <style>    Specify the function naming convention that should" << ::std::endl +         << "                             be used in the generated code." << ::std::endl; + +      os << "--type-regex <regex>         Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema type names to C++" << ::std::endl +         << "                             type names." << ::std::endl; + +      os << "--accessor-regex <regex>     Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema names of" << ::std::endl +         << "                             elements/attributes to C++ accessor function" << ::std::endl +         << "                             names." << ::std::endl; + +      os << "--one-accessor-regex <regex> Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema names of" << ::std::endl +         << "                             elements/attributes with cardinality one to C++" << ::std::endl +         << "                             accessor function names." << ::std::endl; + +      os << "--opt-accessor-regex <regex> Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema names of" << ::std::endl +         << "                             elements/attributes with cardinality optional to" << ::std::endl +         << "                             C++ accessor function names." << ::std::endl; + +      os << "--seq-accessor-regex <regex> Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema names of" << ::std::endl +         << "                             elements/attributes with cardinality sequence to" << ::std::endl +         << "                             C++ accessor function names." << ::std::endl; + +      os << "--modifier-regex <regex>     Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema names of" << ::std::endl +         << "                             elements/attributes to C++ modifier function" << ::std::endl +         << "                             names." << ::std::endl; + +      os << "--one-modifier-regex <regex> Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema names of" << ::std::endl +         << "                             elements/attributes with cardinality one to C++" << ::std::endl +         << "                             modifier function names." << ::std::endl; + +      os << "--opt-modifier-regex <regex> Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema names of" << ::std::endl +         << "                             elements/attributes with cardinality optional to" << ::std::endl +         << "                             C++ modifier function names." << ::std::endl; + +      os << "--seq-modifier-regex <regex> Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema names of" << ::std::endl +         << "                             elements/attributes with cardinality sequence to" << ::std::endl +         << "                             C++ modifier function names." << ::std::endl; + +      os << "--parser-regex <regex>       Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema element names to C++" << ::std::endl +         << "                             parsing function names." << ::std::endl; + +      os << "--serializer-regex <regex>   Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema element names to C++" << ::std::endl +         << "                             serialization function names." << ::std::endl; + +      os << "--const-regex <regex>        Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema-derived names to C++" << ::std::endl +         << "                             constant names." << ::std::endl; + +      os << "--enumerator-regex <regex>   Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema enumeration values to" << ::std::endl +         << "                             C++ enumerator names." << ::std::endl; + +      os << "--element-type-regex <regex> Add <regex> to the list of regular expressions" << ::std::endl +         << "                             used to translate XML Schema element names to C++" << ::std::endl +         << "                             element type names." << ::std::endl; + +      os << "--name-regex-trace           Trace the process of applying regular expressions" << ::std::endl +         << "                             specified with the name transformation options." << ::std::endl; + +      os << "--root-element-first         Treat only the first global element as a document" << ::std::endl +         << "                             root." << ::std::endl; + +      os << "--root-element-last          Treat only the last global element as a document" << ::std::endl +         << "                             root." << ::std::endl; + +      os << "--root-element-all           Treat all global elements as document roots." << ::std::endl; + +      os << "--root-element-none          Do not treat any global elements as document" << ::std::endl +         << "                             roots." << ::std::endl; + +      os << "--root-element <element>     Treat only <element> as a document root." << ::std::endl; + +      os << "--custom-type <map>          Use a custom C++ type instead of the generated" << ::std::endl +         << "                             class." << ::std::endl; + +      os << "--custom-type-regex <regex>  Use custom C++ types instead of the generated" << ::std::endl +         << "                             classes." << ::std::endl; + +      os << "--parts <num>                Split generated source code into <num> parts." << ::std::endl; + +      os << "--parts-suffix <suffix>      Use <suffix> instead of the default '-' to" << ::std::endl +         << "                             separate the file name from the part number." << ::std::endl; + +      p = ::cli::usage_para::option; + +      return p; +    } + +    typedef +    std::map<std::string, void (*) (options&, ::cli::scanner&)> +    _cli_options_map; + +    static _cli_options_map _cli_options_map_; + +    struct _cli_options_map_init +    { +      _cli_options_map_init () +      { +        _cli_options_map_["--generate-polymorphic"] = +        &::cli::thunk< options, &options::generate_polymorphic_ >; +        _cli_options_map_["--polymorphic-type"] = +        &::cli::thunk< options, NarrowStrings, &options::polymorphic_type_, +          &options::polymorphic_type_specified_ >; +        _cli_options_map_["--polymorphic-type-all"] = +        &::cli::thunk< options, &options::polymorphic_type_all_ >; +        _cli_options_map_["--polymorphic-plate"] = +        &::cli::thunk< options, unsigned long, &options::polymorphic_plate_, +          &options::polymorphic_plate_specified_ >; +        _cli_options_map_["--ordered-type"] = +        &::cli::thunk< options, NarrowStrings, &options::ordered_type_, +          &options::ordered_type_specified_ >; +        _cli_options_map_["--ordered-type-derived"] = +        &::cli::thunk< options, &options::ordered_type_derived_ >; +        _cli_options_map_["--ordered-type-mixed"] = +        &::cli::thunk< options, &options::ordered_type_mixed_ >; +        _cli_options_map_["--ordered-type-all"] = +        &::cli::thunk< options, &options::ordered_type_all_ >; +        _cli_options_map_["--order-container"] = +        &::cli::thunk< options, NarrowString, &options::order_container_, +          &options::order_container_specified_ >; +        _cli_options_map_["--generate-serialization"] = +        &::cli::thunk< options, &options::generate_serialization_ >; +        _cli_options_map_["--generate-ostream"] = +        &::cli::thunk< options, &options::generate_ostream_ >; +        _cli_options_map_["--generate-doxygen"] = +        &::cli::thunk< options, &options::generate_doxygen_ >; +        _cli_options_map_["--generate-comparison"] = +        &::cli::thunk< options, &options::generate_comparison_ >; +        _cli_options_map_["--generate-default-ctor"] = +        &::cli::thunk< options, &options::generate_default_ctor_ >; +        _cli_options_map_["--generate-from-base-ctor"] = +        &::cli::thunk< options, &options::generate_from_base_ctor_ >; +        _cli_options_map_["--suppress-assignment"] = +        &::cli::thunk< options, &options::suppress_assignment_ >; +        _cli_options_map_["--generate-detach"] = +        &::cli::thunk< options, &options::generate_detach_ >; +        _cli_options_map_["--generate-wildcard"] = +        &::cli::thunk< options, &options::generate_wildcard_ >; +        _cli_options_map_["--generate-any-type"] = +        &::cli::thunk< options, &options::generate_any_type_ >; +        _cli_options_map_["--generate-insertion"] = +        &::cli::thunk< options, NarrowStrings, &options::generate_insertion_, +          &options::generate_insertion_specified_ >; +        _cli_options_map_["--generate-extraction"] = +        &::cli::thunk< options, NarrowStrings, &options::generate_extraction_, +          &options::generate_extraction_specified_ >; +        _cli_options_map_["--generate-forward"] = +        &::cli::thunk< options, &options::generate_forward_ >; +        _cli_options_map_["--suppress-parsing"] = +        &::cli::thunk< options, &options::suppress_parsing_ >; +        _cli_options_map_["--generate-element-type"] = +        &::cli::thunk< options, &options::generate_element_type_ >; +        _cli_options_map_["--generate-element-map"] = +        &::cli::thunk< options, &options::generate_element_map_ >; +        _cli_options_map_["--generate-intellisense"] = +        &::cli::thunk< options, &options::generate_intellisense_ >; +        _cli_options_map_["--omit-default-attributes"] = +        &::cli::thunk< options, &options::omit_default_attributes_ >; +        _cli_options_map_["--type-naming"] = +        &::cli::thunk< options, NarrowString, &options::type_naming_, +          &options::type_naming_specified_ >; +        _cli_options_map_["--function-naming"] = +        &::cli::thunk< options, NarrowString, &options::function_naming_, +          &options::function_naming_specified_ >; +        _cli_options_map_["--type-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::type_regex_, +          &options::type_regex_specified_ >; +        _cli_options_map_["--accessor-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::accessor_regex_, +          &options::accessor_regex_specified_ >; +        _cli_options_map_["--one-accessor-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::one_accessor_regex_, +          &options::one_accessor_regex_specified_ >; +        _cli_options_map_["--opt-accessor-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::opt_accessor_regex_, +          &options::opt_accessor_regex_specified_ >; +        _cli_options_map_["--seq-accessor-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::seq_accessor_regex_, +          &options::seq_accessor_regex_specified_ >; +        _cli_options_map_["--modifier-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::modifier_regex_, +          &options::modifier_regex_specified_ >; +        _cli_options_map_["--one-modifier-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::one_modifier_regex_, +          &options::one_modifier_regex_specified_ >; +        _cli_options_map_["--opt-modifier-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::opt_modifier_regex_, +          &options::opt_modifier_regex_specified_ >; +        _cli_options_map_["--seq-modifier-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::seq_modifier_regex_, +          &options::seq_modifier_regex_specified_ >; +        _cli_options_map_["--parser-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::parser_regex_, +          &options::parser_regex_specified_ >; +        _cli_options_map_["--serializer-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::serializer_regex_, +          &options::serializer_regex_specified_ >; +        _cli_options_map_["--const-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::const_regex_, +          &options::const_regex_specified_ >; +        _cli_options_map_["--enumerator-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::enumerator_regex_, +          &options::enumerator_regex_specified_ >; +        _cli_options_map_["--element-type-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::element_type_regex_, +          &options::element_type_regex_specified_ >; +        _cli_options_map_["--name-regex-trace"] = +        &::cli::thunk< options, &options::name_regex_trace_ >; +        _cli_options_map_["--root-element-first"] = +        &::cli::thunk< options, &options::root_element_first_ >; +        _cli_options_map_["--root-element-last"] = +        &::cli::thunk< options, &options::root_element_last_ >; +        _cli_options_map_["--root-element-all"] = +        &::cli::thunk< options, &options::root_element_all_ >; +        _cli_options_map_["--root-element-none"] = +        &::cli::thunk< options, &options::root_element_none_ >; +        _cli_options_map_["--root-element"] = +        &::cli::thunk< options, NarrowStrings, &options::root_element_, +          &options::root_element_specified_ >; +        _cli_options_map_["--custom-type"] = +        &::cli::thunk< options, NarrowStrings, &options::custom_type_, +          &options::custom_type_specified_ >; +        _cli_options_map_["--custom-type-regex"] = +        &::cli::thunk< options, NarrowStrings, &options::custom_type_regex_, +          &options::custom_type_regex_specified_ >; +        _cli_options_map_["--parts"] = +        &::cli::thunk< options, std::size_t, &options::parts_, +          &options::parts_specified_ >; +        _cli_options_map_["--parts-suffix"] = +        &::cli::thunk< options, NarrowString, &options::parts_suffix_, +          &options::parts_suffix_specified_ >; +      } +    }; + +    static _cli_options_map_init _cli_options_map_init_; + +    bool options:: +    _parse (const char* o, ::cli::scanner& s) +    { +      _cli_options_map::const_iterator i (_cli_options_map_.find (o)); + +      if (i != _cli_options_map_.end ()) +      { +        (*(i->second)) (*this, s); +        return true; +      } + +      // options base +      // +      if (::CXX::options::_parse (o, s)) +        return true; + +      return false; +    } + +    bool options:: +    _parse (::cli::scanner& s, +            ::cli::unknown_mode opt_mode, +            ::cli::unknown_mode arg_mode) +    { +      // Can't skip combined flags (--no-combined-flags). +      // +      assert (opt_mode != ::cli::unknown_mode::skip); + +      bool r = false; +      bool opt = true; + +      while (s.more ()) +      { +        const char* o = s.peek (); + +        if (std::strcmp (o, "--") == 0) +        { +          opt = false; +          s.skip (); +          r = true; +          continue; +        } + +        if (opt) +        { +          if (_parse (o, s)) +          { +            r = true; +            continue; +          } + +          if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') +          { +            // Handle combined option values. +            // +            std::string co; +            if (const char* v = std::strchr (o, '=')) +            { +              co.assign (o, 0, v - o); +              ++v; + +              int ac (2); +              char* av[] = +              { +                const_cast<char*> (co.c_str ()), +                const_cast<char*> (v) +              }; + +              ::cli::argv_scanner ns (0, ac, av); + +              if (_parse (co.c_str (), ns)) +              { +                // Parsed the option but not its value? +                // +                if (ns.end () != 2) +                  throw ::cli::invalid_value (co, v); + +                s.next (); +                r = true; +                continue; +              } +              else +              { +                // Set the unknown option and fall through. +                // +                o = co.c_str (); +              } +            } + +            // Handle combined flags. +            // +            char cf[3]; +            { +              const char* p = o + 1; +              for (; *p != '\0'; ++p) +              { +                if (!((*p >= 'a' && *p <= 'z') || +                      (*p >= 'A' && *p <= 'Z') || +                      (*p >= '0' && *p <= '9'))) +                  break; +              } + +              if (*p == '\0') +              { +                for (p = o + 1; *p != '\0'; ++p) +                { +                  std::strcpy (cf, "-"); +                  cf[1] = *p; +                  cf[2] = '\0'; + +                  int ac (1); +                  char* av[] = +                  { +                    cf +                  }; + +                  ::cli::argv_scanner ns (0, ac, av); + +                  if (!_parse (cf, ns)) +                    break; +                } + +                if (*p == '\0') +                { +                  // All handled. +                  // +                  s.next (); +                  r = true; +                  continue; +                } +                else +                { +                  // Set the unknown option and fall through. +                  // +                  o = cf; +                } +              } +            } + +            switch (opt_mode) +            { +              case ::cli::unknown_mode::skip: +              { +                s.skip (); +                r = true; +                continue; +              } +              case ::cli::unknown_mode::stop: +              { +                break; +              } +              case ::cli::unknown_mode::fail: +              { +                throw ::cli::unknown_option (o); +              } +            } + +            break; +          } +        } + +        switch (arg_mode) +        { +          case ::cli::unknown_mode::skip: +          { +            s.skip (); +            r = true; +            continue; +          } +          case ::cli::unknown_mode::stop: +          { +            break; +          } +          case ::cli::unknown_mode::fail: +          { +            throw ::cli::unknown_argument (o); +          } +        } + +        break; +      } + +      return r; +    } +  } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/xsd/pregenerated/xsd/cxx/tree/options.hxx b/xsd/pregenerated/xsd/cxx/tree/options.hxx new file mode 100644 index 0000000..f5a808c --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/tree/options.hxx @@ -0,0 +1,414 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef XSD_CXX_TREE_OPTIONS_HXX +#define XSD_CXX_TREE_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <cstddef> + +#include <xsd/types.hxx> + +#include <xsd/cxx/options.hxx> + +namespace CXX +{ +  namespace Tree +  { +    class options: public ::CXX::options +    { +      public: +      options (); + +      options (int& argc, +               char** argv, +               bool erase = false, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      options (int start, +               int& argc, +               char** argv, +               bool erase = false, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      options (int& argc, +               char** argv, +               int& end, +               bool erase = false, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      options (int start, +               int& argc, +               char** argv, +               int& end, +               bool erase = false, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      options (::cli::scanner&, +               ::cli::unknown_mode option = ::cli::unknown_mode::fail, +               ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +      // Option accessors. +      // +      const bool& +      generate_polymorphic () const; + +      const NarrowStrings& +      polymorphic_type () const; + +      bool +      polymorphic_type_specified () const; + +      const bool& +      polymorphic_type_all () const; + +      const unsigned long& +      polymorphic_plate () const; + +      bool +      polymorphic_plate_specified () const; + +      const NarrowStrings& +      ordered_type () const; + +      bool +      ordered_type_specified () const; + +      const bool& +      ordered_type_derived () const; + +      const bool& +      ordered_type_mixed () const; + +      const bool& +      ordered_type_all () const; + +      const NarrowString& +      order_container () const; + +      bool +      order_container_specified () const; + +      const bool& +      generate_serialization () const; + +      const bool& +      generate_ostream () const; + +      const bool& +      generate_doxygen () const; + +      const bool& +      generate_comparison () const; + +      const bool& +      generate_default_ctor () const; + +      const bool& +      generate_from_base_ctor () const; + +      const bool& +      suppress_assignment () const; + +      const bool& +      generate_detach () const; + +      const bool& +      generate_wildcard () const; + +      const bool& +      generate_any_type () const; + +      const NarrowStrings& +      generate_insertion () const; + +      bool +      generate_insertion_specified () const; + +      const NarrowStrings& +      generate_extraction () const; + +      bool +      generate_extraction_specified () const; + +      const bool& +      generate_forward () const; + +      const bool& +      suppress_parsing () const; + +      const bool& +      generate_element_type () const; + +      const bool& +      generate_element_map () const; + +      const bool& +      generate_intellisense () const; + +      const bool& +      omit_default_attributes () const; + +      const NarrowString& +      type_naming () const; + +      bool +      type_naming_specified () const; + +      const NarrowString& +      function_naming () const; + +      bool +      function_naming_specified () const; + +      const NarrowStrings& +      type_regex () const; + +      bool +      type_regex_specified () const; + +      const NarrowStrings& +      accessor_regex () const; + +      bool +      accessor_regex_specified () const; + +      const NarrowStrings& +      one_accessor_regex () const; + +      bool +      one_accessor_regex_specified () const; + +      const NarrowStrings& +      opt_accessor_regex () const; + +      bool +      opt_accessor_regex_specified () const; + +      const NarrowStrings& +      seq_accessor_regex () const; + +      bool +      seq_accessor_regex_specified () const; + +      const NarrowStrings& +      modifier_regex () const; + +      bool +      modifier_regex_specified () const; + +      const NarrowStrings& +      one_modifier_regex () const; + +      bool +      one_modifier_regex_specified () const; + +      const NarrowStrings& +      opt_modifier_regex () const; + +      bool +      opt_modifier_regex_specified () const; + +      const NarrowStrings& +      seq_modifier_regex () const; + +      bool +      seq_modifier_regex_specified () const; + +      const NarrowStrings& +      parser_regex () const; + +      bool +      parser_regex_specified () const; + +      const NarrowStrings& +      serializer_regex () const; + +      bool +      serializer_regex_specified () const; + +      const NarrowStrings& +      const_regex () const; + +      bool +      const_regex_specified () const; + +      const NarrowStrings& +      enumerator_regex () const; + +      bool +      enumerator_regex_specified () const; + +      const NarrowStrings& +      element_type_regex () const; + +      bool +      element_type_regex_specified () const; + +      const bool& +      name_regex_trace () const; + +      const bool& +      root_element_first () const; + +      const bool& +      root_element_last () const; + +      const bool& +      root_element_all () const; + +      const bool& +      root_element_none () const; + +      const NarrowStrings& +      root_element () const; + +      bool +      root_element_specified () const; + +      const NarrowStrings& +      custom_type () const; + +      bool +      custom_type_specified () const; + +      const NarrowStrings& +      custom_type_regex () const; + +      bool +      custom_type_regex_specified () const; + +      const std::size_t& +      parts () const; + +      bool +      parts_specified () const; + +      const NarrowString& +      parts_suffix () const; + +      bool +      parts_suffix_specified () const; + +      // Print usage information. +      // +      static ::cli::usage_para +      print_usage (::std::wostream&, +                   ::cli::usage_para = ::cli::usage_para::none); + +      // Implementation details. +      // +      protected: +      bool +      _parse (const char*, ::cli::scanner&); + +      private: +      bool +      _parse (::cli::scanner&, +              ::cli::unknown_mode option, +              ::cli::unknown_mode argument); + +      public: +      bool generate_polymorphic_; +      NarrowStrings polymorphic_type_; +      bool polymorphic_type_specified_; +      bool polymorphic_type_all_; +      unsigned long polymorphic_plate_; +      bool polymorphic_plate_specified_; +      NarrowStrings ordered_type_; +      bool ordered_type_specified_; +      bool ordered_type_derived_; +      bool ordered_type_mixed_; +      bool ordered_type_all_; +      NarrowString order_container_; +      bool order_container_specified_; +      bool generate_serialization_; +      bool generate_ostream_; +      bool generate_doxygen_; +      bool generate_comparison_; +      bool generate_default_ctor_; +      bool generate_from_base_ctor_; +      bool suppress_assignment_; +      bool generate_detach_; +      bool generate_wildcard_; +      bool generate_any_type_; +      NarrowStrings generate_insertion_; +      bool generate_insertion_specified_; +      NarrowStrings generate_extraction_; +      bool generate_extraction_specified_; +      bool generate_forward_; +      bool suppress_parsing_; +      bool generate_element_type_; +      bool generate_element_map_; +      bool generate_intellisense_; +      bool omit_default_attributes_; +      NarrowString type_naming_; +      bool type_naming_specified_; +      NarrowString function_naming_; +      bool function_naming_specified_; +      NarrowStrings type_regex_; +      bool type_regex_specified_; +      NarrowStrings accessor_regex_; +      bool accessor_regex_specified_; +      NarrowStrings one_accessor_regex_; +      bool one_accessor_regex_specified_; +      NarrowStrings opt_accessor_regex_; +      bool opt_accessor_regex_specified_; +      NarrowStrings seq_accessor_regex_; +      bool seq_accessor_regex_specified_; +      NarrowStrings modifier_regex_; +      bool modifier_regex_specified_; +      NarrowStrings one_modifier_regex_; +      bool one_modifier_regex_specified_; +      NarrowStrings opt_modifier_regex_; +      bool opt_modifier_regex_specified_; +      NarrowStrings seq_modifier_regex_; +      bool seq_modifier_regex_specified_; +      NarrowStrings parser_regex_; +      bool parser_regex_specified_; +      NarrowStrings serializer_regex_; +      bool serializer_regex_specified_; +      NarrowStrings const_regex_; +      bool const_regex_specified_; +      NarrowStrings enumerator_regex_; +      bool enumerator_regex_specified_; +      NarrowStrings element_type_regex_; +      bool element_type_regex_specified_; +      bool name_regex_trace_; +      bool root_element_first_; +      bool root_element_last_; +      bool root_element_all_; +      bool root_element_none_; +      NarrowStrings root_element_; +      bool root_element_specified_; +      NarrowStrings custom_type_; +      bool custom_type_specified_; +      NarrowStrings custom_type_regex_; +      bool custom_type_regex_specified_; +      std::size_t parts_; +      bool parts_specified_; +      NarrowString parts_suffix_; +      bool parts_suffix_specified_; +    }; +  } +} + +#include <xsd/cxx/tree/options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // XSD_CXX_TREE_OPTIONS_HXX diff --git a/xsd/pregenerated/xsd/cxx/tree/options.ixx b/xsd/pregenerated/xsd/cxx/tree/options.ixx new file mode 100644 index 0000000..4d34fd9 --- /dev/null +++ b/xsd/pregenerated/xsd/cxx/tree/options.ixx @@ -0,0 +1,504 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace CXX +{ +  namespace Tree +  { +    // options +    // + +    inline const bool& options:: +    generate_polymorphic () const +    { +      return this->generate_polymorphic_; +    } + +    inline const NarrowStrings& options:: +    polymorphic_type () const +    { +      return this->polymorphic_type_; +    } + +    inline bool options:: +    polymorphic_type_specified () const +    { +      return this->polymorphic_type_specified_; +    } + +    inline const bool& options:: +    polymorphic_type_all () const +    { +      return this->polymorphic_type_all_; +    } + +    inline const unsigned long& options:: +    polymorphic_plate () const +    { +      return this->polymorphic_plate_; +    } + +    inline bool options:: +    polymorphic_plate_specified () const +    { +      return this->polymorphic_plate_specified_; +    } + +    inline const NarrowStrings& options:: +    ordered_type () const +    { +      return this->ordered_type_; +    } + +    inline bool options:: +    ordered_type_specified () const +    { +      return this->ordered_type_specified_; +    } + +    inline const bool& options:: +    ordered_type_derived () const +    { +      return this->ordered_type_derived_; +    } + +    inline const bool& options:: +    ordered_type_mixed () const +    { +      return this->ordered_type_mixed_; +    } + +    inline const bool& options:: +    ordered_type_all () const +    { +      return this->ordered_type_all_; +    } + +    inline const NarrowString& options:: +    order_container () const +    { +      return this->order_container_; +    } + +    inline bool options:: +    order_container_specified () const +    { +      return this->order_container_specified_; +    } + +    inline const bool& options:: +    generate_serialization () const +    { +      return this->generate_serialization_; +    } + +    inline const bool& options:: +    generate_ostream () const +    { +      return this->generate_ostream_; +    } + +    inline const bool& options:: +    generate_doxygen () const +    { +      return this->generate_doxygen_; +    } + +    inline const bool& options:: +    generate_comparison () const +    { +      return this->generate_comparison_; +    } + +    inline const bool& options:: +    generate_default_ctor () const +    { +      return this->generate_default_ctor_; +    } + +    inline const bool& options:: +    generate_from_base_ctor () const +    { +      return this->generate_from_base_ctor_; +    } + +    inline const bool& options:: +    suppress_assignment () const +    { +      return this->suppress_assignment_; +    } + +    inline const bool& options:: +    generate_detach () const +    { +      return this->generate_detach_; +    } + +    inline const bool& options:: +    generate_wildcard () const +    { +      return this->generate_wildcard_; +    } + +    inline const bool& options:: +    generate_any_type () const +    { +      return this->generate_any_type_; +    } + +    inline const NarrowStrings& options:: +    generate_insertion () const +    { +      return this->generate_insertion_; +    } + +    inline bool options:: +    generate_insertion_specified () const +    { +      return this->generate_insertion_specified_; +    } + +    inline const NarrowStrings& options:: +    generate_extraction () const +    { +      return this->generate_extraction_; +    } + +    inline bool options:: +    generate_extraction_specified () const +    { +      return this->generate_extraction_specified_; +    } + +    inline const bool& options:: +    generate_forward () const +    { +      return this->generate_forward_; +    } + +    inline const bool& options:: +    suppress_parsing () const +    { +      return this->suppress_parsing_; +    } + +    inline const bool& options:: +    generate_element_type () const +    { +      return this->generate_element_type_; +    } + +    inline const bool& options:: +    generate_element_map () const +    { +      return this->generate_element_map_; +    } + +    inline const bool& options:: +    generate_intellisense () const +    { +      return this->generate_intellisense_; +    } + +    inline const bool& options:: +    omit_default_attributes () const +    { +      return this->omit_default_attributes_; +    } + +    inline const NarrowString& options:: +    type_naming () const +    { +      return this->type_naming_; +    } + +    inline bool options:: +    type_naming_specified () const +    { +      return this->type_naming_specified_; +    } + +    inline const NarrowString& options:: +    function_naming () const +    { +      return this->function_naming_; +    } + +    inline bool options:: +    function_naming_specified () const +    { +      return this->function_naming_specified_; +    } + +    inline const NarrowStrings& options:: +    type_regex () const +    { +      return this->type_regex_; +    } + +    inline bool options:: +    type_regex_specified () const +    { +      return this->type_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    accessor_regex () const +    { +      return this->accessor_regex_; +    } + +    inline bool options:: +    accessor_regex_specified () const +    { +      return this->accessor_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    one_accessor_regex () const +    { +      return this->one_accessor_regex_; +    } + +    inline bool options:: +    one_accessor_regex_specified () const +    { +      return this->one_accessor_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    opt_accessor_regex () const +    { +      return this->opt_accessor_regex_; +    } + +    inline bool options:: +    opt_accessor_regex_specified () const +    { +      return this->opt_accessor_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    seq_accessor_regex () const +    { +      return this->seq_accessor_regex_; +    } + +    inline bool options:: +    seq_accessor_regex_specified () const +    { +      return this->seq_accessor_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    modifier_regex () const +    { +      return this->modifier_regex_; +    } + +    inline bool options:: +    modifier_regex_specified () const +    { +      return this->modifier_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    one_modifier_regex () const +    { +      return this->one_modifier_regex_; +    } + +    inline bool options:: +    one_modifier_regex_specified () const +    { +      return this->one_modifier_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    opt_modifier_regex () const +    { +      return this->opt_modifier_regex_; +    } + +    inline bool options:: +    opt_modifier_regex_specified () const +    { +      return this->opt_modifier_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    seq_modifier_regex () const +    { +      return this->seq_modifier_regex_; +    } + +    inline bool options:: +    seq_modifier_regex_specified () const +    { +      return this->seq_modifier_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    parser_regex () const +    { +      return this->parser_regex_; +    } + +    inline bool options:: +    parser_regex_specified () const +    { +      return this->parser_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    serializer_regex () const +    { +      return this->serializer_regex_; +    } + +    inline bool options:: +    serializer_regex_specified () const +    { +      return this->serializer_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    const_regex () const +    { +      return this->const_regex_; +    } + +    inline bool options:: +    const_regex_specified () const +    { +      return this->const_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    enumerator_regex () const +    { +      return this->enumerator_regex_; +    } + +    inline bool options:: +    enumerator_regex_specified () const +    { +      return this->enumerator_regex_specified_; +    } + +    inline const NarrowStrings& options:: +    element_type_regex () const +    { +      return this->element_type_regex_; +    } + +    inline bool options:: +    element_type_regex_specified () const +    { +      return this->element_type_regex_specified_; +    } + +    inline const bool& options:: +    name_regex_trace () const +    { +      return this->name_regex_trace_; +    } + +    inline const bool& options:: +    root_element_first () const +    { +      return this->root_element_first_; +    } + +    inline const bool& options:: +    root_element_last () const +    { +      return this->root_element_last_; +    } + +    inline const bool& options:: +    root_element_all () const +    { +      return this->root_element_all_; +    } + +    inline const bool& options:: +    root_element_none () const +    { +      return this->root_element_none_; +    } + +    inline const NarrowStrings& options:: +    root_element () const +    { +      return this->root_element_; +    } + +    inline bool options:: +    root_element_specified () const +    { +      return this->root_element_specified_; +    } + +    inline const NarrowStrings& options:: +    custom_type () const +    { +      return this->custom_type_; +    } + +    inline bool options:: +    custom_type_specified () const +    { +      return this->custom_type_specified_; +    } + +    inline const NarrowStrings& options:: +    custom_type_regex () const +    { +      return this->custom_type_regex_; +    } + +    inline bool options:: +    custom_type_regex_specified () const +    { +      return this->custom_type_regex_specified_; +    } + +    inline const std::size_t& options:: +    parts () const +    { +      return this->parts_; +    } + +    inline bool options:: +    parts_specified () const +    { +      return this->parts_specified_; +    } + +    inline const NarrowString& options:: +    parts_suffix () const +    { +      return this->parts_suffix_; +    } + +    inline bool options:: +    parts_suffix_specified () const +    { +      return this->parts_suffix_specified_; +    } +  } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/xsd/pregenerated/xsd/options.cxx b/xsd/pregenerated/xsd/options.cxx new file mode 100644 index 0000000..3022ec4 --- /dev/null +++ b/xsd/pregenerated/xsd/options.cxx @@ -0,0 +1,1297 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <xsd/options-parser.hxx> +// +// End prologue. + +#include <xsd/options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> +#include <fstream> + +namespace cli +{ +  // unknown_option +  // +  unknown_option:: +  ~unknown_option () noexcept +  { +  } + +  void unknown_option:: +  print (::std::wostream& os) const +  { +    os << "unknown option '" << option ().c_str () << "'"; +  } + +  const char* unknown_option:: +  what () const noexcept +  { +    return "unknown option"; +  } + +  // unknown_argument +  // +  unknown_argument:: +  ~unknown_argument () noexcept +  { +  } + +  void unknown_argument:: +  print (::std::wostream& os) const +  { +    os << "unknown argument '" << argument ().c_str () << "'"; +  } + +  const char* unknown_argument:: +  what () const noexcept +  { +    return "unknown argument"; +  } + +  // missing_value +  // +  missing_value:: +  ~missing_value () noexcept +  { +  } + +  void missing_value:: +  print (::std::wostream& os) const +  { +    os << "missing value for option '" << option ().c_str () << "'"; +  } + +  const char* missing_value:: +  what () const noexcept +  { +    return "missing option value"; +  } + +  // invalid_value +  // +  invalid_value:: +  ~invalid_value () noexcept +  { +  } + +  void invalid_value:: +  print (::std::wostream& os) const +  { +    os << "invalid value '" << value ().c_str () << "' for option '" +       << option ().c_str () << "'"; + +    if (!message ().empty ()) +      os << ": " << message ().c_str (); +  } + +  const char* invalid_value:: +  what () const noexcept +  { +    return "invalid option value"; +  } + +  // eos_reached +  // +  void eos_reached:: +  print (::std::wostream& os) const +  { +    os << what (); +  } + +  const char* eos_reached:: +  what () const noexcept +  { +    return "end of argument stream reached"; +  } + +  // file_io_failure +  // +  file_io_failure:: +  ~file_io_failure () noexcept +  { +  } + +  void file_io_failure:: +  print (::std::wostream& os) const +  { +    os << "unable to open file '" << file ().c_str () << "' or read failure"; +  } + +  const char* file_io_failure:: +  what () const noexcept +  { +    return "unable to open file or read failure"; +  } + +  // unmatched_quote +  // +  unmatched_quote:: +  ~unmatched_quote () noexcept +  { +  } + +  void unmatched_quote:: +  print (::std::wostream& os) const +  { +    os << "unmatched quote in argument '" << argument ().c_str () << "'"; +  } + +  const char* unmatched_quote:: +  what () const noexcept +  { +    return "unmatched quote"; +  } + +  // scanner +  // +  scanner:: +  ~scanner () +  { +  } + +  // argv_scanner +  // +  bool argv_scanner:: +  more () +  { +    return i_ < argc_; +  } + +  const char* argv_scanner:: +  peek () +  { +    if (i_ < argc_) +      return argv_[i_]; +    else +      throw eos_reached (); +  } + +  const char* argv_scanner:: +  next () +  { +    if (i_ < argc_) +    { +      const char* r (argv_[i_]); + +      if (erase_) +      { +        for (int i (i_ + 1); i < argc_; ++i) +          argv_[i - 1] = argv_[i]; + +        --argc_; +        argv_[argc_] = 0; +      } +      else +        ++i_; + +      ++start_position_; +      return r; +    } +    else +      throw eos_reached (); +  } + +  void argv_scanner:: +  skip () +  { +    if (i_ < argc_) +    { +      ++i_; +      ++start_position_; +    } +    else +      throw eos_reached (); +  } + +  std::size_t argv_scanner:: +  position () +  { +    return start_position_; +  } + +  // argv_file_scanner +  // +  int argv_file_scanner::zero_argc_ = 0; +  std::string argv_file_scanner::empty_string_; + +  bool argv_file_scanner:: +  more () +  { +    if (!args_.empty ()) +      return true; + +    while (base::more ()) +    { +      // See if the next argument is the file option. +      // +      const char* a (base::peek ()); +      const option_info* oi = 0; +      const char* ov = 0; + +      if (!skip_) +      { +        if ((oi = find (a)) != 0) +        { +          base::next (); + +          if (!base::more ()) +            throw missing_value (a); + +          ov = base::next (); +        } +        else if (std::strncmp (a, "-", 1) == 0) +        { +          if ((ov = std::strchr (a, '=')) != 0) +          { +            std::string o (a, 0, ov - a); +            if ((oi = find (o.c_str ())) != 0) +            { +              base::next (); +              ++ov; +            } +          } +        } +      } + +      if (oi != 0) +      { +        if (oi->search_func != 0) +        { +          std::string f (oi->search_func (ov, oi->arg)); + +          if (!f.empty ()) +            load (f); +        } +        else +          load (ov); + +        if (!args_.empty ()) +          return true; +      } +      else +      { +        if (!skip_) +          skip_ = (std::strcmp (a, "--") == 0); + +        return true; +      } +    } + +    return false; +  } + +  const char* argv_file_scanner:: +  peek () +  { +    if (!more ()) +      throw eos_reached (); + +    return args_.empty () ? base::peek () : args_.front ().value.c_str (); +  } + +  const std::string& argv_file_scanner:: +  peek_file () +  { +    if (!more ()) +      throw eos_reached (); + +    return args_.empty () ? empty_string_ : *args_.front ().file; +  } + +  std::size_t argv_file_scanner:: +  peek_line () +  { +    if (!more ()) +      throw eos_reached (); + +    return args_.empty () ? 0 : args_.front ().line; +  } + +  const char* argv_file_scanner:: +  next () +  { +    if (!more ()) +      throw eos_reached (); + +    if (args_.empty ()) +      return base::next (); +    else +    { +      hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ().value); +      args_.pop_front (); +      ++start_position_; +      return hold_[i_].c_str (); +    } +  } + +  void argv_file_scanner:: +  skip () +  { +    if (!more ()) +      throw eos_reached (); + +    if (args_.empty ()) +      return base::skip (); +    else +    { +      args_.pop_front (); +      ++start_position_; +    } +  } + +  const argv_file_scanner::option_info* argv_file_scanner:: +  find (const char* a) const +  { +    for (std::size_t i (0); i < options_count_; ++i) +      if (std::strcmp (a, options_[i].option) == 0) +        return &options_[i]; + +    return 0; +  } + +  std::size_t argv_file_scanner:: +  position () +  { +    return start_position_; +  } + +  void argv_file_scanner:: +  load (const std::string& file) +  { +    using namespace std; + +    ifstream is (file.c_str ()); + +    if (!is.is_open ()) +      throw file_io_failure (file); + +    files_.push_back (file); + +    arg a; +    a.file = &*files_.rbegin (); + +    for (a.line = 1; !is.eof (); ++a.line) +    { +      string line; +      getline (is, line); + +      if (is.fail () && !is.eof ()) +        throw file_io_failure (file); + +      string::size_type n (line.size ()); + +      // Trim the line from leading and trailing whitespaces. +      // +      if (n != 0) +      { +        const char* f (line.c_str ()); +        const char* l (f + n); + +        const char* of (f); +        while (f < l && (*f == ' ' || *f == '\t' || *f == '\r')) +          ++f; + +        --l; + +        const char* ol (l); +        while (l > f && (*l == ' ' || *l == '\t' || *l == '\r')) +          --l; + +        if (f != of || l != ol) +          line = f <= l ? string (f, l - f + 1) : string (); +      } + +      // Ignore empty lines, those that start with #. +      // +      if (line.empty () || line[0] == '#') +        continue; + +      string::size_type p (string::npos); +      if (line.compare (0, 1, "-") == 0) +      { +        p = line.find (' '); + +        string::size_type q (line.find ('=')); +        if (q != string::npos && q < p) +          p = q; +      } + +      string s1; +      if (p != string::npos) +      { +        s1.assign (line, 0, p); + +        // Skip leading whitespaces in the argument. +        // +        if (line[p] == '=') +          ++p; +        else +        { +          n = line.size (); +          for (++p; p < n; ++p) +          { +            char c (line[p]); +            if (c != ' ' && c != '\t' && c != '\r') +              break; +          } +        } +      } +      else if (!skip_) +        skip_ = (line == "--"); + +      string s2 (line, p != string::npos ? p : 0); + +      // If the string (which is an option value or argument) is +      // wrapped in quotes, remove them. +      // +      n = s2.size (); +      char cf (s2[0]), cl (s2[n - 1]); + +      if (cf == '"' || cf == '\'' || cl == '"' || cl == '\'') +      { +        if (n == 1 || cf != cl) +          throw unmatched_quote (s2); + +        s2 = string (s2, 1, n - 2); +      } + +      if (!s1.empty ()) +      { +        // See if this is another file option. +        // +        const option_info* oi; +        if (!skip_ && (oi = find (s1.c_str ()))) +        { +          if (s2.empty ()) +            throw missing_value (oi->option); + +          if (oi->search_func != 0) +          { +            string f (oi->search_func (s2.c_str (), oi->arg)); +            if (!f.empty ()) +              load (f); +          } +          else +          { +            // If the path of the file being parsed is not simple and the +            // path of the file that needs to be loaded is relative, then +            // complete the latter using the former as a base. +            // +#ifndef _WIN32 +            string::size_type p (file.find_last_of ('/')); +            bool c (p != string::npos && s2[0] != '/'); +#else +            string::size_type p (file.find_last_of ("/\\")); +            bool c (p != string::npos && s2[1] != ':'); +#endif +            if (c) +              s2.insert (0, file, 0, p + 1); + +            load (s2); +          } + +          continue; +        } + +        a.value = s1; +        args_.push_back (a); +      } + +      a.value = s2; +      args_.push_back (a); +    } +  } + +  template <typename X> +  struct parser +  { +    static void +    parse (X& x, bool& xs, scanner& s) +    { +      using namespace std; + +      const char* o (s.next ()); +      if (s.more ()) +      { +        string v (s.next ()); +        istringstream is (v); +        if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) +          throw invalid_value (o, v); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <> +  struct parser<bool> +  { +    static void +    parse (bool& x, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        const char* v (s.next ()); + +        if (std::strcmp (v, "1")    == 0 || +            std::strcmp (v, "true") == 0 || +            std::strcmp (v, "TRUE") == 0 || +            std::strcmp (v, "True") == 0) +          x = true; +        else if (std::strcmp (v, "0")     == 0 || +                 std::strcmp (v, "false") == 0 || +                 std::strcmp (v, "FALSE") == 0 || +                 std::strcmp (v, "False") == 0) +          x = false; +        else +          throw invalid_value (o, v); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <> +  struct parser<std::string> +  { +    static void +    parse (std::string& x, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +        x = s.next (); +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename X> +  struct parser<std::pair<X, std::size_t> > +  { +    static void +    parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) +    { +      x.second = s.position (); +      parser<X>::parse (x.first, xs, s); +    } +  }; + +  template <typename X> +  struct parser<std::vector<X> > +  { +    static void +    parse (std::vector<X>& c, bool& xs, scanner& s) +    { +      X x; +      bool dummy; +      parser<X>::parse (x, dummy, s); +      c.push_back (x); +      xs = true; +    } +  }; + +  template <typename X, typename C> +  struct parser<std::set<X, C> > +  { +    static void +    parse (std::set<X, C>& c, bool& xs, scanner& s) +    { +      X x; +      bool dummy; +      parser<X>::parse (x, dummy, s); +      c.insert (x); +      xs = true; +    } +  }; + +  template <typename K, typename V, typename C> +  struct parser<std::map<K, V, C> > +  { +    static void +    parse (std::map<K, V, C>& m, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        std::size_t pos (s.position ()); +        std::string ov (s.next ()); +        std::string::size_type p = ov.find ('='); + +        K k = K (); +        V v = V (); +        std::string kstr (ov, 0, p); +        std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + +        int ac (2); +        char* av[] = +        { +          const_cast<char*> (o), +          0 +        }; + +        bool dummy; +        if (!kstr.empty ()) +        { +          av[1] = const_cast<char*> (kstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<K>::parse (k, dummy, s); +        } + +        if (!vstr.empty ()) +        { +          av[1] = const_cast<char*> (vstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<V>::parse (v, dummy, s); +        } + +        m[k] = v; +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename K, typename V, typename C> +  struct parser<std::multimap<K, V, C> > +  { +    static void +    parse (std::multimap<K, V, C>& m, bool& xs, scanner& s) +    { +      const char* o (s.next ()); + +      if (s.more ()) +      { +        std::size_t pos (s.position ()); +        std::string ov (s.next ()); +        std::string::size_type p = ov.find ('='); + +        K k = K (); +        V v = V (); +        std::string kstr (ov, 0, p); +        std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + +        int ac (2); +        char* av[] = +        { +          const_cast<char*> (o), +          0 +        }; + +        bool dummy; +        if (!kstr.empty ()) +        { +          av[1] = const_cast<char*> (kstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<K>::parse (k, dummy, s); +        } + +        if (!vstr.empty ()) +        { +          av[1] = const_cast<char*> (vstr.c_str ()); +          argv_scanner s (0, ac, av, false, pos); +          parser<V>::parse (v, dummy, s); +        } + +        m.insert (typename std::multimap<K, V, C>::value_type (k, v)); +      } +      else +        throw missing_value (o); + +      xs = true; +    } +  }; + +  template <typename X, typename T, T X::*M> +  void +  thunk (X& x, scanner& s) +  { +    parser<T>::parse (x.*M, s); +  } + +  template <typename X, bool X::*M> +  void +  thunk (X& x, scanner& s) +  { +    s.next (); +    x.*M = true; +  } + +  template <typename X, typename T, T X::*M, bool X::*S> +  void +  thunk (X& x, scanner& s) +  { +    parser<T>::parse (x.*M, x.*S, s); +  } +} + +#include <map> + +// help_options +// + +help_options:: +help_options () +: build2_metadata_ (), +  build2_metadata_specified_ (false), +  help_ (), +  version_ (), +  proprietary_license_ () +{ +} + +help_options:: +help_options (int& argc, +              char** argv, +              bool erase, +              ::cli::unknown_mode opt, +              ::cli::unknown_mode arg) +: build2_metadata_ (), +  build2_metadata_specified_ (false), +  help_ (), +  version_ (), +  proprietary_license_ () +{ +  ::cli::argv_scanner s (argc, argv, erase); +  _parse (s, opt, arg); +} + +help_options:: +help_options (int start, +              int& argc, +              char** argv, +              bool erase, +              ::cli::unknown_mode opt, +              ::cli::unknown_mode arg) +: build2_metadata_ (), +  build2_metadata_specified_ (false), +  help_ (), +  version_ (), +  proprietary_license_ () +{ +  ::cli::argv_scanner s (start, argc, argv, erase); +  _parse (s, opt, arg); +} + +help_options:: +help_options (int& argc, +              char** argv, +              int& end, +              bool erase, +              ::cli::unknown_mode opt, +              ::cli::unknown_mode arg) +: build2_metadata_ (), +  build2_metadata_specified_ (false), +  help_ (), +  version_ (), +  proprietary_license_ () +{ +  ::cli::argv_scanner s (argc, argv, erase); +  _parse (s, opt, arg); +  end = s.end (); +} + +help_options:: +help_options (int start, +              int& argc, +              char** argv, +              int& end, +              bool erase, +              ::cli::unknown_mode opt, +              ::cli::unknown_mode arg) +: build2_metadata_ (), +  build2_metadata_specified_ (false), +  help_ (), +  version_ (), +  proprietary_license_ () +{ +  ::cli::argv_scanner s (start, argc, argv, erase); +  _parse (s, opt, arg); +  end = s.end (); +} + +help_options:: +help_options (::cli::scanner& s, +              ::cli::unknown_mode opt, +              ::cli::unknown_mode arg) +: build2_metadata_ (), +  build2_metadata_specified_ (false), +  help_ (), +  version_ (), +  proprietary_license_ () +{ +  _parse (s, opt, arg); +} + +::cli::usage_para help_options:: +print_usage (::std::wostream& os, ::cli::usage_para p) +{ +  CLI_POTENTIALLY_UNUSED (os); + +  return p; +} + +typedef +std::map<std::string, void (*) (help_options&, ::cli::scanner&)> +_cli_help_options_map; + +static _cli_help_options_map _cli_help_options_map_; + +struct _cli_help_options_map_init +{ +  _cli_help_options_map_init () +  { +    _cli_help_options_map_["--build2-metadata"] = +    &::cli::thunk< help_options, std::uint64_t, &help_options::build2_metadata_, +      &help_options::build2_metadata_specified_ >; +    _cli_help_options_map_["--help"] = +    &::cli::thunk< help_options, &help_options::help_ >; +    _cli_help_options_map_["--version"] = +    &::cli::thunk< help_options, &help_options::version_ >; +    _cli_help_options_map_["--proprietary-license"] = +    &::cli::thunk< help_options, &help_options::proprietary_license_ >; +  } +}; + +static _cli_help_options_map_init _cli_help_options_map_init_; + +bool help_options:: +_parse (const char* o, ::cli::scanner& s) +{ +  _cli_help_options_map::const_iterator i (_cli_help_options_map_.find (o)); + +  if (i != _cli_help_options_map_.end ()) +  { +    (*(i->second)) (*this, s); +    return true; +  } + +  return false; +} + +bool help_options:: +_parse (::cli::scanner& s, +        ::cli::unknown_mode opt_mode, +        ::cli::unknown_mode arg_mode) +{ +  // Can't skip combined flags (--no-combined-flags). +  // +  assert (opt_mode != ::cli::unknown_mode::skip); + +  bool r = false; +  bool opt = true; + +  while (s.more ()) +  { +    const char* o = s.peek (); + +    if (std::strcmp (o, "--") == 0) +    { +      opt = false; +      s.skip (); +      r = true; +      continue; +    } + +    if (opt) +    { +      if (_parse (o, s)) +      { +        r = true; +        continue; +      } + +      if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') +      { +        // Handle combined option values. +        // +        std::string co; +        if (const char* v = std::strchr (o, '=')) +        { +          co.assign (o, 0, v - o); +          ++v; + +          int ac (2); +          char* av[] = +          { +            const_cast<char*> (co.c_str ()), +            const_cast<char*> (v) +          }; + +          ::cli::argv_scanner ns (0, ac, av); + +          if (_parse (co.c_str (), ns)) +          { +            // Parsed the option but not its value? +            // +            if (ns.end () != 2) +              throw ::cli::invalid_value (co, v); + +            s.next (); +            r = true; +            continue; +          } +          else +          { +            // Set the unknown option and fall through. +            // +            o = co.c_str (); +          } +        } + +        // Handle combined flags. +        // +        char cf[3]; +        { +          const char* p = o + 1; +          for (; *p != '\0'; ++p) +          { +            if (!((*p >= 'a' && *p <= 'z') || +                  (*p >= 'A' && *p <= 'Z') || +                  (*p >= '0' && *p <= '9'))) +              break; +          } + +          if (*p == '\0') +          { +            for (p = o + 1; *p != '\0'; ++p) +            { +              std::strcpy (cf, "-"); +              cf[1] = *p; +              cf[2] = '\0'; + +              int ac (1); +              char* av[] = +              { +                cf +              }; + +              ::cli::argv_scanner ns (0, ac, av); + +              if (!_parse (cf, ns)) +                break; +            } + +            if (*p == '\0') +            { +              // All handled. +              // +              s.next (); +              r = true; +              continue; +            } +            else +            { +              // Set the unknown option and fall through. +              // +              o = cf; +            } +          } +        } + +        switch (opt_mode) +        { +          case ::cli::unknown_mode::skip: +          { +            s.skip (); +            r = true; +            continue; +          } +          case ::cli::unknown_mode::stop: +          { +            break; +          } +          case ::cli::unknown_mode::fail: +          { +            throw ::cli::unknown_option (o); +          } +        } + +        break; +      } +    } + +    switch (arg_mode) +    { +      case ::cli::unknown_mode::skip: +      { +        s.skip (); +        r = true; +        continue; +      } +      case ::cli::unknown_mode::stop: +      { +        break; +      } +      case ::cli::unknown_mode::fail: +      { +        throw ::cli::unknown_argument (o); +      } +    } + +    break; +  } + +  return r; +} + +// options +// + +options:: +options () +: disable_warning_ (), +  disable_warning_specified_ (false), +  options_file_ (), +  options_file_specified_ (false), +  show_sloc_ (), +  sloc_limit_ (), +  sloc_limit_specified_ (false), +  proprietary_license_ (), +  custom_literals_ (), +  custom_literals_specified_ (false), +  preserve_anonymous_ (), +  show_anonymous_ (), +  anonymous_regex_ (), +  anonymous_regex_specified_ (false), +  anonymous_regex_trace_ (), +  morph_anonymous_ (), +  location_map_ (), +  location_map_specified_ (false), +  location_regex_ (), +  location_regex_specified_ (false), +  location_regex_trace_ (), +  file_per_type_ (), +  type_file_regex_ (), +  type_file_regex_specified_ (false), +  type_file_regex_trace_ (), +  schema_file_regex_ (), +  schema_file_regex_specified_ (false), +  schema_file_regex_trace_ (), +  fat_type_file_ (), +  file_list_ (), +  file_list_specified_ (false), +  file_list_only_ (), +  file_list_prologue_ (), +  file_list_prologue_specified_ (false), +  file_list_epilogue_ (), +  file_list_epilogue_specified_ (false), +  file_list_delim_ ("\n"), +  file_list_delim_specified_ (false), +  disable_multi_import_ (), +  disable_full_check_ () +{ +} + +::cli::usage_para options:: +print_usage (::std::wostream& os, ::cli::usage_para p) +{ +  CLI_POTENTIALLY_UNUSED (os); + +  if (p == ::cli::usage_para::text) +    os << ::std::endl; + +  os << "--disable-warning <warn>     Disable printing warning with id <warn>." << ::std::endl; + +  os << "--options-file <file>        Read additional options from <file>." << ::std::endl; + +  os << "--show-sloc                  Show the number of generated physical source lines" << ::std::endl +     << "                             of code (SLOC)." << ::std::endl; + +  os << "--sloc-limit <num>           Check that the number of generated physical source" << ::std::endl +     << "                             lines of code (SLOC) does not exceed <num>." << ::std::endl; + +  os << "--proprietary-license        Indicate that the generated code is licensed under" << ::std::endl +     << "                             a proprietary license instead of the GPL." << ::std::endl; + +  os << "--custom-literals <file>     Load custom XML string to C++ literal mappings" << ::std::endl +     << "                             from <file>." << ::std::endl; + +  os << "--preserve-anonymous         Preserve anonymous types." << ::std::endl; + +  os << "--show-anonymous             Show elements and attributes that are of anonymous" << ::std::endl +     << "                             types." << ::std::endl; + +  os << "--anonymous-regex <regex>    Add <regex> to the list of regular expressions" << ::std::endl +     << "                             used to derive names for anonymous types from the" << ::std::endl +     << "                             enclosing attributes/elements." << ::std::endl; + +  os << "--anonymous-regex-trace      Trace the process of applying regular expressions" << ::std::endl +     << "                             specified with the --anonymous-regex option." << ::std::endl; + +  os << "--location-map <ol>=<nl>     Map the original schema location <ol> that is" << ::std::endl +     << "                             specified in the XML Schema include or import" << ::std::endl +     << "                             elements to new schema location <nl>." << ::std::endl; + +  os << "--location-regex <regex>     Add <regex> to the list of regular expressions" << ::std::endl +     << "                             used to map schema locations that are specified in" << ::std::endl +     << "                             the XML Schema include or import elements." << ::std::endl; + +  os << "--location-regex-trace       Trace the process of applying regular expressions" << ::std::endl +     << "                             specified with the --location-regex option." << ::std::endl; + +  os << "--file-per-type              Generate a separate set of C++ files for each type" << ::std::endl +     << "                             defined in XML Schema." << ::std::endl; + +  os << "--type-file-regex <regex>    Add <regex> to the list of regular expressions" << ::std::endl +     << "                             used to translate type names to file names when" << ::std::endl +     << "                             the --file-per-type option is specified." << ::std::endl; + +  os << "--type-file-regex-trace      Trace the process of applying regular expressions" << ::std::endl +     << "                             specified with the --type-file-regex option." << ::std::endl; + +  os << "--schema-file-regex <regex>  Add <regex> to the list of regular expressions" << ::std::endl +     << "                             used to translate schema file names when the" << ::std::endl +     << "                             --file-per-type option is specified." << ::std::endl; + +  os << "--schema-file-regex-trace    Trace the process of applying regular expressions" << ::std::endl +     << "                             specified with the --schema-file-regex option." << ::std::endl; + +  os << "--fat-type-file              Generate code corresponding to global elements" << ::std::endl +     << "                             into type files instead of schema files when the" << ::std::endl +     << "                             --type-file-regex option is specified." << ::std::endl; + +  os << "--file-list <file>           Write a list of generated C++ files to <file> or" << ::std::endl +     << "                             to stdout if <file> is -." << ::std::endl; + +  os << "--file-list-only             Only write the list of C++ files that would be" << ::std::endl +     << "                             generated without actually generating them." << ::std::endl; + +  os << "--file-list-prologue <text>  Insert <text> at the beginning of the file list." << ::std::endl; + +  os << "--file-list-epilogue <text>  Insert <text> at the end of the file list." << ::std::endl; + +  os << "--file-list-delim <text>     Delimit file names written to the file list with" << ::std::endl +     << "                             <text> instead of new lines." << ::std::endl; + +  p = ::cli::usage_para::option; + +  return p; +} + +typedef +std::map<std::string, void (*) (options&, ::cli::scanner&)> +_cli_options_map; + +static _cli_options_map _cli_options_map_; + +struct _cli_options_map_init +{ +  _cli_options_map_init () +  { +    _cli_options_map_["--disable-warning"] = +    &::cli::thunk< options, NarrowStrings, &options::disable_warning_, +      &options::disable_warning_specified_ >; +    _cli_options_map_["--options-file"] = +    &::cli::thunk< options, std::string, &options::options_file_, +      &options::options_file_specified_ >; +    _cli_options_map_["--show-sloc"] = +    &::cli::thunk< options, &options::show_sloc_ >; +    _cli_options_map_["--sloc-limit"] = +    &::cli::thunk< options, std::size_t, &options::sloc_limit_, +      &options::sloc_limit_specified_ >; +    _cli_options_map_["--proprietary-license"] = +    &::cli::thunk< options, &options::proprietary_license_ >; +    _cli_options_map_["--custom-literals"] = +    &::cli::thunk< options, NarrowString, &options::custom_literals_, +      &options::custom_literals_specified_ >; +    _cli_options_map_["--preserve-anonymous"] = +    &::cli::thunk< options, &options::preserve_anonymous_ >; +    _cli_options_map_["--show-anonymous"] = +    &::cli::thunk< options, &options::show_anonymous_ >; +    _cli_options_map_["--anonymous-regex"] = +    &::cli::thunk< options, NarrowStrings, &options::anonymous_regex_, +      &options::anonymous_regex_specified_ >; +    _cli_options_map_["--anonymous-regex-trace"] = +    &::cli::thunk< options, &options::anonymous_regex_trace_ >; +    _cli_options_map_["--morph-anonymous"] = +    &::cli::thunk< options, &options::morph_anonymous_ >; +    _cli_options_map_["--location-map"] = +    &::cli::thunk< options, NarrowStrings, &options::location_map_, +      &options::location_map_specified_ >; +    _cli_options_map_["--location-regex"] = +    &::cli::thunk< options, NarrowStrings, &options::location_regex_, +      &options::location_regex_specified_ >; +    _cli_options_map_["--location-regex-trace"] = +    &::cli::thunk< options, &options::location_regex_trace_ >; +    _cli_options_map_["--file-per-type"] = +    &::cli::thunk< options, &options::file_per_type_ >; +    _cli_options_map_["--type-file-regex"] = +    &::cli::thunk< options, NarrowStrings, &options::type_file_regex_, +      &options::type_file_regex_specified_ >; +    _cli_options_map_["--type-file-regex-trace"] = +    &::cli::thunk< options, &options::type_file_regex_trace_ >; +    _cli_options_map_["--schema-file-regex"] = +    &::cli::thunk< options, NarrowStrings, &options::schema_file_regex_, +      &options::schema_file_regex_specified_ >; +    _cli_options_map_["--schema-file-regex-trace"] = +    &::cli::thunk< options, &options::schema_file_regex_trace_ >; +    _cli_options_map_["--fat-type-file"] = +    &::cli::thunk< options, &options::fat_type_file_ >; +    _cli_options_map_["--file-list"] = +    &::cli::thunk< options, NarrowString, &options::file_list_, +      &options::file_list_specified_ >; +    _cli_options_map_["--file-list-only"] = +    &::cli::thunk< options, &options::file_list_only_ >; +    _cli_options_map_["--file-list-prologue"] = +    &::cli::thunk< options, NarrowString, &options::file_list_prologue_, +      &options::file_list_prologue_specified_ >; +    _cli_options_map_["--file-list-epilogue"] = +    &::cli::thunk< options, NarrowString, &options::file_list_epilogue_, +      &options::file_list_epilogue_specified_ >; +    _cli_options_map_["--file-list-delim"] = +    &::cli::thunk< options, NarrowString, &options::file_list_delim_, +      &options::file_list_delim_specified_ >; +    _cli_options_map_["--disable-multi-import"] = +    &::cli::thunk< options, &options::disable_multi_import_ >; +    _cli_options_map_["--disable-full-check"] = +    &::cli::thunk< options, &options::disable_full_check_ >; +  } +}; + +static _cli_options_map_init _cli_options_map_init_; + +bool options:: +_parse (const char* o, ::cli::scanner& s) +{ +  _cli_options_map::const_iterator i (_cli_options_map_.find (o)); + +  if (i != _cli_options_map_.end ()) +  { +    (*(i->second)) (*this, s); +    return true; +  } + +  return false; +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/xsd/pregenerated/xsd/options.hxx b/xsd/pregenerated/xsd/options.hxx new file mode 100644 index 0000000..0f4383c --- /dev/null +++ b/xsd/pregenerated/xsd/options.hxx @@ -0,0 +1,702 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef XSD_OPTIONS_HXX +#define XSD_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <list> +#include <deque> +#include <iosfwd> +#include <string> +#include <cstddef> +#include <exception> + +#ifndef CLI_POTENTIALLY_UNUSED +#  if defined(_MSC_VER) || defined(__xlC__) +#    define CLI_POTENTIALLY_UNUSED(x) (void*)&x +#  else +#    define CLI_POTENTIALLY_UNUSED(x) (void)x +#  endif +#endif + +namespace cli +{ +  class usage_para +  { +    public: +    enum value +    { +      none, +      text, +      option +    }; + +    usage_para (value); + +    operator value () const  +    { +      return v_; +    } + +    private: +    value v_; +  }; + +  class unknown_mode +  { +    public: +    enum value +    { +      skip, +      stop, +      fail +    }; + +    unknown_mode (value); + +    operator value () const  +    { +      return v_; +    } + +    private: +    value v_; +  }; + +  // Exceptions. +  // + +  class exception: public std::exception +  { +    public: +    virtual void +    print (::std::wostream&) const = 0; +  }; + +  ::std::wostream& +  operator<< (::std::wostream&, const exception&); + +  class unknown_option: public exception +  { +    public: +    virtual +    ~unknown_option () noexcept; + +    unknown_option (const std::string& option); + +    const std::string& +    option () const; + +    virtual void +    print (::std::wostream&) const; + +    virtual const char* +    what () const noexcept; + +    private: +    std::string option_; +  }; + +  class unknown_argument: public exception +  { +    public: +    virtual +    ~unknown_argument () noexcept; + +    unknown_argument (const std::string& argument); + +    const std::string& +    argument () const; + +    virtual void +    print (::std::wostream&) const; + +    virtual const char* +    what () const noexcept; + +    private: +    std::string argument_; +  }; + +  class missing_value: public exception +  { +    public: +    virtual +    ~missing_value () noexcept; + +    missing_value (const std::string& option); + +    const std::string& +    option () const; + +    virtual void +    print (::std::wostream&) const; + +    virtual const char* +    what () const noexcept; + +    private: +    std::string option_; +  }; + +  class invalid_value: public exception +  { +    public: +    virtual +    ~invalid_value () noexcept; + +    invalid_value (const std::string& option, +                   const std::string& value, +                   const std::string& message = std::string ()); + +    const std::string& +    option () const; + +    const std::string& +    value () const; + +    const std::string& +    message () const; + +    virtual void +    print (::std::wostream&) const; + +    virtual const char* +    what () const noexcept; + +    private: +    std::string option_; +    std::string value_; +    std::string message_; +  }; + +  class eos_reached: public exception +  { +    public: +    virtual void +    print (::std::wostream&) const; + +    virtual const char* +    what () const noexcept; +  }; + +  class file_io_failure: public exception +  { +    public: +    virtual +    ~file_io_failure () noexcept; + +    file_io_failure (const std::string& file); + +    const std::string& +    file () const; + +    virtual void +    print (::std::wostream&) const; + +    virtual const char* +    what () const noexcept; + +    private: +    std::string file_; +  }; + +  class unmatched_quote: public exception +  { +    public: +    virtual +    ~unmatched_quote () noexcept; + +    unmatched_quote (const std::string& argument); + +    const std::string& +    argument () const; + +    virtual void +    print (::std::wostream&) const; + +    virtual const char* +    what () const noexcept; + +    private: +    std::string argument_; +  }; + +  // Command line argument scanner interface. +  // +  // The values returned by next() are guaranteed to be valid +  // for the two previous arguments up until a call to a third +  // peek() or next(). +  // +  // The position() function returns a monotonically-increasing +  // number which, if stored, can later be used to determine the +  // relative position of the argument returned by the following +  // call to next(). Note that if multiple scanners are used to +  // extract arguments from multiple sources, then the end +  // position of the previous scanner should be used as the +  // start position of the next. +  // +  class scanner +  { +    public: +    virtual +    ~scanner (); + +    virtual bool +    more () = 0; + +    virtual const char* +    peek () = 0; + +    virtual const char* +    next () = 0; + +    virtual void +    skip () = 0; + +    virtual std::size_t +    position () = 0; +  }; + +  class argv_scanner: public scanner +  { +    public: +    argv_scanner (int& argc, +                  char** argv, +                  bool erase = false, +                  std::size_t start_position = 0); + +    argv_scanner (int start, +                  int& argc, +                  char** argv, +                  bool erase = false, +                  std::size_t start_position = 0); + +    int +    end () const; + +    virtual bool +    more (); + +    virtual const char* +    peek (); + +    virtual const char* +    next (); + +    virtual void +    skip (); + +    virtual std::size_t +    position (); + +    protected: +    std::size_t start_position_; +    int i_; +    int& argc_; +    char** argv_; +    bool erase_; +  }; + +  class argv_file_scanner: public argv_scanner +  { +    public: +    argv_file_scanner (int& argc, +                       char** argv, +                       const std::string& option, +                       bool erase = false, +                       std::size_t start_position = 0); + +    argv_file_scanner (int start, +                       int& argc, +                       char** argv, +                       const std::string& option, +                       bool erase = false, +                       std::size_t start_position = 0); + +    argv_file_scanner (const std::string& file, +                       const std::string& option, +                       std::size_t start_position = 0); + +    struct option_info +    { +      // If search_func is not NULL, it is called, with the arg +      // value as the second argument, to locate the options file. +      // If it returns an empty string, then the file is ignored. +      // +      const char* option; +      std::string (*search_func) (const char*, void* arg); +      void* arg; +    }; + +    argv_file_scanner (int& argc, +                        char** argv, +                        const option_info* options, +                        std::size_t options_count, +                        bool erase = false, +                        std::size_t start_position = 0); + +    argv_file_scanner (int start, +                       int& argc, +                       char** argv, +                       const option_info* options, +                       std::size_t options_count, +                       bool erase = false, +                       std::size_t start_position = 0); + +    argv_file_scanner (const std::string& file, +                       const option_info* options = 0, +                       std::size_t options_count = 0, +                       std::size_t start_position = 0); + +    virtual bool +    more (); + +    virtual const char* +    peek (); + +    virtual const char* +    next (); + +    virtual void +    skip (); + +    virtual std::size_t +    position (); + +    // Return the file path if the peeked at argument came from a file and +    // the empty string otherwise. The reference is guaranteed to be valid +    // till the end of the scanner lifetime. +    // +    const std::string& +    peek_file (); + +    // Return the 1-based line number if the peeked at argument came from +    // a file and zero otherwise. +    // +    std::size_t +    peek_line (); + +    private: +    const option_info* +    find (const char*) const; + +    void +    load (const std::string& file); + +    typedef argv_scanner base; + +    const std::string option_; +    option_info option_info_; +    const option_info* options_; +    std::size_t options_count_; + +    struct arg +    { +      std::string value; +      const std::string* file; +      std::size_t line; +    }; + +    std::deque<arg> args_; +    std::list<std::string> files_; + +    // Circular buffer of two arguments. +    // +    std::string hold_[2]; +    std::size_t i_; + +    bool skip_; + +    static int zero_argc_; +    static std::string empty_string_; +  }; + +  template <typename X> +  struct parser; +} + +#include <cstddef> + +#include <cstdint> + +#include <xsd/types.hxx> + +class help_options +{ +  public: +  help_options (); + +  help_options (int& argc, +                char** argv, +                bool erase = false, +                ::cli::unknown_mode option = ::cli::unknown_mode::fail, +                ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +  help_options (int start, +                int& argc, +                char** argv, +                bool erase = false, +                ::cli::unknown_mode option = ::cli::unknown_mode::fail, +                ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +  help_options (int& argc, +                char** argv, +                int& end, +                bool erase = false, +                ::cli::unknown_mode option = ::cli::unknown_mode::fail, +                ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +  help_options (int start, +                int& argc, +                char** argv, +                int& end, +                bool erase = false, +                ::cli::unknown_mode option = ::cli::unknown_mode::fail, +                ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +  help_options (::cli::scanner&, +                ::cli::unknown_mode option = ::cli::unknown_mode::fail, +                ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + +  // Option accessors. +  // +  const std::uint64_t& +  build2_metadata () const; + +  bool +  build2_metadata_specified () const; + +  const bool& +  help () const; + +  const bool& +  version () const; + +  const bool& +  proprietary_license () const; + +  // Print usage information. +  // +  static ::cli::usage_para +  print_usage (::std::wostream&, +               ::cli::usage_para = ::cli::usage_para::none); + +  // Implementation details. +  // +  protected: +  bool +  _parse (const char*, ::cli::scanner&); + +  private: +  bool +  _parse (::cli::scanner&, +          ::cli::unknown_mode option, +          ::cli::unknown_mode argument); + +  public: +  std::uint64_t build2_metadata_; +  bool build2_metadata_specified_; +  bool help_; +  bool version_; +  bool proprietary_license_; +}; + +class options +{ +  public: +  // Option accessors. +  // +  const NarrowStrings& +  disable_warning () const; + +  bool +  disable_warning_specified () const; + +  const std::string& +  options_file () const; + +  bool +  options_file_specified () const; + +  const bool& +  show_sloc () const; + +  const std::size_t& +  sloc_limit () const; + +  bool +  sloc_limit_specified () const; + +  const bool& +  proprietary_license () const; + +  const NarrowString& +  custom_literals () const; + +  bool +  custom_literals_specified () const; + +  const bool& +  preserve_anonymous () const; + +  const bool& +  show_anonymous () const; + +  const NarrowStrings& +  anonymous_regex () const; + +  bool +  anonymous_regex_specified () const; + +  const bool& +  anonymous_regex_trace () const; + +  const bool& +  morph_anonymous () const; + +  const NarrowStrings& +  location_map () const; + +  bool +  location_map_specified () const; + +  const NarrowStrings& +  location_regex () const; + +  bool +  location_regex_specified () const; + +  const bool& +  location_regex_trace () const; + +  const bool& +  file_per_type () const; + +  const NarrowStrings& +  type_file_regex () const; + +  bool +  type_file_regex_specified () const; + +  const bool& +  type_file_regex_trace () const; + +  const NarrowStrings& +  schema_file_regex () const; + +  bool +  schema_file_regex_specified () const; + +  const bool& +  schema_file_regex_trace () const; + +  const bool& +  fat_type_file () const; + +  const NarrowString& +  file_list () const; + +  bool +  file_list_specified () const; + +  const bool& +  file_list_only () const; + +  const NarrowString& +  file_list_prologue () const; + +  bool +  file_list_prologue_specified () const; + +  const NarrowString& +  file_list_epilogue () const; + +  bool +  file_list_epilogue_specified () const; + +  const NarrowString& +  file_list_delim () const; + +  bool +  file_list_delim_specified () const; + +  const bool& +  disable_multi_import () const; + +  const bool& +  disable_full_check () const; + +  // Print usage information. +  // +  static ::cli::usage_para +  print_usage (::std::wostream&, +               ::cli::usage_para = ::cli::usage_para::none); + +  // Implementation details. +  // +  protected: +  options (); + +  bool +  _parse (const char*, ::cli::scanner&); + +  public: +  NarrowStrings disable_warning_; +  bool disable_warning_specified_; +  std::string options_file_; +  bool options_file_specified_; +  bool show_sloc_; +  std::size_t sloc_limit_; +  bool sloc_limit_specified_; +  bool proprietary_license_; +  NarrowString custom_literals_; +  bool custom_literals_specified_; +  bool preserve_anonymous_; +  bool show_anonymous_; +  NarrowStrings anonymous_regex_; +  bool anonymous_regex_specified_; +  bool anonymous_regex_trace_; +  bool morph_anonymous_; +  NarrowStrings location_map_; +  bool location_map_specified_; +  NarrowStrings location_regex_; +  bool location_regex_specified_; +  bool location_regex_trace_; +  bool file_per_type_; +  NarrowStrings type_file_regex_; +  bool type_file_regex_specified_; +  bool type_file_regex_trace_; +  NarrowStrings schema_file_regex_; +  bool schema_file_regex_specified_; +  bool schema_file_regex_trace_; +  bool fat_type_file_; +  NarrowString file_list_; +  bool file_list_specified_; +  bool file_list_only_; +  NarrowString file_list_prologue_; +  bool file_list_prologue_specified_; +  NarrowString file_list_epilogue_; +  bool file_list_epilogue_specified_; +  NarrowString file_list_delim_; +  bool file_list_delim_specified_; +  bool disable_multi_import_; +  bool disable_full_check_; +}; + +#include <xsd/options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // XSD_OPTIONS_HXX diff --git a/xsd/pregenerated/xsd/options.ixx b/xsd/pregenerated/xsd/options.ixx new file mode 100644 index 0000000..d87e59c --- /dev/null +++ b/xsd/pregenerated/xsd/options.ixx @@ -0,0 +1,555 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +#include <cassert> + +namespace cli +{ +  // usage_para +  // +  inline usage_para:: +  usage_para (value v) +  : v_ (v) +  { +  } + +  // unknown_mode +  // +  inline unknown_mode:: +  unknown_mode (value v) +  : v_ (v) +  { +  } + +  // exception +  // +  inline ::std::wostream& +  operator<< (::std::wostream& os, const exception& e) +  { +    e.print (os); +    return os; +  } + +  // unknown_option +  // +  inline unknown_option:: +  unknown_option (const std::string& option) +  : option_ (option) +  { +  } + +  inline const std::string& unknown_option:: +  option () const +  { +    return option_; +  } + +  // unknown_argument +  // +  inline unknown_argument:: +  unknown_argument (const std::string& argument) +  : argument_ (argument) +  { +  } + +  inline const std::string& unknown_argument:: +  argument () const +  { +    return argument_; +  } + +  // missing_value +  // +  inline missing_value:: +  missing_value (const std::string& option) +  : option_ (option) +  { +  } + +  inline const std::string& missing_value:: +  option () const +  { +    return option_; +  } + +  // invalid_value +  // +  inline invalid_value:: +  invalid_value (const std::string& option, +                 const std::string& value, +                 const std::string& message) +  : option_ (option), +    value_ (value), +    message_ (message) +  { +  } + +  inline const std::string& invalid_value:: +  option () const +  { +    return option_; +  } + +  inline const std::string& invalid_value:: +  value () const +  { +    return value_; +  } + +  inline const std::string& invalid_value:: +  message () const +  { +    return message_; +  } + +  // file_io_failure +  // +  inline file_io_failure:: +  file_io_failure (const std::string& file) +  : file_ (file) +  { +  } + +  inline const std::string& file_io_failure:: +  file () const +  { +    return file_; +  } + +  // unmatched_quote +  // +  inline unmatched_quote:: +  unmatched_quote (const std::string& argument) +  : argument_ (argument) +  { +  } + +  inline const std::string& unmatched_quote:: +  argument () const +  { +    return argument_; +  } + +  // argv_scanner +  // +  inline argv_scanner:: +  argv_scanner (int& argc, +                char** argv, +                bool erase, +                std::size_t sp) +  : start_position_ (sp + 1), +    i_ (1), +    argc_ (argc), +    argv_ (argv), +    erase_ (erase) +  { +  } + +  inline argv_scanner:: +  argv_scanner (int start, +                int& argc, +                char** argv, +                bool erase, +                std::size_t sp) +  : start_position_ (sp + static_cast<std::size_t> (start)), +    i_ (start), +    argc_ (argc), +    argv_ (argv), +    erase_ (erase) +  { +  } + +  inline int argv_scanner:: +  end () const +  { +    return i_; +  } + +  // argv_file_scanner +  // +  inline argv_file_scanner:: +  argv_file_scanner (int& argc, +                     char** argv, +                     const std::string& option, +                     bool erase, +                     std::size_t sp) +  : argv_scanner (argc, argv, erase, sp), +    option_ (option), +    options_ (&option_info_), +    options_count_ (1), +    i_ (1), +    skip_ (false) +  { +    option_info_.option = option_.c_str (); +    option_info_.search_func = 0; +  } + +  inline argv_file_scanner:: +  argv_file_scanner (int start, +                     int& argc, +                     char** argv, +                     const std::string& option, +                     bool erase, +                     std::size_t sp) +  : argv_scanner (start, argc, argv, erase, sp), +    option_ (option), +    options_ (&option_info_), +    options_count_ (1), +    i_ (1), +    skip_ (false) +  { +    option_info_.option = option_.c_str (); +    option_info_.search_func = 0; +  } + +  inline argv_file_scanner:: +  argv_file_scanner (const std::string& file, +                     const std::string& option, +                     std::size_t sp) +  : argv_scanner (0, zero_argc_, 0, sp), +    option_ (option), +    options_ (&option_info_), +    options_count_ (1), +    i_ (1), +    skip_ (false) +  { +    option_info_.option = option_.c_str (); +    option_info_.search_func = 0; + +    load (file); +  } + +  inline argv_file_scanner:: +  argv_file_scanner (int& argc, +                     char** argv, +                     const option_info* options, +                     std::size_t options_count, +                     bool erase, +                     std::size_t sp) +  : argv_scanner (argc, argv, erase, sp), +    options_ (options), +    options_count_ (options_count), +    i_ (1), +    skip_ (false) +  { +  } + +  inline argv_file_scanner:: +  argv_file_scanner (int start, +                     int& argc, +                     char** argv, +                     const option_info* options, +                     std::size_t options_count, +                     bool erase, +                     std::size_t sp) +  : argv_scanner (start, argc, argv, erase, sp), +    options_ (options), +    options_count_ (options_count), +    i_ (1), +    skip_ (false) +  { +  } + +  inline argv_file_scanner:: +  argv_file_scanner (const std::string& file, +                     const option_info* options, +                     std::size_t options_count, +                     std::size_t sp) +  : argv_scanner (0, zero_argc_, 0, sp), +    options_ (options), +    options_count_ (options_count), +    i_ (1), +    skip_ (false) +  { +    load (file); +  } +} + +// help_options +// + +inline const std::uint64_t& help_options:: +build2_metadata () const +{ +  return this->build2_metadata_; +} + +inline bool help_options:: +build2_metadata_specified () const +{ +  return this->build2_metadata_specified_; +} + +inline const bool& help_options:: +help () const +{ +  return this->help_; +} + +inline const bool& help_options:: +version () const +{ +  return this->version_; +} + +inline const bool& help_options:: +proprietary_license () const +{ +  return this->proprietary_license_; +} + +// options +// + +inline const NarrowStrings& options:: +disable_warning () const +{ +  return this->disable_warning_; +} + +inline bool options:: +disable_warning_specified () const +{ +  return this->disable_warning_specified_; +} + +inline const std::string& options:: +options_file () const +{ +  return this->options_file_; +} + +inline bool options:: +options_file_specified () const +{ +  return this->options_file_specified_; +} + +inline const bool& options:: +show_sloc () const +{ +  return this->show_sloc_; +} + +inline const std::size_t& options:: +sloc_limit () const +{ +  return this->sloc_limit_; +} + +inline bool options:: +sloc_limit_specified () const +{ +  return this->sloc_limit_specified_; +} + +inline const bool& options:: +proprietary_license () const +{ +  return this->proprietary_license_; +} + +inline const NarrowString& options:: +custom_literals () const +{ +  return this->custom_literals_; +} + +inline bool options:: +custom_literals_specified () const +{ +  return this->custom_literals_specified_; +} + +inline const bool& options:: +preserve_anonymous () const +{ +  return this->preserve_anonymous_; +} + +inline const bool& options:: +show_anonymous () const +{ +  return this->show_anonymous_; +} + +inline const NarrowStrings& options:: +anonymous_regex () const +{ +  return this->anonymous_regex_; +} + +inline bool options:: +anonymous_regex_specified () const +{ +  return this->anonymous_regex_specified_; +} + +inline const bool& options:: +anonymous_regex_trace () const +{ +  return this->anonymous_regex_trace_; +} + +inline const bool& options:: +morph_anonymous () const +{ +  return this->morph_anonymous_; +} + +inline const NarrowStrings& options:: +location_map () const +{ +  return this->location_map_; +} + +inline bool options:: +location_map_specified () const +{ +  return this->location_map_specified_; +} + +inline const NarrowStrings& options:: +location_regex () const +{ +  return this->location_regex_; +} + +inline bool options:: +location_regex_specified () const +{ +  return this->location_regex_specified_; +} + +inline const bool& options:: +location_regex_trace () const +{ +  return this->location_regex_trace_; +} + +inline const bool& options:: +file_per_type () const +{ +  return this->file_per_type_; +} + +inline const NarrowStrings& options:: +type_file_regex () const +{ +  return this->type_file_regex_; +} + +inline bool options:: +type_file_regex_specified () const +{ +  return this->type_file_regex_specified_; +} + +inline const bool& options:: +type_file_regex_trace () const +{ +  return this->type_file_regex_trace_; +} + +inline const NarrowStrings& options:: +schema_file_regex () const +{ +  return this->schema_file_regex_; +} + +inline bool options:: +schema_file_regex_specified () const +{ +  return this->schema_file_regex_specified_; +} + +inline const bool& options:: +schema_file_regex_trace () const +{ +  return this->schema_file_regex_trace_; +} + +inline const bool& options:: +fat_type_file () const +{ +  return this->fat_type_file_; +} + +inline const NarrowString& options:: +file_list () const +{ +  return this->file_list_; +} + +inline bool options:: +file_list_specified () const +{ +  return this->file_list_specified_; +} + +inline const bool& options:: +file_list_only () const +{ +  return this->file_list_only_; +} + +inline const NarrowString& options:: +file_list_prologue () const +{ +  return this->file_list_prologue_; +} + +inline bool options:: +file_list_prologue_specified () const +{ +  return this->file_list_prologue_specified_; +} + +inline const NarrowString& options:: +file_list_epilogue () const +{ +  return this->file_list_epilogue_; +} + +inline bool options:: +file_list_epilogue_specified () const +{ +  return this->file_list_epilogue_specified_; +} + +inline const NarrowString& options:: +file_list_delim () const +{ +  return this->file_list_delim_; +} + +inline bool options:: +file_list_delim_specified () const +{ +  return this->file_list_delim_specified_; +} + +inline const bool& options:: +disable_multi_import () const +{ +  return this->disable_multi_import_; +} + +inline const bool& options:: +disable_full_check () const +{ +  return this->disable_full_check_; +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/xsd/processing/cardinality/processor.cxx b/xsd/processing/cardinality/processor.cxx new file mode 100644 index 0000000..c8c5dc5 --- /dev/null +++ b/xsd/processing/cardinality/processor.cxx @@ -0,0 +1,407 @@ +// file      : xsd/processing/cardinality/processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <map> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/elements.hxx> + +#include <xsd/processing/cardinality/processor.hxx> + +using namespace std; + +namespace Processing +{ +  namespace SemanticGraph = XSDFrontend::SemanticGraph; +  namespace Traversal = XSDFrontend::Traversal; + +  namespace Cardinality +  { +    namespace +    { +      // +      // +      struct ElementInfo +      { +        ElementInfo () +            : min (0), max (0), e_ (0) +        { +        } + +        ElementInfo (SemanticGraph::Element& e) +            : min (1), max (1), e_ (&e) +        { +        } + +        ElementInfo (SemanticGraph::Element& e, size_t min_, size_t max_) +            : min (min_), max (max_), e_ (&e) +        { +        } + +        SemanticGraph::Element& +        element () +        { +          assert (e_ != 0); +          return *e_; +        } + +      public: +        size_t min, max; + +      private: +        SemanticGraph::Element* e_; +      }; + +      typedef map<String, ElementInfo> ElementInfoMap; + +      // +      // +      struct AnyInfo +      { +        AnyInfo () +            : min (0), max (0), a_ (0) +        { +        } + +        AnyInfo (SemanticGraph::Any& a) +            : min (1), max (1), a_ (&a) +        { +        } + +        AnyInfo (SemanticGraph::Any& a, size_t min_, size_t max_) +            : min (min_), max (max_), a_ (&a) +        { +        } + +        SemanticGraph::Any& +        any () +        { +          assert (a_ != 0); +          return *a_; +        } + +      public: +        size_t min, max; + +      private: +        SemanticGraph::Any* a_; +      }; + +      typedef map<String, AnyInfo> AnyInfoMap; + +      // +      // +      struct Particle: Traversal::All, +                       Traversal::Choice, +                       Traversal::Sequence, +                       Traversal::Element, +                       Traversal::Any +      { +        virtual void +        traverse (SemanticGraph::All& a) +        { +          traverse_sequence (a); +        } + +        virtual void +        traverse (SemanticGraph::Choice& c) +        { +          using SemanticGraph::Compositor; + +          // Go over all particles we contain and add them to the map. +          // +          for (Compositor::ContainsIterator ci (c.contains_begin ()); +               ci != c.contains_end (); ++ci) +          { +            Particle t; +            t.dispatch (ci->particle ()); + +            // Handle elements. +            // +            if (ci == c.contains_begin ()) +              el_map = t.el_map; // First arm. +            else +            { +              // For elements that are in the map but not in this +              // arm of choice, we need to set min to 0 while for +              // those that are we need to choose minimum between +              // the two for min and maximum for max. +              // +              for (ElementInfoMap::iterator i (el_map.begin ()); +                   i != el_map.end (); ++i) +              { +                String const& name (i->first); +                ElementInfo& ei (i->second); + +                ElementInfoMap::iterator j (t.el_map.find (name)); + +                if (j == t.el_map.end ()) +                  ei.min = 0; +                else +                { +                  ei.min = j->second.min < ei.min ? j->second.min : ei.min; + +                  // Unbounded is encoded as 0. +                  // +                  if (j->second.max == 0 || ei.max == 0) +                    ei.max = 0; +                  else +                    ei.max = j->second.max > ei.max ? j->second.max : ei.max; +                } +              } + +              // Now elements that are in this arm of choice but are +              // not in the map, we need to add to the map and set their +              // min to 0. +              // +              for (ElementInfoMap::iterator i (t.el_map.begin ()); +                   i != t.el_map.end (); ++i) +              { +                String const& name (i->first); +                ElementInfo& ei (i->second); + +                ElementInfoMap::iterator j (el_map.find (name)); + +                if (j == el_map.end ()) +                  el_map[name] = ElementInfo (ei.element (), 0, ei.max); +              } +            } + +            // Handle wildcards. Since each wildcard is treated as unique, +            // we need to copy them from each arm of choice and set min to +            // 0. +            // +            for (AnyInfoMap::iterator i (t.any_map.begin ()); +                 i != t.any_map.end (); ++i) +            { +              String const& name (i->first); +              AnyInfo& ai (i->second); + +              assert (any_map.find (name) == any_map.end ()); + +              any_map[name] = AnyInfo (ai.any (), 0, ai.max); +            } +          } + +          // Choice's min and max. +          // +          size_t cmin (c.min ()), cmax (c.max ()); + +          // Iterate over elements and wildcards in the maps and multiply +          // their cardinality by cmin and cmax. +          // +          for (ElementInfoMap::iterator i (el_map.begin ()); +               i != el_map.end (); ++i) +          { +            i->second.min *= cmin; +            i->second.max *= cmax; +          } + +          for (AnyInfoMap::iterator i (any_map.begin ()); +               i != any_map.end (); ++i) +          { +            i->second.min *= cmin; // Not really necessary since min == 0. +            i->second.max *= cmax; +          } +        } + +        virtual void +        traverse (SemanticGraph::Sequence& s) +        { +          traverse_sequence (s); +        } + +        void +        traverse_sequence (SemanticGraph::Compositor& c) +        { +          using SemanticGraph::Compositor; + +          // Sequence's min and max. +          // +          size_t smin (c.min ()), smax (c.max ()); + +          // Go over all particles we contain and add them to the map. +          // +          for (Compositor::ContainsIterator ci (c.contains_begin ()); +               ci != c.contains_end (); ++ci) +          { +            Particle t; +            t.dispatch (ci->particle ()); + +            // Handle elements. +            // +            for (ElementInfoMap::iterator i (t.el_map.begin ()); +                 i != t.el_map.end (); ++i) +            { +              String const& name (i->first); +              ElementInfo& ei (i->second); +              size_t min (ei.min * smin); +              size_t max (ei.max * smax); +              ElementInfoMap::iterator j (el_map.find (name)); + +              if (j != el_map.end ()) +              { +                // Add i's cardinality to j +                // +                j->second.min += min; +                j->second.max = (j->second.max == 0 || max == 0) ? +                  0 : (j->second.max + max); +              } +              else +                el_map[name] = ElementInfo (ei.element (), min, max); +            } + +            // Handle wildcards. +            // +            for (AnyInfoMap::iterator i (t.any_map.begin ()); +                 i != t.any_map.end (); ++i) +            { +              String const& name (i->first); +              AnyInfo& ai (i->second); +              size_t min (ai.min * smin); +              size_t max (ai.max * smax); + +              assert (any_map.find (name) == any_map.end ()); + +              any_map[name] = AnyInfo (ai.any (), min, max); +            } +          } +        } + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          SemanticGraph::ContainsParticle& cp (e.contained_particle ()); + +          String name (e.qualified_p () +                       ? e.namespace_ ().name () + L" " + e.name () +                       : e.name ()); + +          el_map[name] = ElementInfo (e, cp.min (), cp.max ()); +        } + +        virtual void +        traverse (SemanticGraph::Any& a) +        { +          SemanticGraph::ContainsParticle& cp (a.contained_particle ()); + +          any_map[a.name ()] = AnyInfo (a, cp.min (), cp.max ()); +        } + +      public: +        AnyInfoMap any_map; +        ElementInfoMap el_map; +      }; + + +      // +      // +      struct Complex: Traversal::Complex +      { +        virtual void +        traverse (Type& c) +        { +          if (c.contains_compositor_p ()) +          { +            Particle t; +            t.dispatch (c.contains_compositor ().compositor ()); + +            for (ElementInfoMap::iterator i (t.el_map.begin ()); +                 i != t.el_map.end (); ++i) +            { +              ElementInfo& ei (i->second); +              SemanticGraph::Context& ctx (ei.element ().context ()); + +              ctx.set ("min", ei.min); +              ctx.set ("max", ei.max); +            } + +            for (AnyInfoMap::iterator i (t.any_map.begin ()); +                 i != t.any_map.end (); ++i) +            { +              AnyInfo& ai (i->second); +              SemanticGraph::Context& ctx (ai.any ().context ()); + +              ctx.set ("min", ai.min); +              ctx.set ("max", ai.max); +            } +          } + +          // Traverse attributes and anonymous types (via elements). +          // +          Complex::names (c); +        } +      }; + + +      // +      // +      struct Attribute: Traversal::Attribute +      { +        virtual void +        traverse (Type& a) +        { +          SemanticGraph::Context& ctx (a.context ()); + +          ctx.set ("min", size_t (a.optional_p () ? 0 : 1)); +          ctx.set ("max", size_t (1)); +        } +      }; + +      // Go into implied/included/imported schemas while making sure +      // we don't process the same stuff more than once. +      // +      struct Uses: Traversal::Uses +      { +        virtual void +        traverse (Type& u) +        { +          SemanticGraph::Schema& s (u.schema ()); + +          if (!s.context ().count ("processing-cardinality-seen")) +          { +            s.context ().set ("processing-cardinality-seen", true); +            Traversal::Uses::traverse (u); +          } +        } +      }; +    } + +    void Processor:: +    process (SemanticGraph::Schema& tu, SemanticGraph::Path const&) +    { +      Traversal::Schema schema; +      Uses uses; + +      schema >> uses >> schema; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; + +      schema >> schema_names >> ns >> ns_names; + +      Complex complex_type; +      AnonymousBase anonymous (complex_type); + +      ns_names >> complex_type; +      ns_names >> anonymous; + +      Attribute attribute; +      Traversal::Names names; + +      complex_type >> names; + +      names >> attribute; +      names >> anonymous; + +      // Some twisted schemas do recusive inclusions. +      // +      tu.context ().set ("processing-cardinality-seen", true); + +      schema.dispatch (tu); +    } +  } +} diff --git a/xsd/processing/cardinality/processor.hxx b/xsd/processing/cardinality/processor.hxx new file mode 100644 index 0000000..93a85fb --- /dev/null +++ b/xsd/processing/cardinality/processor.hxx @@ -0,0 +1,28 @@ +// file      : xsd/processing/cardinality/processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_PROCESSING_CARDINALITY_PROCESSOR_HXX +#define XSD_PROCESSING_CARDINALITY_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph/elements.hxx> // Path +#include <libxsd-frontend/semantic-graph/schema.hxx> + +#include <xsd/types.hxx> + +namespace Processing +{ +  namespace Cardinality +  { +    class Processor +    { +    public: +      struct Failed {}; + +      void +      process (XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file); +    }; +  } +} + +#endif // XSD_PROCESSING_CARDINALITY_PROCESSOR_HXX diff --git a/xsd/processing/inheritance/processor.cxx b/xsd/processing/inheritance/processor.cxx new file mode 100644 index 0000000..6c0e40e --- /dev/null +++ b/xsd/processing/inheritance/processor.cxx @@ -0,0 +1,492 @@ +// file      : xsd/processing/inheritance/processor.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <iostream> + +#include <xsd/processing/inheritance/processor.hxx> + +#include <xsd/elements.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace Processing +{ +  namespace SemanticGraph = XSDFrontend::SemanticGraph; +  namespace Traversal = XSDFrontend::Traversal; + +  namespace Inheritance +  { +    namespace +    { +      struct Dep +      { +        Dep (SemanticGraph::Type& t, +             SemanticGraph::Member* m = 0, +             String const& xpath = L"") +            : type (t), member (m), member_xpath (xpath) +        { +        } + +        SemanticGraph::Type& type; +        SemanticGraph::Member* member; // Member if type is anonymous. +        String member_xpath; +      }; + +      inline bool +      operator< (Dep const& a, Dep const& b) +      { +        return &a.type < &b.type; +      } + +      typedef set<Dep> DepSet; +      typedef set<SemanticGraph::Type*> TypeSet; + +      String +      xpath (SemanticGraph::Nameable& n) +      { +        if (dynamic_cast<SemanticGraph::Namespace*> (&n) != 0) +          return L"<namespace-level>"; // There is a bug if you see this. + +        if (n.named_p ()) +        { +          SemanticGraph::Scope& scope (n.scope ()); + +          if (dynamic_cast<SemanticGraph::Namespace*> (&scope) != 0) +            return n.name (); + +          return xpath (scope) + L"/" + n.name (); +        } +        else +        { +          return L"(anonymous type for " + +            n.context ().get<String> ("instance-name") + L")"; +        } +      } + + +      // Calculate the list of dependencies for this complex +      // type. +      // +      struct ComplexType: Traversal::Complex, +                          Traversal::Member +      { +        ComplexType (DepSet& dep_set) +            : dep_set_ (dep_set), last_ (0) +        { +          *this >> names_ >> *this; +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          using SemanticGraph::Complex; + +          if (c.inherits_p ()) +            dep_set_.insert (Dep (c.inherits ().base (), last_, last_xpath_)); + +          types_seen_.insert (&c); + +          // Go after anonymous types. +          // +          names (c); +        } + +        virtual void +        traverse (SemanticGraph::Member& m) +        { +          SemanticGraph::Type& t (m.type ()); + +          if (!t.named_p () && types_seen_.find (&t) == types_seen_.end ()) +          { +            SemanticGraph::Context& ctx (t.context ()); + +            last_xpath_ = xpath (m); + +            String prev_xpath; + +            if (ctx.count ("instance-name")) +              prev_xpath = ctx.get<String> ("instance-name"); + +            ctx.set ("instance-name", last_xpath_); + +            last_ = &m; +            dispatch (t); + +            if (prev_xpath) +              ctx.set ("instance-name", prev_xpath); +            else +              ctx.remove ("instance-name"); +          } +        } + +      private: +        DepSet& dep_set_; +        TypeSet types_seen_; + +        SemanticGraph::Member* last_; +        String last_xpath_; + +        Traversal::Names names_; +      }; + + +      // +      // +      template <typename N, typename A> +      struct NodeArgs +      { +        NodeArgs (N& node, A arg) +            : node_ (node), arg_ (arg) +        { +        } + +        operator N& () const +        { +          return node_; +        } + +        template <typename E> +        void +        add_edge_left (E& e) +        { +          node_.add_edge_left (e, arg_); +        } + +        template <typename E> +        void +        add_edge_right (E& e) +        { +          node_.add_edge_right (e, arg_); +        } + +      private: +        N& node_; +        A arg_; +      }; + + +      // +      // +      struct Global: Traversal::Type, +                     Traversal::Complex, +                     Traversal::Element +      { +        Global (SemanticGraph::Schema& root, +                SemanticGraph::Schema& schema, +                bool& failed) +            : root_ (root), schema_ (schema), failed_ (failed) +        { +        } + +        virtual void +        traverse (SemanticGraph::Type& t) +        { +          if (t.named_p ()) +            types_seen_.insert (&t); +        } + +        virtual void +        traverse (SemanticGraph::Complex& c) +        { +          check_dep (c, c); +          types_seen_.insert (&c); +        }; + +        virtual void +        traverse (SemanticGraph::Element& e) +        { +          SemanticGraph::Type& t (e.type ()); + +          if (!t.named_p ()) +          { +            t.context ().set ("instance-name", xpath (e)); +            check_dep (e, t); +            t.context ().remove ("instance-name"); +          } +        }; + +      private: +        void +        check_dep (SemanticGraph::Nameable& global, +                   SemanticGraph::Type& type) +        { +          using SemanticGraph::Type; +          using SemanticGraph::Scope; +          using SemanticGraph::Names; +          using SemanticGraph::Schema; + +          DepSet prereqs; + +          // Calculate our prerequisistes. +          // +          { +            ComplexType complex (prereqs); +            complex.dispatch (type); +          } + +          for (DepSet::const_iterator i (prereqs.begin ()); +               i != prereqs.end (); ++i) +          { +            Dep const& dep (*i); +            Type& t (dep.type); + +            // Ignore IDREF templates. +            // +            if (!t.named_p () && +                (t.is_a<SemanticGraph::Fundamental::IdRef> () || +                 t.is_a<SemanticGraph::Fundamental::IdRefs> ())) +              continue; + +            // We won't be able to generate compilable code in case of a +            // dependency on ourselves (e.g., a member element with +            // anonymous type that inherits from us). +            // +            if (&t == &type) +            { +              assert (dep.member != 0); + +              SemanticGraph::Member& m (*dep.member); + +              wcerr << t.file () << ":" << t.line () << ":" << t.column () +                    << " error: nested anonymous type for '" +                    << dep.member_xpath << "' cyclicly inherits from '" +                    << t.name () << "'" << endl; + +              wcerr << t.file () << ":" << t.line () << ":" << t.column () +                    << " error: unable to generate valid code for such " +                    << "cyclic inheritance" << endl; + +              wcerr << m.file () << ":" << m.line () << ":" << m.column () +                    << " info: '" << m.name () << "' element is declared here" +                    << endl; + +              wcerr << t.file () << ":" << t.line () << ":" << t.column () +                    << ": info: consider explicitly naming this type " +                    << "or remove the --preserve-anonymous option" +                    << endl; + +              failed_ = true; +              continue; +            } + +            if (types_seen_.find (&t) == types_seen_.end ()) +            { +              Scope& scope (t.scope ()); +              Schema& schema (dynamic_cast<Schema&> (scope.scope ())); + +              // Don't worry about types that are in included/imported +              // schemas. +              // +              if (&schema != &schema_ && !sources_p (schema_, schema)) +                continue; + +              if (t.context ().count ("seen")) +              { +                wcerr << t.file () << ":" << t.line () << ":" << t.column () +                      << " error: nested anonymous type in '" << t.name () +                      << "' or '" << type.name () << "' inherits from one of " +                      << "these types and makes them mutually dependant" +                      << endl; + +                wcerr << t.file () << ":" << t.line () << ":" << t.column () +                      << " error: unable to generate valid code for such " +                      << "cyclic dependency" << endl; + +                wcerr << type.file () << ":" << type.line () << ":" +                      << type.column () << " info: '" << type.name () +                      << "' type is defined here" +                      << endl; + +                wcerr << t.file () << ":" << t.line () << ":" << t.column () +                      << ": info: consider explicitly naming the anonymous " +                      << "type or remove the --preserve-anonymous option" +                      << endl; + +                failed_ = true; +                continue; +              } + +              //wcerr << "type '" << t.name () << "' needs to be moved " << +              //  "before " << (global.is_a<Type> () ? "type" : "element") << +              //  " '" << global.name () << "'" << endl; + + +              // Delete current Names edge. +              // +              String name (t.name ()); +              { +                Names& n (t.named ()); +                root_.delete_edge (scope, t, n); +              } + +              // Insert a new Names edge before global. +              // +              { +                // t.scope () and global.scope () can be different in +                // case of the chameleon inclusion. +                // +                Scope& scope (global.scope ()); + +                // Convert to the insert-after call. +                // +                Scope::NamesIterator i (scope.find (global.named ())); + +                if (i == scope.names_begin ()) +                  i = scope.names_end (); +                else +                  --i; + +                NodeArgs<Scope, Scope::NamesIterator> na (scope, i); +                root_.new_edge<Names> (na, t, name); +              } + +              // Recursively process the moved type. +              // +              global.context ().set ("seen", true); +              dispatch (t); +              global.context ().remove ("seen"); +            } +          } +        } + +      private: +        // Return true if root sources s. +        // +        bool +        sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) +        { +          using SemanticGraph::Schema; +          using SemanticGraph::Sources; + +          for (Schema::UsesIterator i (root.uses_begin ()); +               i != root.uses_end (); ++i) +          { +            if (i->is_a<Sources> ()) +            { +              if (&i->schema () == &s || sources_p (i->schema (), s)) +                return true; +            } +          } + +          return false; +        } + +      private: +        SemanticGraph::Schema& root_; +        SemanticGraph::Schema& schema_; +        TypeSet types_seen_; +        bool& failed_; +      }; + + +      // Sources traverser that goes into each schema only once. +      // +      struct Sources: Traversal::Sources +      { +        virtual void +        traverse (SemanticGraph::Sources& s) +        { +          if (schemas_.insert (&s.schema ()).second) +            Traversal::Sources::traverse (s); +        } + +      private: +        set<SemanticGraph::Schema*> schemas_; +      }; + +      // Go into included/imported schemas while making sure we don't +      // process the same stuff more than once. +      // +      struct Uses: Traversal::Includes, Traversal::Imports +      { +        Uses (SemanticGraph::Schema& root, bool& failed) +            : root_ (root), failed_ (failed) +        { +        } + +        virtual void +        traverse (SemanticGraph::Includes& i) +        { +          traverse (i.schema ()); +        } + +        virtual void +        traverse (SemanticGraph::Imports& i) +        { +          traverse (i.schema ()); +        } + +      private: +        void +        traverse (SemanticGraph::Schema& s) +        { +          if (!s.context ().count ("processing-inheritance-seen")) +          { +            Traversal::Schema schema; +            Sources sources; + +            schema >> sources >> schema; +            schema >> *this; + +            Traversal::Names schema_names; +            Traversal::Namespace ns; +            Traversal::Names ns_names; + +            schema >> schema_names >> ns >> ns_names; + +            Global global (root_, s, failed_); + +            ns_names >> global; + +            s.context ().set ("processing-inheritance-seen", true); +            schema.dispatch (s); +          } +        } + +      private: +        SemanticGraph::Schema& root_; +        bool& failed_; +      }; +    } + +    void Processor:: +    process (SemanticGraph::Schema& tu, SemanticGraph::Path const&) +    { +      bool failed (false); + +      // We need to process include/imported schemas since other +      // parts of the process, for example, name processors can +      // rely on the order of types in the schema. +      // +      Traversal::Schema schema; +      Sources sources; +      Uses uses (tu, failed); + +      schema >> sources >> schema; +      schema >> uses; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; + +      schema >> schema_names >> ns >> ns_names; + +      Global global (tu, tu, failed); + +      ns_names >> global; + +      // Some twisted schemas do recusive self-inclusion. +      // +      tu.context ().set ("processing-inheritance-seen", true); + +      schema.dispatch (tu); + +      if (failed) +        throw Failed (); +    } +  } +} diff --git a/xsd/processing/inheritance/processor.hxx b/xsd/processing/inheritance/processor.hxx new file mode 100644 index 0000000..2a70e02 --- /dev/null +++ b/xsd/processing/inheritance/processor.hxx @@ -0,0 +1,28 @@ +// file      : xsd/processing/inheritance/processor.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_PROCESSING_INHERITANCE_PROCESSOR_HXX +#define XSD_PROCESSING_INHERITANCE_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph/elements.hxx> // Path +#include <libxsd-frontend/semantic-graph/schema.hxx> + +#include <xsd/types.hxx> + +namespace Processing +{ +  namespace Inheritance +  { +    class Processor +    { +    public: +      struct Failed {}; + +      void +      process (XSDFrontend::SemanticGraph::Schema&, +               XSDFrontend::SemanticGraph::Path const& file); +    }; +  } +} + +#endif // XSD_PROCESSING_INHERITANCE_PROCESSOR_HXX diff --git a/xsd/type-map/lexer.cxx b/xsd/type-map/lexer.cxx new file mode 100644 index 0000000..ae318d1 --- /dev/null +++ b/xsd/type-map/lexer.cxx @@ -0,0 +1,131 @@ +// file      : xsd/type-map/lexer.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <iostream> + +#include <xsd/type-map/lexer.hxx> + +using std::wcerr; +using std::endl; + +namespace TypeMap +{ +  Lexer::Lexer (std::istream& is, String const& path) +      : locale_ ("C"), is_ (is), path_ (path), line_ (1), comment_ (false) +  { +    is_.exceptions (std::ios_base::badbit); +  } + +  Lexer::Token Lexer:: +  next () +  { +    if (held_lexeme_) +    { +      Token t (Token::punct, held_lexeme_, line_); +      held_lexeme_.clear (); +      return t; +    } + +    typedef std::char_traits<char> Traits; +    typedef Traits::char_type CharType; +    typedef Traits::int_type IntType; + +    IntType i; +    CharType c ('\0'); +    NarrowString lexeme; + +    // Skip all whitespaces including comments. +    // +    while (!is_.eof ()) +    { +      i = is_.get (); + +      if (i == Traits::eof ()) +        break; + +      c = Traits::to_char_type (i); + +      if (comment_) +      { +        if (c == '\n') +          comment_ = false; +      } +      else +      { +        if (!(std::isspace (c, locale_) || c == '#')) +          break; + +        if (c == '#') +          comment_ = true; +      } + +      if (c == '\n') +        ++line_; +    } + +    if (is_.eof ()) +      return Token (Token::eos, L"<end-of-stream>", line_); + +    bool quote (c == '"'); + +    if (!quote) +      lexeme += c; + +    if (c != ';' && c != '{' && c != '}') +    { +      // Accumulate non-whitespace character sequence. +      // + +      while (!is_.eof ()) +      { +        i = is_.get (); + +        if (i == Traits::eof ()) +          break; + +        c = Traits::to_char_type (i); + +        if (!quote && c == '#') +        { +          comment_ = true; +          break; +        } + +        if (std::isspace (c, locale_)) +        { +          if (c == '\n') +            ++line_; + +          if (!quote) +            break; +        } + +        if (!quote && (c == ';' || c == '{' || c == '}')) +        { +          held_lexeme_ += c; +          break; +        } + +        if (quote && c == '"') +          break; + +        lexeme += c; +      } + +      if (quote && c != '"') +      { +        wcerr << path_ << ":" << line_ << ": error: closing '\"' expected" +              << endl; + +        throw Failed (); +      } +    } + +    if (!quote && (lexeme == ";" || lexeme == "{" || lexeme == "}")) +    { +      return Token (Token::punct, lexeme, line_); +    } +    else +      return Token (Token::token, lexeme, line_); +  } +} diff --git a/xsd/type-map/lexer.hxx b/xsd/type-map/lexer.hxx new file mode 100644 index 0000000..a0e1e44 --- /dev/null +++ b/xsd/type-map/lexer.hxx @@ -0,0 +1,74 @@ +// file      : xsd/type-map/lexer.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_TYPE_MAP_LEXER_HXX +#define XSD_TYPE_MAP_LEXER_HXX + +#include <locale> +#include <iosfwd> + +#include <xsd/types.hxx> + +namespace TypeMap +{ +  class Lexer +  { +  public: +    class Token +    { +    public: +      enum Type +      { +        token, +        punct, +        eos +      }; + +      Token (Type type, String const& lexeme, size_t line) +          : type_ (type), lexeme_ (lexeme), line_ (line) +      { +      } + +      Type +      type () const +      { +        return type_; +      } + +      String const& +      lexeme () const +      { +        return lexeme_; +      } + +      size_t +      line () const +      { +        return line_; +      } + +    private: +      Type type_; +      String lexeme_; +      size_t line_; +    }; + +    Lexer (std::istream&, String const& path); + +    struct Failed {}; + +    Token +    next (); + +  private: +    std::locale locale_; +    std::istream& is_; +    String path_; +    size_t line_; +    String held_lexeme_; +    bool comment_; +  }; + +} + +#endif // XSD_TYPE_MAP_LEXER_HXX diff --git a/xsd/type-map/parser.cxx b/xsd/type-map/parser.cxx new file mode 100644 index 0000000..f11fac3 --- /dev/null +++ b/xsd/type-map/parser.cxx @@ -0,0 +1,279 @@ +// file      : xsd/type-map/parser.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <iostream> + +#include <libcutl/re.hxx> + +#include <xsd/type-map/parser.hxx> + +using std::endl; + +namespace TypeMap +{ +  typedef Lexer::Token Token; +  typedef cutl::re::wformat Format; + +  Parser::Parser (Lexer& lex, String const& path) +      : lex_ (lex), path_ (path), e (std::wcerr) +  { +  } + +  bool Parser:: +  parse (Namespaces& ns) +  { +    try +    { +      Namespace* global = 0; + +      for (Token t (lex_.next ()); t.type () != Token::eos; t = lex_.next ()) +      { +        String l (t.lexeme ()); + +        if (l == L"namespace") +        { +          global = 0; + +          if (!namespace_ (ns)) +            return false; +        } +        else if (l == L"include") +        { +          if (global == 0) +          { +            ns.push_back (Namespace (Pattern ())); +            global = &(*ns.rbegin ()); +          } + +          if (!include (*global)) +            return false; +        } +        else if (l == L"type" || t.type () == Token::token) +        { +          // Type mapping can have 'type' specifier omitted. +          // +          if (l == L"type") +            t = lex_.next (); + +          if (global == 0) +          { +            ns.push_back (Namespace (Pattern ())); +            global = &(*ns.rbegin ()); +          } + +          if (!type (t, *global)) +            return false; +        } +        else +        { +          e << path_ << ":" << t.line () << ": unexpected '" << l << "'" +            << endl; + +          return false; +        } +      } +    } +    catch (Lexer::Failed const&) +    { +      return false; +    } + +    return true; +  } + +  bool Parser:: +  namespace_ (Namespaces& ns) +  { +    // First get XML namespace. +    // +    Token t (lex_.next ()); + +    Pattern xsd_name; + +    try +    { +      xsd_name = t.lexeme (); +    } +    catch (Format const& ex) +    { +      e << path_ << ":" << t.line () << ": invalid namespace pattern: " +        << ex.description ().c_str () << endl; +      return false; +    } + +    if (t.type () != Token::token) +    { +      e << path_ << ":" << t.line () << ": expected XML namespace " +        << "instead of '" << xsd_name << "'" << endl; +      return false; +    } + + +    // See if we've got optional C++ mapping. +    // +    t = lex_.next (); + +    bool has_cxx_name (false); +    String cxx_name; + +    if (t.type () != Token::token) +    { +      if (t.lexeme () != L"{") +      { +        e << path_ << ":" << t.line () << ": expected C++ namespace or '{' " +          << "instead of '" << t.lexeme () << "'" << endl; +        return false; +      } +    } +    else +    { +      has_cxx_name = true; +      cxx_name = t.lexeme (); +    } + +    // Swallow '{' if needed. +    // +    if (has_cxx_name) +    { +      t = lex_.next (); + +      if (t.type () != Token::punct || t.lexeme () != L"{") +      { +        e << path_ << ":" << t.line () << ": expected '{' instead of '" +          << t.lexeme () << "'" << endl; +        return false; +      } +    } + +    Namespace n (xsd_name, has_cxx_name, cxx_name); + +    // Parse namespace body. +    // +    for (t = lex_.next ();; t = lex_.next ()) +    { +      String l (t.lexeme ()); + +      if (l == L"include") +      { +        if (!include (n)) +          return false; +      } +      else if (l == L"type" || t.type () == Token::token) +      { +        // Type mapping can have 'type' specifier omitted. +        // +        if (l == L"type") +          t = lex_.next (); + +        if (!type (t, n)) +          return false; +      } +      else if (t.type () == Token::punct && l == L"}") +      { +        break; +      } +      else +      { +        e << path_ << ":" << t.line () << ": unexpected '" << l << "'" +          << endl; +        return false; +      } +    } + +    if (cxx_name || n.types_begin () != n.types_end () || +        n.includes_begin () != n.includes_end ()) +    { +      ns.push_back (n); +    } + +    return true; +  } + +  bool Parser:: +  include (Namespace& n) +  { +    Token t (lex_.next ()); + +    String path (t.lexeme ()); + +    if (t.type () != Token::token) +    { +      e << path_ << ":" << t.line () << ": expected include path " +        << "instead of '" << path << "'" << endl; +      return false; +    } + +    if (path && path[0] == L'<') +      n.includes_push_back (path); +    else +      n.includes_push_back (L'"' + path + L'"'); + +    t = lex_.next (); + +    if (t.type () != Token::punct || t.lexeme () != L";") +    { +      e << path_ << ":" << t.line () << ": expected ';' after '" +        << path << "'" << endl; +      return false; +    } + +    return true; +  } + +  bool Parser:: +  type (Token t, Namespace& n) +  { +    Pattern xsd_name; + +    try +    { +      xsd_name = t.lexeme (); +    } +    catch (Format const& ex) +    { +      e << path_ << ":" << t.line () << ": invalid namespace pattern: " +        << ex.description ().c_str () << endl; +      return false; +    } + +    if (t.type () != Token::token) +    { +      e << path_ << ":" << t.line () << ": expected XML Schema type name " +        << "instead of '" << xsd_name << "'" << endl; +      return false; +    } + +    t = lex_.next (); +    String cxx_ret_name (t.lexeme ()); + +    if (t.type () != Token::token) +    { +      e << path_ << ":" << t.line () << ": expected C++ type name " +        << "instead of '" << cxx_ret_name << "'" << endl; +      return false; +    } + +    t = lex_.next (); + +    String cxx_arg_name; + +    // See if we've got optional argument type. +    // +    if (t.type () == Token::token) +    { +      cxx_arg_name = t.lexeme (); +      t = lex_.next (); +    } + +    if (t.type () != Token::punct || t.lexeme () != L";") +    { +      e << path_ << ":" << t.line () << ": expected ';' after '" +        << cxx_arg_name << "'" << endl; +      return false; +    } + +    n.types_push_back (xsd_name, cxx_ret_name, cxx_arg_name); + +    return true; +  } +} diff --git a/xsd/type-map/parser.hxx b/xsd/type-map/parser.hxx new file mode 100644 index 0000000..ec9ea49 --- /dev/null +++ b/xsd/type-map/parser.hxx @@ -0,0 +1,41 @@ +// file      : xsd/type-map/parser.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_TYPE_MAP_PARSER_HXX +#define XSD_TYPE_MAP_PARSER_HXX + +#include <xsd/types.hxx> + +#include <xsd/type-map/type-map.hxx> +#include <xsd/type-map/lexer.hxx> + +namespace TypeMap +{ +  class Parser +  { +  public: +    Parser (Lexer&, String const& path); + +    // Merge parsed namespaces. +    // +    bool +    parse (Namespaces&); + +  private: +    bool +    namespace_ (Namespaces&); + +    bool +    include (Namespace&); + +    bool +    type (Lexer::Token, Namespace&); + +  private: +    Lexer& lex_; +    String path_; +    std::wostream& e; +  }; +} + +#endif // XSD_TYPE_MAP_PARSER_HXX diff --git a/xsd/type-map/type-map.hxx b/xsd/type-map/type-map.hxx new file mode 100644 index 0000000..dd2ec2c --- /dev/null +++ b/xsd/type-map/type-map.hxx @@ -0,0 +1,178 @@ +// file      : xsd/type-map/type-map.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_XSD_TYPE_MAP_TYPE_MAP_HXX +#define XSD_XSD_TYPE_MAP_TYPE_MAP_HXX + +#include <vector> + +#include <libcutl/re.hxx> + +#include <xsd/types.hxx> + +namespace TypeMap +{ +  typedef cutl::re::wregex Pattern; + +  class Type +  { +  public: +    Type (String const& xsd_name, +          String const& cxx_ret_name, +          String const& cxx_arg_name) +        : xsd_name_ (xsd_name), +          cxx_ret_name_ (cxx_ret_name), +          cxx_arg_name_ (cxx_arg_name) +    { +    } + +    Type (Pattern const& xsd_name, +          String const& cxx_ret_name, +          String const& cxx_arg_name) +        : xsd_name_ (xsd_name), +          cxx_ret_name_ (cxx_ret_name), +          cxx_arg_name_ (cxx_arg_name) +    { +    } + +    Pattern const& +    xsd_name () const +    { +      return xsd_name_; +    } + +    String const& +    cxx_ret_name () const +    { +      return cxx_ret_name_; +    } + +    String const& +    cxx_arg_name () const +    { +      return cxx_arg_name_; +    } + +  private: +    Pattern xsd_name_; +    String cxx_ret_name_; +    String cxx_arg_name_; +  }; + +  class Namespace +  { +  public: +    Namespace (String const& xsd_name) +        : xsd_name_ (xsd_name), has_cxx_name_ (false) +    { +    } + +    Namespace (Pattern const& xsd_name) +        : xsd_name_ (xsd_name), has_cxx_name_ (false) +    { +    } + +    Namespace (Pattern const& xsd_name, String const& cxx_name) +        : xsd_name_ (xsd_name), has_cxx_name_ (true), cxx_name_ (cxx_name) +    { +    } + +    Namespace (Pattern const& xsd_name, +               bool has_cxx_name, +               String const& cxx_name) +        : xsd_name_ (xsd_name), +          has_cxx_name_ (has_cxx_name), +          cxx_name_ (cxx_name) +    { +    } + +    // +    // +    typedef std::vector<String> Includes; +    typedef Includes::const_iterator IncludesIterator; + +    IncludesIterator +    includes_begin () const +    { +      return includes_.begin (); +    } + +    IncludesIterator +    includes_end () const +    { +      return includes_.end (); +    } + +    void +    includes_push_back (String const& i) +    { +      includes_.push_back (i); +    } + +    // +    // +    typedef std::vector<Type> Types; +    typedef Types::const_iterator TypesIterator; + +    TypesIterator +    types_begin () const +    { +      return types_.begin (); +    } + +    TypesIterator +    types_end () const +    { +      return types_.end (); +    } + +    void +    types_push_back (String const& xsd_type, +                     String const& cxx_ret_type, +                     String const& cxx_arg_type = L"") +    { +      types_.push_back (Type (xsd_type, cxx_ret_type, cxx_arg_type)); +    } + +    void +    types_push_back (Pattern const& xsd_type, +                     String const& cxx_ret_type, +                     String const& cxx_arg_type = L"") +    { +      types_.push_back (Type (xsd_type, cxx_ret_type, cxx_arg_type)); +    } + +    // +    // +    Pattern const& +    xsd_name () const +    { +      return xsd_name_; +    } + +    // +    // +    bool +    has_cxx_name () const +    { +      return has_cxx_name_; +    } + +    String const& +    cxx_name () const +    { +      return cxx_name_; +    } + +  private: +    Includes includes_; +    Types types_; +    Pattern xsd_name_; +    bool has_cxx_name_; +    String cxx_name_; +  }; + +  typedef std::vector<Namespace> Namespaces; +} + +#endif // XSD_XSD_TYPE_MAP_TYPE_MAP_HXX diff --git a/xsd/types.hxx b/xsd/types.hxx new file mode 100644 index 0000000..b3306dd --- /dev/null +++ b/xsd/types.hxx @@ -0,0 +1,19 @@ +// file      : xsd/types.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_TYPES_HXX +#define XSD_TYPES_HXX + +#include <vector> +#include <cstddef> // std::size_t + +#include <libxsd-frontend/types.hxx> + +using std::size_t; + +using XSDFrontend::String; +using XSDFrontend::NarrowString; + +typedef std::vector<NarrowString> NarrowStrings; + +#endif // XSD_TYPES_HXX diff --git a/xsd/version.hxx.in b/xsd/version.hxx.in new file mode 100644 index 0000000..9bfd8a8 --- /dev/null +++ b/xsd/version.hxx.in @@ -0,0 +1,55 @@ +// file      : xsd/version.hxx.in +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_VERSION // Note: using the version macro itself. + +// The numeric version format is AAAAABBBBBCCCCCDDDE where: +// +// AAAAA - major version number +// BBBBB - minor version number +// CCCCC - bugfix version number +// DDD   - alpha / beta (DDD + 500) version number +// E     - final (0) / snapshot (1) +// +// When DDDE is not 0, 1 is subtracted from AAAAABBBBBCCCCC. For example: +// +// Version      AAAAABBBBBCCCCCDDDE +// +// 0.1.0        0000000001000000000 +// 0.1.2        0000000001000020000 +// 1.2.3        0000100002000030000 +// 2.2.0-a.1    0000200001999990010 +// 3.0.0-b.2    0000299999999995020 +// 2.2.0-a.1.z  0000200001999990011 +// +#define XSD_VERSION       $xsd.version.project_number$ULL +#define XSD_VERSION_STR   "$xsd.version.project$" +#define XSD_VERSION_ID    "$xsd.version.project_id$" +#define XSD_VERSION_FULL  "$xsd.version$" + +#define XSD_VERSION_MAJOR $xsd.version.major$ +#define XSD_VERSION_MINOR $xsd.version.minor$ +#define XSD_VERSION_PATCH $xsd.version.patch$ + +#define XSD_PRE_RELEASE   $xsd.version.pre_release$ + +#define XSD_SNAPSHOT      $xsd.version.snapshot_sn$ULL +#define XSD_SNAPSHOT_ID   "$xsd.version.snapshot_id$" + +#include <xercesc/util/XercesVersion.hpp> + +// Check that we have a compatible Xerces version (3.0.0 or later). +// +#if _XERCES_VERSION < 30000 +#  error Xerces-C++ 2-series is not supported +#endif + +#include <libcutl/version.hxx> + +$libcutl.check(LIBCUTL_VERSION, LIBCUTL_SNAPSHOT)$ + +#include <libxsd-frontend/version.hxx> + +$libxsd_frontend.check(LIBXSD_FRONTEND_VERSION, LIBXSD_FRONTEND_SNAPSHOT)$ + +#endif // XSD_VERSION diff --git a/xsd/xsd.cxx b/xsd/xsd.cxx new file mode 100644 index 0000000..d2b0faf --- /dev/null +++ b/xsd/xsd.cxx @@ -0,0 +1,1157 @@ +// file      : xsd/xsd.cxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <map> +#include <vector> +#include <memory>  // std::unique_ptr +#include <cstddef> // std::size_t +#include <iostream> +#include <fstream> + +#include <xercesc/util/PlatformUtils.hpp> + +#include <libcutl/re.hxx> + +#include <libxsd-frontend/parser.hxx> +#include <libxsd-frontend/transformations/anonymous.hxx> +#include <libxsd-frontend/transformations/enum-synthesis.hxx> +#include <libxsd-frontend/transformations/restriction.hxx> +#include <libxsd-frontend/transformations/schema-per-type.hxx> +#include <libxsd-frontend/transformations/simplifier.hxx> + +#include <xsd/version.hxx> + +#include <xsd/cxx/tree/options.hxx> +#include <xsd/cxx/parser/options.hxx> + +#include <xsd/cxx/tree/generator.hxx> +#include <xsd/cxx/parser/generator.hxx> + +#include <xsd/processing/cardinality/processor.hxx> +#include <xsd/processing/inheritance/processor.hxx> + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> +#include <xsd/options.hxx> + +namespace SemanticGraph = XSDFrontend::SemanticGraph; +namespace Transformations = XSDFrontend::Transformations; + +using namespace std; + +// +// +struct LocationTranslator: XSDFrontend::LocationTranslator +{ +  struct Failed {}; + +  LocationTranslator (NarrowStrings const& map, +                      NarrowStrings const& regex, +                      bool trace); + +  virtual NarrowString +  translate (NarrowString const&); + +private: +  typedef map<NarrowString, NarrowString> Map; + +  typedef cutl::re::regexsub Regex; +  typedef cutl::re::format RegexFormat; +  typedef vector<Regex> RegexVector; + +  typedef map<NarrowString, NarrowString> Cache; + +  Map map_; +  RegexVector regex_; +  Cache cache_; +  bool trace_; +}; + +// +// +struct AnonymousNameTranslator: Transformations::AnonymousNameTranslator +{ +  struct Failed {}; + +  AnonymousNameTranslator (NarrowStrings const& regex, bool trace); + +  virtual String +  translate (String const& file, +             String const& ns, +             String const& name, +             String const& xpath); + +private: +  typedef cutl::re::wregexsub Regex; +  typedef cutl::re::wformat RegexFormat; +  typedef vector<Regex> RegexVector; + +  RegexVector regex_; +  bool trace_; + +}; + +// +// +struct SchemaPerTypeTranslator: Transformations::SchemaPerTypeTranslator +{ +  struct Failed {}; + +  SchemaPerTypeTranslator (NarrowStrings const& type_regex, +                           bool type_trace, +                           NarrowStrings const& schema_regex, +                           bool schema_trace); + +  virtual String +  translate_type (String const& ns, String const& name); + +  virtual NarrowString +  translate_schema (NarrowString const& file); + +private: +  typedef cutl::re::wregexsub TypeRegex; +  typedef cutl::re::wformat TypeRegexFormat; +  typedef vector<TypeRegex> TypeRegexVector; + +  TypeRegexVector type_regex_; +  bool type_trace_; + +  typedef cutl::re::regexsub SchemaRegex; +  typedef cutl::re::format SchemaRegexFormat; +  typedef vector<SchemaRegex> SchemaRegexVector; + +  SchemaRegexVector schema_regex_; +  bool schema_trace_; +}; + +// +// +struct XercesInitializer +{ +  XercesInitializer () +  { +    xercesc::XMLPlatformUtils::Initialize (); +  } + +  ~XercesInitializer () +  { +    xercesc::XMLPlatformUtils::Terminate (); +  } +}; + +// Expand the \n escape sequence. +// +void +expand_nl (NarrowString& s); + +int +main (int argc, char* argv[]) +{ +  wostream& e (wcerr); + +  try +  { +    cli::argv_file_scanner args (argc, argv, "--options-file"); +    help_options help_ops (args, cli::unknown_mode::stop); + +    // Handle --build2-metadata (see also buildfile). +    // +    if (help_ops.build2_metadata_specified ()) +    { +      wostream& o (wcout); + +      // Note that the export.metadata variable should be the first non- +      // blank/comment line. +      // +      o << "# build2 buildfile xsd" << endl +        << "export.metadata = 1 xsd" << endl +        << "xsd.name = [string] xsd" << endl +        << "xsd.version = [string] '" << XSD_VERSION_FULL << '\'' << endl +        << "xsd.checksum = [string] '" << XSD_VERSION_FULL << '\'' << endl; + +      return 0; +    } + +    NarrowString cmd; +    if (args.more ()) +      cmd = args.next (); + +    if (help_ops.version () || cmd == "version") +    { +      wostream& o (wcout); + +      o << "CodeSynthesis XSD XML Schema to C++ compiler " << +        XSD_VERSION_STR << endl +        << "Copyright (c) " << XSD_COPYRIGHT << "." << endl; + +      if (!help_ops.proprietary_license () && cmd == "version") +      { +        // Parse the options after the command to detect trailing +        // --proprietary-license. +        // +        help_ops = help_options (args, cli::unknown_mode::stop); +      } + +      if (help_ops.proprietary_license ()) +      { +        o << "The compiler was invoked in the Proprietary License mode. You " +          << "should have\nreceived a proprietary license from Code Synthesis " +          << "that entitles you to\nuse it in this mode." << endl; +      } +      else +      { +        o << "This is free software; see the source for copying conditions. " +          << "There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS " +          << "FOR A PARTICULAR PURPOSE." << endl; +      } + +      return 0; +    } + +    if (help_ops.help () || cmd == "help") +    { +      wostream& o (wcout); + +      if (cmd == "help" && args.more ()) +      { +        NarrowString arg (args.next ()); + +        if (arg == "cxx-tree") +        { +          o << "Usage: " << argv[0] << " cxx-tree [options] file [file ...]" +            << endl +            << "Options:" << endl; + +          CXX::Tree::Generator::usage (); +        } +        else if (arg == "cxx-parser") +        { +          o << "Usage: " << argv[0] << " cxx-parser [options] file [file ...]" +            << endl +            << "Options:" << endl; + +          CXX::Parser::Generator::usage (); +        } +        else +        { +          o << "error: unknown command '" << arg.c_str () << "'" << endl +            << "info: try '" << argv[0] << " help' for the list of commands" +            << endl; + +          return 1; +        } + +        // Add frontend options at the end. +        // +        options::print_usage (o); +      } +      else +      { +        o << "Usage: " << argv[0] << " <cmd> ..." << endl +          << "Commands:" << endl; + +        o << "  help            Print usage information and exit. Use\n" +          << "                  'help <cmd>' for command-specific options." +          << endl; + +        o << "  version         Print version and exit." +          << endl; + +        o << "  cxx-tree        Generate the C++/Tree mapping." +          << endl; + +        o << "  cxx-parser      Generate the C++/Parser mapping." +          << endl; +      } + +      return 0; +    } + +    if (cmd.empty ()) +    { +      e << "error: no command specified" << endl +        << "info: try '" << argv[0] << " help' for usage information" << endl; + +      return 1; +    } + +    if (cmd != "cxx-tree" && cmd != "cxx-parser") +    { +      e << "error: unknown command '" << cmd.c_str () << "'" << endl +        << "info: try '" << argv[0] << " help' for the list of commands" +        << endl; + +      return 1; +    } + +    // We need to parse command line options before we can get to +    // the arguments. +    // +    unique_ptr<CXX::Tree::options> tree_ops ( +      cmd == "cxx-tree" ? new CXX::Tree::options (args) : 0); + +    unique_ptr<CXX::Parser::options> parser_ops ( +      cmd == "cxx-parser" ? new CXX::Parser::options (args) : 0); + +    CXX::options& common_ops ( +      cmd == "cxx-tree" +      ? static_cast<CXX::options&> (*tree_ops) +      : static_cast<CXX::options&> (*parser_ops)); + +    // Validate options. +    // +    if (common_ops.file_list_only () && !common_ops.file_list_specified ()) +    { +      e << "error: --file-list-only specified without --file-list" << endl; +      return 1; +    } + +    // Disabled warnings. +    // +    WarningSet disabled_w; +    { +      NarrowStrings const& w (common_ops.disable_warning ()); + +      for (NarrowStrings::const_iterator i (w.begin ()); i != w.end (); ++i) +        disabled_w.insert (*i); +    } + +    bool disabled_w_all (disabled_w.find ("all") != disabled_w.end ()); + +    if (common_ops.morph_anonymous () && +        !disabled_w_all && +        disabled_w.find ("D001") == disabled_w.end ()) +    { +      e << "warning D001: the --morph-anonymous option is on by default and " +        << "no longer required" +        << endl; +    } + +    // Collect all the files to compile in a vector. +    // +    NarrowStrings files; + +    while (args.more ()) +      files.push_back (args.next ()); + +    if (files.empty ()) +    { +      e << "error: no input file specified" << endl; +      return 1; +    } + +    bool fpt (common_ops.file_per_type ()); + +    if (cmd == "cxx-tree" || cmd == "cxx-parser") +    { +      bool gen (common_ops.generate_xml_schema ()); +      bool use (common_ops.extern_xml_schema ()); + +      // Things get complicated when we are compiling several schemas at +      // once (non-file-per-type mode) and use the --generate-xml-schema/ +      // --extern-xml-schema options. The only way we can figure out which +      // file corresponds to XML Schema is if the --extern-xml-schema option +      // is also present. So we are going to require it for this case, +      // especially since it generally makes sense. +      // +      if (!fpt) +      { +        if (files.size () > 1 && gen && !use) +        { +          e << "error: --extern-xml-schema is required when compiling more " +            << "than one schema and --generate-xml-schema is specified" +            << endl; + +          return 1; +        } + +        if (files.size () == 1 && gen && use) +        { +          e << "error: --generate-xml-schema and --extern-xml-schema are " +            << "mutually exclusive when compiling a single schema" << endl; + +          return 1; +        } +      } +      else +      { +        // The --file-per-type and --generate-xml-schema options are +        // incompatible. It also makes sense to use --file-per-type +        // and --extern-xml-schema. +        // +        if (gen) +        { +          e << "error: --file-per-type and --generate-xml-schema are " +            << "incompatible" << endl +            << "info: use --generate-xml-schema in a separate invocation " +            << "of the compiler" << endl; + +          return 1; +        } + +        if (!use && +            !disabled_w_all && disabled_w.find ("D002") == disabled_w.end ()) +        { +          e << "warning D002: --extern-xml-schema is recommended when " +            << "--file-per-type is specified to reduce generated code size" +            << endl; +        } +      } +    } + +    // +    // +    FileList file_list; +    AutoUnlinks unlinks; +    size_t sloc (0); + +    LocationTranslator loc_translator ( +      common_ops.location_map (), +      common_ops.location_regex (), +      common_ops.location_regex_trace ()); + +    AnonymousNameTranslator anon_translator ( +      common_ops.anonymous_regex (), +      common_ops.anonymous_regex_trace ()); + +    // Load custom string literals, if any. +    // +    CXX::StringLiteralMap string_literal_map; + +    if (NarrowString file = common_ops.custom_literals ()) +    { +      XercesInitializer xerces_init; + +      if (!CXX::read_literal_map (file, string_literal_map)) +      { +        // Diagnostics has already been issued. +        // +        return 1; +      } +    } + +    if (!fpt) +    { +      // File-per-schema compilation mode. +      // + +      for (size_t i (0); i < files.size (); ++i) +      { +        // Parse schema. +        // +        SemanticGraph::Path tu; + +        try +        { +          tu = SemanticGraph::Path (files[i]); +        } +        catch (SemanticGraph::InvalidPath const&) +        { +          e << "error: '" << files[i].c_str () << "' is not a valid " +            << "filesystem path" << endl; + +          return 1; +        } + +        XSDFrontend::Parser parser ( +          cmd != "cxx-tree", +          !common_ops.disable_multi_import (), +          !common_ops.disable_full_check (), +          loc_translator, +          disabled_w); + +        unique_ptr<SemanticGraph::Schema> schema; + +        if (cmd == "cxx-tree" || cmd == "cxx-parser") +        { +          // See if we are generating code for the XML Schema namespace. +          // 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. +          // +          bool gen_xml_schema (common_ops.generate_xml_schema ()); + +          if (gen_xml_schema) +          { +            if (NarrowString name = common_ops.extern_xml_schema ()) +            { +              if (tu.string () != name) +                gen_xml_schema = false; +            } +          } + +          if (gen_xml_schema) +            schema = parser.xml_schema (tu); +          else +            schema = parser.parse (tu); +        } +        else +          schema = parser.parse (tu); + +        // Morph anonymous types. +        // +        if (!common_ops.preserve_anonymous ()) +        { +          try +          { +            Transformations::Anonymous trans (anon_translator); +            trans.transform (*schema, tu, true); +          } +          catch (Transformations::Anonymous::Failed const&) +          { +            return 1; // Diagnostic has already been issued. +          } +        } + +        // Synthesize enumerations from unions. +        // +        if (cmd == "cxx-tree") +        { +          Transformations::EnumSynthesis trans; +          trans.transform (*schema, tu); +        } + +        // Simplify the schema graph. +        // +        if (cmd == "cxx-parser") +        { +          Transformations::Simplifier trans; +          trans.transform (*schema, tu); +        } + +        // Try to rearrange definitions so that there is no forward +        // inheritance. +        // +        try +        { +          Processing::Inheritance::Processor proc; +          proc.process (*schema, tu); +        } +        catch (Processing::Inheritance::Processor::Failed const&) +        { +          return 1; // Diagnostic has already been issued. +        } + +        // Normalize and annotate complex content restrictions. +        // +        if (cmd == "cxx-parser") +        { +          try +          { +            Transformations::Restriction trans; +            trans.transform (*schema, tu); +          } +          catch (Transformations::Restriction::Failed const&) +          { +            return 1; // Diagnostic has already been issued. +          } +        } + +        // Calculate cardinality. +        // +        { +          Processing::Cardinality::Processor proc; +          proc.process (*schema, tu); +        } + +        // Generate mapping. +        // +        if (cmd == "cxx-tree") +        { +          try +          { +            sloc += CXX::Tree::Generator::generate ( +              *tree_ops, +              *schema, +              tu, +              false, +              string_literal_map, +              disabled_w, +              file_list, +              unlinks); +          } +          catch (CXX::Tree::Generator::Failed const&) +          { +            // Diagnostic has already been issued. +            // +            return 1; +          } +        } +        else if (cmd == "cxx-parser") +        { +          try +          { +            sloc += CXX::Parser::Generator::generate ( +              *parser_ops, +              *schema, +              tu, +              false, +              string_literal_map, +              true, +              disabled_w, +              file_list, +              unlinks); +          } +          catch (CXX::Parser::Generator::Failed const&) +          { +            // Diagnostic has already been issued. +            // +            return 1; +          } +        } +      } +    } +    else +    { +      // File-per-type compilation mode. +      // +      SemanticGraph::Paths paths; + +      for (size_t i (0); i < files.size (); ++i) +      { +        try +        { +          paths.push_back (SemanticGraph::Path (files[i])); +        } +        catch (SemanticGraph::InvalidPath const&) +        { +          e << "error: '" << files[i].c_str () << "' is not a valid " +            << "filesystem path" << endl; + +          return 1; +        } +      } + +      if (cmd == "cxx-parser" && +          paths.size () > 1 && +          parser_ops->generate_test_driver ()) +      { +        e << "info: generating test driver for the first schema only: '" << +          paths[0] << "'" << endl; +      } + +      XSDFrontend::Parser parser ( +        cmd != "cxx-tree", +        !common_ops.disable_multi_import (), +        !common_ops.disable_full_check (), +        loc_translator, +        disabled_w); + +      unique_ptr<SemanticGraph::Schema> schema (parser.parse (paths)); + +      // Morph anonymous types. +      // +      if (!common_ops.preserve_anonymous ()) +      { +        try +        { +          Transformations::Anonymous trans (anon_translator); +          trans.transform (*schema, SemanticGraph::Path (), false); +        } +        catch (Transformations::Anonymous::Failed const&) +        { +          return 1; // Diagnostic has already been issued. +        } +      } + +      // Synthesize enumerations from unions. +      // +      if (cmd == "cxx-tree") +      { +        Transformations::EnumSynthesis trans; +        trans.transform (*schema, SemanticGraph::Path ()); +      } + +      // Simplify the schema graph. +      // +      if (cmd == "cxx-parser") +      { +        Transformations::Simplifier trans; +        trans.transform (*schema, SemanticGraph::Path ()); +      } + +      // Normalize and annotate complex content restrictions. +      // +      if (cmd == "cxx-parser") +      { +        try +        { +          Transformations::Restriction trans; +          trans.transform (*schema, SemanticGraph::Path ()); +        } +        catch (Transformations::Restriction::Failed const&) +        { +          return 1; // Diagnostic has already been issued. +        } +      } + +      // Calculate cardinality. +      // +      { +        Processing::Cardinality::Processor proc; +        proc.process (*schema, SemanticGraph::Path ()); +      } + +      // Rearrange the graph so that each type is in a seperate +      // schema file. +      // +      typedef vector<SemanticGraph::Schema*> Schemas; + +      SchemaPerTypeTranslator type_translator ( +        common_ops.type_file_regex (), +        common_ops.type_file_regex_trace (), +        common_ops.schema_file_regex (), +        common_ops.schema_file_regex_trace ()); + +      Transformations::SchemaPerType trans ( +        type_translator, +        common_ops.fat_type_file ()); + +      Schemas schemas (trans.transform (*schema)); + +      // Generate code. +      // +      for (Schemas::iterator b (schemas.begin ()), i (b), e (schemas.end ()); +           i != e; ++i) +      { +        SemanticGraph::Schema& s (**i); +        SemanticGraph::Path path ( +          s.context ().count ("renamed") +          ? s.context ().get<SemanticGraph::Path> ("renamed") +          : s.used_begin ()->path ()); + +        if (cmd == "cxx-tree") +        { +          try +          { +            sloc += CXX::Tree::Generator::generate ( +              *tree_ops, +              s, +              path, +              true, +              string_literal_map, +              disabled_w, +              file_list, +              unlinks); +          } +          catch (CXX::Tree::Generator::Failed const&) +          { +            // Diagnostic has already been issued. +            // +            return 1; +          } +        } +        else if (cmd == "cxx-parser") +        { +          try +          { +            // Only generate driver for the first schema. +            // +            sloc += CXX::Parser::Generator::generate ( +              *parser_ops, +              s, +              path, +              true, +              string_literal_map, +              i == b, +              disabled_w, +              file_list, +              unlinks); +          } +          catch (CXX::Parser::Generator::Failed const&) +          { +            // Diagnostic has already been issued. +            // +            return 1; +          } +        } +      } +    } + +    // See if we need to produce the file list. +    // +    if (NarrowString fl = common_ops.file_list ()) +    { +      typedef std::ofstream OutputFileStream; + +      try +      { +        OutputFileStream ofs; +        if (fl != "-") +        { +          SemanticGraph::Path path (fl); + +          ofs.open (path.string ().c_str (), ios_base::out); + +          if (!ofs.is_open ()) +          { +            wcerr << path << ": error: unable to open in write mode" << endl; +            return 1; +          } +        } + +        std::ostream& os (ofs.is_open () ? ofs : cout); + +        NarrowString d (common_ops.file_list_delim ()); +        expand_nl (d); + +        if (NarrowString p = common_ops.file_list_prologue ()) +        { +          expand_nl (p); +          os << p; +        } + +        for (FileList::iterator i (file_list.begin ()), e (file_list.end ()); +             i != e;) +        { +          os << *i; + +          if (++i != e) +            os << d; +        } + +        if (NarrowString e = common_ops.file_list_epilogue ()) +        { +          expand_nl (e); +          os << e; +        } +      } +      catch (SemanticGraph::InvalidPath const&) +      { +        wcerr << "error: '" << fl.c_str () << "' is not a valid " +              << "filesystem path" << endl; +        return 1; +      } +    } + +    if (common_ops.show_sloc ()) +      e << "total: " << sloc << endl; + +    if (size_t sloc_limit = common_ops.sloc_limit ()) +    { +      if (sloc_limit < sloc) +      { +        e << "error: SLOC limit of " << sloc_limit +          << " lines has been exceeded" << endl; + +        return 1; +      } +    } + +    unlinks.cancel (); + +    return 0; +  } +  catch (LocationTranslator::Failed const&) +  { +    // Diagnostic has already been issued. +  } +  catch (AnonymousNameTranslator::Failed const&) +  { +    // Diagnostic has already been issued. +  } +  catch (SchemaPerTypeTranslator::Failed const&) +  { +    // Diagnostic has already been issued. +  } +  catch (Transformations::SchemaPerType::Failed const&) +  { +    // Diagnostic has already been issued. +  } +  catch (XSDFrontend::InvalidSchema const&) +  { +    // Diagnostic has already been issued. +  } +  catch (cli::exception const& ex) +  { +    wcerr << ex << endl; +    wcerr << "try '" << argv[0] << " help' for usage information" << endl; +  } + +  return 1; +} + +// LocationTranslator +// + +LocationTranslator:: +LocationTranslator (NarrowStrings const& map, +                    NarrowStrings const& regex, +                    bool trace) +    : trace_ (trace) +{ +  // Map. +  // +  for (NarrowStrings::const_iterator i (map.begin ()); i != map.end (); ++i) +  { +    // Split the string in two parts at the last '='. +    // +    size_t pos (i->rfind ('=')); + +    if (pos == NarrowString::npos) +    { +      wcerr << "error: invalid location map: '" << i->c_str () << +        "': delimiter ('=') not found" << endl; + +      throw Failed (); +    } + +    map_[NarrowString (*i, 0, pos)] = NarrowString (*i, pos + 1); +  } + +  // Regex. +  // +  for (NarrowStrings::const_iterator i (regex.begin ()); i != regex.end (); ++i) +  { +    try +    { +      regex_.push_back (Regex (*i)); +    } +    catch (RegexFormat const& e) +    { +      wcerr << "error: invalid location regex: '" << +        e.regex ().c_str () << "': " << +        e.description ().c_str () << endl; + +      throw Failed (); +    } +  } +} + +NarrowString LocationTranslator:: +translate (NarrowString const& l) +{ +  // First check the cache. +  // +  Cache::const_iterator ci (cache_.find (l)); + +  if (ci != cache_.end ()) +    return ci->second; + +  // Then check the direct map. +  // +  Map::const_iterator mi (map_.find (l)); + +  if (mi != map_.end ()) +  { +    cache_[l] = mi->second; +    return mi->second; +  } + +  // Finally try regex. +  // +  if (trace_) +    wcerr << "location: '" << l.c_str () << "'" << endl; + +  for (RegexVector::reverse_iterator i (regex_.rbegin ()); +       i != regex_.rend (); ++i) +  { +    if (trace_) +      wcerr << "try: '" << i->regex ().str ().c_str () << "' : "; + +    if (i->match (l)) +    { +      NarrowString r (i->replace (l)); + +      if (trace_) +        wcerr << "'" << r.c_str () << "' : +" << endl; + +      cache_[l] = r; +      return r; +    } + +    if (trace_) +      wcerr << '-' << endl; +  } + +  // No match - return the original location. +  // +  cache_[l] = l; +  return l; +} + +// AnonymousNameTranslator +// + +AnonymousNameTranslator:: +AnonymousNameTranslator (NarrowStrings const& regex, bool trace) +    : trace_ (trace) +{ +  for (NarrowStrings::const_iterator i (regex.begin ()); i != regex.end (); ++i) +  { +    try +    { +      regex_.push_back (Regex (String (*i))); +    } +    catch (RegexFormat const& e) +    { +      wcerr << "error: invalid anonymous type regex: '" << +        e.regex () << "': " << e.description ().c_str () << endl; + +      throw Failed (); +    } +  } +} + +String AnonymousNameTranslator:: +translate (String const& file, +           String const& ns, +           String const& name, +           String const& xpath) +{ +  String s (file + L' ' + ns + L' ' + xpath); + +  if (trace_) +    wcerr << "anonymous type: '" << s << "'" << endl; + +  for (RegexVector::reverse_iterator i (regex_.rbegin ()); +       i != regex_.rend (); ++i) +  { +    if (trace_) +      wcerr << "try: '" << i->regex () << "' : "; + +    if (i->match (s)) +    { +      String r (i->replace (s)); + +      if (trace_) +        wcerr << "'" << r << "' : +" << endl; + +      return r; +    } + +    if (trace_) +      wcerr << '-' << endl; +  } + +  // No match - return the name. +  // +  return name; +} + +// SchemaPerTypeTranslator +// + +SchemaPerTypeTranslator:: +SchemaPerTypeTranslator (NarrowStrings const& type_regex, +                         bool type_trace, +                         NarrowStrings const& schema_regex, +                         bool schema_trace) +    : type_trace_ (type_trace), schema_trace_ (schema_trace) +{ +  for (NarrowStrings::const_iterator i (type_regex.begin ()); +       i != type_regex.end (); ++i) +  { +    try +    { +      type_regex_.push_back (TypeRegex (String (*i))); +    } +    catch (TypeRegexFormat const& e) +    { +      wcerr << "error: invalid type file regex: '" << +        e.regex () << "': " << e.description ().c_str () << endl; + +      throw Failed (); +    } +  } + +  for (NarrowStrings::const_iterator i (schema_regex.begin ()); +       i != schema_regex.end (); ++i) +  { +    try +    { +      schema_regex_.push_back (SchemaRegex (*i)); +    } +    catch (SchemaRegexFormat const& e) +    { +      wcerr << "error: invalid type file regex: '" << +        e.regex ().c_str () << "': " << e.description ().c_str () << endl; + +      throw Failed (); +    } +  } +} + +String SchemaPerTypeTranslator:: +translate_type (String const& ns, String const& name) +{ +  String s (ns + L' ' + name); + +  if (type_trace_) +    wcerr << "type: '" << s << "'" << endl; + +  for (TypeRegexVector::reverse_iterator i (type_regex_.rbegin ()); +       i != type_regex_.rend (); ++i) +  { +    if (type_trace_) +      wcerr << "try: '" << i->regex () << "' : "; + +    if (i->match (s)) +    { +      String r (i->replace (s)); + +      if (type_trace_) +        wcerr << "'" << r << "' : +" << endl; + +      return r; +    } + +    if (type_trace_) +      wcerr << '-' << endl; +  } + +  // No match - return empty string. +  // +  return L""; +} + +NarrowString SchemaPerTypeTranslator:: +translate_schema (NarrowString const& file) +{ +  if (schema_trace_) +    wcerr << "schema: '" << file.c_str () << "'" << endl; + +  for (SchemaRegexVector::reverse_iterator i (schema_regex_.rbegin ()); +       i != schema_regex_.rend (); ++i) +  { +    if (schema_trace_) +      wcerr << "try: '" << i->regex ().str ().c_str () << "' : "; + +    if (i->match (file)) +    { +      NarrowString r (i->replace (file)); + +      if (schema_trace_) +        wcerr << "'" << r.c_str () << "' : +" << endl; + +      return r; +    } + +    if (schema_trace_) +      wcerr << '-' << endl; +  } + +  // No match - return empty string. +  // +  return ""; +} + +// +// +void +expand_nl (NarrowString& s) +{ +  for (size_t i (0); i < s.size ();) +  { +    if (s[i] == '\\' && (i + 1) < s.size () && s[i + 1] == 'n') +    { +      NarrowString tmp (s, 0, i); +      tmp += '\n'; +      tmp.append (s.c_str () + i + 2); +      s = tmp; +    } +    else +      ++i; +  } +} diff --git a/xsd/xsd.hxx b/xsd/xsd.hxx new file mode 100644 index 0000000..5ce2926 --- /dev/null +++ b/xsd/xsd.hxx @@ -0,0 +1,24 @@ +// file      : xsd/xsd.hxx +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_XSD_HXX +#define XSD_XSD_HXX + +#include <set> +#include <vector> +#include <cstdio> // std::remove + +#include <libcutl/shared-ptr.hxx> +#include <libcutl/fs/auto-remove.hxx> + +#include <libxsd-frontend/semantic-graph/elements.hxx> // Path + +#include <xsd/types.hxx> + +typedef std::set<NarrowString> WarningSet; +typedef std::vector<NarrowString> FileList; + +typedef cutl::fs::auto_remove AutoUnlink; +typedef cutl::fs::auto_removes AutoUnlinks; + +#endif // XSD_XSD_HXX  | 
