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