Browse Source

struct and switch are now inline

David Rose 21 years ago
parent
commit
932359216f
34 changed files with 703 additions and 187 deletions
  1. 4 3
      direct/src/dcparser/Sources.pp
  2. 5 4
      direct/src/dcparser/dcArrayParameter.cxx
  3. 1 1
      direct/src/dcparser/dcArrayParameter.h
  4. 16 6
      direct/src/dcparser/dcAtomicField.cxx
  5. 1 0
      direct/src/dcparser/dcAtomicField.h
  6. 59 4
      direct/src/dcparser/dcClass.cxx
  7. 4 0
      direct/src/dcparser/dcClass.h
  8. 4 7
      direct/src/dcparser/dcClassParameter.cxx
  9. 1 1
      direct/src/dcparser/dcClassParameter.h
  10. 20 0
      direct/src/dcparser/dcDeclaration.cxx
  11. 9 0
      direct/src/dcparser/dcDeclaration.h
  12. 1 0
      direct/src/dcparser/dcField.h
  13. 56 10
      direct/src/dcparser/dcFile.cxx
  14. 6 3
      direct/src/dcparser/dcFile.h
  15. 16 5
      direct/src/dcparser/dcMolecularField.cxx
  16. 1 0
      direct/src/dcparser/dcMolecularField.h
  17. 4 4
      direct/src/dcparser/dcPacker.I
  18. 19 15
      direct/src/dcparser/dcPacker.cxx
  19. 4 4
      direct/src/dcparser/dcPacker.h
  20. 10 9
      direct/src/dcparser/dcPackerCatalog.cxx
  21. 4 4
      direct/src/dcparser/dcPackerCatalog.h
  22. 4 16
      direct/src/dcparser/dcPackerInterface.cxx
  23. 5 4
      direct/src/dcparser/dcPackerInterface.h
  24. 39 9
      direct/src/dcparser/dcParameter.cxx
  25. 9 3
      direct/src/dcparser/dcParameter.h
  26. 45 15
      direct/src/dcparser/dcParser.yxx
  27. 2 0
      direct/src/dcparser/dcParserDefs.h
  28. 3 3
      direct/src/dcparser/dcSimpleParameter.cxx
  29. 1 1
      direct/src/dcparser/dcSimpleParameter.h
  30. 80 52
      direct/src/dcparser/dcSwitch.cxx
  31. 10 4
      direct/src/dcparser/dcSwitch.h
  32. 198 0
      direct/src/dcparser/dcSwitchParameter.cxx
  33. 61 0
      direct/src/dcparser/dcSwitchParameter.h
  34. 1 0
      direct/src/dcparser/dcparser_composite2.cxx

+ 4 - 3
direct/src/dcparser/Sources.pp

@@ -24,7 +24,8 @@
      dcPacker.h dcPacker.I \
      dcPackerCatalog.h dcPackerCatalog.I \
      dcPackerInterface.h dcPackerInterface.I \
-     dcParameter.h dcClassParameter.h dcArrayParameter.h dcSimpleParameter.h \
+     dcParameter.h dcClassParameter.h dcArrayParameter.h \
+     dcSimpleParameter.h dcSwitchParameter.h \
      dcNumericRange.h dcNumericRange.I \
      dcSwitch.h \
      dcTypedef.h \
@@ -41,8 +42,8 @@
      dcPacker.cxx \
      dcPackerCatalog.cxx \
      dcPackerInterface.cxx \
-     dcParameter.cxx dcClassParameter.cxx \
-     dcArrayParameter.cxx dcSimpleParameter.cxx \
+     dcParameter.cxx dcClassParameter.cxx dcArrayParameter.cxx \
+     dcSimpleParameter.cxx dcSwitchParameter.cxx \
      dcSwitch.cxx \
      dcTypedef.cxx \
      dcindent.cxx  \

+ 5 - 4
direct/src/dcparser/dcArrayParameter.cxx

@@ -188,10 +188,10 @@ validate_num_nested_fields(int num_nested_fields) const {
 //               typename and identifier.
 ////////////////////////////////////////////////////////////////////
 void DCArrayParameter::
-output_instance(ostream &out, const string &prename, const string &name,
-                const string &postname) const {
+output_instance(ostream &out, bool brief, const string &prename,
+                const string &name, const string &postname) const {
   if (get_typedef() != (DCTypedef *)NULL) {
-    output_typedef_name(out, prename, name, postname);
+    output_typedef_name(out, brief, prename, name, postname);
 
   } else {
     ostringstream strm;
@@ -200,7 +200,8 @@ output_instance(ostream &out, const string &prename, const string &name,
     _array_size_range.output(strm);
     strm << "]";
     
-    _element_type->output_instance(out, prename, name, strm.str() + postname);
+    _element_type->output_instance(out, brief, prename, name, 
+                                   strm.str() + postname);
   }
 }
 

+ 1 - 1
direct/src/dcparser/dcArrayParameter.h

@@ -50,7 +50,7 @@ public:
   virtual DCPackerInterface *get_nested_field(int n) const;
   virtual bool validate_num_nested_fields(int num_nested_fields) const;
 
-  virtual void output_instance(ostream &out, const string &prename, 
+  virtual void output_instance(ostream &out, bool brief, const string &prename, 
                                const string &name, const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 

+ 16 - 6
direct/src/dcparser/dcAtomicField.cxx

@@ -266,15 +266,13 @@ compare_flags(const DCAtomicField &other) const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCAtomicField::write
+//     Function: DCAtomicField::output
 //       Access: Public, Virtual
-//  Description: Generates a parseable description of the object to
-//               the indicated output stream.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 void DCAtomicField::
-write(ostream &out, bool brief, int indent_level) const {
-  indent(out, indent_level)
-    << _name << "(";
+output(ostream &out, bool brief) const {
+  out << _name << "(";
 
   if (!_elements.empty()) {
     Elements::const_iterator ei = _elements.begin();
@@ -317,6 +315,18 @@ write(ostream &out, bool brief, int indent_level) const {
   }
 
   out << ";";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::write
+//       Access: Public, Virtual
+//  Description: Generates a parseable description of the object to
+//               the indicated output stream.
+////////////////////////////////////////////////////////////////////
+void DCAtomicField::
+write(ostream &out, bool brief, int indent_level) const {
+  indent(out, indent_level);
+  output(out, brief);
   if (!brief && _number >= 0) {
     out << "  // field " << _number;
   }

+ 1 - 0
direct/src/dcparser/dcAtomicField.h

@@ -65,6 +65,7 @@ PUBLISHED:
   bool compare_flags(const DCAtomicField &other) const;
   
 public:
+  virtual void output(ostream &out, bool brief) const;
   virtual void write(ostream &out, bool brief, int indent_level) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 

+ 59 - 4
direct/src/dcparser/dcClass.cxx

@@ -57,6 +57,16 @@ DCClass::
 #endif
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::as_class
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCClass *DCClass::
+as_class() {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::get_name
 //       Access: Published
@@ -263,7 +273,7 @@ set_class_def(PyObject *class_def) {
 PyObject *DCClass::
 get_class_def() const {
   if (_class_def == NULL) {
-    return Py_BuildValue("");
+    return Py_None;
   }
 
   Py_INCREF(_class_def);
@@ -435,7 +445,7 @@ pack_required_field(DCPacker &packer, PyObject *distobj,
       ostringstream strm;
       strm << "Data element " << field_name
            << ", required by dc file for dclass " << get_name()
-           << ", not defined on object.";
+           << ", not defined on object";
       nassert_raise(strm.str());
       return false;
     }
@@ -661,9 +671,12 @@ void DCClass::
 write(ostream &out, bool brief, int indent_level) const {
   indent(out, indent_level);
   if (_is_struct) {
-    out << "struct " << _name;
+    out << "struct";
   } else {
-    out << "dclass " << _name;
+    out << "dclass";
+  }
+  if (!_name.empty()) {
+    out << " " << _name;
   }
 
   if (!_parents.empty()) {
@@ -690,6 +703,48 @@ write(ostream &out, bool brief, int indent_level) const {
   indent(out, indent_level) << "};\n";
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::output_instance
+//       Access: Public
+//  Description: Generates a parseable description of the object to
+//               the indicated output stream.
+////////////////////////////////////////////////////////////////////
+void DCClass::
+output_instance(ostream &out, bool brief, const string &prename, 
+                const string &name, const string &postname) const {
+  if (_is_struct) {
+    out << "struct";
+  } else {
+    out << "dclass";
+  }
+  if (!_name.empty()) {
+    out << " " << _name;
+  }
+
+  if (!_parents.empty()) {
+    Parents::const_iterator pi = _parents.begin();
+    out << " : " << (*pi)->_name;
+    ++pi;
+    while (pi != _parents.end()) {
+      out << ", " << (*pi)->_name;
+      ++pi;
+    }
+  }
+
+  out << " {";
+
+  Fields::const_iterator fi;
+  for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
+    (*fi)->output(out, brief);
+    out << "; ";
+  }
+
+  out << "}";
+  if (!prename.empty() || !name.empty() || !postname.empty()) {
+    out << " " << prename << name << postname;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::generate_hash
 //       Access: Public, Virtual

+ 4 - 0
direct/src/dcparser/dcClass.h

@@ -38,6 +38,8 @@ public:
   ~DCClass();
 
 PUBLISHED:
+  virtual DCClass *as_class();
+
   const string &get_name() const;
   int get_number() const;
 
@@ -83,6 +85,8 @@ PUBLISHED:
 
 public:
   virtual void write(ostream &out, bool brief, int indent_level) const;
+  void output_instance(ostream &out, bool brief, const string &prename, 
+                       const string &name, const string &postname) const;
   void generate_hash(HashGenerator &hashgen) const;
 
   bool add_field(DCField *field);

+ 4 - 7
direct/src/dcparser/dcClassParameter.cxx

@@ -123,16 +123,13 @@ get_nested_field(int n) const {
 //               typename and identifier.
 ////////////////////////////////////////////////////////////////////
 void DCClassParameter::
-output_instance(ostream &out, const string &prename, const string &name,
-                const string &postname) const {
+output_instance(ostream &out, bool brief, const string &prename, 
+                const string &name, const string &postname) const {
   if (get_typedef() != (DCTypedef *)NULL) {
-    output_typedef_name(out, prename, name, postname);
+    output_typedef_name(out, brief, prename, name, postname);
 
   } else {
-    out << get_name();
-    if (!prename.empty() || !name.empty() || !postname.empty()) {
-      out << " " << prename << name << postname;
-    }
+    _dclass->output_instance(out, brief, prename, name, postname);
   }
 }
 

+ 1 - 1
direct/src/dcparser/dcClassParameter.h

@@ -45,7 +45,7 @@ PUBLISHED:
 public:
   virtual DCPackerInterface *get_nested_field(int n) const;
 
-  virtual void output_instance(ostream &out, const string &prename, 
+  virtual void output_instance(ostream &out, bool brief, const string &prename, 
                                const string &name, const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 

+ 20 - 0
direct/src/dcparser/dcDeclaration.cxx

@@ -27,3 +27,23 @@
 DCDeclaration::
 ~DCDeclaration() {
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCDeclaration::as_class
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCClass *DCDeclaration::
+as_class() {
+  return (DCClass *)NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCDeclaration::as_switch
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCSwitch *DCDeclaration::
+as_switch() {
+  return (DCSwitch *)NULL;
+}

+ 9 - 0
direct/src/dcparser/dcDeclaration.h

@@ -21,6 +21,9 @@
 
 #include "dcbase.h"
 
+class DCClass;
+class DCSwitch;
+
 ////////////////////////////////////////////////////////////////////
 //       Class : DCDeclaration
 // Description : This is a common interface for a declaration in a DC
@@ -34,6 +37,12 @@
 class EXPCL_DIRECT DCDeclaration {
 public:
   virtual ~DCDeclaration();
+
+PUBLISHED:
+  virtual DCClass *as_class();
+  virtual DCSwitch *as_switch();
+
+public:
   virtual void write(ostream &out, bool brief, int indent_level) const=0;
 };
 

+ 1 - 0
direct/src/dcparser/dcField.h

@@ -66,6 +66,7 @@ PUBLISHED:
 #endif 
 
 public:
+  virtual void output(ostream &out, bool brief) const=0;
   virtual void write(ostream &out, bool brief, int indent_level) const=0;
   virtual void generate_hash(HashGenerator &hashgen) const;
 

+ 56 - 10
direct/src/dcparser/dcFile.cxx

@@ -17,6 +17,8 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "dcFile.h"
+#include "dcClass.h"
+#include "dcSwitch.h"
 #include "dcParserDefs.h"
 #include "dcLexerDefs.h"
 #include "dcTypedef.h"
@@ -65,7 +67,7 @@ clear() {
   
   _classes.clear();
   _imports.clear();
-  _classes_by_name.clear();
+  _things_by_name.clear();
 }
 
 #ifdef WITHIN_PANDA
@@ -273,15 +275,32 @@ get_class(int n) const {
 ////////////////////////////////////////////////////////////////////
 DCClass *DCFile::
 get_class_by_name(const string &name) const {
-  ClassesByName::const_iterator ni;
-  ni = _classes_by_name.find(name);
-  if (ni != _classes_by_name.end()) {
-    return (*ni).second;
+  ThingsByName::const_iterator ni;
+  ni = _things_by_name.find(name);
+  if (ni != _things_by_name.end()) {
+    return (*ni).second->as_class();
   }
 
   return (DCClass *)NULL;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCFile::get_switch_by_name
+//       Access: Published
+//  Description: Returns the switch that has the indicated name, or
+//               NULL if there is no such switch.
+////////////////////////////////////////////////////////////////////
+DCSwitch *DCFile::
+get_switch_by_name(const string &name) const {
+  ThingsByName::const_iterator ni;
+  ni = _things_by_name.find(name);
+  if (ni != _things_by_name.end()) {
+    return (*ni).second->as_switch();
+  }
+
+  return (DCSwitch *)NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::all_objects_valid
 //       Access: Published
@@ -426,11 +445,13 @@ generate_hash(HashGenerator &hashgen) const {
 ////////////////////////////////////////////////////////////////////
 bool DCFile::
 add_class(DCClass *dclass) {
-  bool inserted = _classes_by_name.insert
-    (ClassesByName::value_type(dclass->get_name(), dclass)).second;
-
-  if (!inserted) {
-    return false;
+  if (!dclass->get_name().empty()) {
+    bool inserted = _things_by_name.insert
+      (ThingsByName::value_type(dclass->get_name(), dclass)).second;
+    
+    if (!inserted) {
+      return false;
+    }
   }
 
   dclass->set_number(get_num_classes());
@@ -447,6 +468,31 @@ add_class(DCClass *dclass) {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCFile::add_switch
+//       Access: Public
+//  Description: Adds the newly-allocated switch definition
+//               to the file.  The DCFile becomes the owner of the
+//               pointer and will delete it when it destructs.
+//               Returns true if the switch is successfully added, or
+//               false if there was a name conflict.
+////////////////////////////////////////////////////////////////////
+bool DCFile::
+add_switch(DCSwitch *dswitch) {
+  if (!dswitch->get_name().empty()) {
+    bool inserted = _things_by_name.insert
+      (ThingsByName::value_type(dswitch->get_name(), dswitch)).second;
+    
+    if (!inserted) {
+      return false;
+    }
+  }
+
+  _declarations.push_back(dswitch);
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::add_import_module
 //       Access: Public

+ 6 - 3
direct/src/dcparser/dcFile.h

@@ -20,8 +20,9 @@
 #define DCFILE_H
 
 #include "dcbase.h"
-#include "dcClass.h"
 
+class DCClass;
+class DCSwitch;
 class HashGenerator;
 class DCTypedef;
 class DCDeclaration;
@@ -51,6 +52,7 @@ PUBLISHED:
   int get_num_classes() const;
   DCClass *get_class(int n) const;
   DCClass *get_class_by_name(const string &name) const;
+  DCSwitch *get_switch_by_name(const string &name) const;
 
   bool all_objects_valid() const;
 
@@ -68,6 +70,7 @@ PUBLISHED:
 public:
   void generate_hash(HashGenerator &hashgen) const;
   bool add_class(DCClass *dclass);
+  bool add_switch(DCSwitch *dswitch);
   void add_import_module(const string &import_module);
   void add_import_symbol(const string &import_symbol);
   bool add_typedef(DCTypedef *dtypedef);
@@ -76,8 +79,8 @@ private:
   typedef pvector<DCClass *> Classes;
   Classes _classes;
 
-  typedef pmap<string, DCClass *> ClassesByName;
-  ClassesByName _classes_by_name;
+  typedef pmap<string, DCDeclaration *> ThingsByName;
+  ThingsByName _things_by_name;
 
   typedef pvector<string> ImportSymbols;
   class Import {

+ 16 - 5
direct/src/dcparser/dcMolecularField.cxx

@@ -102,14 +102,13 @@ add_atomic(DCAtomicField *atomic) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCMolecularField::write
+//     Function: DCMolecularField::output
 //       Access: Public, Virtual
-//  Description: Generates a parseable description of the object to
-//               the indicated output stream.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 void DCMolecularField::
-write(ostream &out, bool brief, int indent_level) const {
-  indent(out, indent_level) << _name;
+output(ostream &out, bool brief) const {
+  out << _name;
 
   if (!_fields.empty()) {
     Fields::const_iterator fi = _fields.begin();
@@ -122,6 +121,18 @@ write(ostream &out, bool brief, int indent_level) const {
   }
   
   out << ";";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCMolecularField::write
+//       Access: Public, Virtual
+//  Description: Generates a parseable description of the object to
+//               the indicated output stream.
+////////////////////////////////////////////////////////////////////
+void DCMolecularField::
+write(ostream &out, bool brief, int indent_level) const {
+  indent(out, indent_level);
+  output(out, brief);
   if (!brief) {
     out << "  // field " << _number;
   }

+ 1 - 0
direct/src/dcparser/dcMolecularField.h

@@ -45,6 +45,7 @@ PUBLISHED:
 public:
   void add_atomic(DCAtomicField *atomic);
 
+  virtual void output(ostream &out, bool brief) const;
   virtual void write(ostream &out, bool brief, int indent_level) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 

+ 4 - 4
direct/src/dcparser/dcPacker.I

@@ -127,7 +127,7 @@ get_current_field() const {
 //               get_current_parent() will contain the particular
 //               SwitchCase that was selected by the switch.
 ////////////////////////////////////////////////////////////////////
-INLINE const DCSwitch *DCPacker::
+INLINE const DCSwitchParameter *DCPacker::
 get_last_switch() const {
   return _last_switch;
 }
@@ -1122,9 +1122,9 @@ advance() {
     // But if the parent is a switch record, we make a special case so
     // we can get the alternate fields.
     if (_current_parent != (DCPackerInterface *)NULL) {
-      const DCSwitch *dswitch = ((DCPackerInterface *)_current_parent)->as_switch();
-      if (dswitch != (DCSwitch *)NULL) {
-        handle_switch(dswitch);
+      const DCSwitchParameter *switch_parameter = ((DCPackerInterface *)_current_parent)->as_switch_parameter();
+      if (switch_parameter != (DCSwitchParameter *)NULL) {
+        handle_switch(switch_parameter);
       }
     }
 

+ 19 - 15
direct/src/dcparser/dcPacker.cxx

@@ -21,6 +21,7 @@
 #include "dcParserDefs.h"
 #include "dcLexerDefs.h"
 #include "dcClassParameter.h"
+#include "dcSwitchParameter.h"
 #include "dcClass.h"
 
 ////////////////////////////////////////////////////////////////////
@@ -351,7 +352,7 @@ seek(const string &field_name) {
 
     const DCPackerCatalog::Entry &entry = _live_catalog->get_entry(entry_index);
 
-    if (((DCPackerInterface *)entry._parent)->as_switch() != (DCSwitch *)NULL) {
+    if (((DCPackerInterface *)entry._parent)->as_switch_parameter() != (DCSwitchParameter *)NULL) {
       // If the parent is a DCSwitch, that can only mean that the
       // seeked field is a switch parameter.  We can't support seeking
       // to a switch parameter and modifying it directly--what would
@@ -653,13 +654,20 @@ pack_object(PyObject *object) {
     }
 
   } else {
+    int size = PySequence_Size(object);
+    bool is_instance = false;
+
     DCClass *dclass = NULL;
     const DCClassParameter *class_param = ((DCPackerInterface *)get_current_field())->as_class_parameter();
     if (class_param != (DCClassParameter *)NULL) {
       dclass = class_param->get_class();
-    }
 
-    int size = PySequence_Size(object);
+      if (dclass->has_class_def()) {
+        PyObject *class_def = dclass->get_class_def();
+        is_instance = (PyObject_IsInstance(object, dclass->get_class_def()) != 0);
+        Py_DECREF(class_def);
+      }
+    }
 
     // If dclass is not NULL, the packer is expecting a class object.
     // There are then two cases: (1) the user has supplied a matching
@@ -678,10 +686,7 @@ pack_object(PyObject *object) {
 
     // (3) Otherwise, it is considered to be a class object.
 
-    if (dclass != (DCClass *)NULL && 
-        ((dclass->get_class_def() != (PyObject *)NULL && 
-          PyObject_IsInstance(object, dclass->get_class_def())) ||
-         size < 0)) {
+    if (dclass != (DCClass *)NULL && (is_instance || size < 0)) {
       // The supplied object is either an instance of the expected
       // class object, or the size is less than 0--this is case (1) or
       // (3).
@@ -689,7 +694,7 @@ pack_object(PyObject *object) {
 
     } else if (size >= 0) {
       // The supplied object is not an instance of the expected class
-      // object, and it does return a valid size.  This is case (2).
+      // object, but it does have a size.  This is case (2).
       push();
       int size = PySequence_Size(object);
       for (int i = 0; i < size; i++) {
@@ -1021,20 +1026,19 @@ output_hex_string(ostream &out, const string &str) {
 //               appropriate case of the switch record.
 ////////////////////////////////////////////////////////////////////
 void DCPacker::
-handle_switch(const DCSwitch *dswitch) {
+handle_switch(const DCSwitchParameter *switch_parameter) {
   // First, get the value from the key.  This is either found in the
   // unpack or the pack data, depending on what mode we're in.
   const DCPackerInterface *new_parent = NULL;
 
   if (_mode == M_pack || _mode == M_repack) {
     const char *data = _pack_data.get_data();
-    new_parent = dswitch->apply_switch(data + _push_marker,
-                                       _pack_data.get_length() - _push_marker);
+    new_parent = switch_parameter->apply_switch
+      (data + _push_marker, _pack_data.get_length() - _push_marker);
 
   } else if (_mode == M_unpack) {
-    new_parent = dswitch->apply_switch(_unpack_data + _push_marker,
-                                       _unpack_p - _push_marker);
-
+    new_parent = switch_parameter->apply_switch
+      (_unpack_data + _push_marker, _unpack_p - _push_marker);
   }
 
   if (new_parent == (DCPackerInterface *)NULL) {
@@ -1043,7 +1047,7 @@ handle_switch(const DCSwitch *dswitch) {
     return;
   }
 
-  _last_switch = dswitch;
+  _last_switch = switch_parameter;
 
   // Now substitute in the switch case for the previous parent (which
   // replaces the switch node itself).  This will suddenly make a slew

+ 4 - 4
direct/src/dcparser/dcPacker.h

@@ -27,7 +27,7 @@
 #include "dcPython.h"
 
 class DCClass;
-class DCSwitch;
+class DCSwitchParametera;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : DCPacker
@@ -69,7 +69,7 @@ PUBLISHED:
 
   INLINE const DCPackerInterface *get_current_parent() const;
   INLINE const DCPackerInterface *get_current_field() const;
-  INLINE const DCSwitch *get_last_switch() const;
+  INLINE const DCSwitchParameter *get_last_switch() const;
   INLINE DCPackType get_pack_type() const;
 
   void push();
@@ -174,7 +174,7 @@ public:
 
 private:
   INLINE void advance();
-  void handle_switch(const DCSwitch *dswitch);
+  void handle_switch(const DCSwitchParameter *switch_parameter);
   void clear();
 
 #ifdef HAVE_PYTHON
@@ -226,7 +226,7 @@ private:
   // use.
   size_t _pop_marker;
   int _num_nested_fields;
-  const DCSwitch *_last_switch;
+  const DCSwitchParameter *_last_switch;
 
   bool _pack_error;
   bool _range_error;

+ 10 - 9
direct/src/dcparser/dcPackerCatalog.cxx

@@ -19,7 +19,7 @@
 #include "dcPackerCatalog.h"
 #include "dcPackerInterface.h"
 #include "dcPacker.h"
-#include "dcSwitch.h"
+#include "dcSwitchParameter.h"
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerCatalog::Constructor
@@ -135,7 +135,7 @@ get_live_catalog(const char *data, size_t length) const {
   DCPacker packer;
   packer.set_unpack_data(data, length, false);
   packer.begin_unpack(_root);
-  const DCSwitch *last_switch = NULL;
+  const DCSwitchParameter *last_switch = NULL;
   r_fill_live_catalog(live_catalog, packer, last_switch);
   bool okflag = packer.end_unpack();
 
@@ -207,7 +207,7 @@ r_fill_catalog(const string &name_prefix, const DCPackerInterface *field,
                const DCPackerInterface *parent, int field_index) {
   string next_name_prefix = name_prefix;
 
-  if (!field->get_name().empty()) {
+  if (parent != (const DCPackerInterface *)NULL && !field->get_name().empty()) {
     // Record this entry in the catalog.
     next_name_prefix += field->get_name();
     add_entry(next_name_prefix, field, parent, field_index);
@@ -215,14 +215,14 @@ r_fill_catalog(const string &name_prefix, const DCPackerInterface *field,
     next_name_prefix += ".";
   }
 
-  const DCSwitch *dswitch = ((DCPackerInterface *)field)->as_switch();
-  if (dswitch != (DCSwitch *)NULL) {
+  const DCSwitchParameter *switch_parameter = ((DCPackerInterface *)field)->as_switch_parameter();
+  if (switch_parameter != (DCSwitchParameter *)NULL) {
     // If we come upon a DCSwitch while building the catalog, save the
     // name_prefix at this point so we'll have it again when we later
     // encounter the switch while unpacking a live record (and so we
     // can return to this point in the recursion from
     // update_switch_fields).
-    _switch_prefixes[dswitch] = next_name_prefix;
+    _switch_prefixes[switch_parameter] = next_name_prefix;
   }
 
   // Add any children.
@@ -247,7 +247,7 @@ r_fill_catalog(const string &name_prefix, const DCPackerInterface *field,
 ////////////////////////////////////////////////////////////////////
 void DCPackerCatalog::
 r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer,
-                    const DCSwitch *&last_switch) const {
+                    const DCSwitchParameter *&last_switch) const {
   const DCPackerInterface *current_field = packer.get_current_field();
 
   int field_index = live_catalog->find_entry_by_field(current_field);
@@ -281,6 +281,7 @@ r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer,
     nassertv(switch_case != (DCPackerInterface *)NULL);
     const DCPackerCatalog *switch_catalog = 
       live_catalog->_catalog->update_switch_fields(last_switch, switch_case);
+    nassertv(switch_catalog != (DCPackerCatalog *)NULL);
     live_catalog->_catalog = switch_catalog;
 
     // And we also have to expand the live catalog to hold the new
@@ -315,7 +316,7 @@ r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer,
 //               pointer is kept by this object.
 ////////////////////////////////////////////////////////////////////
 const DCPackerCatalog *DCPackerCatalog::
-update_switch_fields(const DCSwitch *dswitch,
+update_switch_fields(const DCSwitchParameter *switch_parameter,
                      const DCPackerInterface *switch_case) const {
   SwitchCatalogs::const_iterator si = _switch_catalogs.find(switch_case);
   if (si != _switch_catalogs.end()) {
@@ -326,7 +327,7 @@ update_switch_fields(const DCSwitch *dswitch,
   // descend from this switch.  This should be stored in this record
   // because we must have come across the DCSwitch when building the
   // catalog the first time.
-  SwitchPrefixes::const_iterator pi = _switch_prefixes.find(dswitch);
+  SwitchPrefixes::const_iterator pi = _switch_prefixes.find(switch_parameter);
   nassertr(pi != _switch_prefixes.end(), NULL);
   string name_prefix = (*pi).second;
 

+ 4 - 4
direct/src/dcparser/dcPackerCatalog.h

@@ -23,7 +23,7 @@
 
 class DCPackerInterface;
 class DCPacker;
-class DCSwitch;
+class DCSwitchParameter;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : DCPackerCatalog
@@ -92,9 +92,9 @@ private:
   void r_fill_catalog(const string &name_prefix, const DCPackerInterface *field,
                       const DCPackerInterface *parent, int field_index);
   void r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer,
-                           const DCSwitch *&last_switch) const;
+                           const DCSwitchParameter *&last_switch) const;
 
-  const DCPackerCatalog *update_switch_fields(const DCSwitch *dswitch,
+  const DCPackerCatalog *update_switch_fields(const DCSwitchParameter *dswitch,
                                               const DCPackerInterface *switch_case) const;
     
 
@@ -113,7 +113,7 @@ private:
   typedef pmap<const DCPackerInterface *, DCPackerCatalog *> SwitchCatalogs;
   SwitchCatalogs _switch_catalogs;
 
-  typedef pmap<const DCSwitch *, string> SwitchPrefixes;
+  typedef pmap<const DCSwitchParameter *, string> SwitchPrefixes;
   SwitchPrefixes _switch_prefixes;
 
   friend class DCPackerInterface;

+ 4 - 16
direct/src/dcparser/dcPackerInterface.cxx

@@ -84,9 +84,9 @@ as_field() {
 //       Access: Published, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-DCSwitch *DCPackerInterface::
-as_switch() {
-  return (DCSwitch *)NULL;
+DCSwitchParameter *DCPackerInterface::
+as_switch_parameter() {
+  return (DCSwitchParameter *)NULL;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -326,17 +326,5 @@ make_catalog() {
   nassertv(_catalog == (DCPackerCatalog *)NULL);
   _catalog = new DCPackerCatalog(this);
 
-  if (has_nested_fields()) {
-    int num_nested = get_num_nested_fields();
-    // num_nested might be -1, indicating there are a dynamic number
-    // of fields (e.g. an array).  But in that case, none of the
-    // fields will be named anyway, so we don't care about them, so
-    // it's ok that the following loop will not visit any fields.
-    for (int i = 0; i < num_nested; i++) {
-      DCPackerInterface *nested = get_nested_field(i);
-      if (nested != (DCPackerInterface *)NULL) {
-        _catalog->r_fill_catalog("", nested, this, i);
-      }
-    }
-  }
+  _catalog->r_fill_catalog("", this, NULL, 0);
 }

+ 5 - 4
direct/src/dcparser/dcPackerInterface.h

@@ -23,7 +23,7 @@
 #include "dcSubatomicType.h"
 
 class DCField;
-class DCSwitch;
+class DCSwitchParameter;
 class DCClassParameter;
 class DCPackData;
 class DCPackerCatalog;
@@ -77,7 +77,7 @@ PUBLISHED:
   INLINE const string &get_name() const;
 
   virtual DCField *as_field();
-  virtual DCSwitch *as_switch();
+  virtual DCSwitchParameter *as_switch_parameter();
   virtual DCClassParameter *as_class_parameter();
 
 public:
@@ -159,6 +159,9 @@ public:
 
   const DCPackerCatalog *get_catalog() const;
 
+private:
+  void make_catalog();
+
 protected:
   string _name;
   bool _has_fixed_byte_size;
@@ -170,8 +173,6 @@ protected:
   DCPackType _pack_type;
 
 private:
-  void make_catalog();
-
   DCPackerCatalog *_catalog;
 };
 

+ 39 - 9
direct/src/dcparser/dcParameter.cxx

@@ -122,7 +122,7 @@ set_typedef(const DCTypedef *dtypedef) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCParameter::output
-//       Access: Public
+//       Access: Public, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void DCParameter::
@@ -131,21 +131,34 @@ output(ostream &out, bool brief) const {
   if (!brief) {
     name = get_name();
   }
-  output_instance(out, "", name, "");
+  output_instance(out, brief, "", name, "");
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCParameter::write
-//       Access: Public
+//       Access: Public, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void DCParameter::
-write(ostream &out, bool, int indent_level) const {
+write(ostream &out, bool brief, int indent_level) const {
   // we must always output the name when the parameter occurs by
-  // itself within a class, so we ignore brief and pass false up to
-  // output().
+  // itself within a class, so we pass get_name() even if brief is
+  // true.
+  write_instance(out, brief, indent_level, "", get_name(), "");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCParameter::write_instance
+//       Access: Public, Virtual
+//  Description: Formats the parameter in the C++-like dc syntax as a
+//               typename and identifier.
+////////////////////////////////////////////////////////////////////
+void DCParameter::
+write_instance(ostream &out, bool brief, int indent_level,
+               const string &prename, const string &name, 
+               const string &postname) const {
   indent(out, indent_level);
-  output(out, false);
+  output_instance(out, brief, prename, name, postname);
   out << ";\n";
 }
 
@@ -156,14 +169,31 @@ write(ostream &out, bool, int indent_level) const {
 //               the typedef name instead.
 ////////////////////////////////////////////////////////////////////
 void DCParameter::
-output_typedef_name(ostream &out, const string &prename, const string &name, 
-                    const string &postname) const {
+output_typedef_name(ostream &out, bool, const string &prename,
+                    const string &name, const string &postname) const {
   out << get_typedef()->get_name();
   if (!prename.empty() || !name.empty() || !postname.empty()) {
     out << " " << prename << name << postname;
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCParameter::write_typedef_name
+//       Access: Public
+//  Description: Formats the instance like write_instance, but uses
+//               the typedef name instead.
+////////////////////////////////////////////////////////////////////
+void DCParameter::
+write_typedef_name(ostream &out, bool, int indent_level, const string &prename,
+                   const string &name, const string &postname) const {
+  indent(out, indent_level)
+    << get_typedef()->get_name();
+  if (!prename.empty() || !name.empty() || !postname.empty()) {
+    out << " " << prename << name << postname;
+  }
+  out << ";\n";
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCParameter::generate_hash
 //       Access: Public, Virtual

+ 9 - 3
direct/src/dcparser/dcParameter.h

@@ -60,12 +60,18 @@ PUBLISHED:
 public:
   void set_typedef(const DCTypedef *dtypedef);
 
-  void output(ostream &out, bool brief) const;
+  virtual void output(ostream &out, bool brief) const;
   virtual void write(ostream &out, bool brief, int indent_level) const;
-  virtual void output_instance(ostream &out, const string &prename, 
+  virtual void output_instance(ostream &out, bool brief, const string &prename, 
                                const string &name, const string &postname) const=0;
-  void output_typedef_name(ostream &out, const string &prename, 
+  virtual void write_instance(ostream &out, bool brief, int indent_level,
+                              const string &prename, const string &name,
+                              const string &postname) const;
+  void output_typedef_name(ostream &out, bool brief, const string &prename, 
                            const string &name, const string &postname) const;
+  void write_typedef_name(ostream &out, bool brief, int indent_level,
+                          const string &prename, const string &name, 
+                          const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 
 private:

+ 45 - 15
direct/src/dcparser/dcParser.yxx

@@ -12,6 +12,7 @@
 #include "dcAtomicField.h"
 #include "dcMolecularField.h"
 #include "dcClassParameter.h"
+#include "dcSwitchParameter.h"
 #include "dcArrayParameter.h"
 #include "dcSimpleParameter.h"
 #include "dcTypedef.h"
@@ -116,12 +117,13 @@ dc_cleanup_parser() {
 
 %type <u.flag> kw_struct_or_kw_dclass
 %type <u.dclass> dclass_name
+%type <u.dclass> dclass
+%type <u.dswitch> switch
 %type <u.atomic> atomic_name
 %type <u.field> dclass_field
 %type <u.field> switch_field
 %type <u.field> atomic_field
 %type <u.field> molecular_field
-%type <u.field> switch
 %type <u.subatomic> type_token
 %type <u.parameter> type_name
 %type <u.parameter> type_definition
@@ -150,24 +152,37 @@ dc:
         empty
         | dc ';'
         | dc dclass
+{
+  if (!dc_file->add_class($2)) {
+    DCClass *old_class = dc_file->get_class_by_name($2->get_name());
+    if (old_class != (DCClass *)NULL && old_class->is_bogus_class()) {
+      yyerror("Base class defined after its first reference: " + $2->get_name());
+    } else {
+      yyerror("Duplicate class name: " + $2->get_name());
+    }
+  }
+}
+        | dc switch
+{
+  if (!dc_file->add_switch($2)) {
+    yyerror("Duplicate class name: " + $2->get_name());
+  }
+}
         | dc import
         | dc typedef_decl
         ;
 
 dclass:
-        kw_struct_or_kw_dclass IDENTIFIER 
+        kw_struct_or_kw_dclass optional_name 
 {
+  $$ = current_class;
   current_class = new DCClass($2, $1, false);
-  if (!dc_file->add_class(current_class)) {
-    DCClass *old_class = dc_file->get_class_by_name(current_class->get_name());
-    if (old_class->is_bogus_class()) {
-      yyerror("Base class defined after its first reference: " + current_class->get_name());
-    } else {
-      yyerror("Duplicate class name: " + current_class->get_name());
-    }
-  }
 }
         dclass_derivation '{' dclass_fields '}'
+{
+  $$ = current_class;
+  current_class = $<u.dclass>3;
+}
         ;
 
 kw_struct_or_kw_dclass:
@@ -291,7 +306,6 @@ dclass_fields:
 dclass_field:
 	atomic_field
 	| molecular_field
-	| switch
 	| unnamed_parameter ';'
 {
   $$ = $1;
@@ -332,6 +346,7 @@ atomic_element:
 	| parameter '=' 
 {
   current_packer = &default_packer;
+  current_packer->clear_data();
   current_packer->begin_pack($1);
 }
 	parameter_value
@@ -435,14 +450,29 @@ type_name:
       // Create an implicit typedef for this.
       dtypedef = new DCTypedef(new DCClassParameter(dclass), true);
     } else {
-      // It's an undefined typedef.  Create a bogus forward reference.
-      dtypedef = new DCTypedef($1);
+      // Maybe it's a switch name.
+      DCSwitch *dswitch = dc_file->get_switch_by_name($1);
+      if (dswitch != (DCSwitch *)NULL) {
+        // This also gets an implicit typedef.
+        dtypedef = new DCTypedef(new DCSwitchParameter(dswitch), true);
+      } else {
+        // It's an undefined typedef.  Create a bogus forward reference.
+        dtypedef = new DCTypedef($1);
+      }
     }
 
     dc_file->add_typedef(dtypedef);
   }
 
   $$ = dtypedef->make_new_parameter();
+}
+	| dclass
+{
+  $$ = new DCClassParameter($1);
+}
+	| switch
+{
+  $$ = new DCSwitchParameter($1);
 }
 	;
 
@@ -917,6 +947,7 @@ switch_case:
 	KW_CASE
 {
   current_packer = &default_packer;
+  current_packer->clear_data();
   current_packer->begin_pack(current_switch->get_key_parameter());
 }
 	parameter_value ':'
@@ -930,8 +961,7 @@ switch_case:
 	;
 
 switch_field:
-	switch
-	| unnamed_parameter ';'
+	unnamed_parameter ';'
 {
   $$ = $1;
 }

+ 2 - 0
direct/src/dcparser/dcParserDefs.h

@@ -24,6 +24,7 @@
 
 class DCFile;
 class DCClass;
+class DCSwitch;
 class DCField;
 class DCAtomicField;
 class DCParameter;
@@ -52,6 +53,7 @@ public:
     double real;
     bool flag;
     DCClass *dclass;
+    DCSwitch *dswitch;
     DCField *field;
     DCAtomicField *atomic;
     DCSubatomicType subatomic;

+ 3 - 3
direct/src/dcparser/dcSimpleParameter.cxx

@@ -1942,10 +1942,10 @@ unpack_skip(const char *data, size_t length, size_t &p) const {
 //               typename and identifier.
 ////////////////////////////////////////////////////////////////////
 void DCSimpleParameter::
-output_instance(ostream &out, const string &prename, const string &name, 
-                const string &postname) const {
+output_instance(ostream &out, bool brief, const string &prename,
+                const string &name, const string &postname) const {
   if (get_typedef() != (DCTypedef *)NULL) {
-    output_typedef_name(out, prename, name, postname);
+    output_typedef_name(out, brief, prename, name, postname);
 
   } else {
     out << _type;

+ 1 - 1
direct/src/dcparser/dcSimpleParameter.h

@@ -82,7 +82,7 @@ public:
                                bool &pack_error, bool &range_error) const;
   virtual bool unpack_skip(const char *data, size_t length, size_t &p) const;
 
-  virtual void output_instance(ostream &out, const string &prename, 
+  virtual void output_instance(ostream &out, bool brief, const string &prename, 
                                const string &name, const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 

+ 80 - 52
direct/src/dcparser/dcSwitch.cxx

@@ -29,21 +29,9 @@
 ////////////////////////////////////////////////////////////////////
 DCSwitch::
 DCSwitch(const string &name, DCParameter *key_parameter) :
-  DCField(name),
+  _name(name),
   _key_parameter(key_parameter)
 {
-  _has_fixed_byte_size = _key_parameter->has_fixed_byte_size();
-  _fixed_byte_size = _key_parameter->get_fixed_byte_size();
-  _has_fixed_structure = false;
-
-  // The DCSwitch presents just one nested field initially, which is
-  // the key parameter.  When we pack or unpack that, the DCPacker
-  // calls apply_switch(), which returns a new record that presents
-  // the remaining nested fields.
-  _has_nested_fields = true;
-  _num_nested_fields = 1;
-
-  _pack_type = PT_switch;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -72,6 +60,16 @@ as_switch() {
   return this;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitch::get_name
+//       Access: Published
+//  Description: Returns the name of this switch.
+////////////////////////////////////////////////////////////////////
+const string &DCSwitch::
+get_name() const {
+  return _name;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSwitch::get_key_parameter
 //       Access: Published
@@ -115,6 +113,17 @@ get_case_by_value(const string &case_value) const {
   return -1;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitch::get_case
+//       Access: Published
+//  Description: Returns the DCPackerInterface that packs the nth case.
+////////////////////////////////////////////////////////////////////
+DCPackerInterface *DCSwitch::
+get_case(int n) const {
+  nassertr(n >= 0 && n < (int)_cases.size(), NULL);
+  return _cases[n];
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSwitch::get_value
 //       Access: Published
@@ -170,23 +179,6 @@ get_field_by_name(int case_index, const string &name) const {
   return NULL;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DCSwitch::get_nested_field
-//       Access: Public, Virtual
-//  Description: Returns the DCPackerInterface object that represents
-//               the nth nested field.  This may return NULL if there
-//               is no such field (but it shouldn't do this if n is in
-//               the range 0 <= n < get_num_nested_fields()).
-////////////////////////////////////////////////////////////////////
-DCPackerInterface *DCSwitch::
-get_nested_field(int) const {
-  // The DCSwitch presents just one nested field initially, which is
-  // the key parameter.  When we pack or unpack that, the DCPacker
-  // calls apply_switch(), which returns a new record that presents
-  // the remaining nested fields.
-  return _key_parameter;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSwitch::add_case
 //       Access: Public
@@ -225,26 +217,6 @@ add_field(DCField *field) {
   if (!_cases.back()->add_field(field)) {
     return false;
   }
-
-  // See if we now have a fixed byte size for the overall switch.
-  // This will be true only if all of the individual cases have the
-  // same fixed byte size.
-  _fixed_byte_size = _cases.back()->get_fixed_byte_size();
-
-  Cases::const_iterator ci;
-  for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
-    const SwitchCase *dcase = (*ci);
-    if (!dcase->has_fixed_byte_size() || 
-        dcase->get_fixed_byte_size() != _fixed_byte_size) {
-
-      // Nope, we have a variable byte size.
-      _has_fixed_byte_size = false;
-      return true;
-    }
-  }
-
-  // Sonofagun, we do have a fixed byte size.
-  _has_fixed_byte_size = true;
   return true;
 }
 
@@ -276,6 +248,58 @@ apply_switch(const char *value_data, size_t length) const {
 ////////////////////////////////////////////////////////////////////
 void DCSwitch::
 write(ostream &out, bool brief, int indent_level) const {
+  write_instance(out, brief, indent_level, "", "", "");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::output_instance
+//       Access: Public
+//  Description: Generates a parseable description of the object to
+//               the indicated output stream.
+////////////////////////////////////////////////////////////////////
+void DCSwitch::
+output_instance(ostream &out, bool brief, const string &prename, 
+                const string &name, const string &postname) const {
+  out << "switch";
+  if (!_name.empty()) {
+    out << " " << _name;
+  }
+  out << " (";
+  _key_parameter->output(out, brief);
+  out << ") {";
+
+  Cases::const_iterator ci;
+  for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
+    const SwitchCase *dcase = (*ci);
+    out << "case " << _key_parameter->format_data(dcase->_value) << ": ";
+    
+    Fields::const_iterator fi;
+    if (!dcase->_fields.empty()) {
+      fi = dcase->_fields.begin();
+      ++fi;
+      while (fi != dcase->_fields.end()) {
+        (*fi)->output(out, brief);
+        out << "; ";
+        ++fi;
+      }
+    }
+  }
+  out << "}";
+  if (!prename.empty() || !name.empty() || !postname.empty()) {
+    out << " " << prename << name << postname;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitch::write_instance
+//       Access: Public, Virtual
+//  Description: Generates a parseable description of the object to
+//               the indicated output stream.
+////////////////////////////////////////////////////////////////////
+void DCSwitch::
+write_instance(ostream &out, bool brief, int indent_level,
+               const string &prename, const string &name, 
+               const string &postname) const {
   indent(out, indent_level)
     << "switch";
   if (!_name.empty()) {
@@ -302,7 +326,11 @@ write(ostream &out, bool brief, int indent_level) const {
     }
   }
   indent(out, indent_level)
-    << "};\n";
+    << "}";
+  if (!prename.empty() || !name.empty() || !postname.empty()) {
+    out << " " << prename << name << postname;
+  }
+  out << ";\n";
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -313,7 +341,7 @@ write(ostream &out, bool brief, int indent_level) const {
 ////////////////////////////////////////////////////////////////////
 void DCSwitch::
 generate_hash(HashGenerator &hashgen) const {
-  DCField::generate_hash(hashgen);
+  hashgen.add_string(_name);
 
   _key_parameter->generate_hash(hashgen);
 

+ 10 - 4
direct/src/dcparser/dcSwitch.h

@@ -20,7 +20,7 @@
 #define DCSWITCH_H
 
 #include "dcbase.h"
-#include "dcField.h"
+#include "dcDeclaration.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : DCSwitch
@@ -29,7 +29,7 @@
 //               alternative unpacking schemes based on the first
 //               field read.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_DIRECT DCSwitch : public DCField {
+class EXPCL_DIRECT DCSwitch : public DCDeclaration {
 public:
   DCSwitch(const string &name, DCParameter *key_parameter);
   virtual ~DCSwitch();
@@ -37,10 +37,12 @@ public:
 PUBLISHED:
   virtual DCSwitch *as_switch();
 
+  const string &get_name() const;
   DCParameter *get_key_parameter() const;
 
   int get_num_cases() const;
   int get_case_by_value(const string &case_value) const;
+  DCPackerInterface *get_case(int n) const;
 
   string get_value(int case_index) const;
   int get_num_fields(int case_index) const;
@@ -48,17 +50,21 @@ PUBLISHED:
   DCField *get_field_by_name(int case_index, const string &name) const;
 
 public:
-  virtual DCPackerInterface *get_nested_field(int n) const;
-
   int add_case(const string &value);
   bool add_field(DCField *field);
 
   const DCPackerInterface *apply_switch(const char *value_data, size_t length) const;
 
   virtual void write(ostream &out, bool brief, int indent_level) const;
+  void output_instance(ostream &out, bool brief, const string &prename, 
+                       const string &name, const string &postname) const;
+  void write_instance(ostream &out, bool brief, int indent_level,
+                      const string &prename, const string &name,
+                      const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 
 private:
+  string _name;
   DCParameter *_key_parameter;
 
   typedef pvector<DCField *> Fields;

+ 198 - 0
direct/src/dcparser/dcSwitchParameter.cxx

@@ -0,0 +1,198 @@
+// Filename: dcSwitchParameter.cxx
+// Created by:  drose (18Jun04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "dcSwitchParameter.h"
+#include "dcSwitch.h"
+#include "hashGenerator.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCSwitchParameter::
+DCSwitchParameter(DCSwitch *dswitch) :
+  _dswitch(dswitch)
+{
+  set_name(dswitch->get_name());
+
+  _has_fixed_byte_size = false;
+  _has_fixed_structure = false;
+
+  // The DCSwitch presents just one nested field initially, which is
+  // the key parameter.  When we pack or unpack that, the DCPacker
+  // calls apply_switch(), which returns a new record that presents
+  // the remaining nested fields.
+  _has_nested_fields = true;
+  _num_nested_fields = 1;
+
+  _pack_type = PT_switch;
+
+  DCParameter *key_parameter = dswitch->get_key_parameter();
+  if (key_parameter->has_fixed_byte_size()) {
+    // See if we have a fixed byte size for the overall switch.  This
+    // will be true only if all of the individual cases have the same
+    // fixed byte size.
+    int num_cases = _dswitch->get_num_cases();
+    _has_fixed_byte_size = true;
+    _fixed_byte_size = 0;
+
+    if (num_cases > 0) {
+      _fixed_byte_size = _dswitch->get_case(0)->get_fixed_byte_size();
+
+      for (int i = 0; i < num_cases && _has_fixed_byte_size; i++) {
+        const DCPackerInterface *dcase = _dswitch->get_case(i);
+        if (!dcase->has_fixed_byte_size() || 
+            dcase->get_fixed_byte_size() != _fixed_byte_size) {
+          
+          // Nope, we have a variable byte size.
+          _has_fixed_byte_size = false;
+        }
+      }
+    }
+
+    _fixed_byte_size += key_parameter->get_fixed_byte_size();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCSwitchParameter::
+DCSwitchParameter(const DCSwitchParameter &copy) :
+  DCParameter(copy),
+  _dswitch(copy._dswitch)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::as_switch_parameter
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCSwitchParameter *DCSwitchParameter::
+as_switch_parameter() {
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::make_copy
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCParameter *DCSwitchParameter::
+make_copy() const {
+  return new DCSwitchParameter(*this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::is_valid
+//       Access: Published, Virtual
+//  Description: Returns false if the type is an invalid type
+//               (e.g. declared from an undefined typedef), true if
+//               it is valid.
+////////////////////////////////////////////////////////////////////
+bool DCSwitchParameter::
+is_valid() const {
+  return true; //_dswitch->is_valid();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::get_switch
+//       Access: Published
+//  Description: Returns the switch object this parameter represents.
+////////////////////////////////////////////////////////////////////
+DCSwitch *DCSwitchParameter::
+get_switch() const {
+  return _dswitch;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::get_nested_field
+//       Access: Public, Virtual
+//  Description: Returns the DCPackerInterface object that represents
+//               the nth nested field.  This may return NULL if there
+//               is no such field (but it shouldn't do this if n is in
+//               the range 0 <= n < get_num_nested_fields()).
+////////////////////////////////////////////////////////////////////
+DCPackerInterface *DCSwitchParameter::
+get_nested_field(int) const {
+  return _dswitch->get_key_parameter();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::apply_switch
+//       Access: Public
+//  Description: Returns the DCPackerInterface that presents the
+//               alternative fields for the case indicated by the
+//               given packed value string, or NULL if the value
+//               string does not match one of the expected cases.
+////////////////////////////////////////////////////////////////////
+const DCPackerInterface *DCSwitchParameter::
+apply_switch(const char *value_data, size_t length) const {
+  return _dswitch->apply_switch(value_data, length);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::output_instance
+//       Access: Public, Virtual
+//  Description: Formats the parameter in the C++-like dc syntax as a
+//               typename and identifier.
+////////////////////////////////////////////////////////////////////
+void DCSwitchParameter::
+output_instance(ostream &out, bool brief, const string &prename, 
+                const string &name, const string &postname) const {
+  if (get_typedef() != (DCTypedef *)NULL) {
+    output_typedef_name(out, brief, prename, name, postname);
+
+  } else {
+    _dswitch->output_instance(out, brief, prename, name, postname);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::write_instance
+//       Access: Public, Virtual
+//  Description: Formats the parameter in the C++-like dc syntax as a
+//               typename and identifier.
+////////////////////////////////////////////////////////////////////
+void DCSwitchParameter::
+write_instance(ostream &out, bool brief, int indent_level,
+               const string &prename, const string &name, 
+               const string &postname) const {
+  if (get_typedef() != (DCTypedef *)NULL) {
+    write_typedef_name(out, brief, indent_level, prename, name, postname);
+
+  } else {
+    _dswitch->write_instance(out, brief, indent_level, prename, name, postname);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::generate_hash
+//       Access: Public, Virtual
+//  Description: Accumulates the properties of this type into the
+//               hash.
+////////////////////////////////////////////////////////////////////
+void DCSwitchParameter::
+generate_hash(HashGenerator &hashgen) const {
+  DCParameter::generate_hash(hashgen);
+  _dswitch->generate_hash(hashgen);
+}

+ 61 - 0
direct/src/dcparser/dcSwitchParameter.h

@@ -0,0 +1,61 @@
+// Filename: dcClassParameter.h
+// Created by:  drose (29Jun04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef DCSWITCHPARAMETER_H
+#define DCSWITCHPARAMETER_H
+
+#include "dcbase.h"
+#include "dcParameter.h"
+
+class DCSwitch;
+
+////////////////////////////////////////////////////////////////////
+//       Class : DCSwitchParameter
+// Description : This represents a switch object used as a
+//               parameter itself, which packs the appropriate fields
+//               of the switch into the message.
+////////////////////////////////////////////////////////////////////
+class EXPCL_DIRECT DCSwitchParameter : public DCParameter {
+public:
+  DCSwitchParameter(DCSwitch *dswitch);
+  DCSwitchParameter(const DCSwitchParameter &copy);
+
+PUBLISHED:
+  virtual DCSwitchParameter *as_switch_parameter();
+  virtual DCParameter *make_copy() const;
+  virtual bool is_valid() const;
+
+  DCSwitch *get_switch() const;
+
+public:
+  virtual DCPackerInterface *get_nested_field(int n) const;
+
+  const DCPackerInterface *apply_switch(const char *value_data, size_t length) const;
+
+  virtual void output_instance(ostream &out, bool brief, const string &prename, 
+                               const string &name, const string &postname) const;
+  virtual void write_instance(ostream &out, bool brief, int indent_level,
+                              const string &prename, const string &name,
+                              const string &postname) const;
+  virtual void generate_hash(HashGenerator &hashgen) const;
+
+private:
+  DCSwitch *_dswitch;
+};
+
+#endif

+ 1 - 0
direct/src/dcparser/dcparser_composite2.cxx

@@ -3,6 +3,7 @@
 #include "dcClassParameter.cxx"
 #include "dcArrayParameter.cxx"
 #include "dcSimpleParameter.cxx"
+#include "dcSwitchParameter.cxx"
 #include "dcField.cxx"
 #include "dcFile.cxx"
 #include "dcMolecularField.cxx"