Panda3D
|
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 }