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

dtool/src/test_interrogate/test_interrogate.cxx

Go to the documentation of this file.
00001 // Filename: test_interrogate.cxx
00002 // Created by:  drose (09Dec99)
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 <dtoolbase.h>
00020 
00021 #include <interrogate_interface.h>
00022 #include <interrogate_request.h>
00023 #include <load_dso.h>
00024 #include <filename.h>
00025 #include <pystub.h>
00026 
00027 #include <stdlib.h>
00028 
00029 #ifndef HAVE_GETOPT
00030 #include <gnu_getopt.h>
00031 #else
00032 #include <getopt.h>
00033 #endif
00034 
00035 
00036 
00037 static ostream &
00038 indent(ostream &out, int indent_level) {
00039   for (int i = 0; i < indent_level; i++) {
00040     out << ' ';
00041   }
00042   return out;
00043 }
00044 
00045 void
00046 show_type(int type, bool verbose = false) {
00047   cout << interrogate_type_name(type) << " ";
00048   if (verbose) {
00049     if (strcmp(interrogate_type_name(type),
00050                interrogate_type_true_name(type)) != 0) {
00051       cout << "(" << interrogate_type_true_name(type) << ") ";
00052     }
00053   }
00054   cout << "(" << type << ")";
00055 }
00056 
00057 void
00058 show_function(int function) {
00059   cout << interrogate_function_scoped_name(function) << " (" << function << ")";
00060 }
00061 
00062 void
00063 describe_wrapper(int wrapper, int indent_level) {
00064   indent(cout, indent_level)
00065     << "Wrapper (" << wrapper << ")";
00066 
00067   if (interrogate_wrapper_has_return_value(wrapper)) {
00068     cout << " returns ";
00069     show_type(interrogate_wrapper_return_type(wrapper));
00070   } else {
00071     cout << " no return value";
00072   }
00073 
00074   int num_params = interrogate_wrapper_number_of_parameters(wrapper);
00075   cout << ", ";
00076   if (num_params == 0) {
00077     cout << "no parameters.\n";
00078   } else if (num_params == 1) {
00079     cout << "1 parameter:\n";
00080   } else {
00081     cout << num_params << " parameters:\n";
00082   }
00083 
00084   for (int i = 0; i < num_params; i++) {
00085     indent(cout, indent_level + 4);
00086     if (interrogate_wrapper_parameter_is_this(wrapper, i)) {
00087       cout << "*";
00088     } else {
00089       cout << i;
00090     }
00091     cout << ": ";
00092     show_type(interrogate_wrapper_parameter_type(wrapper, i));
00093     if (interrogate_wrapper_parameter_has_name(wrapper, i)) {
00094       cout << " '" << interrogate_wrapper_parameter_name(wrapper, i) << "'";
00095     } else {
00096       cout << " (no name)";
00097     }
00098     cout << "\n";
00099   }
00100 
00101 
00102   if (interrogate_wrapper_caller_manages_return_value(wrapper)) {
00103     indent(cout, indent_level + 2)
00104       << "Caller manages return value using ";
00105     show_function(interrogate_wrapper_return_value_destructor(wrapper));
00106     cout << "\n";
00107   }
00108 
00109   indent(cout, indent_level + 2)
00110     << "Wrapper name: " << interrogate_wrapper_name(wrapper);
00111   if (interrogate_wrapper_is_callable_by_name(wrapper)) {
00112     cout << " (callable)";
00113   }
00114   cout << "\n";
00115   if (interrogate_wrapper_has_pointer(wrapper)) {
00116     indent(cout, indent_level + 2)
00117       << "Has pointer: " << interrogate_wrapper_pointer(wrapper) << "\n";
00118   }
00119   string unique_name = interrogate_wrapper_unique_name(wrapper);
00120   indent(cout, indent_level + 2)
00121     << "Unique name is " << unique_name;
00122   int reverse_lookup = interrogate_get_wrapper_by_unique_name(unique_name.c_str());
00123   if (reverse_lookup == 0) {
00124     cout << " (no reverse lookup)";
00125   } else if (reverse_lookup != wrapper) {
00126     cout << " (*** reverse lookup returns " << reverse_lookup << "! ***)";
00127   }
00128   cout << "\n";
00129 }
00130 
00131 void
00132 describe_function(int function, int indent_level) {
00133   indent(cout, indent_level)
00134     << "Function " << interrogate_function_scoped_name(function)
00135     << " (" << function << ")\n";
00136 
00137   indent(cout, indent_level + 2)
00138     << "In C: " << interrogate_function_prototype(function) << "\n";
00139 
00140   if (interrogate_function_is_method(function)) {
00141     indent(cout, indent_level + 2)
00142       << "Method of ";
00143     show_type(interrogate_function_class(function));
00144     cout << "\n";
00145   }
00146 
00147   if (interrogate_function_is_virtual(function)) {
00148     indent(cout, indent_level + 2) << "is virtual.\n";
00149   }
00150 
00151   int w;
00152 
00153   int num_c_wrappers = interrogate_function_number_of_c_wrappers(function);
00154   if (num_c_wrappers == 0) {
00155   } else if (num_c_wrappers == 1) {
00156     indent(cout, indent_level + 2)
00157       << "1 C-style wrapper:\n";
00158   } else {
00159     indent(cout, indent_level + 2)
00160       << num_c_wrappers << " C-style wrappers:\n";
00161   }
00162   for (w = 0; w < num_c_wrappers; w++) {
00163     describe_wrapper(interrogate_function_c_wrapper(function, w),
00164                      indent_level + 4);
00165   }
00166 
00167   int num_python_wrappers =
00168     interrogate_function_number_of_python_wrappers(function);
00169   if (num_python_wrappers == 0) {
00170   } else if (num_python_wrappers == 1) {
00171     indent(cout, indent_level + 2)
00172       << "1 Python-style wrapper:\n";
00173   } else {
00174     indent(cout, indent_level + 2)
00175       << num_python_wrappers << " Python-style wrappers:\n";
00176   }
00177   for (w = 0; w < num_python_wrappers; w++) {
00178     describe_wrapper(interrogate_function_python_wrapper(function, w),
00179                      indent_level + 4);
00180   }
00181 
00182 }
00183 
00184 void
00185 report_manifests() {
00186   int num_manifests = interrogate_number_of_manifests();
00187   cout << "\n" << num_manifests << " manifests:\n";
00188   for (int i = 0; i < num_manifests; i++) {
00189     int manifest = interrogate_get_manifest(i);
00190 
00191     cout << "  Manifest " << interrogate_manifest_name(manifest);
00192     if (interrogate_manifest_has_type(manifest)) {
00193       cout << " of type ";
00194       show_type(interrogate_manifest_get_type(manifest));
00195       cout << "\n";
00196     } else {
00197       cout << " of unknown type\n";
00198     }
00199     cout << "    definition is \""
00200          << interrogate_manifest_definition(manifest) << "\"\n";
00201 
00202     if (interrogate_manifest_has_getter(manifest)) {
00203       cout << "    value getter: ";
00204       show_function(interrogate_manifest_getter(manifest));
00205       cout << "\n";
00206     }
00207 
00208     if (interrogate_manifest_has_int_value(manifest)) {
00209       cout << "    int value = "
00210            << interrogate_manifest_get_int_value(manifest)
00211            << "\n";
00212     }
00213   }
00214 }
00215 
00216 void
00217 describe_element(int element, int indent_level) {
00218   indent(cout, indent_level)
00219     << "Element " << interrogate_element_scoped_name(element)
00220     << " of type ";
00221   show_type(interrogate_element_type(element));
00222   cout << "\n";
00223 
00224   if (interrogate_element_has_getter(element)) {
00225     indent(cout, indent_level + 2)
00226       << "Getter is ";
00227     show_function(interrogate_element_getter(element));
00228     cout << "\n";
00229   }
00230 
00231   if (interrogate_element_has_setter(element)) {
00232     indent(cout, indent_level + 2)
00233       << "Setter is ";
00234     show_function(interrogate_element_setter(element));
00235     cout << "\n";
00236   }
00237 }
00238 
00239 void
00240 report_globals() {
00241   int num_globals = interrogate_number_of_globals();
00242   cout << "\n" << num_globals << " globals:\n";
00243   for (int i = 0; i < num_globals; i++) {
00244     describe_element(interrogate_get_global(i), 2);
00245   }
00246 }
00247 
00248 void
00249 describe_type(int type, int indent_level) {
00250   indent(cout, indent_level) << "Type ";
00251   show_type(type, true);
00252   cout << "\n";
00253   if (interrogate_type_is_nested(type)) {
00254     indent(cout, indent_level + 2)
00255       << "Nested within ";
00256     show_type(interrogate_type_outer_class(type));
00257     cout << "\n";
00258   }
00259   if (interrogate_type_is_atomic(type)) {
00260     indent(cout, indent_level + 2)
00261       << "atomic " << (int)interrogate_type_atomic_token(type) << "\n";
00262   }
00263   if (interrogate_type_is_unsigned(type)) {
00264     indent(cout, indent_level + 2)
00265       << "unsigned\n";
00266   }
00267   if (interrogate_type_is_signed(type)) {
00268     indent(cout, indent_level + 2)
00269       << "signed\n";
00270   }
00271   if (interrogate_type_is_long(type)) {
00272     indent(cout, indent_level + 2)
00273       << "long\n";
00274   }
00275   if (interrogate_type_is_longlong(type)) {
00276     indent(cout, indent_level + 2)
00277       << "long long\n";
00278   }
00279   if (interrogate_type_is_short(type)) {
00280     indent(cout, indent_level + 2)
00281       << "short\n";
00282   }
00283   if (interrogate_type_is_wrapped(type)) {
00284     indent(cout, indent_level + 2)
00285       << "wrapped ";
00286     show_type(interrogate_type_wrapped_type(type));
00287     cout << "\n";
00288   }
00289   if (interrogate_type_is_pointer(type)) {
00290     indent(cout, indent_level + 2)
00291       << "pointer\n";
00292   }
00293   if (interrogate_type_is_const(type)) {
00294     indent(cout, indent_level + 2)
00295       << "const\n";
00296   }
00297   if (interrogate_type_is_fully_defined(type)) {
00298     indent(cout, indent_level + 2)
00299       << "fully defined\n";
00300   }
00301   if (interrogate_type_is_unpublished(type)) {
00302     indent(cout, indent_level + 2)
00303       << "undefined because unpublished\n";
00304   }
00305   if (interrogate_type_is_enum(type)) {
00306     indent(cout, indent_level + 2)
00307       << "is enum type\n";
00308   }
00309   if (interrogate_type_is_struct(type)) {
00310     indent(cout, indent_level + 2)
00311       << "is struct type\n";
00312   }
00313   if (interrogate_type_is_class(type)) {
00314     indent(cout, indent_level + 2)
00315       << "is class type\n";
00316   }
00317   if (interrogate_type_is_union(type)) {
00318     indent(cout, indent_level + 2)
00319       << "is union type\n";
00320   }
00321   int num_enum_values = interrogate_type_number_of_enum_values(type);
00322   if (num_enum_values > 0) {
00323     for (int i = 0; i < num_enum_values; i++) {
00324       indent(cout, indent_level + 4)
00325         << interrogate_type_enum_value_name(type, i)
00326         << " = " << interrogate_type_enum_value(type, i) << "\n";
00327     }
00328   }
00329   int num_constructors = interrogate_type_number_of_constructors(type);
00330   if (num_constructors > 0) {
00331     indent(cout, indent_level + 2)
00332       << num_constructors << " constructors:\n";
00333     for (int i = 0; i < num_constructors; i++) {
00334       describe_function(interrogate_type_get_constructor(type, i), 6);
00335     }
00336   }
00337   if (interrogate_type_has_destructor(type)) {
00338     indent(cout, indent_level + 2)
00339       << "destructor:\n";
00340     describe_function(interrogate_type_get_destructor(type), 6);
00341   }
00342   int num_casts = interrogate_type_number_of_casts(type);
00343   if (num_casts > 0) {
00344     indent(cout, indent_level + 2)
00345       << num_casts << " casts:\n";
00346     for (int i = 0; i < num_casts; i++) {
00347       describe_function(interrogate_type_get_cast(type, i), 6);
00348     }
00349   }
00350   int num_methods = interrogate_type_number_of_methods(type);
00351   if (num_methods > 0) {
00352     indent(cout, indent_level + 2)
00353       << num_methods << " methods:\n";
00354     for (int i = 0; i < num_methods; i++) {
00355       describe_function(interrogate_type_get_method(type, i), 6);
00356     }
00357   }
00358   int num_elements = interrogate_type_number_of_elements(type);
00359   if (num_elements > 0) {
00360     indent(cout, indent_level + 2)
00361       << num_elements << " elements:\n";
00362     for (int i = 0; i < num_elements; i++) {
00363       describe_element(interrogate_type_get_element(type, i), indent_level + 2);
00364     }
00365   }
00366   int num_derivations = interrogate_type_number_of_derivations(type);
00367   if (num_derivations > 0) {
00368     indent(cout, indent_level + 2)
00369       << num_derivations << " derivations:\n";
00370     for (int i = 0; i < num_derivations; i++) {
00371       int derivation = interrogate_type_get_derivation(type, i);
00372       indent(cout, indent_level + 4);
00373       show_type(derivation);
00374       if (interrogate_type_derivation_has_upcast(type, i)) {
00375         cout << " (has upcast)";
00376       }
00377       if (interrogate_type_derivation_downcast_is_impossible(type, i)) {
00378         cout << " (downcast is impossible)";
00379       }
00380       if (interrogate_type_derivation_has_downcast(type, i)) {
00381         cout << " (has downcast)";
00382       }
00383       cout << "\n";
00384       /*
00385         if (interrogate_type_derivation_has_upcast(type, i)) {
00386         describe_function(interrogate_type_get_upcast(type, i), 8);
00387         }
00388         if (interrogate_type_derivation_has_downcast(type, i)) {
00389         describe_function(interrogate_type_get_downcast(type, i), 8);
00390         }
00391       */
00392     }
00393   }
00394   int num_nested_types = interrogate_type_number_of_nested_types(type);
00395   if (num_nested_types > 0) {
00396     indent(cout, indent_level + 2)
00397       << num_nested_types << " nested types:\n";
00398     for (int i = 0; i < num_nested_types; i++) {
00399       indent(cout, indent_level + 4);
00400       show_type(interrogate_type_get_nested_type(type, i));
00401       cout << "\n";
00402     }
00403   }
00404 }
00405 
00406 void
00407 report_global_types() {
00408   int num_types = interrogate_number_of_global_types();
00409   cout << "\n" << num_types << " global types:\n";
00410 
00411   for (int i = 0; i < num_types; i++) {
00412     int type = interrogate_get_global_type(i);
00413     describe_type(type, 2);
00414   }
00415 }
00416 
00417 void
00418 report_global_functions() {
00419   int num_functions = interrogate_number_of_global_functions();
00420   cout << "\n" << num_functions << " global functions:\n";
00421   for (int i = 0; i < num_functions; i++) {
00422     int function = interrogate_get_global_function(i);
00423     describe_function(function, 2);
00424   }
00425 }
00426 
00427 void
00428 report_all_types() {
00429   int num_types = interrogate_number_of_types();
00430   cout << "\n" << num_types << " total types:\n";
00431 
00432   for (int i = 0; i < num_types; i++) {
00433     int type = interrogate_get_type(i);
00434     describe_type(type, 2);
00435   }
00436 }
00437 
00438 void
00439 report_all_functions() {
00440   int num_functions = interrogate_number_of_functions();
00441   cout << "\n" << num_functions << " total functions:\n";
00442   for (int i = 0; i < num_functions; i++) {
00443     int function = interrogate_get_function(i);
00444     describe_function(function, 2);
00445   }
00446 }
00447 
00448 void
00449 usage() {
00450   cerr <<
00451     "\n"
00452     "test_interrogate [opts] libfile.so [libfile.so ...]\n\n"
00453 
00454     "Loads the given shared library or libraries, if possible, and reports the\n"
00455     "symbols, types, and functions available within those libraries as reported\n"
00456     "by interrogate.\n\n"
00457 
00458     "In lieu of loading a shared library, you may also read the interrogate\n"
00459     "database file directly by specifying a filename like libfile.in.  This will\n"
00460     "report the symbols defined in that file only (without pulling in dependent\n"
00461     "files), and will not have any function pointers available.\n\n"
00462 
00463     "Options:\n\n"
00464     "  -f  Give a detailed report of each function in the database, including\n"
00465     "      synthesized functions like upcasts and downcasts.\n"
00466     "  -t  Give a detailed report of every type in the database, including types\n"
00467     "      like pointers and const pointers.\n"
00468     "  -q  Quickly load up each shared library, if possible, and then immediately\n"
00469     "      exit.  Useful for quickly determining whether a library can even load.\n\n";
00470 }
00471 
00472 int
00473 main(int argc, char *argv[]) {
00474   //  extern char *optarg;
00475   extern int optind;
00476   const char *optstr = "ftqh";
00477 
00478   bool all_functions = false;
00479   bool all_types = false;
00480   bool quick_load = false;
00481   int flag = getopt(argc, argv, optstr);
00482 
00483   while (flag != EOF) {
00484     switch (flag) {
00485     case 'f':
00486       all_functions = true;
00487       break;
00488 
00489     case 't':
00490       all_types = true;
00491       break;
00492 
00493     case 'q':
00494       quick_load = true;
00495       break;
00496 
00497     case 'h':
00498       usage();
00499       exit(0);
00500 
00501     default:
00502       exit(1);
00503     }
00504     flag = getopt(argc, argv, optstr);
00505   }
00506 
00507   argc -= (optind-1);
00508   argv += (optind-1);
00509 
00510   if (argc < 2) {
00511     cerr << "No libraries specified.\n";
00512     exit(1);
00513   }
00514 
00515   int return_status = 0;
00516 
00517   for (int i = 1; i < argc; i++) {
00518     string param = argv[i];
00519 
00520     if (param.length() > 3 && param.substr(param.length() - 3) == ".in") {
00521       // If the filename ends in ".in", it's an interrogate database
00522       // file, not a shared library--read it directly.
00523       interrogate_request_database(param.c_str());
00524 
00525     } else {
00526       // Otherwise, assume it's a shared library, and try to load it.
00527       Filename pathname = Filename::dso_filename(argv[i]);
00528       cerr << "Loading " << pathname << "\n";
00529       void *dl = load_dso(pathname);
00530       if (dl == NULL) {
00531         cerr << "Unable to load: " << load_dso_error() << "\n";
00532         return_status++;
00533       }
00534     }
00535   }
00536 
00537   if (!quick_load) {
00538     if (all_types) {
00539       report_all_types();
00540     }
00541     if (all_functions) {
00542       report_all_functions();
00543     }
00544 
00545     if (!all_types && !all_functions) {
00546       report_manifests();
00547       report_globals();
00548       report_global_types();
00549       report_global_functions();
00550     }
00551   }
00552 
00553   return (return_status);
00554 }

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