diff --git a/direct/src/dcparser/dcClass.I b/direct/src/dcparser/dcClass.I index 081ecc84e9..a9e579cf41 100644 --- a/direct/src/dcparser/dcClass.I +++ b/direct/src/dcparser/dcClass.I @@ -17,9 +17,19 @@ //////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +// Function: DCClass::get_dc_file +// Access: Published +// Description: Returns the DCFile object that contains the class. +//////////////////////////////////////////////////////////////////// +INLINE DCFile *DCClass:: +get_dc_file() const { + return _dc_file; +} + //////////////////////////////////////////////////////////////////// // Function: DCClass::is_struct -// Access: Public +// Access: Published // Description: Returns true if the class has been identified with // the "struct" keyword in the dc file, false if it was // declared with "dclass". @@ -31,7 +41,7 @@ is_struct() const { //////////////////////////////////////////////////////////////////// // Function: DCClass::is_bogus_class -// Access: Public +// Access: Published // Description: Returns true if the class has been flagged as a bogus // class. This is set for classes that are generated by // the parser as placeholder for missing classes, as @@ -45,7 +55,7 @@ is_bogus_class() const { //////////////////////////////////////////////////////////////////// // Function: DCClass::start_generate -// Access: Public +// Access: Published // Description: Starts the PStats timer going on the "generate" task, // that is, marks the beginning of the process of // generating a new object, for the purposes of timing @@ -63,7 +73,7 @@ start_generate() { //////////////////////////////////////////////////////////////////// // Function: DCClass::stop_generate -// Access: Public +// Access: Published // Description: Stops the PStats timer on the "generate" task. // This should balance with a preceding call to // start_generate(). diff --git a/direct/src/dcparser/dcClass.cxx b/direct/src/dcparser/dcClass.cxx index eb6bd81171..755802dcc9 100644 --- a/direct/src/dcparser/dcClass.cxx +++ b/direct/src/dcparser/dcClass.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "dcClass.h" +#include "dcFile.h" #include "dcAtomicField.h" #include "hashGenerator.h" #include "dcindent.h" @@ -31,6 +32,14 @@ PStatCollector DCClass::_update_pcollector("App:Show code:readerPollTask:Update"); PStatCollector DCClass::_generate_pcollector("App:Show code:readerPollTask:Generate"); #endif // CPPPARSER + +ConfigVariableBool dc_multiple_inheritance +("dc-multiple-inheritance", false, + PRC_DESC("Set this true to support multiple inheritance in the dc file. " + "If this is false, the old way, multiple inheritance is not " + "supported, but field numbers will be numbered sequentially, " + "which may be required to support old code that assumed this.")); + #endif // WITHIN_PANDA //////////////////////////////////////////////////////////////////// @@ -39,11 +48,12 @@ PStatCollector DCClass::_generate_pcollector("App:Show code:readerPollTask:Gener // Description: //////////////////////////////////////////////////////////////////// DCClass:: -DCClass(const string &name, bool is_struct, bool bogus_class) : +DCClass(DCFile *dc_file, const string &name, bool is_struct, bool bogus_class) : #ifdef WITHIN_PANDA _class_update_pcollector(_update_pcollector, name), _class_generate_pcollector(_generate_pcollector, name), #endif + _dc_file(dc_file), _name(name), _is_struct(is_struct), _bogus_class(bogus_class) @@ -230,6 +240,39 @@ get_field_by_name(const string &name) const { return (DCField *)NULL; } +//////////////////////////////////////////////////////////////////// +// Function: DCClass::get_field_by_index +// Access: Published +// Description: Returns a pointer to the DCField that has the +// indicated index number. If the numbered field is not +// found in the current class, the parent classes will +// be searched, so the value returned may not actually +// be a field within this class. Returns NULL if there +// is no such field defined. +//////////////////////////////////////////////////////////////////// +DCField *DCClass:: +get_field_by_index(int index_number) const { + FieldsByIndex::const_iterator ni; + ni = _fields_by_index.find(index_number); + if (ni != _fields_by_index.end()) { + return (*ni).second; + } + + // We didn't have such a field, so check our parents. + Parents::const_iterator pi; + for (pi = _parents.begin(); pi != _parents.end(); ++pi) { + DCField *result = (*pi)->get_field_by_index(index_number); + if (result != (DCField *)NULL) { + // Cache this result for future lookups. + ((DCClass *)this)->_fields_by_index[index_number] = result; + return result; + } + } + + // Nobody knew what this field is. + return (DCField *)NULL; +} + //////////////////////////////////////////////////////////////////// // Function: DCClass::get_num_inherited_fields // Access: Published @@ -238,33 +281,40 @@ get_field_by_name(const string &name) const { //////////////////////////////////////////////////////////////////// int DCClass:: get_num_inherited_fields() const { - if (!_parents.empty()) { - // This won't work for multiple dclass inheritance. - return _parents.front()->get_num_inherited_fields() + get_num_fields(); + int num_fields = get_num_fields(); + + Parents::const_iterator pi; + for (pi = _parents.begin(); pi != _parents.end(); ++pi) { + num_fields += (*pi)->get_num_inherited_fields(); } - return get_num_fields(); + + return num_fields; } //////////////////////////////////////////////////////////////////// // Function: DCClass::get_inherited_field // Access: Published // Description: Returns the nth field field in the class and all of -// its ancestors. This *is* the field corresponding to -// the given index number, since the fields are ordered -// consecutively beginning at the earliest inherited -// fields. +// its ancestors. +// +// This *used* to be the same thing as +// get_field_by_index(), back when the fields were +// numbered sequentially within a class's inheritance +// hierarchy. Now that fields have a globally unique +// index number, this is no longer true. //////////////////////////////////////////////////////////////////// DCField *DCClass:: get_inherited_field(int n) const { - if (!_parents.empty()) { - // This won't work for multiple dclass inheritance. - int psize = _parents.front()->get_num_inherited_fields(); + Parents::const_iterator pi; + for (pi = _parents.begin(); pi != _parents.end(); ++pi) { + int psize = (*pi)->get_num_inherited_fields(); if (n < psize) { - return _parents.front()->get_inherited_field(n); + return (*pi)->get_inherited_field(n); } n -= psize; } + return get_field(n); } @@ -351,8 +401,16 @@ receive_update(PyObject *distobj, DatagramIterator &di) const { packer.set_unpack_data(di.get_remaining_bytes()); int field_id = packer.raw_unpack_uint16(); - DCField *field = get_inherited_field(field_id); - nassertv_always(field != NULL); + DCField *field = get_field_by_index(field_id); + if (field == (DCField *)NULL) { + ostringstream strm; + strm + << "Received update for field " << field_id << ", not in class " + << get_name(); + nassert_raise(strm.str()); + return; + } + packer.begin_unpack(field); field->receive_update(packer, distobj); packer.end_unpack(); @@ -750,7 +808,7 @@ client_format_generate(PyObject *distobj, int do_id, // Specify all of the required fields. int num_fields = get_num_inherited_fields(); - for (int i = 0; i < num_fields; i++) { + for (int i = 0; i < num_fields; ++i) { DCField *field = get_inherited_field(i); if (field->is_required() && field->as_molecular_field() == NULL) { packer.begin_pack(field); @@ -1104,8 +1162,19 @@ add_field(DCField *field) { } if (!is_struct()) { - field->set_number(get_num_inherited_fields()); + if (dc_multiple_inheritance) { + _dc_file->set_new_index_number(field); + } else { + field->set_number(get_num_inherited_fields()); + } + + bool inserted = _fields_by_index.insert + (FieldsByIndex::value_type(field->get_number(), field)).second; + + // It shouldn't be possible for that to fail. + nassertr(inserted, false); } + _fields.push_back(field); return true; } diff --git a/direct/src/dcparser/dcClass.h b/direct/src/dcparser/dcClass.h index a3515543be..d8fb59c411 100644 --- a/direct/src/dcparser/dcClass.h +++ b/direct/src/dcparser/dcClass.h @@ -26,7 +26,15 @@ #ifdef WITHIN_PANDA #include "pStatCollector.h" -#endif +#include "configVariableBool.h" + +extern ConfigVariableBool dc_multiple_inheritance; + +#else // WITHIN_PANDA + +static const bool dc_multiple_inheritance = true; + +#endif // WITHIN_PANDA class HashGenerator; class DCParameter; @@ -38,13 +46,16 @@ class DCParameter; //////////////////////////////////////////////////////////////////// class EXPCL_DIRECT DCClass : public DCDeclaration { public: - DCClass(const string &name, bool is_struct, bool bogus_class); + DCClass(DCFile *dc_file, const string &name, + bool is_struct, bool bogus_class); ~DCClass(); PUBLISHED: virtual DCClass *as_class(); virtual const DCClass *as_class() const; + INLINE DCFile *get_dc_file() const; + const string &get_name() const; int get_number() const; @@ -57,6 +68,7 @@ PUBLISHED: int get_num_fields() const; DCField *get_field(int n) const; DCField *get_field_by_name(const string &name) const; + DCField *get_field_by_index(int index_number) const; int get_num_inherited_fields() const; DCField *get_inherited_field(int n) const; @@ -124,6 +136,8 @@ private: static PStatCollector _generate_pcollector; #endif + DCFile *_dc_file; + string _name; bool _is_struct; bool _bogus_class; @@ -140,6 +154,9 @@ private: typedef pmap FieldsByName; FieldsByName _fields_by_name; + typedef pmap FieldsByIndex; + FieldsByIndex _fields_by_index; + #ifdef HAVE_PYTHON PyObject *_class_def; #endif diff --git a/direct/src/dcparser/dcField.cxx b/direct/src/dcparser/dcField.cxx index 9804d61410..648a76aba9 100644 --- a/direct/src/dcparser/dcField.cxx +++ b/direct/src/dcparser/dcField.cxx @@ -645,6 +645,12 @@ generate_hash(HashGenerator &hashgen) const { // field with the other fields, so adding it explicitly will be // redundant. However, the field name is significant. hashgen.add_string(_name); + + // Actually, we add _number anyway, since we need to ensure the hash + // code comes out different in the dc_multiple_inheritance case. + if (dc_multiple_inheritance) { + hashgen.add_int(_number); + } } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/dcparser/dcFile.cxx b/direct/src/dcparser/dcFile.cxx index 004cc12b06..595fa0c9a1 100644 --- a/direct/src/dcparser/dcFile.cxx +++ b/direct/src/dcparser/dcFile.cxx @@ -91,7 +91,8 @@ clear() { //////////////////////////////////////////////////////////////////// bool DCFile:: read_all() { - ConfigVariableList dc_files("dc-file", "The list of dc files to load."); + static ConfigVariableList dc_files + ("dc-file", PRC_DESC("The list of dc files to load.")); if (dc_files.size() == 0) { cerr << "No files specified via dc-file Config.prc variable!\n"; @@ -129,36 +130,28 @@ read_all() { //////////////////////////////////////////////////////////////////// bool DCFile:: read(Filename filename) { - ifstream in; - - #ifdef WITHIN_PANDA +#ifdef WITHIN_PANDA filename.set_text(); - if (use_vfs) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - istream *in = vfs->open_read_file(filename); - if (in == (istream *)NULL) { - cerr << "Cannot open " << filename << " for reading.\n"; - return false; - } - bool okflag = read(*in, filename); - - // For some reason--compiler bug in gcc 3.2?--explicitly deleting - // the in pointer does not call the appropriate global delete - // function; instead apparently calling the system delete - // function. So we call the delete function by hand instead. - #ifndef NDEBUG - in->~istream(); - (*global_operator_delete)(in); - #else - delete in; - #endif - - return okflag; + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + istream *in = vfs->open_read_file(filename); + if (in == (istream *)NULL) { + cerr << "Cannot open " << filename << " for reading.\n"; + return false; } - filename.open_read(in); - #else + bool okflag = read(*in, filename); + + // For some reason--compiler bug in gcc 3.2?--explicitly deleting + // the in pointer does not call the appropriate global delete + // function; instead apparently calling the system delete + // function. So we call the delete function by hand instead. + vfs->close_read_file(in); + + return okflag; + +#else // WITHIN_PANDA + + ifstream in; in.open(filename.c_str()); - #endif if (!in) { cerr << "Cannot open " << filename << " for reading.\n"; @@ -166,6 +159,8 @@ read(Filename filename) { } return read(in, filename); + +#endif // WITHIN_PANDA } //////////////////////////////////////////////////////////////////// @@ -319,6 +314,29 @@ get_switch_by_name(const string &name) const { return (DCSwitch *)NULL; } +//////////////////////////////////////////////////////////////////// +// Function: DCFile::get_field_by_index +// Access: Published, Static +// Description: Returns a pointer to the one DCField that has the +// indicated index number, of all the DCFields across +// all classes in the file. +// +// This method is only valid if dc-multiple-inheritance +// is set true in the Config.prc file. Without this +// setting, different DCFields may share the same index +// number, so this global lookup is not possible. +//////////////////////////////////////////////////////////////////// +DCField *DCFile:: +get_field_by_index(int index_number) const { + nassertr(dc_multiple_inheritance, NULL); + + if (index_number >= 0 && index_number < (int)_fields_by_index.size()) { + return _fields_by_index[index_number]; + } + + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: DCFile::all_objects_valid // Access: Published @@ -592,3 +610,17 @@ void DCFile:: add_thing_to_delete(DCDeclaration *decl) { _things_to_delete.push_back(decl); } + +//////////////////////////////////////////////////////////////////// +// Function: DCFile::set_new_index_number +// Access: Public +// Description: Sets the next sequential available index number on +// the indicated field. This is only meant to be called +// by DCClass::add_field(), while the dc file is being +// parsed. +//////////////////////////////////////////////////////////////////// +void DCFile:: +set_new_index_number(DCField *field) { + field->set_number((int)_fields_by_index.size()); + _fields_by_index.push_back(field); +} diff --git a/direct/src/dcparser/dcFile.h b/direct/src/dcparser/dcFile.h index 07d73c6f8a..2a52e5ae16 100644 --- a/direct/src/dcparser/dcFile.h +++ b/direct/src/dcparser/dcFile.h @@ -23,6 +23,7 @@ class DCClass; class DCSwitch; +class DCField; class HashGenerator; class DCTypedef; class DCDeclaration; @@ -54,6 +55,8 @@ PUBLISHED: DCClass *get_class_by_name(const string &name) const; DCSwitch *get_switch_by_name(const string &name) const; + DCField *get_field_by_index(int index_number) const; + bool all_objects_valid() const; int get_num_import_modules() const; @@ -76,6 +79,8 @@ public: bool add_typedef(DCTypedef *dtypedef); void add_thing_to_delete(DCDeclaration *decl); + void set_new_index_number(DCField *field); + private: typedef pvector Classes; Classes _classes; @@ -103,6 +108,9 @@ private: Declarations _declarations; Declarations _things_to_delete; + typedef pvector FieldsByIndex; + FieldsByIndex _fields_by_index; + bool _all_objects_valid; }; diff --git a/direct/src/dcparser/dcParser.cxx.prebuilt b/direct/src/dcparser/dcParser.cxx.prebuilt index 7180505947..a64e69be57 100644 --- a/direct/src/dcparser/dcParser.cxx.prebuilt +++ b/direct/src/dcparser/dcParser.cxx.prebuilt @@ -268,22 +268,22 @@ static const short yyrline[] = 0, 172, 174, 175, 181, 183, 184, 195, 201, 202, 205, 207, 213, 215, 221, 226, 226, 233, 235, 241, 246, 252, 270, 272, 275, 275, 288, 311, 313, 316, - 323, 331, 333, 334, 346, 357, 358, 366, 375, 375, - 388, 411, 413, 416, 423, 431, 433, 434, 444, 452, - 453, 457, 463, 463, 476, 478, 481, 483, 486, 495, - 495, 506, 510, 512, 512, 540, 542, 542, 570, 572, - 575, 577, 580, 585, 589, 595, 600, 609, 625, 639, - 641, 676, 692, 710, 715, 722, 729, 738, 744, 750, - 760, 765, 772, 779, 786, 792, 798, 806, 808, 818, - 824, 839, 854, 860, 870, 873, 884, 898, 902, 906, - 911, 915, 918, 928, 932, 937, 941, 945, 949, 953, - 953, 961, 961, 969, 969, 977, 983, 989, 995, 1003, - 1005, 1008, 1010, 1013, 1015, 1018, 1023, 1027, 1031, 1035, - 1039, 1043, 1047, 1051, 1055, 1059, 1063, 1067, 1071, 1075, - 1079, 1083, 1087, 1091, 1095, 1101, 1106, 1110, 1114, 1118, - 1122, 1126, 1130, 1134, 1138, 1144, 1154, 1154, 1165, 1181, - 1188, 1201, 1206, 1209, 1209, 1223, 1225, 1226, 1227, 1239, - 1239, 1256, 1261, 1267 + 323, 336, 338, 339, 351, 362, 363, 371, 380, 380, + 393, 416, 418, 421, 428, 436, 438, 439, 449, 457, + 458, 462, 468, 468, 481, 483, 486, 488, 491, 500, + 500, 511, 515, 517, 517, 545, 547, 547, 575, 577, + 580, 582, 585, 590, 594, 600, 605, 614, 630, 644, + 646, 681, 697, 715, 720, 727, 734, 743, 749, 755, + 765, 770, 777, 784, 791, 797, 803, 811, 813, 823, + 829, 844, 859, 865, 875, 878, 889, 903, 907, 911, + 916, 920, 923, 933, 937, 942, 946, 950, 954, 958, + 958, 966, 966, 974, 974, 982, 988, 994, 1000, 1008, + 1010, 1013, 1015, 1018, 1020, 1023, 1028, 1032, 1036, 1040, + 1044, 1048, 1052, 1056, 1060, 1064, 1068, 1072, 1076, 1080, + 1084, 1088, 1092, 1096, 1100, 1106, 1111, 1115, 1119, 1123, + 1127, 1131, 1135, 1139, 1143, 1149, 1159, 1159, 1170, 1186, + 1193, 1206, 1211, 1214, 1214, 1228, 1230, 1231, 1232, 1244, + 1244, 1261, 1266, 1272 }; #endif @@ -1402,13 +1402,18 @@ case 29: case 30: #line 324 "dcParser.yxx" { - if (yyvsp[0].u.dclass != (DCClass *)NULL) { - current_class->add_parent(yyvsp[0].u.dclass); + if (!dc_multiple_inheritance) { + yyerror("Multiple inheritance is not supported without \"dc-multiple-inheritance 1\" in your Config.prc file."); + + } else { + if (yyvsp[0].u.dclass != (DCClass *)NULL) { + current_class->add_parent(yyvsp[0].u.dclass); + } } } break; case 33: -#line 335 "dcParser.yxx" +#line 340 "dcParser.yxx" { if (yyvsp[0].u.field == (DCField *)NULL) { // Pass this error up. @@ -1420,7 +1425,7 @@ case 33: } break; case 34: -#line 348 "dcParser.yxx" +#line 353 "dcParser.yxx" { if (yyvsp[-1].u.field != (DCField *)NULL) { if (yyvsp[-1].u.field->get_name().empty()) { @@ -1432,7 +1437,7 @@ case 34: } break; case 36: -#line 359 "dcParser.yxx" +#line 364 "dcParser.yxx" { yyerror("Unnamed parameters are not allowed on a dclass"); if (yyvsp[-2].u.parameter != (DCField *)NULL) { @@ -1442,7 +1447,7 @@ case 36: } break; case 37: -#line 367 "dcParser.yxx" +#line 372 "dcParser.yxx" { if (yyvsp[-1].u.parameter != (DCField *)NULL) { yyvsp[-1].u.parameter->set_flags(yyvsp[0].u.s_int); @@ -1451,21 +1456,21 @@ case 37: } break; case 38: -#line 377 "dcParser.yxx" +#line 382 "dcParser.yxx" { yyval.u.dclass = current_class; current_class = new DCClass(yyvsp[0].str, true, false); } break; case 39: -#line 382 "dcParser.yxx" +#line 387 "dcParser.yxx" { yyval.u.dclass = current_class; current_class = yyvsp[-4].u.dclass; } break; case 40: -#line 390 "dcParser.yxx" +#line 395 "dcParser.yxx" { if (dc_file == (DCFile *)NULL) { yyerror("No DCFile available, so no struct names are predefined."); @@ -1487,7 +1492,7 @@ case 40: } break; case 43: -#line 418 "dcParser.yxx" +#line 423 "dcParser.yxx" { if (yyvsp[0].u.dclass != (DCClass *)NULL) { current_class->add_parent(yyvsp[0].u.dclass); @@ -1495,7 +1500,7 @@ case 43: } break; case 44: -#line 424 "dcParser.yxx" +#line 429 "dcParser.yxx" { if (yyvsp[0].u.dclass != (DCClass *)NULL) { current_class->add_parent(yyvsp[0].u.dclass); @@ -1503,7 +1508,7 @@ case 44: } break; case 47: -#line 435 "dcParser.yxx" +#line 440 "dcParser.yxx" { if (yyvsp[0].u.field == (DCField *)NULL) { // Pass this error up. @@ -1513,7 +1518,7 @@ case 47: } break; case 48: -#line 446 "dcParser.yxx" +#line 451 "dcParser.yxx" { if (yyvsp[-1].u.field->get_name().empty()) { yyerror("Field name required."); @@ -1522,33 +1527,33 @@ case 48: } break; case 50: -#line 454 "dcParser.yxx" +#line 459 "dcParser.yxx" { yyval.u.field = yyvsp[-2].u.parameter; } break; case 51: -#line 458 "dcParser.yxx" +#line 463 "dcParser.yxx" { yyval.u.field = yyvsp[-1].u.parameter; } break; case 52: -#line 465 "dcParser.yxx" +#line 470 "dcParser.yxx" { yyval.u.field = current_atomic; current_atomic = new DCAtomicField(yyvsp[-1].str, current_class); } break; case 53: -#line 470 "dcParser.yxx" +#line 475 "dcParser.yxx" { yyval.u.field = current_atomic; current_atomic = yyvsp[-2].u.atomic; } break; case 58: -#line 488 "dcParser.yxx" +#line 493 "dcParser.yxx" { if (yyvsp[0].u.parameter != (DCParameter *)NULL) { current_atomic->add_element(yyvsp[0].u.parameter); @@ -1556,19 +1561,19 @@ case 58: } break; case 59: -#line 497 "dcParser.yxx" +#line 502 "dcParser.yxx" { current_parameter = yyvsp[0].u.parameter; } break; case 60: -#line 501 "dcParser.yxx" +#line 506 "dcParser.yxx" { yyval.u.parameter = yyvsp[0].u.parameter; } break; case 63: -#line 513 "dcParser.yxx" +#line 518 "dcParser.yxx" { current_packer = &default_packer; current_packer->clear_data(); @@ -1578,7 +1583,7 @@ case 63: } break; case 64: -#line 521 "dcParser.yxx" +#line 526 "dcParser.yxx" { bool is_valid = false; if (yyvsp[-3].u.parameter != (DCField *)NULL) { @@ -1598,7 +1603,7 @@ case 64: } break; case 66: -#line 543 "dcParser.yxx" +#line 548 "dcParser.yxx" { current_packer = &default_packer; current_packer->clear_data(); @@ -1608,7 +1613,7 @@ case 66: } break; case 67: -#line 551 "dcParser.yxx" +#line 556 "dcParser.yxx" { bool is_valid = false; if (yyvsp[-3].u.parameter != (DCField *)NULL) { @@ -1628,31 +1633,31 @@ case 67: } break; case 72: -#line 582 "dcParser.yxx" +#line 587 "dcParser.yxx" { yyval.u.field = yyvsp[-1].u.field; } break; case 73: -#line 586 "dcParser.yxx" +#line 591 "dcParser.yxx" { yyval.u.field = yyvsp[-1].u.parameter; } break; case 74: -#line 590 "dcParser.yxx" +#line 595 "dcParser.yxx" { yyval.u.field = yyvsp[-1].u.parameter; } break; case 75: -#line 597 "dcParser.yxx" +#line 602 "dcParser.yxx" { yyval.u.parameter = new DCSimpleParameter(yyvsp[0].u.subatomic); } break; case 76: -#line 601 "dcParser.yxx" +#line 606 "dcParser.yxx" { DCSimpleParameter *simple_param = yyvsp[-3].u.parameter->as_simple_parameter(); nassertr(simple_param != (DCSimpleParameter *)NULL, 0); @@ -1663,7 +1668,7 @@ case 76: } break; case 77: -#line 610 "dcParser.yxx" +#line 615 "dcParser.yxx" { DCSimpleParameter *simple_param = yyvsp[-2].u.parameter->as_simple_parameter(); nassertr(simple_param != (DCSimpleParameter *)NULL, 0); @@ -1681,7 +1686,7 @@ case 77: } break; case 78: -#line 626 "dcParser.yxx" +#line 631 "dcParser.yxx" { DCSimpleParameter *simple_param = yyvsp[-2].u.parameter->as_simple_parameter(); nassertr(simple_param != (DCSimpleParameter *)NULL, 0); @@ -1695,7 +1700,7 @@ case 78: } break; case 80: -#line 642 "dcParser.yxx" +#line 647 "dcParser.yxx" { if (dc_file == (DCFile *)NULL) { yyerror("Invalid type."); @@ -1732,7 +1737,7 @@ case 80: } break; case 81: -#line 677 "dcParser.yxx" +#line 682 "dcParser.yxx" { // This is an inline struct definition. if (yyvsp[0].u.dclass == (DCClass *)NULL) { @@ -1750,7 +1755,7 @@ case 81: } break; case 82: -#line 693 "dcParser.yxx" +#line 698 "dcParser.yxx" { // This is an inline switch definition. if (yyvsp[0].u.dswitch == (DCSwitch *)NULL) { @@ -1768,13 +1773,13 @@ case 82: } break; case 83: -#line 712 "dcParser.yxx" +#line 717 "dcParser.yxx" { double_range.clear(); } break; case 84: -#line 716 "dcParser.yxx" +#line 721 "dcParser.yxx" { double_range.clear(); if (!double_range.add_range(yyvsp[0].u.real, yyvsp[0].u.real)) { @@ -1783,7 +1788,7 @@ case 84: } break; case 85: -#line 723 "dcParser.yxx" +#line 728 "dcParser.yxx" { double_range.clear(); if (!double_range.add_range(yyvsp[-2].u.real, yyvsp[0].u.real)) { @@ -1792,7 +1797,7 @@ case 85: } break; case 86: -#line 730 "dcParser.yxx" +#line 735 "dcParser.yxx" { double_range.clear(); if (yyvsp[0].u.real >= 0) { @@ -1803,7 +1808,7 @@ case 86: } break; case 87: -#line 739 "dcParser.yxx" +#line 744 "dcParser.yxx" { if (!double_range.add_range(yyvsp[0].u.real, yyvsp[0].u.real)) { yyerror("Overlapping range"); @@ -1811,7 +1816,7 @@ case 87: } break; case 88: -#line 745 "dcParser.yxx" +#line 750 "dcParser.yxx" { if (!double_range.add_range(yyvsp[-2].u.real, yyvsp[0].u.real)) { yyerror("Overlapping range"); @@ -1819,7 +1824,7 @@ case 88: } break; case 89: -#line 751 "dcParser.yxx" +#line 756 "dcParser.yxx" { if (yyvsp[0].u.real >= 0) { yyerror("Syntax error"); @@ -1829,13 +1834,13 @@ case 89: } break; case 90: -#line 762 "dcParser.yxx" +#line 767 "dcParser.yxx" { uint_range.clear(); } break; case 91: -#line 766 "dcParser.yxx" +#line 771 "dcParser.yxx" { uint_range.clear(); if (!uint_range.add_range(yyvsp[0].u.s_uint, yyvsp[0].u.s_uint)) { @@ -1844,7 +1849,7 @@ case 91: } break; case 92: -#line 773 "dcParser.yxx" +#line 778 "dcParser.yxx" { uint_range.clear(); if (!uint_range.add_range(yyvsp[-2].u.s_uint, yyvsp[0].u.s_uint)) { @@ -1853,7 +1858,7 @@ case 92: } break; case 93: -#line 780 "dcParser.yxx" +#line 785 "dcParser.yxx" { uint_range.clear(); if (!uint_range.add_range(yyvsp[-1].u.s_uint, yyvsp[0].u.s_uint)) { @@ -1862,7 +1867,7 @@ case 93: } break; case 94: -#line 787 "dcParser.yxx" +#line 792 "dcParser.yxx" { if (!uint_range.add_range(yyvsp[0].u.s_uint, yyvsp[0].u.s_uint)) { yyerror("Overlapping range"); @@ -1870,7 +1875,7 @@ case 94: } break; case 95: -#line 793 "dcParser.yxx" +#line 798 "dcParser.yxx" { if (!uint_range.add_range(yyvsp[-2].u.s_uint, yyvsp[0].u.s_uint)) { yyerror("Overlapping range"); @@ -1878,7 +1883,7 @@ case 95: } break; case 96: -#line 799 "dcParser.yxx" +#line 804 "dcParser.yxx" { if (!uint_range.add_range(yyvsp[-1].u.s_uint, yyvsp[0].u.s_uint)) { yyerror("Overlapping range"); @@ -1886,7 +1891,7 @@ case 96: } break; case 98: -#line 809 "dcParser.yxx" +#line 814 "dcParser.yxx" { if (yyvsp[-3].u.parameter == (DCParameter *)NULL) { yyval.u.parameter = NULL; @@ -1896,14 +1901,14 @@ case 98: } break; case 99: -#line 820 "dcParser.yxx" +#line 825 "dcParser.yxx" { current_parameter->set_name(yyvsp[0].str); yyval.u.parameter = current_parameter; } break; case 100: -#line 825 "dcParser.yxx" +#line 830 "dcParser.yxx" { DCSimpleParameter *simple_param = yyvsp[-2].u.parameter->as_simple_parameter(); if (simple_param == NULL || simple_param->get_typedef() != (DCTypedef *)NULL) { @@ -1920,7 +1925,7 @@ case 100: } break; case 101: -#line 840 "dcParser.yxx" +#line 845 "dcParser.yxx" { DCSimpleParameter *simple_param = yyvsp[-2].u.parameter->as_simple_parameter(); if (simple_param == NULL || simple_param->get_typedef() != (DCTypedef *)NULL) { @@ -1937,13 +1942,13 @@ case 101: } break; case 102: -#line 855 "dcParser.yxx" +#line 860 "dcParser.yxx" { yyval.u.parameter = yyvsp[-3].u.parameter->append_array_specification(uint_range); } break; case 103: -#line 862 "dcParser.yxx" +#line 867 "dcParser.yxx" { if (yyvsp[0].str.length() != 1) { yyerror("Single character required."); @@ -1954,7 +1959,7 @@ case 103: } break; case 105: -#line 875 "dcParser.yxx" +#line 880 "dcParser.yxx" { yyval.u.s_uint = (unsigned int)yyvsp[0].u.uint64; if (yyval.u.s_uint != yyvsp[0].u.uint64) { @@ -1964,7 +1969,7 @@ case 105: } break; case 106: -#line 886 "dcParser.yxx" +#line 891 "dcParser.yxx" { yyval.u.s_uint = (unsigned int)-yyvsp[0].u.int64; if (yyvsp[0].u.int64 >= 0) { @@ -1977,19 +1982,19 @@ case 106: } break; case 109: -#line 908 "dcParser.yxx" +#line 913 "dcParser.yxx" { yyval.u.real = (double)yyvsp[0].u.uint64; } break; case 110: -#line 912 "dcParser.yxx" +#line 917 "dcParser.yxx" { yyval.u.real = (double)yyvsp[0].u.int64; } break; case 112: -#line 920 "dcParser.yxx" +#line 925 "dcParser.yxx" { if (yyvsp[0].str.length() != 1) { yyerror("Single character required."); @@ -2000,73 +2005,73 @@ case 112: } break; case 114: -#line 934 "dcParser.yxx" +#line 939 "dcParser.yxx" { current_packer->pack_int64(yyvsp[0].u.int64); } break; case 115: -#line 938 "dcParser.yxx" +#line 943 "dcParser.yxx" { current_packer->pack_uint64(yyvsp[0].u.uint64); } break; case 116: -#line 942 "dcParser.yxx" +#line 947 "dcParser.yxx" { current_packer->pack_double(yyvsp[0].u.real); } break; case 117: -#line 946 "dcParser.yxx" +#line 951 "dcParser.yxx" { current_packer->pack_string(yyvsp[0].str); } break; case 118: -#line 950 "dcParser.yxx" +#line 955 "dcParser.yxx" { current_packer->pack_literal_value(yyvsp[0].str); } break; case 119: -#line 954 "dcParser.yxx" +#line 959 "dcParser.yxx" { current_packer->push(); } break; case 120: -#line 958 "dcParser.yxx" +#line 963 "dcParser.yxx" { current_packer->pop(); } break; case 121: -#line 962 "dcParser.yxx" +#line 967 "dcParser.yxx" { current_packer->push(); } break; case 122: -#line 966 "dcParser.yxx" +#line 971 "dcParser.yxx" { current_packer->pop(); } break; case 123: -#line 970 "dcParser.yxx" +#line 975 "dcParser.yxx" { current_packer->push(); } break; case 124: -#line 974 "dcParser.yxx" +#line 979 "dcParser.yxx" { current_packer->pop(); } break; case 125: -#line 978 "dcParser.yxx" +#line 983 "dcParser.yxx" { for (unsigned int i = 0; i < yyvsp[0].u.s_uint; i++) { current_packer->pack_int64(yyvsp[-2].u.int64); @@ -2074,7 +2079,7 @@ case 125: } break; case 126: -#line 984 "dcParser.yxx" +#line 989 "dcParser.yxx" { for (unsigned int i = 0; i < yyvsp[0].u.s_uint; i++) { current_packer->pack_uint64(yyvsp[-2].u.uint64); @@ -2082,7 +2087,7 @@ case 126: } break; case 127: -#line 990 "dcParser.yxx" +#line 995 "dcParser.yxx" { for (unsigned int i = 0; i < yyvsp[0].u.s_uint; i++) { current_packer->pack_double(yyvsp[-2].u.real); @@ -2090,7 +2095,7 @@ case 127: } break; case 128: -#line 996 "dcParser.yxx" +#line 1001 "dcParser.yxx" { for (unsigned int i = 0; i < yyvsp[0].u.s_uint; i++) { current_packer->pack_literal_value(yyvsp[-2].str); @@ -2098,187 +2103,187 @@ case 128: } break; case 135: -#line 1020 "dcParser.yxx" +#line 1025 "dcParser.yxx" { yyval.u.subatomic = ST_int8; } break; case 136: -#line 1024 "dcParser.yxx" +#line 1029 "dcParser.yxx" { yyval.u.subatomic = ST_int16; } break; case 137: -#line 1028 "dcParser.yxx" +#line 1033 "dcParser.yxx" { yyval.u.subatomic = ST_int32; } break; case 138: -#line 1032 "dcParser.yxx" +#line 1037 "dcParser.yxx" { yyval.u.subatomic = ST_int64; } break; case 139: -#line 1036 "dcParser.yxx" +#line 1041 "dcParser.yxx" { yyval.u.subatomic = ST_uint8; } break; case 140: -#line 1040 "dcParser.yxx" +#line 1045 "dcParser.yxx" { yyval.u.subatomic = ST_uint16; } break; case 141: -#line 1044 "dcParser.yxx" +#line 1049 "dcParser.yxx" { yyval.u.subatomic = ST_uint32; } break; case 142: -#line 1048 "dcParser.yxx" +#line 1053 "dcParser.yxx" { yyval.u.subatomic = ST_uint64; } break; case 143: -#line 1052 "dcParser.yxx" +#line 1057 "dcParser.yxx" { yyval.u.subatomic = ST_float64; } break; case 144: -#line 1056 "dcParser.yxx" +#line 1061 "dcParser.yxx" { yyval.u.subatomic = ST_string; } break; case 145: -#line 1060 "dcParser.yxx" +#line 1065 "dcParser.yxx" { yyval.u.subatomic = ST_blob; } break; case 146: -#line 1064 "dcParser.yxx" +#line 1069 "dcParser.yxx" { yyval.u.subatomic = ST_blob32; } break; case 147: -#line 1068 "dcParser.yxx" +#line 1073 "dcParser.yxx" { yyval.u.subatomic = ST_int8array; } break; case 148: -#line 1072 "dcParser.yxx" +#line 1077 "dcParser.yxx" { yyval.u.subatomic = ST_int16array; } break; case 149: -#line 1076 "dcParser.yxx" +#line 1081 "dcParser.yxx" { yyval.u.subatomic = ST_int32array; } break; case 150: -#line 1080 "dcParser.yxx" +#line 1085 "dcParser.yxx" { yyval.u.subatomic = ST_uint8array; } break; case 151: -#line 1084 "dcParser.yxx" +#line 1089 "dcParser.yxx" { yyval.u.subatomic = ST_uint16array; } break; case 152: -#line 1088 "dcParser.yxx" +#line 1093 "dcParser.yxx" { yyval.u.subatomic = ST_uint32array; } break; case 153: -#line 1092 "dcParser.yxx" +#line 1097 "dcParser.yxx" { yyval.u.subatomic = ST_uint32uint8array; } break; case 154: -#line 1096 "dcParser.yxx" +#line 1101 "dcParser.yxx" { yyval.u.subatomic = ST_char; } break; case 155: -#line 1103 "dcParser.yxx" +#line 1108 "dcParser.yxx" { yyval.u.s_int = 0; } break; case 156: -#line 1107 "dcParser.yxx" +#line 1112 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_required; } break; case 157: -#line 1111 "dcParser.yxx" +#line 1116 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_broadcast; } break; case 158: -#line 1115 "dcParser.yxx" +#line 1120 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_p2p; } break; case 159: -#line 1119 "dcParser.yxx" +#line 1124 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_ram; } break; case 160: -#line 1123 "dcParser.yxx" +#line 1128 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_db; } break; case 161: -#line 1127 "dcParser.yxx" +#line 1132 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_clsend; } break; case 162: -#line 1131 "dcParser.yxx" +#line 1136 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_clrecv; } break; case 163: -#line 1135 "dcParser.yxx" +#line 1140 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_ownsend; } break; case 164: -#line 1139 "dcParser.yxx" +#line 1144 "dcParser.yxx" { yyval.u.s_int = yyvsp[-1].u.s_int | DCAtomicField::F_airecv; } break; case 165: -#line 1146 "dcParser.yxx" +#line 1151 "dcParser.yxx" { if (yyvsp[0].u.s_int != 0) { yyerror("Server flags are not allowed here."); @@ -2287,19 +2292,19 @@ case 165: } break; case 166: -#line 1156 "dcParser.yxx" +#line 1161 "dcParser.yxx" { current_molecular = new DCMolecularField(yyvsp[-1].str, current_class); } break; case 167: -#line 1160 "dcParser.yxx" +#line 1165 "dcParser.yxx" { yyval.u.field = current_molecular; } break; case 168: -#line 1167 "dcParser.yxx" +#line 1172 "dcParser.yxx" { DCField *field = current_class->get_field_by_name(yyvsp[0].str); yyval.u.atomic = (DCAtomicField *)NULL; @@ -2314,7 +2319,7 @@ case 168: } break; case 169: -#line 1183 "dcParser.yxx" +#line 1188 "dcParser.yxx" { if (yyvsp[0].u.atomic != (DCAtomicField *)NULL) { current_molecular->add_atomic(yyvsp[0].u.atomic); @@ -2322,7 +2327,7 @@ case 169: } break; case 170: -#line 1189 "dcParser.yxx" +#line 1194 "dcParser.yxx" { if (yyvsp[0].u.atomic != (DCAtomicField *)NULL) { current_molecular->add_atomic(yyvsp[0].u.atomic); @@ -2335,27 +2340,27 @@ case 170: } break; case 171: -#line 1203 "dcParser.yxx" +#line 1208 "dcParser.yxx" { yyval.str = ""; } break; case 173: -#line 1211 "dcParser.yxx" +#line 1216 "dcParser.yxx" { yyval.u.dswitch = current_switch; current_switch = new DCSwitch(yyvsp[-4].str, yyvsp[-2].u.parameter); } break; case 174: -#line 1216 "dcParser.yxx" +#line 1221 "dcParser.yxx" { yyval.u.dswitch = current_switch; current_switch = (DCSwitch *)yyvsp[-2].u.parameter; } break; case 178: -#line 1228 "dcParser.yxx" +#line 1233 "dcParser.yxx" { if (current_switch->get_num_cases() == 0) { yyerror("case declaration required before first element"); @@ -2367,7 +2372,7 @@ case 178: } break; case 179: -#line 1241 "dcParser.yxx" +#line 1246 "dcParser.yxx" { current_packer = &default_packer; current_packer->clear_data(); @@ -2375,7 +2380,7 @@ case 179: } break; case 180: -#line 1247 "dcParser.yxx" +#line 1252 "dcParser.yxx" { if (!current_packer->end_pack()) { yyerror("Invalid value for switch parameter"); @@ -2385,13 +2390,13 @@ case 180: } break; case 181: -#line 1258 "dcParser.yxx" +#line 1263 "dcParser.yxx" { yyval.u.field = yyvsp[-1].u.parameter; } break; case 182: -#line 1262 "dcParser.yxx" +#line 1267 "dcParser.yxx" { yyval.u.field = yyvsp[0].u.parameter; } @@ -2629,4 +2634,4 @@ yyreturn: #endif return yyresult; } -#line 1270 "dcParser.yxx" +#line 1275 "dcParser.yxx" diff --git a/direct/src/dcparser/dcParser.yxx b/direct/src/dcparser/dcParser.yxx index 76f73ece51..30946a2bae 100644 --- a/direct/src/dcparser/dcParser.yxx +++ b/direct/src/dcparser/dcParser.yxx @@ -276,7 +276,7 @@ dclass: KW_DCLASS optional_name { $$ = current_class; - current_class = new DCClass($2, false, false); + current_class = new DCClass(dc_file, $2, false, false); } dclass_derivation '{' dclass_fields '}' { @@ -296,7 +296,7 @@ dclass_name: 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); + dclass = new DCClass(dc_file, $1, false, true); dc_file->add_class(dclass); } if (dclass->is_struct()) { @@ -322,8 +322,13 @@ dclass_base_list: } | dclass_base_list ',' dclass_name { - if ($3 != (DCClass *)NULL) { - current_class->add_parent($3); + if (!dc_multiple_inheritance) { + yyerror("Multiple inheritance is not supported without \"dc-multiple-inheritance 1\" in your Config.prc file."); + + } else { + if ($3 != (DCClass *)NULL) { + current_class->add_parent($3); + } } } ; @@ -376,7 +381,7 @@ struct: KW_STRUCT optional_name { $$ = current_class; - current_class = new DCClass($2, true, false); + current_class = new DCClass(dc_file, $2, true, false); } struct_derivation '{' struct_fields '}' { @@ -396,7 +401,7 @@ struct_name: 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); + dstruct = new DCClass(dc_file, $1, false, true); dc_file->add_class(dstruct); } if (!dstruct->is_struct()) { diff --git a/direct/src/dcparser/dcSimpleParameter.cxx b/direct/src/dcparser/dcSimpleParameter.cxx index 0ba37a8f48..14eacbb5b6 100644 --- a/direct/src/dcparser/dcSimpleParameter.cxx +++ b/direct/src/dcparser/dcSimpleParameter.cxx @@ -2475,7 +2475,7 @@ create_nested_field(DCSubatomicType type, unsigned int divisor) { DCPackerInterface *DCSimpleParameter:: create_uint32uint8_type() { if (_uint32uint8_type == NULL) { - DCClass *dclass = new DCClass("", true, false); + DCClass *dclass = new DCClass(NULL, "", true, false); dclass->add_field(new DCSimpleParameter(ST_uint32)); dclass->add_field(new DCSimpleParameter(ST_uint8)); _uint32uint8_type = new DCClassParameter(dclass); diff --git a/direct/src/distributed/ServerRepository.py b/direct/src/distributed/ServerRepository.py index a05a0e674d..0c17ed26f8 100644 --- a/direct/src/distributed/ServerRepository.py +++ b/direct/src/distributed/ServerRepository.py @@ -14,6 +14,7 @@ from direct.distributed.PyDatagram import PyDatagram from direct.distributed.PyDatagramIterator import PyDatagramIterator #from PointerToConnection import PointerToConnection import time +import types class ServerRepository: @@ -265,7 +266,12 @@ class ServerRepository: doid = dgi.getUint32() fieldid = dgi.getUint16() dclass = self.DOIDtoDClass[doid] - dcfield = dclass.getField(fieldid) + dcfield = dclass.getFieldByIndex(fieldid) + if dcfield == None: + self.notify.error( + "Received update for field %s on object %s; no such field for class %s." % ( + fieldid, doid, dclass.getName())) + return if (dcfield.isBroadcast()): if (dcfield.isP2p()): self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0) diff --git a/direct/src/distributed/cConnectionRepository.cxx b/direct/src/distributed/cConnectionRepository.cxx index d0c4e0d685..37b6b3e2aa 100644 --- a/direct/src/distributed/cConnectionRepository.cxx +++ b/direct/src/distributed/cConnectionRepository.cxx @@ -510,11 +510,11 @@ describe_message(ostream &out, const string &prefix, } else { out << prefix << "update for " << dclass->get_name() << " " << do_id << ": "; - if (field_id < 0 || field_id >= dclass->get_num_inherited_fields()) { + DCField *field = dclass->get_field_by_index(field_id); + if (field == (DCField *)NULL) { out << "unknown field " << field_id << "\n"; } else { - DCField *field = dclass->get_inherited_field(field_id); out << field->get_name(); packer.begin_unpack(field); packer.unpack_and_format(out);