Panda3D
|
00001 // Filename: dcFile.cxx 00002 // Created by: drose (05Oct00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "dcFile.h" 00016 #include "dcClass.h" 00017 #include "dcSwitch.h" 00018 #include "dcParserDefs.h" 00019 #include "dcLexerDefs.h" 00020 #include "dcTypedef.h" 00021 #include "dcKeyword.h" 00022 #include "hashGenerator.h" 00023 00024 #ifdef WITHIN_PANDA 00025 #include "filename.h" 00026 #include "config_express.h" 00027 #include "virtualFileSystem.h" 00028 #include "executionEnvironment.h" 00029 #include "configVariableList.h" 00030 #endif 00031 00032 00033 //////////////////////////////////////////////////////////////////// 00034 // Function: DCFile::Constructor 00035 // Access: Published 00036 // Description: 00037 //////////////////////////////////////////////////////////////////// 00038 DCFile:: 00039 DCFile() { 00040 _all_objects_valid = true; 00041 _inherited_fields_stale = false; 00042 00043 setup_default_keywords(); 00044 } 00045 00046 //////////////////////////////////////////////////////////////////// 00047 // Function: DCFile::Destructor 00048 // Access: Published 00049 // Description: 00050 //////////////////////////////////////////////////////////////////// 00051 DCFile:: 00052 ~DCFile() { 00053 clear(); 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: DCFile::clear 00058 // Access: Published 00059 // Description: Removes all of the classes defined within the DCFile 00060 // and prepares it for reading a new file. 00061 //////////////////////////////////////////////////////////////////// 00062 void DCFile:: 00063 clear() { 00064 Declarations::iterator di; 00065 for (di = _declarations.begin(); di != _declarations.end(); ++di) { 00066 delete (*di); 00067 } 00068 for (di = _things_to_delete.begin(); di != _things_to_delete.end(); ++di) { 00069 delete (*di); 00070 } 00071 00072 _classes.clear(); 00073 _imports.clear(); 00074 _things_by_name.clear(); 00075 _typedefs.clear(); 00076 _typedefs_by_name.clear(); 00077 _keywords.clear_keywords(); 00078 _declarations.clear(); 00079 _things_to_delete.clear(); 00080 setup_default_keywords(); 00081 00082 _all_objects_valid = true; 00083 _inherited_fields_stale = false; 00084 } 00085 00086 #ifdef WITHIN_PANDA 00087 00088 //////////////////////////////////////////////////////////////////// 00089 // Function: DCFile::read_all 00090 // Access: Published 00091 // Description: This special method reads all of the .dc files named 00092 // by the "dc-file" config.prc variable, and loads them 00093 // into the DCFile namespace. 00094 //////////////////////////////////////////////////////////////////// 00095 bool DCFile:: 00096 read_all() { 00097 static ConfigVariableList dc_files 00098 ("dc-file", PRC_DESC("The list of dc files to load.")); 00099 00100 if (dc_files.size() == 0) { 00101 cerr << "No files specified via dc-file Config.prc variable!\n"; 00102 return false; 00103 } 00104 00105 int size = dc_files.size(); 00106 00107 // Load the DC files in opposite order, because we want to load the 00108 // least-important (most fundamental) files first. 00109 for (int i = size - 1; i >= 0; --i) { 00110 string dc_file = ExecutionEnvironment::expand_string(dc_files[i]); 00111 Filename filename = Filename::from_os_specific(dc_file); 00112 if (!read(filename)) { 00113 return false; 00114 } 00115 } 00116 00117 return true; 00118 } 00119 00120 #endif // WITHIN_PANDA 00121 00122 //////////////////////////////////////////////////////////////////// 00123 // Function: DCFile::read 00124 // Access: Published 00125 // Description: Opens and reads the indicated .dc file by name. The 00126 // distributed classes defined in the file will be 00127 // appended to the set of distributed classes already 00128 // recorded, if any. 00129 // 00130 // Returns true if the file is successfully read, false 00131 // if there was an error (in which case the file might 00132 // have been partially read). 00133 //////////////////////////////////////////////////////////////////// 00134 bool DCFile:: 00135 read(Filename filename) { 00136 #ifdef WITHIN_PANDA 00137 filename.set_text(); 00138 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00139 istream *in = vfs->open_read_file(filename, true); 00140 if (in == (istream *)NULL) { 00141 cerr << "Cannot open " << filename << " for reading.\n"; 00142 return false; 00143 } 00144 bool okflag = read(*in, filename); 00145 00146 // For some reason--compiler bug in gcc 3.2?--explicitly deleting 00147 // the in pointer does not call the appropriate global delete 00148 // function; instead apparently calling the system delete 00149 // function. So we call the delete function by hand instead. 00150 vfs->close_read_file(in); 00151 00152 return okflag; 00153 00154 #else // WITHIN_PANDA 00155 00156 pifstream in; 00157 in.open(filename.c_str()); 00158 00159 if (!in) { 00160 cerr << "Cannot open " << filename << " for reading.\n"; 00161 return false; 00162 } 00163 00164 return read(in, filename); 00165 00166 #endif // WITHIN_PANDA 00167 } 00168 00169 //////////////////////////////////////////////////////////////////// 00170 // Function: DCFile::read 00171 // Access: Published 00172 // Description: Parses the already-opened input stream for 00173 // distributed class descriptions. The filename 00174 // parameter is optional and is only used when reporting 00175 // errors. 00176 // 00177 // The distributed classes defined in the file will be 00178 // appended to the set of distributed classes already 00179 // recorded, if any. 00180 // 00181 // Returns true if the file is successfully read, false 00182 // if there was an error (in which case the file might 00183 // have been partially read). 00184 //////////////////////////////////////////////////////////////////// 00185 bool DCFile:: 00186 read(istream &in, const string &filename) { 00187 cerr << "DCFile::read of " << filename << "\n"; 00188 dc_init_parser(in, filename, *this); 00189 dcyyparse(); 00190 dc_cleanup_parser(); 00191 00192 return (dc_error_count() == 0); 00193 } 00194 00195 //////////////////////////////////////////////////////////////////// 00196 // Function: DCFile::write 00197 // Access: Published 00198 // Description: Opens the indicated filename for output and writes a 00199 // parseable description of all the known distributed 00200 // classes to the file. 00201 // 00202 // Returns true if the description is successfully 00203 // written, false otherwise. 00204 //////////////////////////////////////////////////////////////////// 00205 bool DCFile:: 00206 write(Filename filename, bool brief) const { 00207 pofstream out; 00208 00209 #ifdef WITHIN_PANDA 00210 filename.set_text(); 00211 filename.open_write(out); 00212 #else 00213 out.open(filename.c_str()); 00214 #endif 00215 00216 if (!out) { 00217 cerr << "Can't open " << filename << " for output.\n"; 00218 return false; 00219 } 00220 return write(out, brief); 00221 } 00222 00223 //////////////////////////////////////////////////////////////////// 00224 // Function: DCFile::write 00225 // Access: Published 00226 // Description: Writes a parseable description of all the known 00227 // distributed classes to the stream. 00228 // 00229 // Returns true if the description is successfully 00230 // written, false otherwise. 00231 //////////////////////////////////////////////////////////////////// 00232 bool DCFile:: 00233 write(ostream &out, bool brief) const { 00234 if (!_imports.empty()) { 00235 Imports::const_iterator ii; 00236 for (ii = _imports.begin(); ii != _imports.end(); ++ii) { 00237 const Import &import = (*ii); 00238 if (import._symbols.empty()) { 00239 out << "import " << import._module << "\n"; 00240 } else { 00241 out << "from " << import._module << " import "; 00242 ImportSymbols::const_iterator si = import._symbols.begin(); 00243 out << *si; 00244 ++si; 00245 while (si != import._symbols.end()) { 00246 out << ", " << *si; 00247 ++si; 00248 } 00249 out << "\n"; 00250 } 00251 } 00252 out << "\n"; 00253 } 00254 00255 Declarations::const_iterator di; 00256 for (di = _declarations.begin(); di != _declarations.end(); ++di) { 00257 (*di)->write(out, brief, 0); 00258 out << "\n"; 00259 } 00260 00261 return !out.fail(); 00262 } 00263 00264 //////////////////////////////////////////////////////////////////// 00265 // Function: DCFile::get_num_classes 00266 // Access: Published 00267 // Description: Returns the number of classes read from the .dc 00268 // file(s). 00269 //////////////////////////////////////////////////////////////////// 00270 int DCFile:: 00271 get_num_classes() const { 00272 return _classes.size(); 00273 } 00274 00275 //////////////////////////////////////////////////////////////////// 00276 // Function: DCFile::get_class 00277 // Access: Published 00278 // Description: Returns the nth class read from the .dc file(s). 00279 //////////////////////////////////////////////////////////////////// 00280 DCClass *DCFile:: 00281 get_class(int n) const { 00282 nassertr(n >= 0 && n < (int)_classes.size(), NULL); 00283 return _classes[n]; 00284 } 00285 00286 //////////////////////////////////////////////////////////////////// 00287 // Function: DCFile::get_class_by_name 00288 // Access: Published 00289 // Description: Returns the class that has the indicated name, or 00290 // NULL if there is no such class. 00291 //////////////////////////////////////////////////////////////////// 00292 DCClass *DCFile:: 00293 get_class_by_name(const string &name) const { 00294 ThingsByName::const_iterator ni; 00295 ni = _things_by_name.find(name); 00296 if (ni != _things_by_name.end()) { 00297 return (*ni).second->as_class(); 00298 } 00299 00300 return (DCClass *)NULL; 00301 } 00302 00303 //////////////////////////////////////////////////////////////////// 00304 // Function: DCFile::get_switch_by_name 00305 // Access: Published 00306 // Description: Returns the switch that has the indicated name, or 00307 // NULL if there is no such switch. 00308 //////////////////////////////////////////////////////////////////// 00309 DCSwitch *DCFile:: 00310 get_switch_by_name(const string &name) const { 00311 ThingsByName::const_iterator ni; 00312 ni = _things_by_name.find(name); 00313 if (ni != _things_by_name.end()) { 00314 return (*ni).second->as_switch(); 00315 } 00316 00317 return (DCSwitch *)NULL; 00318 } 00319 00320 //////////////////////////////////////////////////////////////////// 00321 // Function: DCFile::get_field_by_index 00322 // Access: Published, Static 00323 // Description: Returns a pointer to the one DCField that has the 00324 // indicated index number, of all the DCFields across 00325 // all classes in the file. 00326 // 00327 // This method is only valid if dc-multiple-inheritance 00328 // is set true in the Config.prc file. Without this 00329 // setting, different DCFields may share the same index 00330 // number, so this global lookup is not possible. 00331 //////////////////////////////////////////////////////////////////// 00332 DCField *DCFile:: 00333 get_field_by_index(int index_number) const { 00334 nassertr(dc_multiple_inheritance, NULL); 00335 00336 if (index_number >= 0 && index_number < (int)_fields_by_index.size()) { 00337 return _fields_by_index[index_number]; 00338 } 00339 00340 return NULL; 00341 } 00342 00343 //////////////////////////////////////////////////////////////////// 00344 // Function: DCFile::get_num_import_modules 00345 // Access: Published 00346 // Description: Returns the number of import lines read from the .dc 00347 // file(s). 00348 //////////////////////////////////////////////////////////////////// 00349 int DCFile:: 00350 get_num_import_modules() const { 00351 return _imports.size(); 00352 } 00353 00354 //////////////////////////////////////////////////////////////////// 00355 // Function: DCFile::get_import_module 00356 // Access: Published 00357 // Description: Returns the module named by the nth import line read 00358 // from the .dc file(s). 00359 //////////////////////////////////////////////////////////////////// 00360 string DCFile:: 00361 get_import_module(int n) const { 00362 nassertr(n >= 0 && n < (int)_imports.size(), string()); 00363 return _imports[n]._module; 00364 } 00365 00366 //////////////////////////////////////////////////////////////////// 00367 // Function: DCFile::get_num_import_symbols 00368 // Access: Published 00369 // Description: Returns the number of symbols explicitly imported by 00370 // the nth import line. If this is 0, the line is 00371 // "import modulename"; if it is more than 0, the line 00372 // is "from modulename import symbol, symbol ... ". 00373 //////////////////////////////////////////////////////////////////// 00374 int DCFile:: 00375 get_num_import_symbols(int n) const { 00376 nassertr(n >= 0 && n < (int)_imports.size(), 0); 00377 return _imports[n]._symbols.size(); 00378 } 00379 00380 //////////////////////////////////////////////////////////////////// 00381 // Function: DCFile::get_import_symbol 00382 // Access: Published 00383 // Description: Returns the ith symbol named by the nth import line 00384 // read from the .dc file(s). 00385 //////////////////////////////////////////////////////////////////// 00386 string DCFile:: 00387 get_import_symbol(int n, int i) const { 00388 nassertr(n >= 0 && n < (int)_imports.size(), string()); 00389 nassertr(i >= 0 && i < (int)_imports[n]._symbols.size(), string()); 00390 return _imports[n]._symbols[i]; 00391 } 00392 00393 //////////////////////////////////////////////////////////////////// 00394 // Function: DCFile::get_num_typedefs 00395 // Access: Published 00396 // Description: Returns the number of typedefs read from the .dc 00397 // file(s). 00398 //////////////////////////////////////////////////////////////////// 00399 int DCFile:: 00400 get_num_typedefs() const { 00401 return _typedefs.size(); 00402 } 00403 00404 //////////////////////////////////////////////////////////////////// 00405 // Function: DCFile::get_typedef 00406 // Access: Published 00407 // Description: Returns the nth typedef read from the .dc file(s). 00408 //////////////////////////////////////////////////////////////////// 00409 DCTypedef *DCFile:: 00410 get_typedef(int n) const { 00411 nassertr(n >= 0 && n < (int)_typedefs.size(), NULL); 00412 return _typedefs[n]; 00413 } 00414 00415 //////////////////////////////////////////////////////////////////// 00416 // Function: DCFile::get_typedef_by_name 00417 // Access: Published 00418 // Description: Returns the typedef that has the indicated name, or 00419 // NULL if there is no such typedef name. 00420 //////////////////////////////////////////////////////////////////// 00421 DCTypedef *DCFile:: 00422 get_typedef_by_name(const string &name) const { 00423 TypedefsByName::const_iterator ni; 00424 ni = _typedefs_by_name.find(name); 00425 if (ni != _typedefs_by_name.end()) { 00426 return (*ni).second; 00427 } 00428 00429 return NULL; 00430 } 00431 00432 //////////////////////////////////////////////////////////////////// 00433 // Function: DCFile::get_num_keywords 00434 // Access: Published 00435 // Description: Returns the number of keywords read from the .dc 00436 // file(s). 00437 //////////////////////////////////////////////////////////////////// 00438 int DCFile:: 00439 get_num_keywords() const { 00440 return _keywords.get_num_keywords(); 00441 } 00442 00443 //////////////////////////////////////////////////////////////////// 00444 // Function: DCFile::get_keyword 00445 // Access: Published 00446 // Description: Returns the nth keyword read from the .dc file(s). 00447 //////////////////////////////////////////////////////////////////// 00448 const DCKeyword *DCFile:: 00449 get_keyword(int n) const { 00450 return _keywords.get_keyword(n); 00451 } 00452 00453 //////////////////////////////////////////////////////////////////// 00454 // Function: DCFile::get_keyword_by_name 00455 // Access: Published 00456 // Description: Returns the keyword that has the indicated name, or 00457 // NULL if there is no such keyword name. 00458 //////////////////////////////////////////////////////////////////// 00459 const DCKeyword *DCFile:: 00460 get_keyword_by_name(const string &name) const { 00461 const DCKeyword *keyword = _keywords.get_keyword_by_name(name); 00462 if (keyword == (const DCKeyword *)NULL) { 00463 keyword = _default_keywords.get_keyword_by_name(name); 00464 if (keyword != (const DCKeyword *)NULL) { 00465 // One of the historical default keywords was used, but wasn't 00466 // defined. Define it implicitly right now. 00467 ((DCFile *)this)->_keywords.add_keyword(keyword); 00468 } 00469 } 00470 00471 return keyword; 00472 } 00473 00474 //////////////////////////////////////////////////////////////////// 00475 // Function: DCFile::get_hash 00476 // Access: Published 00477 // Description: Returns a 32-bit hash index associated with this 00478 // file. This number is guaranteed to be consistent if 00479 // the contents of the file have not changed, and it is 00480 // very likely to be different if the contents of the 00481 // file do change. 00482 //////////////////////////////////////////////////////////////////// 00483 unsigned long DCFile:: 00484 get_hash() const { 00485 HashGenerator hashgen; 00486 generate_hash(hashgen); 00487 return hashgen.get_hash(); 00488 } 00489 00490 //////////////////////////////////////////////////////////////////// 00491 // Function: DCFile::generate_hash 00492 // Access: Public, Virtual 00493 // Description: Accumulates the properties of this file into the 00494 // hash. 00495 //////////////////////////////////////////////////////////////////// 00496 void DCFile:: 00497 generate_hash(HashGenerator &hashgen) const { 00498 if (dc_virtual_inheritance) { 00499 // Just to make the hash number change in this case. 00500 if (dc_sort_inheritance_by_file) { 00501 hashgen.add_int(1); 00502 } else { 00503 hashgen.add_int(2); 00504 } 00505 } 00506 00507 hashgen.add_int(_classes.size()); 00508 Classes::const_iterator ci; 00509 for (ci = _classes.begin(); ci != _classes.end(); ++ci) { 00510 (*ci)->generate_hash(hashgen); 00511 } 00512 } 00513 00514 //////////////////////////////////////////////////////////////////// 00515 // Function: DCFile::add_class 00516 // Access: Public 00517 // Description: Adds the newly-allocated distributed class definition 00518 // to the file. The DCFile becomes the owner of the 00519 // pointer and will delete it when it destructs. 00520 // Returns true if the class is successfully added, or 00521 // false if there was a name conflict. 00522 //////////////////////////////////////////////////////////////////// 00523 bool DCFile:: 00524 add_class(DCClass *dclass) { 00525 if (!dclass->get_name().empty()) { 00526 bool inserted = _things_by_name.insert 00527 (ThingsByName::value_type(dclass->get_name(), dclass)).second; 00528 00529 if (!inserted) { 00530 return false; 00531 } 00532 } 00533 00534 if (!dclass->is_struct()) { 00535 dclass->set_number(get_num_classes()); 00536 } 00537 _classes.push_back(dclass); 00538 00539 if (dclass->is_bogus_class()) { 00540 _all_objects_valid = false; 00541 } 00542 00543 if (!dclass->is_bogus_class()) { 00544 _declarations.push_back(dclass); 00545 } else { 00546 _things_to_delete.push_back(dclass); 00547 } 00548 00549 return true; 00550 } 00551 00552 //////////////////////////////////////////////////////////////////// 00553 // Function: DCFile::add_switch 00554 // Access: Public 00555 // Description: Adds the newly-allocated switch definition 00556 // to the file. The DCFile becomes the owner of the 00557 // pointer and will delete it when it destructs. 00558 // Returns true if the switch is successfully added, or 00559 // false if there was a name conflict. 00560 //////////////////////////////////////////////////////////////////// 00561 bool DCFile:: 00562 add_switch(DCSwitch *dswitch) { 00563 if (!dswitch->get_name().empty()) { 00564 bool inserted = _things_by_name.insert 00565 (ThingsByName::value_type(dswitch->get_name(), dswitch)).second; 00566 00567 if (!inserted) { 00568 return false; 00569 } 00570 } 00571 00572 _declarations.push_back(dswitch); 00573 00574 return true; 00575 } 00576 00577 //////////////////////////////////////////////////////////////////// 00578 // Function: DCFile::add_import_module 00579 // Access: Public 00580 // Description: Adds a new name to the list of names of Python 00581 // modules that are to be imported by the client or AI 00582 // to define the code that is associated with the class 00583 // interfaces named within the .dc file. 00584 //////////////////////////////////////////////////////////////////// 00585 void DCFile:: 00586 add_import_module(const string &import_module) { 00587 Import import; 00588 import._module = import_module; 00589 _imports.push_back(import); 00590 } 00591 00592 //////////////////////////////////////////////////////////////////// 00593 // Function: DCFile::add_import_symbol 00594 // Access: Public 00595 // Description: Adds a new name to the list of symbols that are to be 00596 // explicitly imported from the most-recently added 00597 // module, e.g. "from module_name import symbol". If 00598 // the list of symbols is empty, the syntax is taken to 00599 // be "import module_name". 00600 //////////////////////////////////////////////////////////////////// 00601 void DCFile:: 00602 add_import_symbol(const string &import_symbol) { 00603 nassertv(!_imports.empty()); 00604 _imports.back()._symbols.push_back(import_symbol); 00605 } 00606 00607 //////////////////////////////////////////////////////////////////// 00608 // Function: DCFile::add_typedef 00609 // Access: Public 00610 // Description: Adds the newly-allocated distributed typedef definition 00611 // to the file. The DCFile becomes the owner of the 00612 // pointer and will delete it when it destructs. 00613 // Returns true if the typedef is successfully added, or 00614 // false if there was a name conflict. 00615 //////////////////////////////////////////////////////////////////// 00616 bool DCFile:: 00617 add_typedef(DCTypedef *dtypedef) { 00618 bool inserted = _typedefs_by_name.insert 00619 (TypedefsByName::value_type(dtypedef->get_name(), dtypedef)).second; 00620 00621 if (!inserted) { 00622 return false; 00623 } 00624 00625 dtypedef->set_number(get_num_typedefs()); 00626 _typedefs.push_back(dtypedef); 00627 00628 if (dtypedef->is_bogus_typedef()) { 00629 _all_objects_valid = false; 00630 } 00631 00632 if (!dtypedef->is_bogus_typedef() && !dtypedef->is_implicit_typedef()) { 00633 _declarations.push_back(dtypedef); 00634 } else { 00635 _things_to_delete.push_back(dtypedef); 00636 } 00637 00638 return true; 00639 } 00640 00641 //////////////////////////////////////////////////////////////////// 00642 // Function: DCFile::add_keyword 00643 // Access: Public 00644 // Description: Adds the indicated keyword string to the list of 00645 // keywords known to the DCFile. These keywords may 00646 // then be added to DCFields. It is not an error to add 00647 // a particular keyword more than once. 00648 //////////////////////////////////////////////////////////////////// 00649 bool DCFile:: 00650 add_keyword(const string &name) { 00651 DCKeyword *keyword = new DCKeyword(name); 00652 bool added = _keywords.add_keyword(keyword); 00653 00654 if (added) { 00655 _declarations.push_back(keyword); 00656 } else { 00657 delete keyword; 00658 } 00659 00660 return added; 00661 } 00662 00663 //////////////////////////////////////////////////////////////////// 00664 // Function: DCFile::add_thing_to_delete 00665 // Access: Public 00666 // Description: Adds the indicated declaration to the list of 00667 // declarations that are not reported with the file, but 00668 // will be deleted when the DCFile object destructs. 00669 // That is, transfers ownership of the indicated pointer 00670 // to the DCFile. 00671 //////////////////////////////////////////////////////////////////// 00672 void DCFile:: 00673 add_thing_to_delete(DCDeclaration *decl) { 00674 _things_to_delete.push_back(decl); 00675 } 00676 00677 //////////////////////////////////////////////////////////////////// 00678 // Function: DCFile::set_new_index_number 00679 // Access: Public 00680 // Description: Sets the next sequential available index number on 00681 // the indicated field. This is only meant to be called 00682 // by DCClass::add_field(), while the dc file is being 00683 // parsed. 00684 //////////////////////////////////////////////////////////////////// 00685 void DCFile:: 00686 set_new_index_number(DCField *field) { 00687 field->set_number((int)_fields_by_index.size()); 00688 _fields_by_index.push_back(field); 00689 } 00690 00691 //////////////////////////////////////////////////////////////////// 00692 // Function: DCFile::setup_default_keywords 00693 // Access: Private 00694 // Description: Adds an entry for each of the default keywords that 00695 // are defined for every DCFile for legacy reasons. 00696 //////////////////////////////////////////////////////////////////// 00697 void DCFile:: 00698 setup_default_keywords() { 00699 struct KeywordDef { 00700 const char *name; 00701 int flag; 00702 }; 00703 static KeywordDef default_keywords[] = { 00704 { "required", 0x0001 }, 00705 { "broadcast", 0x0002 }, 00706 { "ownrecv", 0x0004 }, 00707 { "ram", 0x0008 }, 00708 { "db", 0x0010 }, 00709 { "clsend", 0x0020 }, 00710 { "clrecv", 0x0040 }, 00711 { "ownsend", 0x0080 }, 00712 { "airecv", 0x0100 }, 00713 { NULL, 0 } 00714 }; 00715 00716 _default_keywords.clear_keywords(); 00717 for (int i = 0; default_keywords[i].name != NULL; ++i) { 00718 DCKeyword *keyword = 00719 new DCKeyword(default_keywords[i].name, 00720 default_keywords[i].flag); 00721 00722 _default_keywords.add_keyword(keyword); 00723 _things_to_delete.push_back(keyword); 00724 } 00725 } 00726 00727 //////////////////////////////////////////////////////////////////// 00728 // Function: DCFile::rebuild_inherited_fields 00729 // Access: Private 00730 // Description: Reconstructs the inherited fields table of all 00731 // classes. 00732 //////////////////////////////////////////////////////////////////// 00733 void DCFile:: 00734 rebuild_inherited_fields() { 00735 _inherited_fields_stale = false; 00736 00737 Classes::iterator ci; 00738 for (ci = _classes.begin(); ci != _classes.end(); ++ci) { 00739 (*ci)->clear_inherited_fields(); 00740 } 00741 for (ci = _classes.begin(); ci != _classes.end(); ++ci) { 00742 (*ci)->rebuild_inherited_fields(); 00743 } 00744 }