Panda3D
dcparse.cxx
1 // Filename: dcparse.cxx
2 // Created by: drose (05Oct00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "dcbase.h"
16 #include "dcFile.h"
17 #include "dcClass.h"
18 #include "dcTypedef.h"
19 #include "memoryUsage.h"
20 #include "indent.h"
21 #include "panda_getopt.h"
22 
23 void
24 usage() {
25  cerr <<
26  "\n"
27  "Usage:\n\n"
28  "dcparse [options] [file1 file2 ...]\n"
29  "dcparse -h\n\n";
30 }
31 
32 void
33 help() {
34  usage();
35  cerr <<
36  "This program reads one or more DC files, which are used to describe the\n"
37  "communication channels in the distributed class system. By default,\n"
38  "the file(s) are read and concatenated, and a single hash code is printed\n"
39  "corresponding to the file's contents.\n\n"
40 
41  "Options:\n\n"
42 
43  " -v Writes a complete parseable version of the file to standard\n"
44  " output instead of printing a hash code.\n\n"
45 
46  " -b Writes a brief parseable version of the file instead of a full\n"
47  " version. This is semantically the same as the output produced\n"
48  " the above -v option--reading it would produce exactly the same\n"
49  " results--but it is designed to be slightly obfuscated. The\n"
50  " comments and parameter names are not included.\n\n"
51 
52  " -c Write a list of class names, showing the inheritance hierarchy.\n"
53  " Some class names will be listed twice in the presence of multiple\n"
54  " inheritance.\n\n"
55 
56  " -f Write a complete list of field names available for each class,\n"
57  " including all inherited fields.\n\n";
58 }
59 
60 void
61 write_class_hierarchy(int indent_level, const DCFile &file,
62  const DCClass *this_dclass) {
63  indent(cout, indent_level)
64  << this_dclass->get_name() << "\n";
65 
66  int num_classes = file.get_num_classes();
67  for (int i = 0; i < num_classes; ++i) {
68  const DCClass *dclass = file.get_class(i);
69  bool is_my_child = false;
70  int num_parents = dclass->get_num_parents();
71  for (int j = 0; j < num_parents && !is_my_child; ++j) {
72  is_my_child = (dclass->get_parent(j) == this_dclass);
73  }
74 
75  if (is_my_child) {
76  write_class_hierarchy(indent_level + 2, file, dclass);
77  }
78  }
79 }
80 
81 void
82 write_class_hierarchy(const DCFile &file) {
83  int num_classes = file.get_num_classes();
84  for (int i = 0; i < num_classes; ++i) {
85  const DCClass *dclass = file.get_class(i);
86  if (dclass->get_num_parents() == 0) {
87  write_class_hierarchy(0, file, dclass);
88  cout << "\n";
89  }
90  }
91 }
92 
93 void
94 write_complete_field_list(const DCFile &file) {
95  int num_classes = file.get_num_classes();
96  for (int i = 0; i < num_classes; ++i) {
97  const DCClass *dclass = file.get_class(i);
98  cout << "\n" << dclass->get_name() << "\n";
99  int num_inherited_fields = dclass->get_num_inherited_fields();
100  for (int j = 0; j < num_inherited_fields; ++j) {
101  const DCField *field = dclass->get_inherited_field(j);
102  cout << " ";
103  if (field->get_class() != dclass) {
104  cout << field->get_class()->get_name() << "::";
105  }
106  cout << field->get_name();
107  if (field->as_atomic_field() != (DCAtomicField *)NULL ||
108  field->as_molecular_field() != (DCMolecularField *)NULL) {
109  // It's a "method".
110  cout << "()";
111  }
112  field->output_keywords(cout);
113  cout << "\n";
114  }
115  }
116 }
117 
118 int
119 main(int argc, char *argv[]) {
120  // extern char *optarg;
121  extern int optind;
122  const char *optstr = "bvcfh";
123 
124  bool dump_verbose = false;
125  bool dump_brief = false;
126  bool dump_classes = false;
127  bool dump_fields = false;
128 
129  int flag = getopt(argc, argv, optstr);
130 
131  while (flag != EOF) {
132  switch (flag) {
133  case 'b':
134  dump_brief = true;
135  break;
136 
137  case 'v':
138  dump_verbose = true;
139  break;
140 
141  case 'c':
142  dump_classes = true;
143  break;
144 
145  case 'f':
146  dump_fields = true;
147  break;
148 
149  case 'h':
150  help();
151  exit(1);
152 
153  default:
154  exit(1);
155  }
156  flag = getopt(argc, argv, optstr);
157  }
158 
159  argc -= (optind-1);
160  argv += (optind-1);
161 
162  if (argc < 2) {
163  usage();
164  exit(1);
165  }
166 
167  DCFile file;
168  for (int i = 1; i < argc; i++) {
169  if (!file.read(argv[i])) {
170  return (1);
171  }
172  }
173 
174  if (!file.all_objects_valid() && !dump_brief) {
175  cerr << "File is incomplete. The following objects are undefined:\n";
176 
177  int num_typedefs = file.get_num_typedefs();
178  int i;
179  for (i = 0; i < num_typedefs; i++) {
180  DCTypedef *dtypedef = file.get_typedef(i);
181  if (dtypedef->is_bogus_typedef()) {
182  cerr << " " << dtypedef->get_name() << "\n";
183  }
184  }
185 
186  int num_classes = file.get_num_classes();
187  for (i = 0; i < num_classes; i++) {
188  DCClass *dclass = file.get_class(i);
189  if (dclass->is_bogus_class()) {
190  cerr << " " << dclass->get_name() << "\n";
191  }
192  }
193 
194  return 1;
195  }
196 
197  if (dump_verbose || dump_brief) {
198  if (!file.write(cout, dump_brief)) {
199  return 1;
200  }
201 
202  } else if (dump_classes) {
203  write_class_hierarchy(file);
204 
205  } else if (dump_fields) {
206  write_complete_field_list(file);
207 
208  } else {
209  unsigned long hash = file.get_hash();
210  cerr << "File hash is " << hash << " (signed " << (long)hash << ")\n";
211  }
212 
213 #ifdef DO_MEMORY_USAGE
214  if (MemoryUsage::is_tracking()) {
215  file.clear();
216  MemoryUsage::show_current_types();
217  for (int i = 1; i < argc; i++) {
218  file.read(argv[i]);
219  }
220  file.clear();
221  MemoryUsage::show_current_types();
222  }
223 #endif
224 
225  return 0;
226 }
This represents a single typedef declaration in the dc file.
Definition: dcTypedef.h:29
DCClass * get_class() const
Returns the DCClass pointer for the class that contains this field.
Definition: dcField.I:35
DCClass * get_parent(int n) const
Returns the nth parent class this class inherits from.
Definition: dcClass.cxx:154
A single field of a Distributed Class, either atomic or molecular.
Definition: dcField.h:40
const string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
virtual DCAtomicField * as_atomic_field()
Returns the same field pointer converted to an atomic field pointer, if this is in fact an atomic fie...
Definition: dcField.cxx:124
bool read(Filename filename)
Opens and reads the indicated .dc file by name.
Definition: dcFile.cxx:135
Defines a particular DistributedClass as read from an input .dc file.
Definition: dcClass.h:47
int get_num_typedefs() const
Returns the number of typedefs read from the .dc file(s).
Definition: dcFile.cxx:400
bool write(Filename filename, bool brief) const
Opens the indicated filename for output and writes a parseable description of all the known distribut...
Definition: dcFile.cxx:206
A single atomic field of a Distributed Class, as read from a .dc file.
Definition: dcAtomicField.h:34
virtual DCMolecularField * as_molecular_field()
Returns the same field pointer converted to a molecular field pointer, if this is in fact a molecular...
Definition: dcField.cxx:148
DCTypedef * get_typedef(int n) const
Returns the nth typedef read from the .dc file(s).
Definition: dcFile.cxx:410
bool all_objects_valid() const
Returns true if all of the classes read from the DC file were defined and valid, or false if any of t...
Definition: dcFile.I:25
Represents the complete list of Distributed Class descriptions as read from a .dc file...
Definition: dcFile.h:34
DCClass * get_class(int n) const
Returns the nth class read from the .dc file(s).
Definition: dcFile.cxx:281
DCField * get_inherited_field(int n) const
Returns the nth field field in the class and all of its ancestors.
Definition: dcClass.cxx:324
unsigned long get_hash() const
Returns a 32-bit hash index associated with this file.
Definition: dcFile.cxx:484
bool is_bogus_typedef() const
Returns true if the typedef has been flagged as a bogus typedef.
Definition: dcTypedef.cxx:106
const string & get_name() const
Returns the name of this typedef.
Definition: dcTypedef.cxx:79
int get_num_parents() const
Returns the number of base classes this class inherits from.
Definition: dcClass.cxx:143
int get_num_inherited_fields() const
Returns the total number of field fields defined in this class and all ancestor classes.
Definition: dcClass.cxx:286
void clear()
Removes all of the classes defined within the DCFile and prepares it for reading a new file...
Definition: dcFile.cxx:63
int get_num_classes() const
Returns the number of classes read from the .dc file(s).
Definition: dcFile.cxx:271
A single molecular field of a Distributed Class, as read from a .dc file.
const string & get_name() const
Returns the name of this class.
Definition: dcClass.I:32
bool is_bogus_class() const
Returns true if the class has been flagged as a bogus class.
Definition: dcClass.I:70