Bläddra i källkod

add check_match

David Rose 21 år sedan
förälder
incheckning
37b1ea93da

+ 51 - 0
direct/src/dcparser/dcArrayParameter.cxx

@@ -17,6 +17,8 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "dcArrayParameter.h"
+#include "dcSimpleParameter.h"
+#include "dcClassParameter.h"
 #include "hashGenerator.h"
 
 ////////////////////////////////////////////////////////////////////
@@ -276,3 +278,52 @@ pack_default_value(DCPackData &pack_data, bool &pack_error) const {
 
   return true;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCArrayParameter::do_check_match
+//       Access: Protected, Virtual
+//  Description: Returns true if the other interface is bitwise the
+//               same as this one--that is, a uint32 only matches a
+//               uint32, etc. Names of components, and range limits,
+//               are not compared.
+////////////////////////////////////////////////////////////////////
+bool DCArrayParameter::
+do_check_match(const DCPackerInterface *other) const {
+  return other->do_check_match_array_parameter(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCArrayParameter::do_check_match_simple_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               simple parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCArrayParameter::
+do_check_match_simple_parameter(const DCSimpleParameter *other) const {
+  return ((const DCPackerInterface *)other)->do_check_match_array_parameter(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCArrayParameter::do_check_match_class_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               class parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCArrayParameter::
+do_check_match_class_parameter(const DCClassParameter *other) const {
+  return ((const DCPackerInterface *)other)->do_check_match_array_parameter(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCArrayParameter::do_check_match_array_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               array parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCArrayParameter::
+do_check_match_array_parameter(const DCArrayParameter *other) const {
+  if (_array_size != other->_array_size) {
+    return false;
+  }
+  return _element_type->check_match(other->_element_type);
+}

+ 6 - 0
direct/src/dcparser/dcArrayParameter.h

@@ -56,6 +56,12 @@ public:
   virtual void generate_hash(HashGenerator &hashgen) const;
   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
+protected:
+  virtual bool do_check_match(const DCPackerInterface *other) const;
+  virtual bool do_check_match_simple_parameter(const DCSimpleParameter *other) const;
+  virtual bool do_check_match_class_parameter(const DCClassParameter *other) const;
+  virtual bool do_check_match_array_parameter(const DCArrayParameter *other) const;
+
 private:
   DCParameter *_element_type;
   int _array_size;

+ 33 - 0
direct/src/dcparser/dcAtomicField.cxx

@@ -284,6 +284,39 @@ add_element(DCParameter *element) {
   _default_value_stale = true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::do_check_match
+//       Access: Protected, Virtual
+//  Description: Returns true if the other interface is bitwise the
+//               same as this one--that is, a uint32 only matches a
+//               uint32, etc. Names of components, and range limits,
+//               are not compared.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::
+do_check_match(const DCPackerInterface *other) const {
+  return other->do_check_match_atomic_field(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::do_check_match_atomic_field
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               atomic field, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::
+do_check_match_atomic_field(const DCAtomicField *other) const {
+  if (_elements.size() != other->_elements.size()) {
+    return false;
+  }
+  for (size_t i = 0; i < _elements.size(); i++) {
+    if (!_elements[i]->check_match(other->_elements[i])) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCAtomicField::output_element
 //       Access: Private

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

@@ -63,6 +63,10 @@ public:
 
   virtual DCPackerInterface *get_nested_field(int n) const;
 
+protected:
+  virtual bool do_check_match(const DCPackerInterface *other) const;
+  virtual bool do_check_match_atomic_field(const DCAtomicField *other) const;
+
 private:
   void output_element(ostream &out, bool brief, DCParameter *element) const;
 

+ 20 - 18
direct/src/dcparser/dcClass.cxx

@@ -876,27 +876,29 @@ generate_hash(HashGenerator &hashgen) const {
 ////////////////////////////////////////////////////////////////////
 bool DCClass::
 add_field(DCField *field) {
-  if (!_name.empty() && field->get_name() == _name) {
-    // This field is a constructor.
-    if (_constructor != (DCField *)NULL) {
-      // We already have a constructor.
-      return false;
-    }
-    if (field->as_atomic_field() == (DCAtomicField *)NULL) {
-      // The constructor must be an atomic field.
-      return false;
+  if (!field->get_name().empty()) {
+    if (field->get_name() == _name) {
+      // This field is a constructor.
+      if (_constructor != (DCField *)NULL) {
+        // We already have a constructor.
+        return false;
+      }
+      if (field->as_atomic_field() == (DCAtomicField *)NULL) {
+        // The constructor must be an atomic field.
+        return false;
+      }
+      _constructor = field;
+      _fields_by_name.insert
+        (FieldsByName::value_type(field->get_name(), field));
+      return true;
     }
-    _constructor = field;
-    _fields_by_name.insert
-      (FieldsByName::value_type(field->get_name(), field));
-    return true;
-  }
 
-  bool inserted = _fields_by_name.insert
-    (FieldsByName::value_type(field->get_name(), field)).second;
+    bool inserted = _fields_by_name.insert
+      (FieldsByName::value_type(field->get_name(), field)).second;
 
-  if (!inserted) {
-    return false;
+    if (!inserted) {
+      return false;
+    }
   }
 
   if (!is_struct()) {

+ 58 - 0
direct/src/dcparser/dcClassParameter.cxx

@@ -18,6 +18,7 @@
 
 #include "dcClassParameter.h"
 #include "dcClass.h"
+#include "dcArrayParameter.h"
 #include "hashGenerator.h"
 
 ////////////////////////////////////////////////////////////////////
@@ -176,3 +177,60 @@ generate_hash(HashGenerator &hashgen) const {
   DCParameter::generate_hash(hashgen);
   _dclass->generate_hash(hashgen);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCClassParameter::do_check_match
+//       Access: Protected, Virtual
+//  Description: Returns true if the other interface is bitwise the
+//               same as this one--that is, a uint32 only matches a
+//               uint32, etc. Names of components, and range limits,
+//               are not compared.
+////////////////////////////////////////////////////////////////////
+bool DCClassParameter::
+do_check_match(const DCPackerInterface *other) const {
+  return other->do_check_match_class_parameter(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCClassParameter::do_check_match_class_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               class parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCClassParameter::
+do_check_match_class_parameter(const DCClassParameter *other) const {
+  if (_nested_fields.size() != other->_nested_fields.size()) {
+    return false;
+  }
+  for (size_t i = 0; i < _nested_fields.size(); i++) {
+    if (!_nested_fields[i]->check_match(other->_nested_fields[i])) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCClassParameter::do_check_match_array_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               array parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCClassParameter::
+do_check_match_array_parameter(const DCArrayParameter *other) const {
+  if ((int)_nested_fields.size() != other->get_array_size()) {
+    // We can only match a fixed-size array whose size happens to
+    // exactly match our number of fields.
+    return false;
+  }
+
+  const DCPackerInterface *element_type = other->get_element_type();
+  for (size_t i = 0; i < _nested_fields.size(); i++) {
+    if (!_nested_fields[i]->check_match(element_type)) {
+      return false;
+    }
+  }
+
+  return true;
+}

+ 5 - 0
direct/src/dcparser/dcClassParameter.h

@@ -50,6 +50,11 @@ public:
                                const string &name, const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 
+protected:
+  virtual bool do_check_match(const DCPackerInterface *other) const;
+  virtual bool do_check_match_class_parameter(const DCClassParameter *other) const;
+  virtual bool do_check_match_array_parameter(const DCArrayParameter *other) const;
+
 private:
   typedef pvector<DCPackerInterface *> Fields;
   Fields _nested_fields;

+ 66 - 55
direct/src/dcparser/dcLexer.cxx.prebuilt

@@ -569,6 +569,13 @@ dc_start_parameter_value() {
   initial_token = START_PARAMETER_VALUE;
 }
 
+void
+dc_start_parameter_description() {
+  /* Set the initial state to begin parsing a parameter description, instead
+     of at the beginning of the dc file. */
+  initial_token = START_PARAMETER_DESCRIPTION;
+}
+
 int
 dc_error_count() {
   return error_count;
@@ -627,6 +634,10 @@ input_chars(char *buffer, int &result, int max_size) {
   if (*inp) {
     inp->read(buffer, max_size);
     result = inp->gcount();
+    if (result >= 0 && result < max_size) {
+      // Truncate at the end of the read.
+      buffer[result] = '\0';
+    }
 
     if (line_number == 0) {
       // This is a special case.  If we are reading the very first bit
@@ -888,7 +899,7 @@ inline void accept() {
   col_number += yyleng;
 }
 
-#line 893 "lex.yy.c"
+#line 904 "lex.yy.c"
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
@@ -1039,7 +1050,7 @@ YY_DECL
 	register char *yy_cp = NULL, *yy_bp = NULL;
 	register int yy_act;
 
-#line 395 "dcLexer.lxx"
+#line 406 "dcLexer.lxx"
 
 
 
@@ -1050,7 +1061,7 @@ YY_DECL
   }
 
 
-#line 1055 "lex.yy.c"
+#line 1066 "lex.yy.c"
 
 	if ( yy_init )
 		{
@@ -1135,7 +1146,7 @@ do_action:	/* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 405 "dcLexer.lxx"
+#line 416 "dcLexer.lxx"
 {
   // New line.  Save a copy of the line so we can print it out for the
   // benefit of the user in case we get an error.
@@ -1152,7 +1163,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 419 "dcLexer.lxx"
+#line 430 "dcLexer.lxx"
 { 
   // Eat whitespace.
   accept();
@@ -1160,7 +1171,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 424 "dcLexer.lxx"
+#line 435 "dcLexer.lxx"
 { 
   // Eat C++-style comments.
   accept();
@@ -1168,7 +1179,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 429 "dcLexer.lxx"
+#line 440 "dcLexer.lxx"
 {
   // Eat C-style comments.
   accept();
@@ -1177,7 +1188,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 436 "dcLexer.lxx"
+#line 447 "dcLexer.lxx"
 {
   accept();
   return KW_DCLASS;
@@ -1185,7 +1196,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 441 "dcLexer.lxx"
+#line 452 "dcLexer.lxx"
 {
   accept();
   return KW_STRUCT;
@@ -1193,7 +1204,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 446 "dcLexer.lxx"
+#line 457 "dcLexer.lxx"
 {
   accept();
   return KW_FROM;
@@ -1201,7 +1212,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 451 "dcLexer.lxx"
+#line 462 "dcLexer.lxx"
 {
   accept();
   return KW_IMPORT;
@@ -1209,7 +1220,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 456 "dcLexer.lxx"
+#line 467 "dcLexer.lxx"
 {
   accept();
   return KW_TYPEDEF;
@@ -1217,7 +1228,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 461 "dcLexer.lxx"
+#line 472 "dcLexer.lxx"
 {
   accept();
   return KW_SWITCH;
@@ -1225,7 +1236,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 466 "dcLexer.lxx"
+#line 477 "dcLexer.lxx"
 {
   accept();
   return KW_CASE;
@@ -1233,7 +1244,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 471 "dcLexer.lxx"
+#line 482 "dcLexer.lxx"
 {
   accept();
   return KW_INT8;
@@ -1241,7 +1252,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 476 "dcLexer.lxx"
+#line 487 "dcLexer.lxx"
 {
   accept();
   return KW_INT16;
@@ -1249,7 +1260,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 481 "dcLexer.lxx"
+#line 492 "dcLexer.lxx"
 {
   accept();
   return KW_INT32;
@@ -1257,7 +1268,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 486 "dcLexer.lxx"
+#line 497 "dcLexer.lxx"
 {
   accept();
   return KW_INT64;
@@ -1265,7 +1276,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 491 "dcLexer.lxx"
+#line 502 "dcLexer.lxx"
 {
   accept();
   return KW_UINT8;
@@ -1273,7 +1284,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 496 "dcLexer.lxx"
+#line 507 "dcLexer.lxx"
 {
   accept();
   return KW_UINT16;
@@ -1281,7 +1292,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 501 "dcLexer.lxx"
+#line 512 "dcLexer.lxx"
 {
   accept();
   return KW_UINT32;
@@ -1289,7 +1300,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 506 "dcLexer.lxx"
+#line 517 "dcLexer.lxx"
 {
   accept();
   return KW_UINT64;
@@ -1297,7 +1308,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 511 "dcLexer.lxx"
+#line 522 "dcLexer.lxx"
 {
   accept();
   return KW_FLOAT64;
@@ -1305,7 +1316,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 516 "dcLexer.lxx"
+#line 527 "dcLexer.lxx"
 {
   accept();
   return KW_STRING;
@@ -1313,7 +1324,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 521 "dcLexer.lxx"
+#line 532 "dcLexer.lxx"
 {
   accept();
   return KW_BLOB;
@@ -1321,7 +1332,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 526 "dcLexer.lxx"
+#line 537 "dcLexer.lxx"
 {
   accept();
   return KW_BLOB32;
@@ -1329,7 +1340,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 531 "dcLexer.lxx"
+#line 542 "dcLexer.lxx"
 {
   accept();
   return KW_INT8ARRAY;
@@ -1337,7 +1348,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 536 "dcLexer.lxx"
+#line 547 "dcLexer.lxx"
 {
   accept();
   return KW_INT16ARRAY;
@@ -1345,7 +1356,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 541 "dcLexer.lxx"
+#line 552 "dcLexer.lxx"
 {
   accept();
   return KW_INT32ARRAY;
@@ -1353,7 +1364,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 546 "dcLexer.lxx"
+#line 557 "dcLexer.lxx"
 {
   accept();
   return KW_UINT8ARRAY;
@@ -1361,7 +1372,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 551 "dcLexer.lxx"
+#line 562 "dcLexer.lxx"
 {
   accept();
   return KW_UINT16ARRAY;
@@ -1369,7 +1380,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 556 "dcLexer.lxx"
+#line 567 "dcLexer.lxx"
 {
   accept();
   return KW_UINT32ARRAY;
@@ -1377,7 +1388,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 561 "dcLexer.lxx"
+#line 572 "dcLexer.lxx"
 {
   accept();
   return KW_UINT32UINT8ARRAY;
@@ -1385,7 +1396,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 566 "dcLexer.lxx"
+#line 577 "dcLexer.lxx"
 {
   accept();
   return KW_CHAR;
@@ -1393,7 +1404,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 571 "dcLexer.lxx"
+#line 582 "dcLexer.lxx"
 {
   accept();
   return KW_REQUIRED;
@@ -1401,7 +1412,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 576 "dcLexer.lxx"
+#line 587 "dcLexer.lxx"
 {
   accept();
   return KW_BROADCAST;
@@ -1409,7 +1420,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 581 "dcLexer.lxx"
+#line 592 "dcLexer.lxx"
 {
   accept();
   return KW_P2P;
@@ -1417,7 +1428,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 586 "dcLexer.lxx"
+#line 597 "dcLexer.lxx"
 {
   accept();
   return KW_RAM;
@@ -1425,7 +1436,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 591 "dcLexer.lxx"
+#line 602 "dcLexer.lxx"
 {
   accept();
   return KW_DB;
@@ -1433,7 +1444,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 596 "dcLexer.lxx"
+#line 607 "dcLexer.lxx"
 {
   accept();
   return KW_CLSEND;
@@ -1441,7 +1452,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 601 "dcLexer.lxx"
+#line 612 "dcLexer.lxx"
 {
   accept();
   return KW_CLRECV;
@@ -1449,7 +1460,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 606 "dcLexer.lxx"
+#line 617 "dcLexer.lxx"
 {
   accept();
   return KW_OWNSEND;
@@ -1457,7 +1468,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 611 "dcLexer.lxx"
+#line 622 "dcLexer.lxx"
 {
   accept();
   return KW_AIRECV;
@@ -1465,7 +1476,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 616 "dcLexer.lxx"
+#line 627 "dcLexer.lxx"
 { 
   // An unsigned integer number.
   accept();
@@ -1491,7 +1502,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 639 "dcLexer.lxx"
+#line 650 "dcLexer.lxx"
 { 
   // A signed integer number.
   accept();
@@ -1540,7 +1551,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 685 "dcLexer.lxx"
+#line 696 "dcLexer.lxx"
 {
   // A hexadecimal integer number.
   accept(); 
@@ -1570,7 +1581,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 712 "dcLexer.lxx"
+#line 723 "dcLexer.lxx"
 { 
   // A floating-point number.
   accept(); 
@@ -1581,7 +1592,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 720 "dcLexer.lxx"
+#line 731 "dcLexer.lxx"
 {
   // Quoted string.
   accept();
@@ -1591,7 +1602,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 727 "dcLexer.lxx"
+#line 738 "dcLexer.lxx"
 {
   // Single-quoted string.
   accept();
@@ -1601,7 +1612,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 734 "dcLexer.lxx"
+#line 745 "dcLexer.lxx"
 {
   // Long hex string.
   accept();
@@ -1611,7 +1622,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 48:
 YY_RULE_SETUP
-#line 741 "dcLexer.lxx"
+#line 752 "dcLexer.lxx"
 { 
   // Identifier.
   accept();
@@ -1621,7 +1632,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 749 "dcLexer.lxx"
+#line 760 "dcLexer.lxx"
 {
   // Send any other printable character as itself.
   accept(); 
@@ -1630,10 +1641,10 @@ YY_RULE_SETUP
 	YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 755 "dcLexer.lxx"
+#line 766 "dcLexer.lxx"
 ECHO;
 	YY_BREAK
-#line 1638 "lex.yy.c"
+#line 1649 "lex.yy.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -2514,4 +2525,4 @@ int main()
 	return 0;
 	}
 #endif
-#line 755 "dcLexer.lxx"
+#line 766 "dcLexer.lxx"

+ 11 - 0
direct/src/dcparser/dcLexer.lxx

@@ -66,6 +66,13 @@ dc_start_parameter_value() {
   initial_token = START_PARAMETER_VALUE;
 }
 
+void
+dc_start_parameter_description() {
+  /* Set the initial state to begin parsing a parameter description, instead
+     of at the beginning of the dc file. */
+  initial_token = START_PARAMETER_DESCRIPTION;
+}
+
 int
 dc_error_count() {
   return error_count;
@@ -124,6 +131,10 @@ input_chars(char *buffer, int &result, int max_size) {
   if (*inp) {
     inp->read(buffer, max_size);
     result = inp->gcount();
+    if (result >= 0 && result < max_size) {
+      // Truncate at the end of the read.
+      buffer[result] = '\0';
+    }
 
     if (line_number == 0) {
       // This is a special case.  If we are reading the very first bit

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

@@ -23,6 +23,7 @@
 
 void dc_init_lexer(istream &in, const string &filename);
 void dc_start_parameter_value();
+void dc_start_parameter_description();
 int dc_error_count();
 int dc_warning_count();
 

+ 33 - 0
direct/src/dcparser/dcMolecularField.cxx

@@ -192,3 +192,36 @@ get_nested_field(int n) const {
   nassertr(n >= 0 && n < (int)_nested_fields.size(), NULL);
   return _nested_fields[n];
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCMolecularField::do_check_match
+//       Access: Protected, Virtual
+//  Description: Returns true if the other interface is bitwise the
+//               same as this one--that is, a uint32 only matches a
+//               uint32, etc. Names of components, and range limits,
+//               are not compared.
+////////////////////////////////////////////////////////////////////
+bool DCMolecularField::
+do_check_match(const DCPackerInterface *other) const {
+  return other->do_check_match_molecular_field(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCMolecularField::do_check_match_molecular_field
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               molecular field, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCMolecularField::
+do_check_match_molecular_field(const DCMolecularField *other) const {
+  if (_nested_fields.size() != other->_nested_fields.size()) {
+    return false;
+  }
+  for (size_t i = 0; i < _nested_fields.size(); i++) {
+    if (!_nested_fields[i]->check_match(other->_nested_fields[i])) {
+      return false;
+    }
+  }
+
+  return true;
+}

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

@@ -52,6 +52,10 @@ public:
 
   virtual DCPackerInterface *get_nested_field(int n) const;
 
+protected:
+  virtual bool do_check_match(const DCPackerInterface *other) const;
+  virtual bool do_check_match_molecular_field(const DCMolecularField *other) const;
+
 private:
   // These members define the primary interface to the molecular field
   // definition as read from the file.

+ 16 - 1
direct/src/dcparser/dcPackerCatalog.cxx

@@ -190,8 +190,23 @@ add_entry(const string &name, const DCPackerInterface *field,
 
   int entry_index = (int)_entries.size();
   _entries.push_back(entry);
-  _entries_by_name.insert(EntriesByName::value_type(name, entry_index));
   _entries_by_field.insert(EntriesByField::value_type(field, entry_index));
+
+  // Add an entry for the fully-qualified field name
+  // (e.g. dna.topTex).  If there was another entry for this name
+  // previously, completely replace it--the fully-qualified name is
+  // supposed to be unique and trumps the local field names (which are
+  // not necessarily unique).
+  _entries_by_name[name] = entry_index;
+
+  // We'll also add an entry for the local field name, for the user's
+  // convenience.  This won't override a fully-qualified name that
+  // might already have been recorded, and a fully-qualified name
+  // discovered later that conflicts with this name will replace it.
+  string local_name = field->get_name();
+  if (local_name != name) {
+    _entries_by_name.insert(EntriesByName::value_type(local_name, entry_index));
+  }
 }
 
 ////////////////////////////////////////////////////////////////////

+ 13 - 0
direct/src/dcparser/dcPackerInterface.I

@@ -28,6 +28,19 @@ get_name() const {
   return _name;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::check_match
+//       Access: Published
+//  Description: Returns true if the other interface is bitwise the
+//               same as this one--that is, a uint32 only matches a
+//               uint32, etc. Names of components, and range limits,
+//               are not compared.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCPackerInterface::
+check_match(const DCPackerInterface *other) const {
+  return do_check_match(other);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::set_name
 //       Access: Public

+ 104 - 0
direct/src/dcparser/dcPackerInterface.cxx

@@ -18,6 +18,8 @@
 
 #include "dcPackerInterface.h"
 #include "dcPackerCatalog.h"
+#include "dcParserDefs.h"
+#include "dcLexerDefs.h"
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::Constructor
@@ -151,6 +153,42 @@ as_class_parameter() const {
   return (DCClassParameter *)NULL;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::check_match
+//       Access: Published
+//  Description: Returns true if this interface is bitwise the same as
+//               the interface described with the indicated formatted
+//               string, e.g. "(uint8, uint8, int16)", or false
+//               otherwise.
+//
+//               If DCFile is not NULL, it specifies the DCFile that
+//               was previously loaded, from which some predefined
+//               structs and typedefs may be referenced in the
+//               description string.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+check_match(const string &description, DCFile *dcfile) const {
+  bool match = false;
+
+  istringstream strm(description);
+  dc_init_parser_parameter_description(strm, "check_match", dcfile);
+  dcyyparse();
+  dc_cleanup_parser();
+
+  DCField *field = dc_get_parameter_description();
+  if (field != NULL) {
+    match = check_match(field);
+    delete field;
+  }
+
+  if (dc_error_count() == 0) {
+    return match;
+  }
+
+  // Parse error: no match is allowed.
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::calc_num_nested_fields
 //       Access: Public, Virtual
@@ -417,6 +455,72 @@ get_catalog() const {
   return _catalog;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::do_check_match_simple_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               simple parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+do_check_match_simple_parameter(const DCSimpleParameter *) const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::do_check_match_class_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               class parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+do_check_match_class_parameter(const DCClassParameter *) const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::do_check_match_switch_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               switch parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+do_check_match_switch_parameter(const DCSwitchParameter *) const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::do_check_match_array_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               array parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+do_check_match_array_parameter(const DCArrayParameter *) const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::do_check_match_atomic_field
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               atomic field, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+do_check_match_atomic_field(const DCAtomicField *) const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::do_check_match_molecular_field
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               molecular field, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+do_check_match_molecular_field(const DCMolecularField *) const {
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::make_catalog
 //       Access: Private

+ 22 - 0
direct/src/dcparser/dcPackerInterface.h

@@ -22,9 +22,14 @@
 #include "dcbase.h"
 #include "dcSubatomicType.h"
 
+class DCFile;
 class DCField;
+class DCSimpleParameter;
 class DCSwitchParameter;
 class DCClassParameter;
+class DCArrayParameter;
+class DCAtomicField;
+class DCMolecularField;
 class DCPackData;
 class DCPackerCatalog;
 
@@ -84,6 +89,9 @@ PUBLISHED:
   virtual DCClassParameter *as_class_parameter();
   virtual const DCClassParameter *as_class_parameter() const;
 
+  INLINE bool check_match(const DCPackerInterface *other) const;
+  bool check_match(const string &description, DCFile *dcfile = NULL) const;
+
 public:
   INLINE void set_name(const string &name);
   INLINE bool has_fixed_byte_size() const;
@@ -166,6 +174,20 @@ public:
 
   const DCPackerCatalog *get_catalog() const;
 
+protected:
+  virtual bool do_check_match(const DCPackerInterface *other) const=0;
+
+public:
+  // These are declared public just so the derived classes can call
+  // them easily.  They're not intended to be called directly.
+
+  virtual bool do_check_match_simple_parameter(const DCSimpleParameter *other) const;
+  virtual bool do_check_match_class_parameter(const DCClassParameter *other) const;
+  virtual bool do_check_match_switch_parameter(const DCSwitchParameter *other) const;
+  virtual bool do_check_match_array_parameter(const DCArrayParameter *other) const;
+  virtual bool do_check_match_atomic_field(const DCAtomicField *other) const;
+  virtual bool do_check_match_molecular_field(const DCMolecularField *other) const;
+
 private:
   void make_catalog();
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 465 - 374
direct/src/dcparser/dcParser.cxx.prebuilt


+ 1 - 0
direct/src/dcparser/dcParser.h.prebuilt

@@ -45,6 +45,7 @@
 # define	KW_AIRECV	298
 # define	START_DC	299
 # define	START_PARAMETER_VALUE	300
+# define	START_PARAMETER_DESCRIPTION	301
 
 
 extern YYSTYPE dcyylval;

+ 173 - 68
direct/src/dcparser/dcParser.yxx

@@ -37,6 +37,7 @@ static DCPacker default_packer;
 static DCPacker *current_packer;
 static DCDoubleRange double_range;
 static DCUnsignedIntRange uint_range;
+static DCField *parameter_description = (DCField *)NULL;
 
 ////////////////////////////////////////////////////////////////////
 // Defining the interface to the parser.
@@ -57,6 +58,20 @@ dc_init_parser_parameter_value(istream &in, const string &filename,
   dc_start_parameter_value();
 }
 
+void
+dc_init_parser_parameter_description(istream &in, const string &filename,
+                                     DCFile *file) {
+  dc_file = file;
+  dc_init_lexer(in, filename);
+  parameter_description = NULL;
+  dc_start_parameter_description();
+}
+
+DCField *
+dc_get_parameter_description() {
+  return parameter_description;
+}
+
 void
 dc_cleanup_parser() {
   dc_file = (DCFile *)NULL;
@@ -113,6 +128,7 @@ dc_cleanup_parser() {
    of the input stream. */
 %token START_DC
 %token START_PARAMETER_VALUE
+%token START_PARAMETER_DESCRIPTION
 
 %type <u.atomic> atomic_name
 %type <u.s_int> server_flags
@@ -124,6 +140,7 @@ dc_cleanup_parser() {
 %type <u.dclass> struct_name
 %type <u.dclass> struct
 %type <u.field> struct_field
+%type <u.field> parameter_description
 %type <u.dswitch> switch
 %type <u.field> switch_field
 %type <u.field> atomic_field
@@ -153,6 +170,10 @@ dc_cleanup_parser() {
 grammar:
 	START_DC dc
 	| START_PARAMETER_VALUE	parameter_value
+	| START_PARAMETER_DESCRIPTION parameter_description
+{
+  parameter_description = $2;
+}
 	;
 
 dc:
@@ -229,14 +250,16 @@ import_symbol_list:
 typedef_decl:
         KW_TYPEDEF parameter_with_default
 {
-  DCTypedef *dtypedef = new DCTypedef($2);
-
-  if (!dc_file->add_typedef(dtypedef)) {
-    DCTypedef *old_typedef = dc_file->get_typedef_by_name(dtypedef->get_name());
-    if (old_typedef->is_bogus_typedef()) {
-      yyerror("typedef defined after its first reference: " + dtypedef->get_name());
-    } else {
-      yyerror("Duplicate typedef name: " + dtypedef->get_name());
+  if ($2 != (DCParameter *)NULL) {
+    DCTypedef *dtypedef = new DCTypedef($2);
+    
+    if (!dc_file->add_typedef(dtypedef)) {
+      DCTypedef *old_typedef = dc_file->get_typedef_by_name(dtypedef->get_name());
+      if (old_typedef->is_bogus_typedef()) {
+        yyerror("typedef defined after its first reference: " + dtypedef->get_name());
+      } else {
+        yyerror("Duplicate typedef name: " + dtypedef->get_name());
+      }
     }
   }
 }
@@ -263,17 +286,23 @@ dclass:
 dclass_name:
         IDENTIFIER
 {
-  DCClass *dclass = dc_file->get_class_by_name($1);
-  if (dclass == (DCClass *)NULL) {
-    // Create a bogus class as a forward reference.
-    dclass = new DCClass($1, false, true);
-    dc_file->add_class(dclass);
-  }
-  if (dclass->is_struct()) {
-    yyerror("struct name not allowed");
-  }
+  if (dc_file == (DCFile *)NULL) {
+    yyerror("No DCFile available, so no class names are predefined.");
+    $$ = NULL;
+
+  } else {
+    DCClass *dclass = dc_file->get_class_by_name($1);
+    if (dclass == (DCClass *)NULL) {
+      // Create a bogus class as a forward reference.
+      dclass = new DCClass($1, false, true);
+      dc_file->add_class(dclass);
+    }
+    if (dclass->is_struct()) {
+      yyerror("struct name not allowed");
+    }
   
-  $$ = dclass;
+    $$ = dclass;
+  }
 }
 	;
 
@@ -302,7 +331,9 @@ dclass_fields:
         | dclass_fields ';'
         | dclass_fields dclass_field
 {
-  if (!current_class->add_field($2)) {
+  if ($2 == (DCField *)NULL) {
+    // Pass this error up.
+  } else if (!current_class->add_field($2)) {
     yyerror("Duplicate field name: " + $2->get_name());
   } else if ($2->get_number() < 0) {
     yyerror("A non-network field cannot be stored on a dclass");
@@ -313,20 +344,29 @@ dclass_fields:
 dclass_field:
 	atomic_field server_flags
 {
+  if ($1 != (DCField *)NULL) {
+    if ($1->get_name().empty()) {
+      yyerror("Field name required.");
+    }
+    $1->set_flags($2);
+  }
   $$ = $1;
-  $$->set_flags($2);
 }
 	| molecular_field no_server_flags
 	| unnamed_parameter_with_default server_flags ';'
 {
   yyerror("Unnamed parameters are not allowed on a dclass");
+  if ($1 != (DCField *)NULL) {
+    $1->set_flags($2);
+  }
   $$ = $1;
-  $$->set_flags($2);
 }
 	| named_parameter_with_default server_flags
 {
+  if ($1 != (DCField *)NULL) {
+    $1->set_flags($2);
+  }
   $$ = $1;
-  $$->set_flags($2);
 }
 	;
 
@@ -346,17 +386,23 @@ struct:
 struct_name:
         IDENTIFIER
 {
-  DCClass *dstruct = dc_file->get_class_by_name($1);
-  if (dstruct == (DCClass *)NULL) {
-    // Create a bogus class as a forward reference.
-    dstruct = new DCClass($1, false, true);
-    dc_file->add_class(dstruct);
-  }
-  if (!dstruct->is_struct()) {
-    yyerror("struct name required");
-  }
+  if (dc_file == (DCFile *)NULL) {
+    yyerror("No DCFile available, so no struct names are predefined.");
+    $$ = NULL;
+
+  } else {
+    DCClass *dstruct = dc_file->get_class_by_name($1);
+    if (dstruct == (DCClass *)NULL) {
+      // Create a bogus class as a forward reference.
+      dstruct = new DCClass($1, false, true);
+      dc_file->add_class(dstruct);
+    }
+    if (!dstruct->is_struct()) {
+      yyerror("struct name required");
+    }
   
-  $$ = dstruct;
+    $$ = dstruct;
+  }
 }
 	;
 
@@ -385,7 +431,9 @@ struct_fields:
         | struct_fields ';'
         | struct_fields struct_field
 {
-  if (!current_class->add_field($2)) {
+  if ($2 == (DCField *)NULL) {
+    // Pass this error up.
+  } else if (!current_class->add_field($2)) {
     yyerror("Duplicate field name: " + $2->get_name());
   }
 }
@@ -393,6 +441,12 @@ struct_fields:
 
 struct_field:
 	atomic_field no_server_flags
+{
+  if ($1->get_name().empty()) {
+    yyerror("Field name required.");
+  }
+  $$ = $1;
+}
 	| molecular_field no_server_flags
 	| unnamed_parameter_with_default no_server_flags ';'
 {
@@ -405,7 +459,7 @@ struct_field:
 	;
 
 atomic_field:
-        IDENTIFIER '('
+        optional_name '('
 {
   $$ = current_atomic;
   current_atomic = new DCAtomicField($1);
@@ -430,7 +484,9 @@ nonempty_parameter_list:
 atomic_element:
         parameter_with_default
 {
-  current_atomic->add_element($1);
+  if ($1 != (DCParameter *)NULL) {
+    current_atomic->add_element($1);
+  }
 }
 	;
 
@@ -455,11 +511,16 @@ named_parameter_with_default:
 {
   current_packer = &default_packer;
   current_packer->clear_data();
-  current_packer->begin_pack($1);
+  if ($1 != (DCField *)NULL) {
+    current_packer->begin_pack($1);
+  }
 }
 	parameter_value
 {
-  bool is_valid = $1->is_valid();
+  bool is_valid = false;
+  if ($1 != (DCField *)NULL) {
+    is_valid = $1->is_valid();
+  }
   if (current_packer->end_pack()) {
     $1->set_default_value(current_packer->get_string());
 
@@ -480,11 +541,16 @@ unnamed_parameter_with_default:
 {
   current_packer = &default_packer;
   current_packer->clear_data();
-  current_packer->begin_pack($1);
+  if ($1 != (DCField *)NULL) {
+    current_packer->begin_pack($1);
+  }
 }
 	parameter_value
 {
-  bool is_valid = $1->is_valid();
+  bool is_valid = false;
+  if ($1 != (DCField *)NULL) {
+    is_valid = $1->is_valid();
+  }
   if (current_packer->end_pack()) {
     $1->set_default_value(current_packer->get_string());
 
@@ -509,6 +575,21 @@ parameter_with_default:
         | unnamed_parameter_with_default
         ;
 
+parameter_description:
+	atomic_field no_server_flags
+{
+  $$ = $1;
+}
+	| unnamed_parameter_with_default no_server_flags
+{
+  $$ = $1;
+}
+	| named_parameter_with_default no_server_flags
+{
+  $$ = $1;
+}
+	;
+
 type_name:
         type_token
 {
@@ -563,44 +644,62 @@ type_name:
 }
 	| IDENTIFIER
 {
-  DCTypedef *dtypedef = dc_file->get_typedef_by_name($1);
-  if (dtypedef == (DCTypedef *)NULL) {
-    // Maybe it's a class name.
-    DCClass *dclass = dc_file->get_class_by_name($1);
-    if (dclass != (DCClass *)NULL) {
-      if (!dclass->is_struct()) {
-        yyerror("cannot embed a dclass object within a message; use a struct");
-      }
-      // Create an implicit typedef for this.
-      dtypedef = new DCTypedef(new DCClassParameter(dclass), true);
-    } else {
-      // 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);
+  if (dc_file == (DCFile *)NULL) {
+    yyerror("Invalid type.");
+    $$ = NULL;
+
+  } else {
+    DCTypedef *dtypedef = dc_file->get_typedef_by_name($1);
+    if (dtypedef == (DCTypedef *)NULL) {
+      // Maybe it's a class name.
+      DCClass *dclass = dc_file->get_class_by_name($1);
+      if (dclass != (DCClass *)NULL) {
+        if (!dclass->is_struct()) {
+          yyerror("cannot embed a dclass object within a message; use a struct");
+        }
+        // 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);
     }
-
-    dc_file->add_typedef(dtypedef);
+    
+    $$ = dtypedef->make_new_parameter();
   }
-
-  $$ = dtypedef->make_new_parameter();
 }
 	| struct
 {
   // This is an inline struct definition.
-  dc_file->add_thing_to_delete($1);
-  $$ = new DCClassParameter($1);
+  if ($1 == (DCClass *)NULL) {
+    $$ = NULL;
+  } else {
+    if (dc_file != (DCFile *)NULL) {
+      dc_file->add_thing_to_delete($1);
+    }
+    $$ = new DCClassParameter($1);
+  }
 }
 	| switch
 {
   // This is an inline switch definition.
-  dc_file->add_thing_to_delete($1);
-  $$ = new DCSwitchParameter($1);
+  if ($1 == (DCSwitch *)NULL) {
+    $$ = NULL;
+  } else {
+    if (dc_file != (DCFile *)NULL) {
+      dc_file->add_thing_to_delete($1);
+    }
+    $$ = new DCSwitchParameter($1);
+  }
 }
 	;
 
@@ -691,7 +790,11 @@ type_definition:
         type_name
 	| type_definition '[' uint_range ']'
 {
-  $$ = new DCArrayParameter($1, uint_range);
+  if ($1 == (DCParameter *)NULL) {
+    $$ = NULL;
+  } else {
+    $$ = new DCArrayParameter($1, uint_range);
+  }
 }
 	;
 
@@ -1078,8 +1181,10 @@ switch_fields:
 {
   if (current_switch->get_num_cases() == 0) {
     yyerror("case declaration required before first element");
-  } else if (!current_switch->add_field($2)) {
-    yyerror("Duplicate field name: " + $2->get_name());
+  } else if ($2 != (DCField *)NULL) {
+    if (!current_switch->add_field($2)) {
+      yyerror("Duplicate field name: " + $2->get_name());
+    }
   }
 }
         ;

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

@@ -33,6 +33,9 @@ class DCPacker;
 void dc_init_parser(istream &in, const string &filename, DCFile &file);
 void dc_init_parser_parameter_value(istream &in, const string &filename, 
                                     DCPacker &packer);
+void dc_init_parser_parameter_description(istream &in, const string &filename,
+                                          DCFile *file);
+DCField *dc_get_parameter_description();
 void dc_cleanup_parser();
 int dcyyparse();
 

+ 89 - 38
direct/src/dcparser/dcSimpleParameter.cxx

@@ -19,11 +19,14 @@
 #include "dcSimpleParameter.h"
 #include "dcPackData.h"
 #include "dcTypedef.h"
+#include "dcArrayParameter.h"
+#include "dcClassParameter.h"
+#include "dcClass.h"
 #include "hashGenerator.h"
 #include <math.h>
 
 DCSimpleParameter::NestedFieldMap DCSimpleParameter::_nested_field_map;
-DCSimpleParameter::Uint32Uint8Type *DCSimpleParameter::_uint32uint8_type = NULL;
+DCClassParameter *DCSimpleParameter::_uint32uint8_type = NULL;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSimpleParameter::Constructor
@@ -2150,6 +2153,87 @@ generate_hash(HashGenerator &hashgen) const {
   _double_range.generate_hash(hashgen);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSimpleParameter::do_check_match
+//       Access: Protected, Virtual
+//  Description: Returns true if the other interface is bitwise the
+//               same as this one--that is, a uint32 only matches a
+//               uint32, etc. Names of components, and range limits,
+//               are not compared.
+////////////////////////////////////////////////////////////////////
+bool DCSimpleParameter::
+do_check_match(const DCPackerInterface *other) const {
+  return other->do_check_match_simple_parameter(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSimpleParameter::do_check_match_simple_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               simple parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCSimpleParameter::
+do_check_match_simple_parameter(const DCSimpleParameter *other) const {
+  if (_divisor != other->_divisor) {
+    return false;
+  }
+
+  if (_type == other->_type) {
+    return true;
+  }
+
+  // Check for certain types that are considered equivalent to each
+  // other.
+  switch (_type) {
+  case ST_uint8:
+  case ST_char:
+    switch (other->_type) {
+    case ST_uint8:
+    case ST_char:
+      return true;
+
+    default:
+      return false;
+    }
+
+  case ST_string:
+  case ST_blob:
+  case ST_uint8array:
+    switch (other->_type) {
+    case ST_string:
+    case ST_blob:
+    case ST_uint8array:
+      return true;
+
+    default:
+      return false;
+    }
+
+  default:
+    return false;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSimpleParameter::do_check_match_array_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               array parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCSimpleParameter::
+do_check_match_array_parameter(const DCArrayParameter *other) const {
+  if (other->get_array_size() != -1) {
+    // We cannot match a fixed-size array.
+    return false;
+  }
+  if (_nested_field == NULL) {
+    // Only an array-style simple parameter can match a DCArrayParameter.
+    return false;
+  }
+
+  return _nested_field->check_match(other->get_element_type());
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSimpleParameter::create_nested_field
 //       Access: Private, Static
@@ -2180,43 +2264,10 @@ create_nested_field(DCSubatomicType type, unsigned int divisor) {
 DCPackerInterface *DCSimpleParameter::
 create_uint32uint8_type() {
   if (_uint32uint8_type == NULL) {
-    _uint32uint8_type = new Uint32Uint8Type;
+    DCClass *dclass = new DCClass("", true, false);
+    dclass->add_field(new DCSimpleParameter(ST_uint32));
+    dclass->add_field(new DCSimpleParameter(ST_uint8));
+    _uint32uint8_type = new DCClassParameter(dclass);
   }
   return _uint32uint8_type;
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCSimpleParameter::Uint32Uint8Type::Constructor
-//       Access: Public
-//  Description: This special packer interface is provided just to
-//               implement uint32uint8array, which is a special kind
-//               of array that consists of nested pairs of (uint32,
-//               uint8) values.
-////////////////////////////////////////////////////////////////////
-DCSimpleParameter::Uint32Uint8Type::
-Uint32Uint8Type() {
-  _uint32_type = new DCSimpleParameter(ST_uint32);
-  _uint8_type = new DCSimpleParameter(ST_uint8);
-  _has_nested_fields = true;
-  _num_nested_fields = 2;
-  _pack_type = PT_class;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCSimpleParameter::Uint32Uint8Type::get_nested_field
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-DCPackerInterface *DCSimpleParameter::Uint32Uint8Type::
-get_nested_field(int n) const {
-  switch (n) {
-  case 0:
-    return _uint32_type;
-
-  case 1:
-    return _uint8_type;
-
-  default:
-    return NULL;
-  }
-}

+ 6 - 10
direct/src/dcparser/dcSimpleParameter.h

@@ -89,6 +89,11 @@ public:
                                const string &name, const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 
+protected:
+  virtual bool do_check_match(const DCPackerInterface *other) const;
+  virtual bool do_check_match_simple_parameter(const DCSimpleParameter *other) const;
+  virtual bool do_check_match_array_parameter(const DCArrayParameter *other) const;
+
 private:
   static DCSimpleParameter *create_nested_field(DCSubatomicType type, 
                                                 unsigned int divisor);
@@ -109,22 +114,13 @@ private:
   typedef pmap<DCSubatomicType, DivisorMap> NestedFieldMap;
   static NestedFieldMap _nested_field_map;
 
-  class Uint32Uint8Type : public DCPackerInterface {
-  public:
-    Uint32Uint8Type();
-    virtual DCPackerInterface *get_nested_field(int n) const;
-
-    DCSimpleParameter *_uint32_type;
-    DCSimpleParameter *_uint8_type;
-  };
-
   DCIntRange _int_range;
   DCUnsignedIntRange _uint_range;
   DCInt64Range _int64_range;
   DCUnsignedInt64Range _uint64_range;
   DCDoubleRange _double_range;
 
-  static Uint32Uint8Type *_uint32uint8_type;
+  static DCClassParameter *_uint32uint8_type;
 };
 
 #endif

+ 83 - 5
direct/src/dcparser/dcSwitch.cxx

@@ -410,6 +410,45 @@ pack_default_value(DCPackData &pack_data, bool &pack_error) const {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitch::do_check_match_switch
+//       Access: Public
+//  Description: Returns true if this switch matches the indicated
+//               switch, false otherwise.  This is only intended to be
+//               called internally from
+//               DCSwitchParameter::do_check_match_switch_parameter().
+////////////////////////////////////////////////////////////////////
+bool DCSwitch::
+do_check_match_switch(const DCSwitch *other) const {
+  if (!_key_parameter->check_match(other->_key_parameter)) {
+    return false;
+  }
+
+  if (_cases.size() != other->_cases.size()) {
+    return false;
+  }
+
+  Cases::const_iterator ci;
+  for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
+    const SwitchCase *c1 = (*ci);
+    CasesByValue::const_iterator vi;
+    vi = other->_cases_by_value.find(c1->_value);
+    if (vi == other->_cases_by_value.end()) {
+      // No matching value.
+      return false;
+    }
+    int c2_index = (*vi).second;
+    nassertr(c2_index >= 0 && c2_index < (int)other->_cases.size(), false);
+    const SwitchCase *c2 = other->_cases[c2_index];
+
+    if (!c1->do_check_match_switch_case(c2)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSwitch::SwitchCase::Constructor
 //       Access: Public
@@ -477,11 +516,13 @@ get_nested_field(int n) const {
 ////////////////////////////////////////////////////////////////////
 bool DCSwitch::SwitchCase::
 add_field(DCField *field) {
-  bool inserted = _fields_by_name.insert
-    (FieldsByName::value_type(field->get_name(), field)).second;
-
-  if (!inserted) {
-    return false;
+  if (!field->get_name().empty()) {
+    bool inserted = _fields_by_name.insert
+      (FieldsByName::value_type(field->get_name(), field)).second;
+    
+    if (!inserted) {
+      return false;
+    }
   }
 
   _fields.push_back(field);
@@ -504,3 +545,40 @@ add_field(DCField *field) {
   }
   return true;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitch::SwitchCase::do_check_match_switch_case
+//       Access: Public
+//  Description: Returns true if this case matches the indicated
+//               case, false otherwise.  This is only intended to be
+//               called internally from
+//               DCSwitch::do_check_match_switch().
+////////////////////////////////////////////////////////////////////
+bool DCSwitch::SwitchCase::
+do_check_match_switch_case(const DCSwitch::SwitchCase *other) const {
+  if (_fields.size() != other->_fields.size()) {
+    return false;
+  }
+  for (size_t i = 0; i < _fields.size(); i++) {
+    if (!_fields[i]->check_match(other->_fields[i])) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitch::SwitchCase::do_check_match
+//       Access: Protected, Virtual
+//  Description: Returns true if the other interface is bitwise the
+//               same as this one--that is, a uint32 only matches a
+//               uint32, etc. Names of components, and range limits,
+//               are not compared.
+////////////////////////////////////////////////////////////////////
+bool DCSwitch::SwitchCase::
+do_check_match(const DCPackerInterface *) const {
+  // This should never be called on a SwitchCase.
+  nassertr(false, false);
+  return false;
+}

+ 7 - 0
direct/src/dcparser/dcSwitch.h

@@ -70,6 +70,8 @@ public:
   virtual void generate_hash(HashGenerator &hashgen) const;
   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
+  bool do_check_match_switch(const DCSwitch *other) const;
+
 public:
   typedef pvector<DCField *> Fields;
   typedef pmap<string, DCField *> FieldsByName;
@@ -81,7 +83,12 @@ public:
     virtual DCPackerInterface *get_nested_field(int n) const;
 
     bool add_field(DCField *field);
+    bool do_check_match_switch_case(const SwitchCase *other) const;
+
+  protected:
+    virtual bool do_check_match(const DCPackerInterface *other) const;
 
+  public:
     string _value;
     Fields _fields;
     FieldsByName _fields_by_name;

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

@@ -224,3 +224,27 @@ pack_default_value(DCPackData &pack_data, bool &pack_error) const {
 
   return _dswitch->pack_default_value(pack_data, pack_error);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::do_check_match
+//       Access: Protected, Virtual
+//  Description: Returns true if the other interface is bitwise the
+//               same as this one--that is, a uint32 only matches a
+//               uint32, etc. Names of components, and range limits,
+//               are not compared.
+////////////////////////////////////////////////////////////////////
+bool DCSwitchParameter::
+do_check_match(const DCPackerInterface *other) const {
+  return other->do_check_match_switch_parameter(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::do_check_match_switch_parameter
+//       Access: Protected, Virtual
+//  Description: Returns true if this field matches the indicated
+//               switch parameter, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCSwitchParameter::
+do_check_match_switch_parameter(const DCSwitchParameter *other) const {
+  return _dswitch->do_check_match_switch(other->_dswitch);
+}

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

@@ -56,6 +56,10 @@ public:
   virtual void generate_hash(HashGenerator &hashgen) const;
   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
+protected:
+  virtual bool do_check_match(const DCPackerInterface *other) const;
+  virtual bool do_check_match_switch_parameter(const DCSwitchParameter *other) const;
+
 private:
   const DCSwitch *_dswitch;
 };

Vissa filer visades inte eftersom för många filer har ändrats