00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "interfaceMaker.h"
00020 #include "interrogateBuilder.h"
00021 #include "typeManager.h"
00022 #include "interrogate.h"
00023 #include "functionRemap.h"
00024 #include "parameterRemap.h"
00025 #include "parameterRemapThis.h"
00026 #include "parameterRemapUnchanged.h"
00027 #include "parameterRemapReferenceToPointer.h"
00028 #include "parameterRemapConcreteToPointer.h"
00029 #include "parameterRemapEnumToInt.h"
00030 #include "parameterRemapConstToNonConst.h"
00031 #include "parameterRemapReferenceToConcrete.h"
00032 #include "parameterRemapCharStarToString.h"
00033 #include "parameterRemapBasicStringToString.h"
00034 #include "parameterRemapBasicStringRefToString.h"
00035 #include "parameterRemapPTToPointer.h"
00036
00037 #include "interrogateDatabase.h"
00038 #include "interrogateManifest.h"
00039 #include "interrogateElement.h"
00040 #include "cppFunctionType.h"
00041 #include "cppParameterList.h"
00042 #include "notify.h"
00043
00044 static InterrogateType dummy_type;
00045
00046
00047
00048
00049
00050
00051 InterfaceMaker::Function::
00052 Function(const string &name,
00053 const InterrogateType &itype,
00054 const InterrogateFunction &ifunc) :
00055 _name(name),
00056 _itype(itype),
00057 _ifunc(ifunc)
00058 {
00059 _has_this = false;
00060 }
00061
00062
00063
00064
00065
00066
00067 InterfaceMaker::Function::
00068 ~Function() {
00069 Remaps::iterator ri;
00070 for (ri = _remaps.begin(); ri != _remaps.end(); ++ri) {
00071 delete (*ri);
00072 }
00073 }
00074
00075
00076
00077
00078
00079
00080 InterfaceMaker::Object::
00081 Object(const InterrogateType &itype) :
00082 _itype(itype)
00083 {
00084 _destructor = (Function *)NULL;
00085 }
00086
00087
00088
00089
00090
00091
00092 InterfaceMaker::Object::
00093 ~Object() {
00094 }
00095
00096
00097
00098
00099
00100
00101 InterfaceMaker::
00102 InterfaceMaker(InterrogateModuleDef *def) :
00103 _def(def)
00104 {
00105 }
00106
00107
00108
00109
00110
00111
00112 InterfaceMaker::
00113 ~InterfaceMaker() {
00114 Objects::iterator oi;
00115 for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
00116 Object *object = (*oi).second;
00117 delete object;
00118 }
00119 Functions::iterator fi;
00120 for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00121 delete (*fi);
00122 }
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 void InterfaceMaker::
00135 generate_wrappers() {
00136 InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
00137
00138
00139
00140
00141 int ti = 0;
00142 while (ti < idb->get_num_all_types()) {
00143 TypeIndex type_index = idb->get_all_type(ti);
00144 record_object(type_index);
00145 ++ti;
00146 }
00147
00148 int num_functions = idb->get_num_global_functions();
00149 for (int fi = 0; fi < num_functions; fi++) {
00150 FunctionIndex func_index = idb->get_global_function(fi);
00151 record_function(dummy_type, func_index);
00152 }
00153
00154 int num_manifests = idb->get_num_global_manifests();
00155 for (int mi = 0; mi < num_manifests; mi++) {
00156 ManifestIndex manifest_index = idb->get_global_manifest(mi);
00157 const InterrogateManifest &iman = idb->get_manifest(manifest_index);
00158 if (iman.has_getter()) {
00159 FunctionIndex func_index = iman.get_getter();
00160 record_function(dummy_type, func_index);
00161 }
00162 }
00163
00164 int num_elements = idb->get_num_global_elements();
00165 for (int ei = 0; ei < num_elements; ei++) {
00166 ElementIndex element_index = idb->get_global_element(ei);
00167 const InterrogateElement &ielement = idb->get_element(element_index);
00168 if (ielement.has_getter()) {
00169 FunctionIndex func_index = ielement.get_getter();
00170 record_function(dummy_type, func_index);
00171 }
00172 if (ielement.has_setter()) {
00173 FunctionIndex func_index = ielement.get_setter();
00174 record_function(dummy_type, func_index);
00175 }
00176 }
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186 void InterfaceMaker::
00187 write_includes(ostream &) {
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197 void InterfaceMaker::
00198 write_prototypes(ostream &out) {
00199 _function_writers.write_prototypes(out);
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 void InterfaceMaker::
00209 write_functions(ostream &out) {
00210 _function_writers.write_code(out);
00211 }
00212
00213
00214
00215
00216
00217
00218
00219 void InterfaceMaker::
00220 write_module(ostream &, InterrogateModuleDef *) {
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 ParameterRemap *InterfaceMaker::
00237 remap_parameter(CPPType *struct_type, CPPType *param_type) {
00238 if (convert_strings) {
00239 if (TypeManager::is_char_pointer(param_type)) {
00240 return new ParameterRemapCharStarToString(param_type);
00241 }
00242
00243
00244
00245
00246 if (struct_type == (CPPType *)NULL ||
00247 !TypeManager::is_basic_string_char(struct_type)) {
00248 if (TypeManager::is_basic_string_char(param_type)) {
00249 return new ParameterRemapBasicStringToString(param_type);
00250
00251 } else if (TypeManager::is_const_ref_to_basic_string_char(param_type)) {
00252 return new ParameterRemapBasicStringRefToString(param_type);
00253 }
00254 }
00255 }
00256
00257 if (manage_reference_counts) {
00258 if (TypeManager::is_pointer_to_base(param_type) ||
00259 TypeManager::is_const_ref_to_pointer_to_base(param_type)) {
00260 CPPType *pt_type = TypeManager::unwrap_reference(param_type);
00261
00262
00263
00264 if (struct_type == (CPPType *)NULL ||
00265 !(pt_type->get_local_name(&parser) == struct_type->get_local_name(&parser))) {
00266 return new ParameterRemapPTToPointer(param_type);
00267 }
00268 }
00269 }
00270
00271 if (TypeManager::is_reference(param_type)) {
00272 return new ParameterRemapReferenceToPointer(param_type);
00273
00274 } else if (TypeManager::is_struct(param_type)) {
00275 return new ParameterRemapConcreteToPointer(param_type);
00276
00277
00278
00279
00280
00281
00282 } else if (TypeManager::is_const_simple(param_type)) {
00283 return new ParameterRemapConstToNonConst(param_type);
00284
00285 } else if (TypeManager::is_const_ref_to_simple(param_type)) {
00286 return new ParameterRemapReferenceToConcrete(param_type);
00287
00288 } else if (TypeManager::is_pointer(param_type) || TypeManager::is_simple(param_type)) {
00289 return new ParameterRemapUnchanged(param_type);
00290
00291 } else {
00292
00293 return (ParameterRemap *)NULL;
00294 }
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 bool InterfaceMaker::
00306 synthesize_this_parameter() {
00307 return false;
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 bool InterfaceMaker::
00322 separate_overloading() {
00323 return true;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 void InterfaceMaker::
00336 get_function_remaps(vector<FunctionRemap *> &remaps) {
00337 Functions::iterator fi;
00338 for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00339 Function *func = (*fi);
00340 Function::Remaps::const_iterator ri;
00341 for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
00342 FunctionRemap *remap = (*ri);
00343 remaps.push_back(remap);
00344 }
00345 }
00346 }
00347
00348
00349
00350
00351
00352
00353 ostream &InterfaceMaker::
00354 indent(ostream &out, int indent_level) {
00355 for (int i = 0; i < indent_level; i++) {
00356 out << ' ';
00357 }
00358 return out;
00359 }
00360
00361
00362
00363
00364
00365
00366
00367 FunctionRemap *InterfaceMaker::
00368 make_function_remap(const InterrogateType &itype,
00369 const InterrogateFunction &ifunc,
00370 CPPInstance *cppfunc, int num_default_parameters) {
00371 FunctionRemap *remap =
00372 new FunctionRemap(itype, ifunc, cppfunc, num_default_parameters, this);
00373 if (remap->_is_valid) {
00374 if (separate_overloading()) {
00375 hash_function_signature(remap);
00376 remap->_unique_name =
00377 get_unique_prefix() + _def->library_hash_name + remap->_hash;
00378 remap->_wrapper_name =
00379 get_wrapper_prefix() + _def->library_hash_name + remap->_hash;
00380 }
00381 return remap;
00382 }
00383
00384
00385 delete remap;
00386 return (FunctionRemap *)NULL;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 string InterfaceMaker::
00402 get_wrapper_name(const InterrogateType &itype,
00403 const InterrogateFunction &ifunc,
00404 FunctionIndex func_index) {
00405 string func_name = ifunc.get_scoped_name();
00406 string clean_name = InterrogateBuilder::clean_identifier(func_name);
00407
00408 ostringstream new_name;
00409 new_name << get_wrapper_prefix() << clean_name << "_" << func_index;
00410 return new_name.str();
00411 }
00412
00413
00414
00415
00416
00417
00418
00419 string InterfaceMaker::
00420 get_wrapper_prefix() {
00421 return "xx_";
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431 string InterfaceMaker::
00432 get_unique_prefix() {
00433 return "x";
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443 InterfaceMaker::Function *InterfaceMaker::
00444 record_function(const InterrogateType &itype, FunctionIndex func_index) {
00445 InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
00446 const InterrogateFunction &ifunc = idb->get_function(func_index);
00447
00448 string wrapper_name = get_wrapper_name(itype, ifunc, func_index);
00449 Function *func = new Function(wrapper_name, itype, ifunc);
00450 _functions.push_back(func);
00451
00452
00453 if (ifunc._instances != (InterrogateFunction::Instances *)NULL) {
00454 InterrogateFunction::Instances::const_iterator ii;
00455 for (ii = ifunc._instances->begin();
00456 ii != ifunc._instances->end();
00457 ++ii) {
00458 CPPInstance *cppfunc = (*ii).second;
00459 CPPFunctionType *ftype = cppfunc->_type->as_function_type();
00460 int max_default_parameters = 0;
00461
00462 if (separate_overloading()) {
00463
00464
00465 CPPParameterList *parameters = ftype->_parameters;
00466 CPPParameterList::Parameters::reverse_iterator pi;
00467 for (pi = parameters->_parameters.rbegin();
00468 pi != parameters->_parameters.rend();
00469 ++pi) {
00470 CPPInstance *param = (*pi);
00471 if (param->_initializer != (CPPExpression *)NULL) {
00472
00473 max_default_parameters++;
00474 } else {
00475
00476 break;
00477 }
00478 }
00479 }
00480
00481
00482
00483
00484
00485 for (int num_default_parameters = 0;
00486 num_default_parameters <= max_default_parameters;
00487 num_default_parameters++) {
00488 FunctionRemap *remap =
00489 make_function_remap(itype, ifunc, cppfunc, num_default_parameters);
00490 if (remap != (FunctionRemap *)NULL) {
00491 func->_remaps.push_back(remap);
00492
00493
00494
00495
00496 if (remap->_has_this) {
00497 func->_has_this = true;
00498 }
00499
00500
00501 FunctionWrapperIndex wrapper_index =
00502 remap->make_wrapper_entry(func_index);
00503 if (wrapper_index != 0) {
00504 InterrogateFunction &mod_ifunc = idb->update_function(func_index);
00505 record_function_wrapper(mod_ifunc, wrapper_index);
00506 }
00507 }
00508 }
00509 }
00510 }
00511
00512 return func;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521 void InterfaceMaker::
00522 record_function_wrapper(InterrogateFunction &, FunctionWrapperIndex) {
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532 InterfaceMaker::Object *InterfaceMaker::
00533 record_object(TypeIndex type_index) {
00534 if (type_index == 0) {
00535
00536 return (Object *)NULL;
00537 }
00538
00539 Objects::iterator oi = _objects.find(type_index);
00540 if (oi != _objects.end()) {
00541
00542 return (*oi).second;
00543 }
00544
00545 InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
00546 const InterrogateType &itype = idb->get_type(type_index);
00547
00548 Object *object = new Object(itype);
00549 bool inserted = _objects.insert(Objects::value_type(type_index, object)).second;
00550 assert(inserted);
00551
00552 Function *function;
00553
00554 int num_constructors = itype.number_of_constructors();
00555 for (int ci = 0; ci < num_constructors; ci++) {
00556 function = record_function(itype, itype.get_constructor(ci));
00557 object->_constructors.push_back(function);
00558 }
00559
00560 if (itype.has_destructor() && !itype.destructor_is_inherited()) {
00561 function = record_function(itype, itype.get_destructor());
00562 object->_destructor = function;
00563 }
00564
00565 int num_methods = itype.number_of_methods();
00566 int mi;
00567 for (mi = 0; mi < num_methods; mi++) {
00568 function = record_function(itype, itype.get_method(mi));
00569 object->_methods.push_back(function);
00570 }
00571
00572 int num_casts = itype.number_of_casts();
00573 for (mi = 0; mi < num_casts; mi++) {
00574 function = record_function(itype, itype.get_cast(mi));
00575 object->_methods.push_back(function);
00576 }
00577
00578 int num_derivations = itype.number_of_derivations();
00579 for (int di = 0; di < num_derivations; di++) {
00580 if (itype.derivation_has_upcast(di)) {
00581 record_function(itype, itype.derivation_get_upcast(di));
00582 }
00583 if (itype.derivation_has_downcast(di)) {
00584
00585 TypeIndex base_type_index = itype.get_derivation(di);
00586 const InterrogateType &base_type = idb->get_type(base_type_index);
00587 record_function(base_type, itype.derivation_get_downcast(di));
00588 }
00589 }
00590
00591 int num_elements = itype.number_of_elements();
00592 for (int ei = 0; ei < num_elements; ei++) {
00593 ElementIndex element_index = itype.get_element(ei);
00594 const InterrogateElement &ielement = idb->get_element(element_index);
00595 if (ielement.has_getter()) {
00596 FunctionIndex func_index = ielement.get_getter();
00597 record_function(itype, func_index);
00598 }
00599 if (ielement.has_setter()) {
00600 FunctionIndex func_index = ielement.get_setter();
00601 record_function(itype, func_index);
00602 }
00603 }
00604
00605 int num_nested = itype.number_of_nested_types();
00606 for (int ni = 0; ni < num_nested; ni++) {
00607 TypeIndex nested_index = itype.get_nested_type(ni);
00608 record_object(nested_index);
00609 }
00610
00611 return object;
00612 }
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 string InterfaceMaker::
00623 manage_return_value(ostream &out, int indent_level,
00624 FunctionRemap *remap, const string &return_expr) const {
00625 if (remap->_manage_reference_count) {
00626
00627
00628 if (return_expr == "return_value") {
00629
00630
00631 output_ref(out, indent_level, remap, return_expr);
00632 return return_expr;
00633
00634 } else {
00635
00636
00637 CPPType *type = remap->_return_type->get_temporary_type();
00638 indent(out, indent_level);
00639 type->output_instance(out, "refcount", &parser);
00640 out << " = " << return_expr << ";\n";
00641
00642 indent(out, indent_level)
00643 << "if (" << return_expr << " != ("
00644 << remap->_return_type->get_new_type()->get_local_name(&parser) << ")0) {\n";
00645 indent(out, indent_level + 2)
00646 << return_expr << "->ref();\n";
00647 indent(out, indent_level)
00648 << "}\n";
00649 output_ref(out, indent_level, remap, "refcount");
00650 return remap->_return_type->temporary_to_return("refcount");
00651 }
00652 }
00653
00654
00655 return return_expr;
00656 }
00657
00658
00659
00660
00661
00662
00663
00664 void InterfaceMaker::
00665 output_ref(ostream &out, int indent_level, FunctionRemap *remap,
00666 const string &varname) const {
00667 if (remap->_type == FunctionRemap::T_constructor ||
00668 remap->_type == FunctionRemap::T_typecast) {
00669
00670
00671 indent(out, indent_level)
00672 << varname << "->ref();\n";
00673
00674 } else {
00675
00676
00677
00678 indent(out, indent_level)
00679 << "if (" << varname << " != ("
00680 << remap->_return_type->get_new_type()->get_local_name(&parser) << ")0) {\n";
00681 indent(out, indent_level + 2)
00682 << varname << "->ref();\n";
00683 indent(out, indent_level)
00684 << "}\n";
00685 }
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696 void InterfaceMaker::
00697 hash_function_signature(FunctionRemap *remap) {
00698 string hash = InterrogateBuilder::hash_string(remap->_function_signature, 5);
00699
00700
00701 WrappersByHash::iterator hi;
00702 hi = _wrappers_by_hash.find(hash);
00703 if (hi == _wrappers_by_hash.end()) {
00704
00705 _wrappers_by_hash[hash] = remap;
00706 remap->_hash = hash;
00707 return;
00708 }
00709
00710 if ((*hi).second != (FunctionRemap *)NULL &&
00711 (*hi).second->_function_signature == remap->_function_signature) {
00712
00713
00714 nout << "Internal error! Function signature "
00715 << remap->_function_signature << " repeated!\n";
00716 remap->_hash = hash;
00717 abort();
00718 return;
00719 }
00720
00721
00722
00723 if ((*hi).second != (FunctionRemap *)NULL) {
00724 FunctionRemap *other_remap = (*hi).second;
00725 (*hi).second = (FunctionRemap *)NULL;
00726 other_remap->_hash +=
00727 InterrogateBuilder::hash_string(other_remap->_function_signature, 11);
00728 bool inserted = _wrappers_by_hash.insert
00729 (WrappersByHash::value_type(other_remap->_hash, other_remap)).second;
00730 if (!inserted) {
00731 nout << "Internal error! Hash " << other_remap->_hash
00732 << " already appears!\n";
00733 }
00734 }
00735
00736 hash += InterrogateBuilder::hash_string(remap->_function_signature, 11);
00737 bool inserted = _wrappers_by_hash.insert
00738 (WrappersByHash::value_type(hash, remap)).second;
00739
00740 if (!inserted) {
00741
00742
00743 string old_hash = hash;
00744 for (char ch = 'a'; ch <= 'z' && !inserted; ch++) {
00745 hash = old_hash + ch;
00746 inserted = _wrappers_by_hash.insert
00747 (WrappersByHash::value_type(hash, remap)).second;
00748 }
00749 if (!inserted) {
00750 nout << "Internal error! Too many conflicts with hash "
00751 << hash << "\n";
00752 }
00753 }
00754
00755 remap->_hash = hash;
00756 }
00757
00758
00759
00760
00761
00762
00763
00764 void InterfaceMaker::
00765 write_spam_message(ostream &out, FunctionRemap *remap) const {
00766 ostringstream strm;
00767 remap->write_orig_prototype(strm, 0);
00768 string prototype = strm.str();
00769
00770 out <<
00771 " if (interrogatedb_cat.is_spam()) {\n"
00772 " interrogatedb_cat.spam() << \"";
00773
00774 for (string::const_iterator si = prototype.begin();
00775 si != prototype.end();
00776 ++si) {
00777 switch (*si) {
00778 case '"':
00779 out << "\\\"";
00780 break;
00781
00782 case '\\':
00783 out << "\\\\";
00784 break;
00785
00786 default:
00787 out << *si;
00788 }
00789 }
00790
00791 out << "\\n\";\n"
00792 " }\n";
00793 }