Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

dtool/src/interrogate/interfaceMaker.cxx

Go to the documentation of this file.
00001 // Filename: interfaceMaker.cxx
00002 // Created by:  drose (19Sep01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
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 //     Function: InterfaceMaker::Function::Constructor
00048 //       Access: Public
00049 //  Description:
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 //     Function: InterfaceMaker::Function::Destructor
00064 //       Access: Public
00065 //  Description:
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 //     Function: InterfaceMaker::Object::Constructor
00077 //       Access: Public
00078 //  Description:
00079 ////////////////////////////////////////////////////////////////////
00080 InterfaceMaker::Object::
00081 Object(const InterrogateType &itype) :
00082   _itype(itype)
00083 {
00084   _destructor = (Function *)NULL;
00085 }
00086 
00087 ////////////////////////////////////////////////////////////////////
00088 //     Function: InterfaceMaker::Object::Destructor
00089 //       Access: Public
00090 //  Description:
00091 ////////////////////////////////////////////////////////////////////
00092 InterfaceMaker::Object::
00093 ~Object() {
00094 }
00095 
00096 ////////////////////////////////////////////////////////////////////
00097 //     Function: InterfaceMaker::Constructor
00098 //       Access: Public
00099 //  Description:
00100 ////////////////////////////////////////////////////////////////////
00101 InterfaceMaker::
00102 InterfaceMaker(InterrogateModuleDef *def) :
00103   _def(def)
00104 {
00105 }
00106 
00107 ////////////////////////////////////////////////////////////////////
00108 //     Function: InterfaceMaker::Destructor
00109 //       Access: Public, Virtual
00110 //  Description:
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 //     Function: InterfaceMaker::generate_wrappers
00127 //       Access: Public, Virtual
00128 //  Description: Walks through the set of functions in the database
00129 //               and generates wrappers for each function, storing
00130 //               these in the database.  No actual code should be
00131 //               output yet; this just updates the database with the
00132 //               wrapper information.
00133 ////////////////////////////////////////////////////////////////////
00134 void InterfaceMaker::
00135 generate_wrappers() {
00136   InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
00137 
00138   // We use a while loop rather than a simple for loop, because we
00139   // might increase the number of types recursively during the
00140   // traversal.
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 //     Function: InterfaceMaker::write_includes
00181 //       Access: Public, Virtual
00182 //  Description: Generates the list of #include ... whatever that's
00183 //               required by this particular interface to the
00184 //               indicated output stream.
00185 ////////////////////////////////////////////////////////////////////
00186 void InterfaceMaker::
00187 write_includes(ostream &) {
00188 }
00189 
00190 ////////////////////////////////////////////////////////////////////
00191 //     Function: InterfaceMaker::write_prototypes
00192 //       Access: Public, Virtual
00193 //  Description: Generates the list of function prototypes
00194 //               corresponding to the functions that will be output in
00195 //               write_functions().
00196 ////////////////////////////////////////////////////////////////////
00197 void InterfaceMaker::
00198 write_prototypes(ostream &out) {
00199   _function_writers.write_prototypes(out);
00200 }
00201 
00202 ////////////////////////////////////////////////////////////////////
00203 //     Function: InterfaceMaker::write_functions
00204 //       Access: Public, Virtual
00205 //  Description: Generates the list of functions that are appropriate
00206 //               for this interface.
00207 ////////////////////////////////////////////////////////////////////
00208 void InterfaceMaker::
00209 write_functions(ostream &out) {
00210   _function_writers.write_code(out);
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: InterfaceMaker::write_module
00215 //       Access: Public, Virtual
00216 //  Description: Generates whatever additional code is required to
00217 //               support a module file.
00218 ////////////////////////////////////////////////////////////////////
00219 void InterfaceMaker::
00220 write_module(ostream &, InterrogateModuleDef *) {
00221 }
00222 
00223 
00224 ////////////////////////////////////////////////////////////////////
00225 //     Function: InterfaceMaker::remap_parameter
00226 //       Access: Public, Virtual
00227 //  Description: Allocates a new ParameterRemap object suitable to the
00228 //               indicated parameter type.  If struct_type is
00229 //               non-NULL, it is the type of the enclosing class for
00230 //               the function (method) in question.
00231 //
00232 //               The return value is a newly-allocated ParameterRemap
00233 //               object, if the parameter type is acceptable, or NULL
00234 //               if the parameter type cannot be handled.
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     // If we're exporting a method of basic_string<char> itself, don't
00244     // convert basic_string<char>'s to atomic strings.
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       // Don't convert PointerTo<>'s to pointers for methods of the
00263       // PointerTo itself!
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   } else if (TypeManager::is_enum(param_type) || TypeManager::is_const_ref_to_enum(param_type)) {
00279     return new ParameterRemapEnumToInt(param_type);
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     // Here's something we have a problem with.
00293     return (ParameterRemap *)NULL;
00294   }
00295 }
00296 
00297 ////////////////////////////////////////////////////////////////////
00298 //     Function: InterfaceMaker::synthesize_this_parameter
00299 //       Access: Public, Virtual
00300 //  Description: This method should be overridden and redefined to
00301 //               return true for interfaces that require the implicit
00302 //               "this" parameter, if present, to be passed as the
00303 //               first parameter to any wrapper functions.
00304 ////////////////////////////////////////////////////////////////////
00305 bool InterfaceMaker::
00306 synthesize_this_parameter() {
00307   return false;
00308 }
00309 
00310 ////////////////////////////////////////////////////////////////////
00311 //     Function: InterfaceMaker::separate_overloading
00312 //       Access: Public, Virtual
00313 //  Description: This method should be overridden and redefined to
00314 //               return true for interfaces that require overloaded
00315 //               instances of a function to be defined as separate
00316 //               functions (each with its own hashed name), or false
00317 //               for interfaces that can support overloading natively,
00318 //               and thus only require one wrapper function per each
00319 //               overloaded input function.
00320 ////////////////////////////////////////////////////////////////////
00321 bool InterfaceMaker::
00322 separate_overloading() {
00323   return true;
00324 }
00325 
00326 ////////////////////////////////////////////////////////////////////
00327 //     Function: InterfaceMaker::get_function_remaps
00328 //       Access: Public
00329 //  Description: Fills up the indicated vector with all of the
00330 //               FunctionRemap pointers created by this
00331 //               InterfaceMaker.  It is the user's responsibility to
00332 //               empty the vector before calling this function; the
00333 //               new pointers will simply be added to the end.
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 //     Function: InterfaceMaker::indent
00350 //       Access: Public, Static
00351 //  Description:
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 //     Function: InterfaceMaker::make_function_remap
00363 //       Access: Protected, Virtual
00364 //  Description: Creates a FunctionRemap object corresponding to the
00365 //               particular function wrapper.
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   // No such FunctionRemap is valid.  Return NULL.
00385   delete remap;
00386   return (FunctionRemap *)NULL;
00387 }
00388 
00389 ////////////////////////////////////////////////////////////////////
00390 //     Function: InterfaceMaker::get_wrapper_name
00391 //       Access: Protected, Virtual
00392 //  Description: Returns the function name that will be used to wrap
00393 //               the indicated function.
00394 //
00395 //               This is the name for the overall wrapper function,
00396 //               including all of the overloaded instances.
00397 //               Interfaces that must define a different wrapper for
00398 //               each FunctionRemap object (i.e. for each instance of
00399 //               an overloaded function) need not define a name here.
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 //     Function: InterfaceMaker::get_wrapper_prefix
00415 //       Access: Protected, Virtual
00416 //  Description: Returns the prefix string used to generate wrapper
00417 //               function names.
00418 ////////////////////////////////////////////////////////////////////
00419 string InterfaceMaker::
00420 get_wrapper_prefix() {
00421   return "xx_";
00422 }
00423 
00424 ////////////////////////////////////////////////////////////////////
00425 //     Function: InterfaceMaker::get_unique_prefix
00426 //       Access: Protected, Virtual
00427 //  Description: Returns the prefix string used to generate unique
00428 //               symbolic names, which are not necessarily C-callable
00429 //               function names.
00430 ////////////////////////////////////////////////////////////////////
00431 string InterfaceMaker::
00432 get_unique_prefix() {
00433   return "x";
00434 }
00435 
00436 ////////////////////////////////////////////////////////////////////
00437 //     Function: InterfaceMaker::record_function
00438 //       Access: Protected
00439 //  Description: Records the indicated function, along with all of its
00440 //               FunctionRemap flavors and FunctionWriter helpers, for
00441 //               future output.  Returns the new Function pointer.
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   // Now get all the valid FunctionRemaps for the function.
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         // Count up the number of default parameters this function might
00464         // take.
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             // This parameter has a default value.
00473             max_default_parameters++;
00474           } else {
00475             // The first parameter without a default value ends the search.
00476             break;
00477           }
00478         }
00479       }
00480       
00481       // Now make a different wrapper for each combination of default
00482       // parameters.  This will happen only if separate_overloading(),
00483       // tested above, returned true; otherwise, max_default_parameters
00484       // will be 0 and the loop will only be traversed once.
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           // If *any* of the variants of this function has a "this"
00494           // pointer, the entire set of functions is deemed to have a
00495           // "this" pointer.
00496           if (remap->_has_this) {
00497             func->_has_this = true;
00498           }
00499           
00500           // Make a wrapper for the function.
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 //     Function: InterfaceMaker::record_function_wrapper
00517 //       Access: Protected, Virtual
00518 //  Description: Associates the function wrapper with its function in
00519 //               the appropriate structures in the database.
00520 ////////////////////////////////////////////////////////////////////
00521 void InterfaceMaker::
00522 record_function_wrapper(InterrogateFunction &, FunctionWrapperIndex) {
00523 }
00524 
00525 ////////////////////////////////////////////////////////////////////
00526 //     Function: InterfaceMaker::record_object
00527 //       Access: Protected
00528 //  Description: Records the indicated type, which may be a struct
00529 //               type, along with all of its associated methods, if
00530 //               any.
00531 ////////////////////////////////////////////////////////////////////
00532 InterfaceMaker::Object *InterfaceMaker::
00533 record_object(TypeIndex type_index) {
00534   if (type_index == 0) {
00535     // An invalid type.
00536     return (Object *)NULL;
00537   }
00538 
00539   Objects::iterator oi = _objects.find(type_index);
00540   if (oi != _objects.end()) {
00541     // The object has previously been recorded.
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       // Downcasts are methods of the base class, not the child class.
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 //     Function: InterfaceMaker::manage_return_value
00616 //       Access: Protected
00617 //  Description: Does any additional processing that we might want to
00618 //               do on the return value for the function, just before
00619 //               we return it.  Returns the string representing the
00620 //               new return value after processing.
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     // If we're managing reference counts, and we're about to return a
00627     // reference countable object, then increment its count.
00628     if (return_expr == "return_value") {
00629       // If the expression is just a variable name, we can just ref it
00630       // directly.
00631       output_ref(out, indent_level, remap, return_expr);
00632       return return_expr;
00633 
00634     } else {
00635       // Otherwise, we should probably assign it to a temporary first,
00636       // so we don't invoke the function twice or something.
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   // Otherwise, just return the expression unchanged.
00655   return return_expr;
00656 }
00657 
00658 ////////////////////////////////////////////////////////////////////
00659 //     Function: InterfaceMaker::output_ref
00660 //       Access: Protected
00661 //  Description: Outputs the code to increment the reference count for
00662 //               the indicated variable name.
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     // In either of these cases, we can safely assume the pointer will
00670     // never be NULL.
00671     indent(out, indent_level)
00672       << varname << "->ref();\n";
00673 
00674   } else {
00675     // However, in the general case, we have to check for that before
00676     // we attempt to ref it.
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 //     Function: InterfaceMaker::hash_function_signature
00690 //       Access: Protected
00691 //  Description: Generates a unique string that corresponds to the
00692 //               function signature for the indicated FunctionRemap
00693 //               object, and stores the generated string in the _hash
00694 //               member of the FunctionRemap.
00695 ////////////////////////////////////////////////////////////////////
00696 void InterfaceMaker::
00697 hash_function_signature(FunctionRemap *remap) {
00698   string hash = InterrogateBuilder::hash_string(remap->_function_signature, 5);
00699 
00700   // Now make sure we don't have another function with the same hash.
00701   WrappersByHash::iterator hi;
00702   hi = _wrappers_by_hash.find(hash);
00703   if (hi == _wrappers_by_hash.end()) {
00704     // No other name; we're in the clear.
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     // The same function signature has already appeared.  This
00713     // shouldn't happen.
00714     nout << "Internal error!  Function signature "
00715          << remap->_function_signature << " repeated!\n";
00716     remap->_hash = hash;
00717     abort(); 
00718     return;
00719   }
00720 
00721   // We have a conflict.  Extend both strings to resolve the
00722   // ambiguity.
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     // Huh.  We still have a conflict.  This should be extremely rare.
00742     // Well, just tack on a letter until it's resolved.
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 //     Function: InterfaceMaker::write_spam_message
00760 //       Access: Protected
00761 //  Description: Generates a string to output a spammy message to
00762 //               notify indicating we have just called this function.
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 }

Generated on Thu May 1 22:13:01 2003 for DTool by doxygen1.3