aboutsummaryrefslogtreecommitdiff
path: root/xsde/cxx/hybrid/tree-size-processor.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xsde/cxx/hybrid/tree-size-processor.cxx')
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.cxx164
1 files changed, 146 insertions, 18 deletions
diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx
index d492b24..a3b2231 100644
--- a/xsde/cxx/hybrid/tree-size-processor.cxx
+++ b/xsde/cxx/hybrid/tree-size-processor.cxx
@@ -9,9 +9,14 @@
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
+#include <cult/containers/map.hxx>
#include <cult/containers/set.hxx>
#include <cult/containers/vector.hxx>
+#include <iostream>
+
+using std::wcerr;
+
namespace CXX
{
namespace Hybrid
@@ -20,6 +25,15 @@ namespace CXX
{
typedef Cult::Containers::Set<String> TypeSet;
+
+ struct CustomType
+ {
+ Boolean fixed;
+ String base;
+ };
+
+ typedef Cult::Containers::Map<String, CustomType> CustomTypeMap;
+
Boolean
test (SemanticGraph::Type& t)
{
@@ -225,8 +239,14 @@ namespace CXX
Traversal::Union,
Traversal::Complex
{
- Type (TypeSet& custom_data, Boolean stl_)
- : custom_data_ (custom_data), stl (stl_)
+ Type (Boolean& valid,
+ TypeSet& custom_data,
+ CustomTypeMap& custom_type_map,
+ Boolean stl_)
+ : valid_ (valid),
+ custom_data_ (custom_data),
+ custom_type_map_ (custom_type_map),
+ stl (stl_)
{
}
@@ -263,7 +283,9 @@ namespace CXX
if (ctx.count ("recurse"))
{
- set (c, false);
+ if (!test (c))
+ set (c, false);
+
ctx.set ("recursive", true);
// Mark all the types involved in the cycle as recursive.
@@ -339,7 +361,35 @@ namespace CXX
}
private:
+ Void
+ set (SemanticGraph::Type& t, Boolean v)
+ {
+ // Check if this is a custom type.
+ //
+ CustomTypeMap::Iterator i = custom_type_map_.find (t.name ());
+
+ if (i != custom_type_map_.end ())
+ {
+ if (i->second.base && i->second.fixed && !v)
+ {
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << ": error: generated base type '" << i->second.base
+ << "' is variable-length while the custom type is "
+ << "declared fixed-length" << endl;
+
+ valid_ = false;
+ }
+
+ Hybrid::set (t, i->second.fixed);
+ }
+ else
+ Hybrid::set (t, v);
+ }
+
+ private:
+ Boolean& valid_;
TypeSet& custom_data_;
+ CustomTypeMap& custom_type_map_;
Boolean stl;
typedef Containers::Vector<SemanticGraph::Complex*> Path;
@@ -751,11 +801,12 @@ namespace CXX
}
};
- Void
+ Boolean
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
SemanticGraph::Path const&)
{
+ Boolean valid (true);
Boolean stl (!ops.value<CLI::no_stl> ());
// Root schema in the file-per-type mode is just a bunch
@@ -826,34 +877,111 @@ namespace CXX
}
}
- Traversal::Schema schema;
- Uses uses;
+ // Prepare a map of types custom types that specify type
+ // size.
+ //
+ CustomTypeMap custom_type_map;
+
+ {
+ typedef Containers::Vector<NarrowString> Vector;
+ Vector const& v (ops.value<CLI::custom_type> ());
- schema >> uses >> schema;
+ for (Vector::ConstIterator i (v.begin ()), e (v.end ());
+ i != e; ++i)
+ {
+ String s (*i);
- Traversal::Names schema_names;
- Traversal::Namespace ns;
- Traversal::Names ns_names;
- Type type (custom_data_types, stl);
+ if (s.empty ())
+ continue;
- schema >> schema_names >> ns >> ns_names >> type;
+ // Split the string in two parts at the last '='.
+ //
+ Size pos (s.rfind ('='));
- // Some twisted schemas do recusive self-inclusion.
- //
- tu.context ().set ("cxx-hybrid-size-processor-seen", true);
+ if (pos == String::npos)
+ continue;
- schema.dispatch (tu);
+ String name (s, 0, pos);
+ String fb (s, pos + 1);
+
+ pos = fb.find ('/');
+
+ String flags, base;
+
+ if (pos != String::npos)
+ {
+ flags.assign (fb, 0, pos);
+
+ // Skip the type component.
+ //
+ pos = fb.find ('/', pos + 1);
+
+ if (pos != String::npos)
+ {
+ String b (fb, pos + 1);
+
+ // See if we've got the include component.
+ //
+ pos = b.find ('/');
+
+ if (pos != String::npos)
+ base.assign (b, 0, pos);
+ else
+ base = b;
+ }
+ }
+ else
+ flags = fb;
+
+ if (!flags)
+ continue;
+
+ if (flags != L"f" && flags != L"v")
+ {
+ wcerr << "error: invalid custom type flag: '" <<
+ flags << "'" << endl;
+
+ valid = false;
+ }
+
+ custom_type_map[name].base = base;
+ custom_type_map[name].fixed = (flags == L"f");
+ }
+ }
+
+ if (valid)
+ {
+ Traversal::Schema schema;
+ Uses uses;
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ Type type (valid, custom_data_types, custom_type_map, stl);
+
+ schema >> schema_names >> ns >> ns_names >> type;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set ("cxx-hybrid-size-processor-seen", true);
+
+ schema.dispatch (tu);
+ }
}
}
+
+ return valid;
}
}
- Void TreeSizeProcessor::
+ Boolean TreeSizeProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
SemanticGraph::Path const& file)
{
- process_impl (ops, tu, file);
+ return process_impl (ops, tu, file);
}
}
}