Panda3D

dcparse.cxx

00001 // Filename: dcparse.cxx
00002 // Created by:  drose (05Oct00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "dcbase.h"
00016 #include "dcFile.h"
00017 #include "dcClass.h"
00018 #include "dcTypedef.h"
00019 #include "memoryUsage.h"
00020 #include "indent.h"
00021 #include "panda_getopt.h"
00022 
00023 void
00024 usage() {
00025   cerr << 
00026     "\n"
00027     "Usage:\n\n"
00028     "dcparse [options]  [file1 file2 ...]\n"
00029     "dcparse -h\n\n";
00030 }
00031 
00032 void
00033 help() {
00034   usage();
00035   cerr << 
00036     "This program reads one or more DC files, which are used to describe the\n"
00037     "communication channels in the distributed class system.  By default,\n"
00038     "the file(s) are read and concatenated, and a single hash code is printed\n"
00039     "corresponding to the file's contents.\n\n"
00040 
00041     "Options:\n\n"
00042 
00043     "  -v Writes a complete parseable version of the file to standard\n"
00044     "     output instead of printing a hash code.\n\n"
00045 
00046     "  -b Writes a brief parseable version of the file instead of a full\n"
00047     "     version.  This is semantically the same as the output produced\n"
00048     "     the above -v option--reading it would produce exactly the same\n"
00049     "     results--but it is designed to be slightly obfuscated.  The\n"
00050     "     comments and parameter names are not included.\n\n"
00051 
00052     "  -c Write a list of class names, showing the inheritance hierarchy.\n"
00053     "     Some class names will be listed twice in the presence of multiple\n"
00054     "     inheritance.\n\n"
00055 
00056     "  -f Write a complete list of field names available for each class,\n"
00057     "     including all inherited fields.\n\n";
00058 }
00059 
00060 void
00061 write_class_hierarchy(int indent_level, const DCFile &file, 
00062                       const DCClass *this_dclass) {
00063   indent(cout, indent_level)
00064     << this_dclass->get_name() << "\n";
00065 
00066   int num_classes = file.get_num_classes();
00067   for (int i = 0; i < num_classes; ++i) {
00068     const DCClass *dclass = file.get_class(i);
00069     bool is_my_child = false;
00070     int num_parents = dclass->get_num_parents();
00071     for (int j = 0; j < num_parents && !is_my_child; ++j) {
00072       is_my_child = (dclass->get_parent(j) == this_dclass);
00073     }
00074 
00075     if (is_my_child) {
00076       write_class_hierarchy(indent_level + 2, file, dclass);
00077     }
00078   }
00079 }
00080 
00081 void
00082 write_class_hierarchy(const DCFile &file) {
00083   int num_classes = file.get_num_classes();
00084   for (int i = 0; i < num_classes; ++i) {
00085     const DCClass *dclass = file.get_class(i);
00086     if (dclass->get_num_parents() == 0) {
00087       write_class_hierarchy(0, file, dclass);
00088       cout << "\n";
00089     }
00090   }
00091 }
00092 
00093 void
00094 write_complete_field_list(const DCFile &file) {
00095   int num_classes = file.get_num_classes();
00096   for (int i = 0; i < num_classes; ++i) {
00097     const DCClass *dclass = file.get_class(i);
00098     cout << "\n" << dclass->get_name() << "\n";
00099     int num_inherited_fields = dclass->get_num_inherited_fields();
00100     for (int j = 0; j < num_inherited_fields; ++j) {
00101       const DCField *field = dclass->get_inherited_field(j);
00102       cout << "  ";
00103       if (field->get_class() != dclass) {
00104         cout << field->get_class()->get_name() << "::";
00105       }
00106       cout << field->get_name();
00107       if (field->as_atomic_field() != (DCAtomicField *)NULL ||
00108           field->as_molecular_field() != (DCMolecularField *)NULL) {
00109         // It's a "method".
00110         cout << "()";
00111       }
00112       field->output_keywords(cout);
00113       cout << "\n";
00114     }
00115   }
00116 }
00117 
00118 int
00119 main(int argc, char *argv[]) {
00120   //  extern char *optarg;
00121   extern int optind;
00122   const char *optstr = "bvcfh";
00123 
00124   bool dump_verbose = false;
00125   bool dump_brief = false;
00126   bool dump_classes = false;
00127   bool dump_fields = false;
00128 
00129   int flag = getopt(argc, argv, optstr);
00130 
00131   while (flag != EOF) {
00132     switch (flag) {
00133     case 'b':
00134       dump_brief = true;
00135       break;
00136 
00137     case 'v':
00138       dump_verbose = true;
00139       break;
00140 
00141     case 'c':
00142       dump_classes = true;
00143       break;
00144 
00145     case 'f':
00146       dump_fields = true;
00147       break;
00148 
00149     case 'h':
00150       help();
00151       exit(1);
00152 
00153     default:
00154       exit(1);
00155     }
00156     flag = getopt(argc, argv, optstr);
00157   }
00158 
00159   argc -= (optind-1);
00160   argv += (optind-1);
00161 
00162   if (argc < 2) {
00163     usage();
00164     exit(1);
00165   }
00166 
00167   DCFile file;
00168   for (int i = 1; i < argc; i++) {
00169     if (!file.read(argv[i])) {
00170       return (1);
00171     }
00172   }
00173 
00174   if (!file.all_objects_valid() && !dump_brief) {
00175     cerr << "File is incomplete.  The following objects are undefined:\n";
00176 
00177     int num_typedefs = file.get_num_typedefs();
00178     int i;
00179     for (i = 0; i < num_typedefs; i++) {
00180       DCTypedef *dtypedef = file.get_typedef(i);
00181       if (dtypedef->is_bogus_typedef()) {
00182         cerr << "  " << dtypedef->get_name() << "\n";
00183       }
00184     }
00185 
00186     int num_classes = file.get_num_classes();
00187     for (i = 0; i < num_classes; i++) {
00188       DCClass *dclass = file.get_class(i);
00189       if (dclass->is_bogus_class()) {
00190         cerr << "  " << dclass->get_name() << "\n";
00191       }
00192     }
00193 
00194     return 1;
00195   }
00196 
00197   if (dump_verbose || dump_brief) {
00198     if (!file.write(cout, dump_brief)) {
00199       return 1;
00200     }
00201 
00202   } else if (dump_classes) {
00203     write_class_hierarchy(file);
00204 
00205   } else if (dump_fields) {
00206     write_complete_field_list(file);
00207 
00208   } else {
00209     unsigned long hash = file.get_hash();
00210     cerr << "File hash is " << hash << " (signed " << (long)hash << ")\n";
00211   }
00212 
00213 #ifdef DO_MEMORY_USAGE
00214   if (MemoryUsage::is_tracking()) {
00215     file.clear();
00216     MemoryUsage::show_current_types();
00217     for (int i = 1; i < argc; i++) {
00218       file.read(argv[i]);
00219     }
00220     file.clear();
00221     MemoryUsage::show_current_types();
00222   }
00223 #endif
00224 
00225   return 0;
00226 }
 All Classes Functions Variables Enumerations