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