/** * PANDA 3D SOFTWARE * Copyright (c) Carnegie Mellon University. All rights reserved. * * All use of this software is subject to the terms of the revised BSD * license. You should have received a copy of this license along * with this source code in a file named "LICENSE." * * @file dcparse.cxx * @author drose * @date 2000-10-05 */ #include "dcbase.h" #include "dcFile.h" #include "dcClass.h" #include "dcTypedef.h" #include "memoryUsage.h" #include "indent.h" #include "panda_getopt.h" void usage() { cerr << "\n" "Usage:\n\n" "dcparse [options] [file1 file2 ...]\n" "dcparse -h\n\n"; } void help() { usage(); cerr << "This program reads one or more DC files, which are used to describe the\n" "communication channels in the distributed class system. By default,\n" "the file(s) are read and concatenated, and a single hash code is printed\n" "corresponding to the file's contents.\n\n" "Options:\n\n" " -v Writes a complete parseable version of the file to standard\n" " output instead of printing a hash code.\n\n" " -b Writes a brief parseable version of the file instead of a full\n" " version. This is semantically the same as the output produced\n" " the above -v option--reading it would produce exactly the same\n" " results--but it is designed to be slightly obfuscated. The\n" " comments and parameter names are not included.\n\n" " -c Write a list of class names, showing the inheritance hierarchy.\n" " Some class names will be listed twice in the presence of multiple\n" " inheritance.\n\n" " -f Write a complete list of field names available for each class,\n" " including all inherited fields.\n\n"; } void write_class_hierarchy(int indent_level, const DCFile &file, const DCClass *this_dclass) { indent(cout, indent_level) << this_dclass->get_name() << "\n"; int num_classes = file.get_num_classes(); for (int i = 0; i < num_classes; ++i) { const DCClass *dclass = file.get_class(i); bool is_my_child = false; int num_parents = dclass->get_num_parents(); for (int j = 0; j < num_parents && !is_my_child; ++j) { is_my_child = (dclass->get_parent(j) == this_dclass); } if (is_my_child) { write_class_hierarchy(indent_level + 2, file, dclass); } } } void write_class_hierarchy(const DCFile &file) { int num_classes = file.get_num_classes(); for (int i = 0; i < num_classes; ++i) { const DCClass *dclass = file.get_class(i); if (dclass->get_num_parents() == 0) { write_class_hierarchy(0, file, dclass); cout << "\n"; } } } void write_complete_field_list(const DCFile &file) { int num_classes = file.get_num_classes(); for (int i = 0; i < num_classes; ++i) { const DCClass *dclass = file.get_class(i); cout << "\n" << dclass->get_name() << "\n"; int num_inherited_fields = dclass->get_num_inherited_fields(); for (int j = 0; j < num_inherited_fields; ++j) { const DCField *field = dclass->get_inherited_field(j); cout << " "; if (field->get_class() != dclass) { cout << field->get_class()->get_name() << "::"; } cout << field->get_name(); if (field->as_atomic_field() != (DCAtomicField *)NULL || field->as_molecular_field() != (DCMolecularField *)NULL) { // It's a "method". cout << "()"; } field->output_keywords(cout); cout << "\n"; } } } int main(int argc, char *argv[]) { // extern char *optarg; extern int optind; const char *optstr = "bvcfh"; bool dump_verbose = false; bool dump_brief = false; bool dump_classes = false; bool dump_fields = false; int flag = getopt(argc, argv, optstr); while (flag != EOF) { switch (flag) { case 'b': dump_brief = true; break; case 'v': dump_verbose = true; break; case 'c': dump_classes = true; break; case 'f': dump_fields = true; break; case 'h': help(); exit(1); default: exit(1); } flag = getopt(argc, argv, optstr); } argc -= (optind-1); argv += (optind-1); if (argc < 2) { usage(); exit(1); } DCFile file; for (int i = 1; i < argc; i++) { if (!file.read(argv[i])) { return (1); } } if (!file.all_objects_valid() && !dump_brief) { cerr << "File is incomplete. The following objects are undefined:\n"; int num_typedefs = file.get_num_typedefs(); int i; for (i = 0; i < num_typedefs; i++) { DCTypedef *dtypedef = file.get_typedef(i); if (dtypedef->is_bogus_typedef()) { cerr << " " << dtypedef->get_name() << "\n"; } } int num_classes = file.get_num_classes(); for (i = 0; i < num_classes; i++) { DCClass *dclass = file.get_class(i); if (dclass->is_bogus_class()) { cerr << " " << dclass->get_name() << "\n"; } } return 1; } if (dump_verbose || dump_brief) { if (!file.write(cout, dump_brief)) { return 1; } } else if (dump_classes) { write_class_hierarchy(file); } else if (dump_fields) { write_complete_field_list(file); } else { unsigned long hash = file.get_hash(); cerr << "File hash is " << hash << " (signed " << (long)hash << ")\n"; } #ifdef DO_MEMORY_USAGE if (MemoryUsage::is_tracking()) { file.clear(); MemoryUsage::show_current_types(); for (int i = 1; i < argc; i++) { file.read(argv[i]); } file.clear(); MemoryUsage::show_current_types(); } #endif return 0; }