00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "interrogateBuilder.h"
00020 #include "interrogate.h"
00021 #include "parameterRemap.h"
00022 #include "typeManager.h"
00023 #include "functionWriters.h"
00024 #include "interfaceMakerC.h"
00025 #include "interfaceMakerPythonObj.h"
00026 #include "interfaceMakerPythonSimple.h"
00027 #include "functionRemap.h"
00028
00029 #include <interrogateType.h>
00030 #include <interrogateDatabase.h>
00031 #include <indexRemapper.h>
00032 #include <cppParser.h>
00033 #include <cppDeclaration.h>
00034 #include <cppFunctionGroup.h>
00035 #include <cppFunctionType.h>
00036 #include <cppParameterList.h>
00037 #include <cppInstance.h>
00038 #include <cppSimpleType.h>
00039 #include <cppPointerType.h>
00040 #include <cppReferenceType.h>
00041 #include <cppArrayType.h>
00042 #include <cppConstType.h>
00043 #include <cppExtensionType.h>
00044 #include <cppStructType.h>
00045 #include <cppExpression.h>
00046 #include <cppTypedef.h>
00047 #include <cppTypeDeclaration.h>
00048 #include <cppEnumType.h>
00049 #include <cppCommentBlock.h>
00050 #include <notify.h>
00051
00052 #include <ctype.h>
00053 #include <algorithm>
00054
00055 InterrogateBuilder builder;
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 void InterrogateBuilder::
00079 add_source_file(const string &filename) {
00080 if (filename.empty()) {
00081 return;
00082 }
00083
00084 _include_files[filename] = '"';
00085 }
00086
00087
00088
00089
00090
00091
00092
00093 void InterrogateBuilder::
00094 read_command_file(istream &in) {
00095 string line;
00096 getline(in, line);
00097 while (!in.fail() && !in.eof()) {
00098
00099 size_t hash = line.find('#');
00100 if (hash != string::npos) {
00101 line = line.substr(0, hash);
00102 }
00103
00104
00105 size_t p = 0;
00106 while (p < line.length() && isspace(line[p])) {
00107 p++;
00108 }
00109
00110 if (p < line.length()) {
00111
00112 size_t q = p;
00113 while (q < line.length() && !isspace(line[q])) {
00114 q++;
00115 }
00116 string command = line.substr(p, q - p);
00117
00118
00119 p = q;
00120 while (p < line.length() && isspace(line[p])) {
00121 p++;
00122 }
00123
00124 q = line.length();
00125 while (q > p && isspace(line[q - 1])) {
00126 q--;
00127 }
00128 string params = line.substr(p, q - p);
00129
00130 do_command(command, params);
00131 }
00132 getline(in, line);
00133 }
00134 }
00135
00136
00137
00138
00139
00140
00141 void InterrogateBuilder::
00142 do_command(const string &command, const string ¶ms) {
00143 if (command == "forcetype") {
00144
00145 CPPType *type = parser.parse_type(params);
00146 if (type == (CPPType *)NULL) {
00147 nout << "Unknown type: forcetype " << params << "\n";
00148 } else {
00149 type = type->resolve_type(&parser, &parser);
00150 _forcetype.insert(type->get_local_name(&parser));
00151 }
00152
00153 } else if (command == "renametype") {
00154
00155
00156
00157
00158 size_t space = params.rfind(' ');
00159 if (space == string::npos) {
00160 nout << "No new name specified for renametype " << params << "\n";
00161 } else {
00162 string orig_name = params.substr(0, space);
00163 string new_name = params.substr(space + 1);
00164
00165 CPPType *type = parser.parse_type(orig_name);
00166 if (type == (CPPType *)NULL) {
00167 nout << "Unknown type: renametype " << orig_name << "\n";
00168 } else {
00169 type = type->resolve_type(&parser, &parser);
00170 _renametype[type->get_local_name(&parser)] = new_name;
00171 }
00172 }
00173
00174 } else if (command == "ignoretype") {
00175
00176 CPPType *type = parser.parse_type(params);
00177 if (type == (CPPType *)NULL) {
00178 nout << "Unknown type: ignoretype " << params << "\n";
00179 } else {
00180 type = type->resolve_type(&parser, &parser);
00181 _ignoretype.insert(type->get_local_name(&parser));
00182 }
00183
00184 } else if (command == "ignoreinvolved") {
00185 _ignoreinvolved.insert(params);
00186
00187 } else if (command == "ignorefile") {
00188 insert_param_list(_ignorefile, params);
00189
00190 } else if (command == "ignoremember") {
00191 insert_param_list(_ignoremember, params);
00192
00193 } else if (command == "noinclude") {
00194 insert_param_list(_noinclude, params);
00195
00196 } else {
00197 nout << "Ignoring " << command << " " << params << "\n";
00198 }
00199 }
00200
00201
00202
00203
00204
00205
00206 void InterrogateBuilder::
00207 build() {
00208 _library_hash_name = hash_string(library_name, 5);
00209
00210
00211 CPPParser::Includes::const_iterator ii;
00212 for (ii = parser._quote_includes.begin();
00213 ii != parser._quote_includes.end();
00214 ++ii) {
00215 const string &filename = (*ii);
00216 _include_files[filename] = '"';
00217 }
00218 for (ii = parser._angle_includes.begin();
00219 ii != parser._angle_includes.end();
00220 ++ii) {
00221 const string &filename = (*ii);
00222 _include_files[filename] = '<';
00223 }
00224
00225
00226 Commands::const_iterator ci;
00227 for (ci = _forcetype.begin();
00228 ci != _forcetype.end();
00229 ++ci) {
00230 CPPType *type = parser.parse_type(*ci);
00231 assert(type != (CPPType *)NULL);
00232 get_type(type, true);
00233 }
00234
00235
00236
00237 CPPScope::Declarations::const_iterator di;
00238 for (di = parser._declarations.begin();
00239 di != parser._declarations.end();
00240 ++di) {
00241 if ((*di)->get_subtype() == CPPDeclaration::ST_instance) {
00242 CPPInstance *inst = (*di)->as_instance();
00243 if (inst->_type->get_subtype() == CPPDeclaration::ST_function) {
00244
00245 scan_function(inst);
00246
00247 } else {
00248
00249 scan_element(inst, (CPPStructType *)NULL, &parser);
00250 }
00251
00252 } else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) {
00253 CPPTypedef *tdef = (*di)->as_typedef();
00254 if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) {
00255
00256
00257 CPPStructType *struct_type =
00258 tdef->_type->resolve_type(&parser, &parser)->as_struct_type();
00259 scan_struct_type(struct_type);
00260 }
00261
00262 } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) {
00263 CPPType *type = (*di)->as_type_declaration()->_type;
00264 type->_vis = (*di)->_vis;
00265
00266 if (type->get_subtype() == CPPDeclaration::ST_struct) {
00267 CPPStructType *struct_type =
00268 type->as_type()->resolve_type(&parser, &parser)->as_struct_type();
00269 scan_struct_type(struct_type);
00270
00271 } else if (type->get_subtype() == CPPDeclaration::ST_enum) {
00272 CPPEnumType *enum_type =
00273 type->as_type()->resolve_type(&parser, &parser)->as_enum_type();
00274 scan_enum_type(enum_type);
00275 }
00276 }
00277 }
00278
00279 CPPPreprocessor::Manifests::const_iterator mi;
00280 for (mi = parser._manifests.begin(); mi != parser._manifests.end(); ++mi) {
00281 CPPManifest *manifest = (*mi).second;
00282 scan_manifest(manifest);
00283 }
00284
00285
00286
00287
00288 }
00289
00290
00291
00292
00293
00294
00295
00296 void InterrogateBuilder::
00297 write_code(ostream &out, InterrogateModuleDef *def) {
00298 typedef vector<InterfaceMaker *> InterfaceMakers;
00299 InterfaceMakers makers;
00300
00301 if (build_c_wrappers) {
00302 InterfaceMaker *maker = new InterfaceMakerC(def);
00303 makers.push_back(maker);
00304 }
00305
00306 if (build_python_wrappers) {
00307 InterfaceMaker *maker = new InterfaceMakerPythonSimple(def);
00308 makers.push_back(maker);
00309 }
00310
00311 if (build_python_obj_wrappers) {
00312 InterfaceMaker *maker = new InterfaceMakerPythonObj(def);
00313 makers.push_back(maker);
00314 }
00315
00316 InterfaceMakers::iterator mi;
00317
00318
00319 for (mi = makers.begin(); mi != makers.end(); ++mi) {
00320 (*mi)->generate_wrappers();
00321 }
00322
00323
00324
00325
00326
00327 ostringstream function_bodies;
00328 for (mi = makers.begin(); mi != makers.end(); ++mi) {
00329 (*mi)->write_functions(function_bodies);
00330 }
00331
00332
00333 if (!no_database) {
00334 out << "#include \"dtoolbase.h\"\n"
00335 << "#include \"interrogate_request.h\"\n"
00336 << "#include \"dconfig.h\"\n";
00337 }
00338 if (watch_asserts) {
00339 out << "#include \"notify.h\"\n";
00340 }
00341 out << "\n";
00342
00343 IncludeFiles::const_iterator ifi;
00344 for (ifi = _include_files.begin();
00345 ifi != _include_files.end();
00346 ++ifi) {
00347 const string &filename = (*ifi).first;
00348 char delimiter = (*ifi).second;
00349 if (should_include(filename)) {
00350 if (delimiter == '"') {
00351 out << "#include \"" << filename << "\"\n";
00352 } else {
00353 out << "#include <" << filename << ">\n";
00354 }
00355 }
00356 }
00357 out << "\n";
00358
00359 for (mi = makers.begin(); mi != makers.end(); ++mi) {
00360 (*mi)->write_includes(out);
00361 }
00362
00363 if (generate_spam) {
00364 out << "#include \"config_interrogatedb.h\"\n"
00365 << "#include \"notifyCategoryProxy.h\"\n\n"
00366 << "NotifyCategoryDeclNoExport(in_" << library_name << ");\n"
00367 << "NotifyCategoryDef(in_" << library_name << ", interrogatedb_cat);\n\n";
00368 }
00369
00370 out << "\n";
00371
00372
00373 for (mi = makers.begin(); mi != makers.end(); ++mi) {
00374 (*mi)->write_prototypes(out);
00375 }
00376
00377 out << "\n";
00378
00379
00380 out << function_bodies.str() << "\n";
00381
00382 if (output_module_specific) {
00383
00384 for (mi = makers.begin(); mi != makers.end(); ++mi) {
00385 (*mi)->write_module(out, def);
00386 }
00387 }
00388
00389
00390 vector<FunctionRemap *> remaps;
00391 for (mi = makers.begin(); mi != makers.end(); ++mi) {
00392 (*mi)->get_function_remaps(remaps);
00393 }
00394
00395
00396
00397
00398 remap_indices(remaps);
00399
00400
00401 int num_wrappers = 0;
00402 map<int, FunctionRemap *> wrappers_by_index;
00403
00404 vector<FunctionRemap *>::iterator ri;
00405 for (ri = remaps.begin(); ri != remaps.end(); ++ri) {
00406 FunctionRemap *remap = (*ri);
00407 wrappers_by_index[remap->_wrapper_index] = remap;
00408 num_wrappers++;
00409 }
00410
00411 if (output_function_pointers) {
00412
00413 out << "static void *_in_fptrs[" << num_wrappers << "] = {\n";
00414 int next_index = 1;
00415 map<int, FunctionRemap *>::iterator ii;
00416 for (ii = wrappers_by_index.begin();
00417 ii != wrappers_by_index.end();
00418 ++ii) {
00419 int this_index = (*ii).first;
00420 while (next_index < this_index) {
00421 out << " (void *)0,\n";
00422 next_index++;
00423 }
00424 assert(next_index == this_index);
00425 FunctionRemap *remap = (*ii).second;
00426
00427 out << " (void *)&" << remap->_wrapper_name << ",\n";
00428 next_index++;
00429 }
00430 while (next_index < num_wrappers + 1) {
00431 out << " (void *)0,\n";
00432 next_index++;
00433 }
00434 out << "};\n\n";
00435 }
00436
00437 if (save_unique_names) {
00438
00439 out << "static InterrogateUniqueNameDef _in_unique_names["
00440 << num_wrappers << "] = {\n";
00441 for (ri = remaps.begin(); ri != remaps.end(); ++ri) {
00442 FunctionRemap *remap = (*ri);
00443 out << " { \""
00444 << remap->_unique_name << "\", "
00445 << remap->_wrapper_index - 1 << " },\n";
00446 }
00447 out << "};\n\n";
00448 }
00449
00450 if (!no_database) {
00451
00452
00453 out << "static InterrogateModuleDef _in_module_def = {\n"
00454 << " " << def->file_identifier << ", /* file_identifier */\n"
00455 << " \"" << def->library_name << "\", /* library_name */\n"
00456 << " \"" << def->library_hash_name << "\", /* library_hash_name */\n"
00457 << " \"" << def->module_name << "\", /* module_name */\n";
00458 if (def->database_filename != (const char *)NULL) {
00459 out << " \"" << def->database_filename
00460 << "\", /* database_filename */\n";
00461 } else {
00462 out << " (const char *)0, /* database_filename */\n";
00463 }
00464
00465 if (save_unique_names) {
00466 out << " _in_unique_names,\n"
00467 << " " << num_wrappers << ", /* num_unique_names */\n";
00468 } else {
00469 out << " (InterrogateUniqueNameDef *)0, /* unique_names */\n"
00470 << " 0, /* num_unique_names */\n";
00471 }
00472
00473 if (output_function_pointers) {
00474 out << " _in_fptrs,\n"
00475 << " " << num_wrappers << ", /* num_fptrs */\n";
00476 } else {
00477 out << " (void **)0, /* fptrs */\n"
00478 << " 0, /* num_fptrs */\n";
00479 }
00480
00481 out << " 1, /* first_index */\n"
00482 << " " << InterrogateDatabase::get_ptr()->get_next_index()
00483 << " /* next_index */\n"
00484 << "};\n\n";
00485
00486
00487
00488 out << "Configure(_in_configure_" << library_name << ");\n"
00489 << "ConfigureFn(_in_configure_" << library_name << ") {\n"
00490 << " interrogate_request_module(&_in_module_def);\n"
00491 << "}\n\n";
00492 }
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 InterrogateModuleDef *InterrogateBuilder::
00509 make_module_def(int file_identifier) {
00510 InterrogateModuleDef *def = new InterrogateModuleDef;
00511 memset(def, 0, sizeof(InterrogateModuleDef));
00512
00513 def->file_identifier = file_identifier;
00514 def->library_name = library_name.c_str();
00515 def->library_hash_name = _library_hash_name.c_str();
00516 def->module_name = module_name.c_str();
00517 if (!output_data_filename.empty()) {
00518 def->database_filename = output_data_basename.c_str();
00519 }
00520
00521 return def;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 string InterrogateBuilder::
00535 clean_identifier(const string &name) {
00536 string result;
00537
00538 bool last_invalid = false;
00539
00540 string::const_iterator ni;
00541 for (ni = name.begin(); ni != name.end(); ++ni) {
00542 if (isalnum(*ni)) {
00543 if (last_invalid) {
00544 result += '_';
00545 last_invalid = false;
00546 }
00547 result += (*ni);
00548 } else {
00549 last_invalid = true;
00550 }
00551 }
00552
00553 return result;
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563 string InterrogateBuilder::
00564 descope(const string &name) {
00565 if (name.length() >= 2 && name.substr(0, 2) == "::") {
00566 return name.substr(2);
00567 }
00568 return name;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578 FunctionIndex InterrogateBuilder::
00579 get_destructor_for(CPPType *type) {
00580 TypeIndex type_index = get_type(type, false);
00581
00582 const InterrogateType &itype =
00583 InterrogateDatabase::get_ptr()->get_type(type_index);
00584
00585 return itype.get_destructor();
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 string InterrogateBuilder::
00599 get_preferred_name(CPPType *type) {
00600 string true_name = type->get_local_name(&parser);
00601 string name = in_renametype(true_name);
00602 if (!name.empty()) {
00603 return name;
00604 }
00605 return type->get_preferred_name();
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615 string InterrogateBuilder::
00616 hash_string(const string &name, int shift_offset) {
00617 int hash = 0;
00618
00619 int shift = 0;
00620 string::const_iterator ni;
00621 for (ni = name.begin(); ni != name.end(); ++ni) {
00622 int c = (int)(unsigned char)(*ni);
00623 int shifted_c = (c << shift) & 0xffffff;
00624 if (shift > 16) {
00625
00626 shifted_c |= ((c >> (24 - shift)) & 0xff) ;
00627 }
00628 hash = (hash + shifted_c) & 0xffffff;
00629 shift = (shift + shift_offset) % 24;
00630 }
00631
00632
00633
00634
00635
00636 int prime = 4999;
00637 int low_order = (hash * prime) & 0xffffff;
00638 int high_order = (int)((double)hash * (double)prime / (double)(1 << 24));
00639 hash = low_order ^ high_order;
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 string result;
00652 int extract_h = hash;
00653 for (int i = 0; i < 4; i++) {
00654 int value = (extract_h & 0x3f);
00655 extract_h >>= 6;
00656 if (value < 26) {
00657 result += (char)('A' + value);
00658
00659 } else if (value < 52) {
00660 result += (char)('a' + value - 26);
00661
00662 } else if (value < 62) {
00663 result += (char)('0' + value - 52);
00664
00665 } else {
00666 result += '_';
00667 }
00668 }
00669
00670 return result;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679 void InterrogateBuilder::
00680 insert_param_list(InterrogateBuilder::Commands &commands,
00681 const string ¶ms) {
00682 size_t p = 0;
00683 while (p < params.length()) {
00684 while (p < params.length() && isspace(params[p])) {
00685 p++;
00686 }
00687 size_t q = p;
00688 while (q < params.length() && !isspace(params[q])) {
00689 q++;
00690 }
00691 if (p < q) {
00692 commands.insert(params.substr(p, q - p));
00693 }
00694 p = q;
00695 }
00696 }
00697
00698
00699
00700
00701
00702
00703
00704 bool InterrogateBuilder::
00705 in_forcetype(const string &name) const {
00706 return (_forcetype.count(name) != 0);
00707 }
00708
00709
00710
00711
00712
00713
00714
00715
00716 string InterrogateBuilder::
00717 in_renametype(const string &name) const {
00718 CommandParams::const_iterator pi;
00719 pi = _renametype.find(name);
00720 if (pi != _renametype.end()) {
00721 return (*pi).second;
00722 }
00723 return string();
00724 }
00725
00726
00727
00728
00729
00730
00731
00732 bool InterrogateBuilder::
00733 in_ignoretype(const string &name) const {
00734 return (_ignoretype.count(name) != 0);
00735 }
00736
00737
00738
00739
00740
00741
00742
00743 bool InterrogateBuilder::
00744 in_ignoreinvolved(const string &name) const {
00745 return (_ignoreinvolved.count(name) != 0);
00746 }
00747
00748
00749
00750
00751
00752
00753
00754 bool InterrogateBuilder::
00755 in_ignoreinvolved(CPPType *type) const {
00756 switch (type->get_subtype()) {
00757 case CPPDeclaration::ST_pointer:
00758 {
00759 CPPPointerType *ptr = type->as_pointer_type();
00760 return in_ignoreinvolved(ptr->_pointing_at);
00761 }
00762
00763 case CPPDeclaration::ST_array:
00764 {
00765 CPPArrayType *ary = type->as_array_type();
00766 return in_ignoreinvolved(ary->_element_type);
00767 }
00768
00769 case CPPDeclaration::ST_reference:
00770 {
00771 CPPReferenceType *ref = type->as_reference_type();
00772 return in_ignoreinvolved(ref->_pointing_at);
00773 }
00774
00775 case CPPDeclaration::ST_const:
00776 {
00777 CPPConstType *cnst = type->as_const_type();
00778 return in_ignoreinvolved(cnst->_wrapped_around);
00779 }
00780
00781 case CPPDeclaration::ST_function:
00782 {
00783 CPPFunctionType *ftype = type->as_function_type();
00784 if (in_ignoreinvolved(ftype->_return_type)) {
00785 return true;
00786 }
00787 const CPPParameterList::Parameters ¶ms =
00788 ftype->_parameters->_parameters;
00789 CPPParameterList::Parameters::const_iterator pi;
00790 for (pi = params.begin(); pi != params.end(); ++pi) {
00791 if (in_ignoreinvolved((*pi)->_type)) {
00792 return true;
00793 }
00794 }
00795 return false;
00796 }
00797
00798 default:
00799 return in_ignoreinvolved(type->get_simple_name());
00800 }
00801 }
00802
00803
00804
00805
00806
00807
00808
00809 bool InterrogateBuilder::
00810 in_ignorefile(const string &name) const {
00811 return (_ignorefile.count(name) != 0);
00812 }
00813
00814
00815
00816
00817
00818
00819
00820 bool InterrogateBuilder::
00821 in_ignoremember(const string &name) const {
00822 return (_ignoremember.count(name) != 0);
00823 }
00824
00825
00826
00827
00828
00829
00830
00831 bool InterrogateBuilder::
00832 in_noinclude(const string &name) const {
00833 return (_noinclude.count(name) != 0);
00834 }
00835
00836
00837
00838
00839
00840
00841
00842
00843 bool InterrogateBuilder::
00844 should_include(const string &filename) const {
00845
00846 if (CPPFile::is_c_or_i_file(filename)) {
00847 return false;
00848 }
00849
00850
00851
00852 if (in_noinclude(filename)) {
00853 return false;
00854 }
00855
00856
00857
00858
00859 if (filename == "winbase.h" || filename == "windows.h") {
00860 return false;
00861 }
00862
00863
00864
00865 if (filename.length() > 6 && filename.substr(filename.length() - 6) == "_src.h") {
00866 return false;
00867 }
00868 if (filename.length() > 8 && filename.substr(filename.length() - 8) == "_src.cxx") {
00869 return false;
00870 }
00871
00872
00873 return true;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 void InterrogateBuilder::
00894 remap_indices(vector<FunctionRemap *> &remaps) {
00895 IndexRemapper index_remap;
00896 InterrogateDatabase::get_ptr()->remap_indices(1, index_remap);
00897
00898 TypesByName::iterator ti;
00899 for (ti = _types_by_name.begin(); ti != _types_by_name.end(); ++ti) {
00900 (*ti).second = index_remap.map_from((*ti).second);
00901 }
00902
00903 FunctionsByName::iterator fi;
00904 for (fi = _functions_by_name.begin();
00905 fi != _functions_by_name.end();
00906 ++fi) {
00907 (*fi).second = index_remap.map_from((*fi).second);
00908 }
00909
00910 vector<FunctionRemap *>::iterator ri;
00911 for (ri = remaps.begin(); ri != remaps.end(); ++ri) {
00912 FunctionRemap *remap = (*ri);
00913 remap->_wrapper_index = index_remap.map_from(remap->_wrapper_index);
00914 }
00915 }
00916
00917
00918
00919
00920
00921
00922
00923 void InterrogateBuilder::
00924 scan_function(CPPFunctionGroup *fgroup) {
00925 CPPFunctionGroup::Instances::const_iterator fi;
00926 for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
00927 CPPInstance *function = (*fi);
00928 scan_function(function);
00929 }
00930 }
00931
00932
00933
00934
00935
00936
00937
00938 void InterrogateBuilder::
00939 scan_function(CPPInstance *function) {
00940 assert(function != (CPPInstance *)NULL);
00941 assert(function->_type != (CPPType *)NULL &&
00942 function->_type->as_function_type() != (CPPFunctionType *)NULL);
00943 CPPFunctionType *ftype =
00944 function->_type->resolve_type(&parser, &parser)->as_function_type();
00945 assert(ftype != (CPPFunctionType *)NULL);
00946
00947 CPPScope *scope = &parser;
00948 if (function->is_scoped()) {
00949 scope = function->get_scope(&parser, &parser);
00950 if (scope == (CPPScope *)NULL) {
00951
00952 nout << "Invalid scope: " << *function->_ident << "\n";
00953 return;
00954 }
00955
00956 if (scope->get_struct_type() != (CPPStructType *)NULL) {
00957
00958
00959
00960
00961 update_method_comment(function, scope->get_struct_type(), scope);
00962 return;
00963 }
00964 }
00965
00966 if (function->is_template()) {
00967
00968 return;
00969 }
00970
00971 if (function->_file.is_c_file()) {
00972
00973
00974 return;
00975 }
00976
00977 if (function->_file._source != CPPFile::S_local ||
00978 in_ignorefile(function->_file._filename_as_referenced)) {
00979
00980
00981 return;
00982 }
00983
00984 if (function->_vis > min_vis) {
00985
00986 return;
00987 }
00988
00989 if ((function->_storage_class & CPPInstance::SC_static) != 0) {
00990
00991 return;
00992 }
00993
00994 if (TypeManager::involves_protected(ftype)) {
00995
00996
00997 return;
00998 }
00999
01000 if (in_ignoreinvolved(ftype)) {
01001
01002
01003 return;
01004 }
01005
01006 get_function(function, "",
01007 (CPPStructType *)NULL, scope,
01008 InterrogateFunction::F_global);
01009 }
01010
01011
01012
01013
01014
01015
01016
01017 void InterrogateBuilder::
01018 scan_struct_type(CPPStructType *type) {
01019 if (type == (CPPStructType *)NULL) {
01020 return;
01021 }
01022
01023 if (type->is_template()) {
01024
01025 return;
01026 }
01027
01028 if (type->_file.is_c_file()) {
01029
01030
01031 return;
01032 }
01033
01034 if (type->_file._source != CPPFile::S_local ||
01035 in_ignorefile(type->_file._filename_as_referenced)) {
01036
01037
01038 return;
01039 }
01040
01041
01042
01043 if (type->_vis > min_vis) {
01044 CPPScope *scope = type->_scope;
01045
01046 bool any_exported = false;
01047 CPPScope::Declarations::const_iterator di;
01048 for (di = scope->_declarations.begin();
01049 di != scope->_declarations.end() && !any_exported;
01050 ++di) {
01051 if ((*di)->_vis <= min_vis) {
01052 any_exported = true;
01053 }
01054 }
01055
01056 if (!any_exported) {
01057 return;
01058 }
01059 }
01060
01061 get_type(type, true);
01062 }
01063
01064
01065
01066
01067
01068
01069
01070 void InterrogateBuilder::
01071 scan_enum_type(CPPEnumType *type) {
01072 if (type == (CPPEnumType *)NULL) {
01073 return;
01074 }
01075
01076 if (type->is_template()) {
01077
01078 return;
01079 }
01080
01081 if (type->_file.is_c_file()) {
01082
01083
01084 return;
01085 }
01086
01087 if (type->_file._source != CPPFile::S_local ||
01088 in_ignorefile(type->_file._filename_as_referenced)) {
01089
01090
01091 return;
01092 }
01093
01094 if (type->_vis > min_vis) {
01095
01096 return;
01097 }
01098
01099 get_type(type, true);
01100 }
01101
01102
01103
01104
01105
01106
01107
01108 void InterrogateBuilder::
01109 scan_manifest(CPPManifest *manifest) {
01110 if (manifest == (CPPManifest *)NULL) {
01111 return;
01112 }
01113
01114 if (manifest->_file.is_c_file()) {
01115
01116
01117 return;
01118 }
01119
01120 if (manifest->_file._source != CPPFile::S_local ||
01121 in_ignorefile(manifest->_file._filename_as_referenced)) {
01122
01123
01124 return;
01125 }
01126
01127 if (manifest->_vis > min_vis) {
01128
01129 return;
01130 }
01131
01132 if (manifest->_has_parameters) {
01133
01134 return;
01135 }
01136
01137 InterrogateManifest imanifest;
01138 imanifest._name = manifest->_name;
01139 imanifest._definition = manifest->expand();
01140
01141 CPPType *type = manifest->determine_type();
01142 if (type != (CPPType *)NULL) {
01143 imanifest._flags |= InterrogateManifest::F_has_type;
01144 imanifest._type = get_type(type, false);
01145
01146 CPPExpression *expr = manifest->_expr;
01147 CPPExpression::Result result = expr->evaluate();
01148 if (result._type == CPPExpression::RT_integer) {
01149
01150 imanifest._flags |= InterrogateManifest::F_has_int_value;
01151 imanifest._int_value = result.as_integer();
01152
01153 } else {
01154
01155
01156 FunctionIndex getter =
01157 get_getter(type, manifest->_name, (CPPStructType *)NULL, &parser,
01158 (CPPInstance *)NULL);
01159
01160 if (getter != 0) {
01161 imanifest._flags |= InterrogateManifest::F_has_getter;
01162 imanifest._getter = getter;
01163 }
01164 }
01165 }
01166
01167 ManifestIndex index =
01168 InterrogateDatabase::get_ptr()->get_next_index();
01169 InterrogateDatabase::get_ptr()->add_manifest(index, imanifest);
01170 }
01171
01172
01173
01174
01175
01176
01177
01178 ElementIndex InterrogateBuilder::
01179 scan_element(CPPInstance *element, CPPStructType *struct_type,
01180 CPPScope *scope) {
01181 if (element == (CPPInstance *)NULL) {
01182 return 0;
01183 }
01184
01185 if (element->is_template()) {
01186
01187 return 0;
01188 }
01189
01190 if (element->is_scoped()) {
01191 if (element->get_scope(scope, &parser) != scope) {
01192
01193
01194 return 0;
01195 }
01196 }
01197
01198 if (element->_file.is_c_file()) {
01199
01200
01201 return 0;
01202 }
01203
01204 if (element->_file._source != CPPFile::S_local ||
01205 in_ignorefile(element->_file._filename_as_referenced)) {
01206
01207
01208 return 0;
01209 }
01210
01211 if (element->_vis > min_vis) {
01212
01213 return 0;
01214 }
01215
01216 if ((element->_storage_class & CPPInstance::SC_static) != 0) {
01217
01218 return 0;
01219 }
01220
01221
01222 if (element->_ident->_native_scope != scope) {
01223 element = new CPPInstance(*element);
01224 element->_ident = new CPPIdentifier(*element->_ident);
01225 element->_ident->_native_scope = scope;
01226 }
01227
01228 CPPType *element_type = TypeManager::resolve_type(element->_type, scope);
01229 CPPType *parameter_type = element_type;
01230
01231 InterrogateElement ielement;
01232 ielement._name = element->get_local_name(scope);
01233 ielement._scoped_name = descope(element->get_local_name(&parser));
01234
01235 ielement._type = get_type(TypeManager::unwrap_reference(element_type), false);
01236 if (ielement._type == 0) {
01237
01238 return 0;
01239 }
01240
01241 if (!TypeManager::involves_protected(element_type)) {
01242
01243
01244
01245 if (parameter_type->as_struct_type() != (CPPStructType *)NULL) {
01246
01247 parameter_type = TypeManager::wrap_const_reference(parameter_type);
01248 }
01249
01250
01251 FunctionIndex getter =
01252 get_getter(parameter_type, element->get_local_name(scope),
01253 struct_type, scope, element);
01254 if (getter != 0) {
01255 ielement._flags |= InterrogateElement::F_has_getter;
01256 ielement._getter = getter;
01257 }
01258
01259 if (TypeManager::is_assignable(element_type)) {
01260 FunctionIndex setter =
01261 get_setter(parameter_type, element->get_local_name(scope),
01262 struct_type, scope, element);
01263 if (setter != 0) {
01264 ielement._flags |= InterrogateElement::F_has_setter;
01265 ielement._setter = setter;
01266 }
01267 }
01268 }
01269
01270 if (struct_type == (CPPStructType *)NULL) {
01271
01272 ielement._flags |= InterrogateElement::F_global;
01273 }
01274
01275 ElementIndex index =
01276 InterrogateDatabase::get_ptr()->get_next_index();
01277 InterrogateDatabase::get_ptr()->add_element(index, ielement);
01278
01279 return index;
01280 }
01281
01282
01283
01284
01285
01286
01287
01288 FunctionIndex InterrogateBuilder::
01289 get_getter(CPPType *expr_type, string expression,
01290 CPPStructType *struct_type, CPPScope *scope,
01291 CPPInstance *element) {
01292
01293 string fname = clean_identifier("get_" + expression);
01294
01295
01296
01297 while (expr_type->as_const_type() != (CPPConstType *)NULL) {
01298 expr_type = expr_type->as_const_type()->_wrapped_around;
01299 assert(expr_type != (CPPType *)NULL);
01300 }
01301
01302
01303 CPPParameterList *params = new CPPParameterList;
01304 CPPFunctionType *ftype = new CPPFunctionType(expr_type, params, 0);
01305
01306
01307 CPPInstance *function = new CPPInstance(ftype, fname);
01308 function->_ident->_native_scope = scope;
01309
01310 int getter_flags = InterrogateFunction::F_getter;
01311
01312 if (struct_type != (CPPStructType *)NULL) {
01313
01314 assert(element != (CPPInstance *)NULL);
01315 assert(scope != (CPPScope *)NULL);
01316
01317 if ((element->_storage_class & CPPInstance::SC_static) != 0) {
01318
01319
01320 function->_storage_class |= CPPInstance::SC_static;
01321
01322
01323 expression = element->get_local_name(&parser);
01324
01325 } else {
01326
01327
01328 ftype->_flags |= CPPFunctionType::F_const_method;
01329
01330
01331 expression = element->get_local_name(scope);
01332 getter_flags |= InterrogateFunction::F_method;
01333 }
01334 }
01335
01336
01337
01338
01339 string function_name = TypeManager::get_function_name(function);
01340 if (_functions_by_name.count(function_name) != 0) {
01341 return 0;
01342 }
01343
01344 ostringstream desc;
01345 desc << "getter for ";
01346 if (element != (CPPInstance *)NULL) {
01347 element->_initializer = (CPPExpression *)NULL;
01348 element->output(desc, 0, &parser, false);
01349 desc << ";";
01350 } else {
01351 desc << expression;
01352 }
01353 string description = desc.str();
01354
01355
01356 FunctionIndex index =
01357 get_function(function, description,
01358 struct_type, scope,
01359 getter_flags, expression);
01360
01361 InterrogateDatabase::get_ptr()->update_function(index)._comment = description;
01362 return index;
01363 }
01364
01365
01366
01367
01368
01369
01370
01371 FunctionIndex InterrogateBuilder::
01372 get_setter(CPPType *expr_type, string expression,
01373 CPPStructType *struct_type, CPPScope *scope,
01374 CPPInstance *element) {
01375
01376 string fname = clean_identifier("set_" + expression);
01377
01378
01379 CPPParameterList *params = new CPPParameterList;
01380 CPPInstance *param0 = new CPPInstance(expr_type, "value");
01381 params->_parameters.push_back(param0);
01382 CPPType *void_type = TypeManager::get_void_type();
01383 CPPFunctionType *ftype = new CPPFunctionType(void_type, params, 0);
01384
01385
01386 CPPInstance *function = new CPPInstance(ftype, fname);
01387 function->_ident->_native_scope = scope;
01388
01389 int setter_flags = InterrogateFunction::F_setter;
01390
01391 if (struct_type != (CPPStructType *)NULL) {
01392
01393 assert(element != (CPPInstance *)NULL);
01394 assert(scope != (CPPScope *)NULL);
01395
01396 if ((element->_storage_class & CPPInstance::SC_static) != 0) {
01397
01398
01399 function->_storage_class |= CPPInstance::SC_static;
01400
01401
01402 expression = element->get_local_name(&parser);
01403
01404 } else {
01405
01406
01407 expression = element->get_local_name(scope);
01408 setter_flags |= InterrogateFunction::F_method;
01409 }
01410 }
01411
01412
01413
01414
01415 string function_name = TypeManager::get_function_name(function);
01416 if (_functions_by_name.count(function_name) != 0) {
01417 return 0;
01418 }
01419
01420 ostringstream desc;
01421 desc << "setter for ";
01422 if (element != (CPPInstance *)NULL) {
01423 element->_initializer = (CPPExpression *)NULL;
01424 element->output(desc, 0, &parser, false);
01425 desc << ";";
01426 } else {
01427 desc << expression;
01428 }
01429 string description = desc.str();
01430
01431
01432 FunctionIndex index =
01433 get_function(function, description,
01434 struct_type, scope,
01435 setter_flags, expression);
01436
01437 InterrogateDatabase::get_ptr()->update_function(index)._comment = description;
01438 return index;
01439 }
01440
01441
01442
01443
01444
01445
01446
01447
01448 FunctionIndex InterrogateBuilder::
01449 get_cast_function(CPPType *to_type, CPPType *from_type,
01450 const string &prefix) {
01451 CPPInstance *function;
01452 CPPStructType *struct_type = from_type->as_struct_type();
01453 CPPScope *scope = &parser;
01454
01455 if (struct_type != (CPPStructType *)NULL) {
01456
01457 scope = struct_type->get_scope();
01458
01459
01460 string fname =
01461 clean_identifier(prefix + "_to_" + get_preferred_name(to_type));
01462
01463
01464 CPPType *to_ptr_type = CPPType::new_type(new CPPPointerType(to_type));
01465
01466 CPPParameterList *params = new CPPParameterList;
01467 CPPFunctionType *ftype = new CPPFunctionType(to_ptr_type, params, 0);
01468
01469
01470 function = new CPPInstance(ftype, fname);
01471
01472 } else {
01473
01474
01475
01476
01477 string fname =
01478 clean_identifier(prefix + "_" + get_preferred_name(from_type) +
01479 "_to_" + get_preferred_name(to_type));
01480
01481
01482 CPPType *from_ptr_type = CPPType::new_type(new CPPPointerType(from_type));
01483 CPPType *to_ptr_type = CPPType::new_type(new CPPPointerType(to_type));
01484
01485 CPPInstance *param0 = new CPPInstance(from_ptr_type, "this");
01486 CPPParameterList *params = new CPPParameterList;
01487 params->_parameters.push_back(param0);
01488 CPPFunctionType *ftype = new CPPFunctionType(to_ptr_type, params, 0);
01489
01490
01491 function = new CPPInstance(ftype, fname);
01492 }
01493
01494 ostringstream desc;
01495 desc << prefix << " from " << *from_type << " to " << *to_type;
01496 string description = desc.str();
01497
01498 FunctionIndex index =
01499 get_function(function, description,
01500 struct_type, scope,
01501 InterrogateFunction::F_typecast);
01502
01503 InterrogateDatabase::get_ptr()->update_function(index)._comment = description;
01504 return index;
01505 }
01506
01507
01508
01509
01510
01511
01512
01513
01514 FunctionIndex InterrogateBuilder::
01515 get_function(CPPInstance *function, string description,
01516 CPPStructType *struct_type,
01517 CPPScope *scope, int flags,
01518 const string &expression) {
01519
01520
01521
01522 if (function->_ident->_native_scope != scope) {
01523 function = new CPPInstance(*function);
01524 function->_ident = new CPPIdentifier(*function->_ident);
01525 function->_ident->_native_scope = scope;
01526 }
01527 CPPFunctionType *ftype =
01528 function->_type->resolve_type(scope, &parser)->as_function_type();
01529 function->_type = ftype;
01530
01531 if ((ftype->_flags & CPPFunctionType::F_constructor) &&
01532 struct_type != (CPPStructType *)NULL &&
01533 struct_type->is_abstract()) {
01534
01535 return 0;
01536 }
01537
01538 string function_name = TypeManager::get_function_name(function);
01539 string function_signature = TypeManager::get_function_signature(function);
01540
01541
01542 FunctionsByName::const_iterator tni =
01543 _functions_by_name.find(function_name);
01544 if (tni != _functions_by_name.end()) {
01545 FunctionIndex index = (*tni).second;
01546
01547 InterrogateFunction &ifunction =
01548 InterrogateDatabase::get_ptr()->update_function(index);
01549
01550 ifunction._flags |= flags;
01551
01552
01553 if (function->_leading_comment != (CPPCommentBlock *)NULL) {
01554 string comment = trim_blanks(function->_leading_comment->_comment);
01555 if (!ifunction._comment.empty()) {
01556 ifunction._comment += "\n\n";
01557 }
01558 ifunction._comment += comment;
01559 }
01560
01561
01562 ifunction._instances->insert(InterrogateFunction::Instances::value_type(function_signature, function));
01563
01564 return index;
01565 }
01566
01567
01568 FunctionIndex index =
01569 InterrogateDatabase::get_ptr()->get_next_index();
01570 _functions_by_name[function_name] = index;
01571
01572 InterrogateFunction *ifunction = new InterrogateFunction;
01573 ifunction->_name = function->get_local_name(scope);
01574 ifunction->_scoped_name = descope(function->get_local_name(&parser));
01575 ifunction->_instances = new InterrogateFunction::Instances;
01576
01577 if (function->_leading_comment != (CPPCommentBlock *)NULL) {
01578 ifunction->_comment = trim_blanks(function->_leading_comment->_comment);
01579 }
01580
01581 ostringstream prototype;
01582 function->output(prototype, 0, &parser, false);
01583 prototype << ";";
01584 ifunction->_prototype = prototype.str();
01585
01586 if (struct_type != (CPPStructType *)NULL) {
01587
01588 ifunction->_flags |= InterrogateFunction::F_method;
01589 ifunction->_class = get_type(struct_type, false);
01590 }
01591
01592 ifunction->_flags |= flags;
01593 ifunction->_instances->insert(InterrogateFunction::Instances::value_type(function_signature, function));
01594 ifunction->_expression = expression;
01595
01596 InterrogateDatabase::get_ptr()->add_function(index, ifunction);
01597
01598 return index;
01599 }
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611 TypeIndex InterrogateBuilder::
01612 get_atomic_string_type() {
01613
01614
01615 string true_name = "atomic string";
01616
01617 TypesByName::const_iterator tni = _types_by_name.find(true_name);
01618 if (tni != _types_by_name.end()) {
01619 return (*tni).second;
01620 }
01621
01622
01623
01624
01625 TypeIndex index = InterrogateDatabase::get_ptr()->get_next_index();
01626 _types_by_name[true_name] = index;
01627
01628 InterrogateType itype;
01629 itype._flags |= InterrogateType::F_atomic;
01630 itype._atomic_token = AT_string;
01631 itype._true_name = true_name;
01632 itype._scoped_name = true_name;
01633 itype._name = true_name;
01634
01635 InterrogateDatabase::get_ptr()->add_type(index, itype);
01636
01637 return index;
01638 }
01639
01640
01641
01642
01643
01644
01645
01646
01647 TypeIndex InterrogateBuilder::
01648 get_type(CPPType *type, bool global) {
01649 if (type->is_template()) {
01650
01651 return 0;
01652 }
01653
01654 TypeIndex index = 0;
01655
01656
01657 string true_name = type->get_local_name(&parser);
01658 TypesByName::const_iterator tni = _types_by_name.find(true_name);
01659 if (tni != _types_by_name.end()) {
01660
01661 index = (*tni).second;
01662 if (index == 0) {
01663
01664 return 0;
01665 }
01666
01667 InterrogateType &itype = InterrogateDatabase::get_ptr()->update_type(index);
01668 if (global) {
01669 itype._flags |= InterrogateType::F_global;
01670 }
01671
01672 if ((itype._flags & InterrogateType::F_fully_defined) != 0) {
01673 return index;
01674 }
01675
01676
01677
01678 }
01679
01680 bool forced = in_forcetype(true_name);
01681
01682 if (index == 0) {
01683
01684 index = InterrogateDatabase::get_ptr()->get_next_index();
01685 _types_by_name[true_name] = index;
01686
01687 InterrogateType itype;
01688 if (global) {
01689 itype._flags |= InterrogateType::F_global;
01690 }
01691 InterrogateDatabase::get_ptr()->add_type(index, itype);
01692 }
01693
01694 InterrogateType &itype =
01695 InterrogateDatabase::get_ptr()->update_type(index);
01696
01697 itype._name = get_preferred_name(type);
01698 itype._scoped_name = true_name;
01699 itype._true_name = true_name;
01700 itype._cpptype = type;
01701
01702 if (type->_declaration != (CPPTypeDeclaration *)NULL) {
01703
01704
01705 CPPTypeDeclaration *decl = type->_declaration;
01706 if (decl->_leading_comment != (CPPCommentBlock *)NULL) {
01707 itype._comment = trim_blanks(decl->_leading_comment->_comment);
01708 }
01709 }
01710
01711 CPPExtensionType *ext_type = type->as_extension_type();
01712 if (ext_type != (CPPExtensionType *)NULL) {
01713
01714 if (ext_type->_ident != (CPPIdentifier *)NULL) {
01715 CPPScope *scope = ext_type->_ident->get_scope(&parser, &parser);
01716 while (scope->as_template_scope() != (CPPTemplateScope *)NULL) {
01717 assert(scope->get_parent_scope() != scope);
01718 scope = scope->get_parent_scope();
01719 assert(scope != (CPPScope *)NULL);
01720 }
01721 itype._cppscope = scope;
01722
01723 if (scope != &parser) {
01724
01725 itype._scoped_name =
01726 descope(scope->get_local_name(&parser) + "::" + itype._name);
01727 CPPStructType *struct_type = scope->get_struct_type();
01728
01729 if (struct_type != (CPPStructType *)NULL) {
01730 itype._flags |= InterrogateType::F_nested;
01731 itype._outer_class = get_type(struct_type, false);
01732 }
01733 }
01734 }
01735 }
01736
01737 if (forced || !in_ignoretype(true_name)) {
01738 itype._flags |= InterrogateType::F_fully_defined;
01739
01740 if (type->as_simple_type() != (CPPSimpleType *)NULL) {
01741 define_atomic_type(itype, type->as_simple_type());
01742
01743 } else if (type->as_pointer_type() != (CPPPointerType *)NULL) {
01744 define_wrapped_type(itype, type->as_pointer_type());
01745
01746 } else if (type->as_const_type() != (CPPConstType *)NULL) {
01747 define_wrapped_type(itype, type->as_const_type());
01748
01749 } else if (type->as_struct_type() != (CPPStructType *)NULL) {
01750 define_struct_type(itype, type->as_struct_type(), index, forced);
01751
01752 } else if (type->as_enum_type() != (CPPEnumType *)NULL) {
01753 define_enum_type(itype, type->as_enum_type());
01754
01755 } else if (type->as_extension_type() != (CPPExtensionType *)NULL) {
01756 define_extension_type(itype, type->as_extension_type());
01757
01758 } else {
01759
01760
01761
01762 InterrogateDatabase::get_ptr()->remove_type(index);
01763 _types_by_name[true_name] = 0;
01764 index = 0;
01765 }
01766 }
01767
01768 return index;
01769 }
01770
01771
01772
01773
01774
01775
01776 void InterrogateBuilder::
01777 define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype) {
01778 itype._flags |= InterrogateType::F_atomic;
01779
01780 switch (cpptype->_type) {
01781 case CPPSimpleType::T_bool:
01782 itype._atomic_token = AT_bool;
01783 break;
01784
01785 case CPPSimpleType::T_char:
01786 itype._atomic_token = AT_char;
01787 break;
01788
01789 case CPPSimpleType::T_int:
01790 itype._atomic_token = AT_int;
01791 break;
01792
01793 case CPPSimpleType::T_float:
01794 itype._atomic_token = AT_float;
01795 break;
01796
01797 case CPPSimpleType::T_double:
01798 itype._atomic_token = AT_double;
01799 break;
01800
01801 case CPPSimpleType::T_void:
01802 itype._atomic_token = AT_void;
01803 break;
01804
01805 default:
01806 nout << "Invalid CPPSimpleType: " << (int)cpptype->_type << "\n";
01807 itype._atomic_token = AT_not_atomic;
01808 }
01809
01810 if ((cpptype->_flags & CPPSimpleType::F_longlong) != 0) {
01811 itype._flags |= InterrogateType::F_longlong;
01812
01813 } else if ((cpptype->_flags & CPPSimpleType::F_long) != 0) {
01814 itype._flags |= InterrogateType::F_long;
01815 }
01816
01817 if ((cpptype->_flags & CPPSimpleType::F_short) != 0) {
01818 itype._flags |= InterrogateType::F_short;
01819 }
01820 if ((cpptype->_flags & CPPSimpleType::F_unsigned) != 0) {
01821 itype._flags |= InterrogateType::F_unsigned;
01822 }
01823 if ((cpptype->_flags & CPPSimpleType::F_signed) != 0) {
01824 itype._flags |= InterrogateType::F_signed;
01825 }
01826 }
01827
01828
01829
01830
01831
01832
01833 void InterrogateBuilder::
01834 define_wrapped_type(InterrogateType &itype, CPPPointerType *cpptype) {
01835 itype._flags |= (InterrogateType::F_wrapped | InterrogateType::F_pointer);
01836 itype._wrapped_type = get_type(cpptype->_pointing_at, false);
01837 }
01838
01839
01840
01841
01842
01843
01844 void InterrogateBuilder::
01845 define_wrapped_type(InterrogateType &itype, CPPConstType *cpptype) {
01846 itype._flags |= (InterrogateType::F_wrapped | InterrogateType::F_const);
01847 itype._wrapped_type = get_type(cpptype->_wrapped_around, false);
01848 }
01849
01850
01851
01852
01853
01854
01855 void InterrogateBuilder::
01856 define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
01857 TypeIndex type_index, bool forced) {
01858 if (cpptype->get_simple_name().empty()) {
01859
01860
01861 return;
01862 }
01863
01864 cpptype = TypeManager::resolve_type(cpptype)->as_struct_type();
01865 assert(cpptype != (CPPStructType *)NULL);
01866 cpptype->check_virtual();
01867
01868 switch (cpptype->_type) {
01869 case CPPExtensionType::T_class:
01870 itype._flags |= InterrogateType::F_class;
01871 break;
01872
01873 case CPPExtensionType::T_struct:
01874 itype._flags |= InterrogateType::F_struct;
01875 break;
01876
01877 case CPPExtensionType::T_union:
01878 itype._flags |= InterrogateType::F_union;
01879 break;
01880
01881 default:
01882 break;
01883 }
01884
01885 if (cpptype->_file.is_c_file()) {
01886
01887
01888 return;
01889 }
01890
01891 if (!forced &&
01892 (cpptype->_file._source != CPPFile::S_local ||
01893 in_ignorefile(cpptype->_file._filename_as_referenced))) {
01894
01895
01896
01897
01898
01899
01900
01901
01902 itype._flags &= ~InterrogateType::F_fully_defined;
01903 return;
01904 }
01905
01906
01907
01908
01909 if (TypeManager::involves_unpublished(cpptype)) {
01910 itype._flags &= ~InterrogateType::F_fully_defined;
01911 itype._flags |= InterrogateType::F_unpublished;
01912 return;
01913 }
01914 if (TypeManager::involves_protected(cpptype)) {
01915 itype._flags &= ~InterrogateType::F_fully_defined;
01916 return;
01917 }
01918
01919
01920 itype._flags |= InterrogateType::F_global;
01921
01922 CPPScope *scope = cpptype->_scope;
01923
01924 CPPStructType::Derivation::const_iterator bi;
01925 for (bi = cpptype->_derivation.begin();
01926 bi != cpptype->_derivation.end();
01927 ++bi) {
01928 const CPPStructType::Base &base = (*bi);
01929 if (base._vis <= V_public) {
01930 CPPType *base_type = TypeManager::resolve_type(base._base, scope);
01931 TypeIndex base_index = get_type(base_type, true);
01932
01933 if (base_index == 0) {
01934 nout << *cpptype << " reports a derivation from an invalid type.\n";
01935
01936 } else {
01937 InterrogateType::Derivation d;
01938 d._flags = 0;
01939 d._base = base_index;
01940 d._upcast = 0;
01941 d._downcast = 0;
01942
01943
01944 bool generate_casts = false;
01945 if (base._is_virtual) {
01946
01947 generate_casts = true;
01948
01949 } else if (bi != cpptype->_derivation.begin()) {
01950
01951
01952 generate_casts = true;
01953
01954 } else if (cpptype->_derivation.size() != 1 &&
01955 left_inheritance_requires_upcast) {
01956
01957
01958
01959
01960 generate_casts = true;
01961 }
01962
01963 if (generate_casts) {
01964 d._upcast = get_cast_function(base_type, cpptype, "upcast");
01965 d._flags |= InterrogateType::DF_upcast;
01966
01967 if (base._is_virtual) {
01968
01969
01970 d._flags |= InterrogateType::DF_downcast_impossible;
01971 } else {
01972 d._downcast = get_cast_function(cpptype, base_type, "downcast");
01973 d._flags |= InterrogateType::DF_downcast;
01974 }
01975 }
01976
01977 itype._derivations.push_back(d);
01978 }
01979 }
01980 }
01981
01982 CPPScope::Declarations::const_iterator di;
01983 for (di = scope->_declarations.begin();
01984 di != scope->_declarations.end();
01985 ++di) {
01986 if ((*di)->get_subtype() == CPPDeclaration::ST_instance) {
01987 CPPInstance *inst = (*di)->as_instance();
01988 if (inst->_type->get_subtype() == CPPDeclaration::ST_function) {
01989
01990 define_method(inst, itype, cpptype, scope);
01991
01992 } else {
01993
01994 ElementIndex data_member = scan_element(inst, cpptype, scope);
01995 if (data_member != 0) {
01996 itype._elements.push_back(data_member);
01997 }
01998 }
01999
02000 } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) {
02001 CPPType *type = (*di)->as_type_declaration()->_type;
02002
02003 if ((*di)->_vis <= min_vis) {
02004 if (type->as_struct_type() != (CPPStructType *)NULL ||
02005 type->as_enum_type() != (CPPEnumType *)NULL) {
02006
02007 type->_vis = (*di)->_vis;
02008
02009 CPPExtensionType *nested_type = type->as_extension_type();
02010 assert(nested_type != (CPPExtensionType *)NULL);
02011
02012
02013 if (nested_type->_ident != (CPPIdentifier *)NULL) {
02014 TypeIndex nested_index = get_type(nested_type, false);
02015 itype._nested_types.push_back(nested_index);
02016 }
02017 }
02018 }
02019 }
02020 }
02021
02022 if ((itype._flags & InterrogateType::F_inherited_destructor) != 0) {
02023
02024
02025 assert(!itype._derivations.empty());
02026 TypeIndex base_type_index = itype._derivations.front()._base;
02027 InterrogateType &base_type = InterrogateDatabase::get_ptr()->
02028 update_type(base_type_index);
02029
02030 itype._destructor = base_type._destructor;
02031
02032 } else if ((itype._flags &
02033 (InterrogateType::F_true_destructor |
02034 InterrogateType::F_private_destructor |
02035 InterrogateType::F_inherited_destructor |
02036 InterrogateType::F_implicit_destructor)) == 0) {
02037
02038
02039 string function_name = "~" + cpptype->get_simple_name();
02040
02041
02042 CPPType *void_type = TypeManager::get_void_type();
02043 CPPParameterList *params = new CPPParameterList;
02044 CPPFunctionType *ftype = new CPPFunctionType(void_type, params, 0);
02045 ftype->_flags |= CPPFunctionType::F_destructor;
02046
02047
02048 CPPInstance *function = new CPPInstance(ftype, function_name);
02049
02050 itype._destructor = get_function(function, "",
02051 cpptype, cpptype->get_scope(),
02052 0);
02053 itype._flags |= InterrogateType::F_implicit_destructor;
02054 }
02055 }
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067 void InterrogateBuilder::
02068 update_method_comment(CPPInstance *function, CPPStructType *struct_type,
02069 CPPScope *scope) {
02070 if (function->_leading_comment == (CPPCommentBlock *)NULL) {
02071
02072 return;
02073 }
02074
02075
02076 if (function->_ident->_native_scope != scope) {
02077 function = new CPPInstance(*function);
02078 function->_ident = new CPPIdentifier(*function->_ident);
02079 function->_ident->_native_scope = scope;
02080 }
02081 CPPFunctionType *ftype =
02082 function->_type->resolve_type(scope, &parser)->as_function_type();
02083 function->_type = ftype;
02084
02085 string function_name = TypeManager::get_function_name(function);
02086
02087
02088 FunctionsByName::const_iterator tni =
02089 _functions_by_name.find(function_name);
02090 if (tni != _functions_by_name.end()) {
02091 FunctionIndex index = (*tni).second;
02092
02093
02094 InterrogateFunction &ifunction =
02095 InterrogateDatabase::get_ptr()->update_function(index);
02096
02097
02098 string comment = trim_blanks(function->_leading_comment->_comment);
02099 if (!ifunction._comment.empty()) {
02100 ifunction._comment += "\n\n";
02101 }
02102 ifunction._comment += comment;
02103
02104
02105
02106
02107
02108 }
02109 }
02110
02111
02112
02113
02114
02115
02116
02117 void InterrogateBuilder::
02118 define_method(CPPFunctionGroup *fgroup, InterrogateType &itype,
02119 CPPStructType *struct_type, CPPScope *scope) {
02120 CPPFunctionGroup::Instances::const_iterator fi;
02121 for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
02122 CPPInstance *function = (*fi);
02123 define_method(function, itype, struct_type, scope);
02124 }
02125 }
02126
02127
02128
02129
02130
02131
02132 void InterrogateBuilder::
02133 define_method(CPPInstance *function, InterrogateType &itype,
02134 CPPStructType *struct_type, CPPScope *scope) {
02135 assert(function != (CPPInstance *)NULL);
02136 assert(function->_type != (CPPType *)NULL &&
02137 function->_type->as_function_type() != (CPPFunctionType *)NULL);
02138 CPPFunctionType *ftype =
02139 function->_type->resolve_type(scope, &parser)->as_function_type();
02140
02141 if (function->is_template()) {
02142
02143 return;
02144 }
02145
02146
02147
02148
02149
02150
02151 bool force_publish = false;
02152 if (function->get_simple_name() == "get_class_type" &&
02153 (function->_storage_class && CPPInstance::SC_static) != 0 &&
02154 function->_vis <= V_public) {
02155 force_publish = true;
02156 }
02157
02158 if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) {
02159
02160
02161
02162
02163 if (function->_vis > V_public) {
02164 itype._flags |= InterrogateType::F_private_destructor;
02165 return;
02166 }
02167 force_publish = true;
02168 }
02169
02170 if (!force_publish && function->_vis > min_vis) {
02171
02172 return;
02173 }
02174
02175 if (TypeManager::involves_protected(ftype)) {
02176
02177
02178 return;
02179 }
02180
02181 if (in_ignoreinvolved(ftype)) {
02182
02183
02184 if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) {
02185 itype._flags |= InterrogateType::F_private_destructor;
02186 }
02187 return;
02188 }
02189
02190 if (in_ignoremember(function->get_simple_name())) {
02191
02192 if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) {
02193 itype._flags |= InterrogateType::F_private_destructor;
02194 }
02195 return;
02196 }
02197
02198 if ((function->_storage_class & CPPInstance::SC_inherited_virtual) != 0 &&
02199 struct_type->_derivation.size() == 1 &&
02200 struct_type->_derivation[0]._vis <= V_public &&
02201 !struct_type->_derivation[0]._is_virtual) {
02202
02203
02204
02205
02206
02207 if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) {
02208 itype._flags |= InterrogateType::F_inherited_destructor;
02209 }
02210 return;
02211 }
02212
02213
02214 FunctionIndex index = get_function(function, "", struct_type, scope, 0);
02215 if (index != 0) {
02216 if ((ftype->_flags & CPPFunctionType::F_constructor) != 0) {
02217 if (find(itype._constructors.begin(), itype._constructors.end(),
02218 index) == itype._constructors.end()) {
02219 itype._constructors.push_back(index);
02220 }
02221
02222 } else if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) {
02223 itype._flags |= InterrogateType::F_true_destructor;
02224 itype._destructor = index;
02225
02226 } else if ((ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) {
02227 if (find(itype._casts.begin(), itype._casts.end(),
02228 index) == itype._casts.end()) {
02229 itype._casts.push_back(index);
02230 }
02231
02232 } else {
02233 if (find(itype._methods.begin(), itype._methods.end(),
02234 index) == itype._methods.end()) {
02235 itype._methods.push_back(index);
02236 }
02237 }
02238 }
02239 }
02240
02241
02242
02243
02244
02245
02246 void InterrogateBuilder::
02247 define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) {
02248 itype._flags |= InterrogateType::F_enum;
02249
02250 CPPScope *scope = &parser;
02251 if (cpptype->_ident != (CPPIdentifier *)NULL) {
02252 scope = cpptype->_ident->get_scope(&parser, &parser);
02253 }
02254
02255
02256
02257
02258 if (TypeManager::involves_unpublished(cpptype)) {
02259 itype._flags &= ~InterrogateType::F_fully_defined;
02260 itype._flags |= InterrogateType::F_unpublished;
02261 return;
02262 }
02263
02264 int next_value = 0;
02265
02266 CPPEnumType::Elements::const_iterator ei;
02267 for (ei = cpptype->_elements.begin();
02268 ei != cpptype->_elements.end();
02269 ++ei) {
02270 CPPInstance *element = (*ei);
02271
02272
02273
02274
02275 if (element->_ident->_native_scope != scope) {
02276 element = new CPPInstance(*element);
02277 element->_ident = new CPPIdentifier(*element->_ident);
02278 element->_ident->_native_scope = scope;
02279 }
02280
02281 InterrogateType::EnumValue evalue;
02282 evalue._name = element->get_simple_name();
02283 evalue._scoped_name = descope(element->get_local_name(&parser));
02284
02285 if (element->_initializer != (CPPExpression *)NULL) {
02286 CPPExpression::Result result = element->_initializer->evaluate();
02287 next_value = result.as_integer();
02288 }
02289 evalue._value = next_value;
02290 itype._enum_values.push_back(evalue);
02291
02292 next_value++;
02293 }
02294 }
02295
02296
02297
02298
02299
02300
02301 void InterrogateBuilder::
02302 define_extension_type(InterrogateType &itype, CPPExtensionType *cpptype) {
02303
02304
02305 itype._flags &= ~InterrogateType::F_fully_defined;
02306
02307
02308
02309 switch (cpptype->_type) {
02310 case CPPExtensionType::T_enum:
02311 itype._flags |= InterrogateType::F_enum;
02312 break;
02313
02314 case CPPExtensionType::T_class:
02315 itype._flags |= InterrogateType::F_class;
02316 break;
02317
02318 case CPPExtensionType::T_struct:
02319 itype._flags |= InterrogateType::F_struct;
02320 break;
02321
02322 case CPPExtensionType::T_union:
02323 itype._flags |= InterrogateType::F_union;
02324 break;
02325 }
02326 }
02327
02328
02329
02330
02331
02332
02333 string InterrogateBuilder::
02334 trim_blanks(const string &str) {
02335 size_t start = 0;
02336 while (start < str.length() && isspace(str[start])) {
02337 start++;
02338 }
02339
02340 size_t end = str.length();
02341 while (end > start && isspace(str[end - 1])) {
02342 end--;
02343 }
02344
02345 return str.substr(start, end - start);
02346 }