00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00110 cout << "()";
00111 }
00112 field->output_keywords(cout);
00113 cout << "\n";
00114 }
00115 }
00116 }
00117
00118 int
00119 main(int argc, char *argv[]) {
00120
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 }