1 | #!/usr/bin/perl
|
---|
2 | # Use -*-perl-*- mode in emacs.
|
---|
3 |
|
---|
4 | @files = ();
|
---|
5 |
|
---|
6 | $clssection = "section";
|
---|
7 | $clssubsection = "subsection";
|
---|
8 |
|
---|
9 | #for $i (@ARGV) {
|
---|
10 | while ($i = shift) {
|
---|
11 | if ($i eq '-clssection') {
|
---|
12 | $clssection = shift;
|
---|
13 | }
|
---|
14 | elsif ($i eq '-clssubsection') {
|
---|
15 | $clssubsection = shift;
|
---|
16 | }
|
---|
17 | else {
|
---|
18 | @files = (@files, $i);
|
---|
19 | }
|
---|
20 | }
|
---|
21 | @ARGV = @files;
|
---|
22 |
|
---|
23 | $printmember = 0;
|
---|
24 | $printmembercase = 0;
|
---|
25 | $template_param = '';
|
---|
26 | $class = '';
|
---|
27 | $classdoc = '';
|
---|
28 | %item = ();
|
---|
29 | %sectionname = (pri, "Private", pro, "Protected", pub, "Public");
|
---|
30 | @sectionorder = (pub, pro, pri);
|
---|
31 | while(<>) {
|
---|
32 |
|
---|
33 | while(/^\s*\/\//) {
|
---|
34 | if (/^\s*\/\/\.\s+(.*)/) {
|
---|
35 | do get_doc($1);
|
---|
36 | }
|
---|
37 | elsif (/^\s*\/\/\.\s*$/) {
|
---|
38 | do get_doc('');
|
---|
39 | }
|
---|
40 | else {
|
---|
41 | last;
|
---|
42 | }
|
---|
43 | }
|
---|
44 |
|
---|
45 | if (/^\s*class\s+([a-zA-Z_][a-zA-Z0-9_]*)/) {
|
---|
46 | do new_class($1,'','');
|
---|
47 | }
|
---|
48 | elsif (/^\s*template <(.*)>\s*class\s+([a-zA-Z_][a-zA-Z0-9_]*)/) {
|
---|
49 | do new_class($2,$1,'');
|
---|
50 | }
|
---|
51 | elsif (/^\s*template <(.*)>\s*$/) {
|
---|
52 | $tmp_template_param = $1;
|
---|
53 | while (<>) { last; }
|
---|
54 | if (/^\s*class\s+([a-zA-Z_][a-zA-Z0-9_]*)/) {
|
---|
55 | do new_class($1,$tmp_template_param,'');
|
---|
56 | }
|
---|
57 | }
|
---|
58 | elsif (/^\s*private\s*:/) {
|
---|
59 | $interface = 'pri';
|
---|
60 | }
|
---|
61 | elsif (/^\s*public\s*:/) {
|
---|
62 | $interface = 'pub';
|
---|
63 | }
|
---|
64 | elsif (/^\s*protected\s*:/) {
|
---|
65 | $interface = 'pro';
|
---|
66 | }
|
---|
67 | }
|
---|
68 |
|
---|
69 | do write_doc();
|
---|
70 |
|
---|
71 | sub new_class {
|
---|
72 | # flush out the documentation for the previous class
|
---|
73 | do write_doc();
|
---|
74 | $class = $_[0];
|
---|
75 | $template_param = $_[1];
|
---|
76 | $classdoc = $_[2];
|
---|
77 | $interface = 'pri';
|
---|
78 | $private = '';
|
---|
79 | $protected = '';
|
---|
80 | $public = '';
|
---|
81 | }
|
---|
82 |
|
---|
83 | sub write_doc {
|
---|
84 | local($nsection) = keys(%item);
|
---|
85 | if ($classdoc ne ''
|
---|
86 | || $item{'pri'} ne ''
|
---|
87 | || $item{'pro'} ne ''
|
---|
88 | || $item{'pub'} ne '') {
|
---|
89 | $template_param =~ s/_/\\_/g;
|
---|
90 | if (!open(OUTPUT, ">doc/$class.cls.tex")) {
|
---|
91 | die "Can't open doc/$class.cls.tex: $!";
|
---|
92 | }
|
---|
93 | print "writing $class.cls.tex\n";
|
---|
94 | if ($template_param eq '') {
|
---|
95 | print OUTPUT "\\$clssection\{The \\clsnm{$class} Class}";
|
---|
96 | print OUTPUT "\\label{$class}\\index{$class}\n";
|
---|
97 | #print OUTPUT "\\clssection{$class}\n";
|
---|
98 | }
|
---|
99 | else {
|
---|
100 | print OUTPUT "\\$clssection\{The \\clsnm{$class";
|
---|
101 | print OUTPUT "\$<\$$template_param\$>\$} Class Template}";
|
---|
102 | print OUTPUT "\\label{$class}\\index{$class}\n";
|
---|
103 | #print OUTPUT "\\tclssection{$class}{$template_param}\n";
|
---|
104 | }
|
---|
105 | print OUTPUT "\\index{$class}\n";
|
---|
106 | if ($classdoc ne '') {
|
---|
107 | print OUTPUT "$classdoc\n";
|
---|
108 | }
|
---|
109 | for (@sectionorder) {
|
---|
110 | if ($item{$_} ne '') {
|
---|
111 | if ($template_param eq '') {
|
---|
112 | print OUTPUT "\\$clssubsection\{The $sectionname{$_} \\clsnm{$class} Interface}\n";
|
---|
113 | }
|
---|
114 | else {
|
---|
115 | print OUTPUT "\\$clssubsection\{The \\clsnm{$class";
|
---|
116 | print OUTPUT "\$<\$$template_param\$>\$} Class Template Interface}\n";
|
---|
117 | }
|
---|
118 | local($memberdoc) = $item{$_};
|
---|
119 | # two items in a row shouldn't have an mbox
|
---|
120 | $memberdoc =~ s/\\mbox{}\\\\\s*\\item\[/\n\\item\[/g;
|
---|
121 | print OUTPUT "\\begin{classinterface}\n";
|
---|
122 | print OUTPUT $memberdoc;
|
---|
123 | print OUTPUT "\\end{classinterface}\n";
|
---|
124 | }
|
---|
125 | }
|
---|
126 | close(OUTPUT);
|
---|
127 | }
|
---|
128 | %item = ();
|
---|
129 | $classdoc = '';
|
---|
130 | }
|
---|
131 |
|
---|
132 | sub beautify_member {
|
---|
133 | $m = $_[0];
|
---|
134 |
|
---|
135 | print "MEM=$m\n" if ($printmember);
|
---|
136 |
|
---|
137 | $_ = $m;
|
---|
138 |
|
---|
139 | # remove inline
|
---|
140 | s/inline//;
|
---|
141 |
|
---|
142 | # remove parent/member constructor calls
|
---|
143 | s/::/SAVEDCOLONCOLON/g;
|
---|
144 | s/:.*$//;
|
---|
145 | s/SAVEDCOLONCOLON/::/g;
|
---|
146 |
|
---|
147 | $virtual = 0;
|
---|
148 | $static = 0;
|
---|
149 | $constreturn = 0;
|
---|
150 | # check for a constructor
|
---|
151 | if (/^\s*[A-Za-z_][A-Za-z0-9_]*\s*\(/) {
|
---|
152 | $typename = 'void';
|
---|
153 | }
|
---|
154 | # check for a destructor
|
---|
155 | elsif (/^\s*(virtual\s)?\s*~\s*[A-Za-z_][A-Za-z0-9_]*\s*\(/) {
|
---|
156 | $typename = 'void';
|
---|
157 | if (s/^\s*virtual//) { $virtual = 1; }
|
---|
158 | }
|
---|
159 | else {
|
---|
160 | # parse the virtual and static qualifiers
|
---|
161 | if (s/^\s*virtual//) {
|
---|
162 | $virtual = 1;
|
---|
163 | }
|
---|
164 | elsif (s/^\s*static//) {
|
---|
165 | $static = 1;
|
---|
166 | }
|
---|
167 |
|
---|
168 | # parse the const qualifier
|
---|
169 | if (s/^\s*const//) {
|
---|
170 | $constreturn = 1;
|
---|
171 | }
|
---|
172 |
|
---|
173 | # parse the type name
|
---|
174 | /^\s*([A-Za-z_][A-Za-z_0-9<>,]*)(.*)/;
|
---|
175 | $typename = $1;
|
---|
176 | $_ = $2;
|
---|
177 |
|
---|
178 | # parse the reference and pointer and const qualifiers
|
---|
179 | while (/^\s*(&)(.*)/ || /^\s*(\*)(.*)/ || /^\s*(const)(.*)/) {
|
---|
180 | $typename = "$typename $1";
|
---|
181 | $_ = $2;
|
---|
182 | }
|
---|
183 |
|
---|
184 | $typename =~ s/&/\\&/g;
|
---|
185 | $typename =~ s/_/\\_/g;
|
---|
186 | $typename =~ s/</\$<\$/g;
|
---|
187 | $typename =~ s/>/\$>\$/g;
|
---|
188 | $typename = "const $typename" if ($constreturn);
|
---|
189 | }
|
---|
190 |
|
---|
191 | # parse the member name
|
---|
192 | ($destructor, $membername, $rest) =
|
---|
193 | /^\s*(~?)\s*([A-Za-z_][A-Za-z0-9_]*)(.*)/;
|
---|
194 | $_ = $rest;
|
---|
195 | $membername = "$destructor$membername";
|
---|
196 | if ($typename eq "operator") {
|
---|
197 | # fixup type conversion operators
|
---|
198 | $typename = "$membername";
|
---|
199 | $membername = "operator $membername";
|
---|
200 | }
|
---|
201 | elsif ($membername eq 'operator') {
|
---|
202 | # operator () is a special case
|
---|
203 | if (/^\s*\(\s*\)(.*)/) {
|
---|
204 | $membername = "$membername ()";
|
---|
205 | $_ = $1;
|
---|
206 | }
|
---|
207 | else {
|
---|
208 | /^\s*([^(]*)\s*(\(.*)/;
|
---|
209 | $membername = "$membername $1";
|
---|
210 | $_ = $2;
|
---|
211 | }
|
---|
212 | }
|
---|
213 | #print "MN = $membername, _ = $_\n";
|
---|
214 |
|
---|
215 | # look for underscores in membername
|
---|
216 | #@membername = split(/_/,$membername);
|
---|
217 | #$item = "";
|
---|
218 | #foreach $i (0 .. $#membername) {
|
---|
219 | # $item = join('$item',"{\\bfseries $membername[$i]}");
|
---|
220 | # if ($i != $#membername) {
|
---|
221 | # $item = "$item\_";
|
---|
222 | # }
|
---|
223 | #}
|
---|
224 | $item = "{\\bfseries $membername}";
|
---|
225 | $item =~ s/_/\\_/g;
|
---|
226 |
|
---|
227 | # take care of special characters in item
|
---|
228 | $item =~ s/&/\\&/g;
|
---|
229 | $item =~ s/</\$<\$/g;
|
---|
230 | $item =~ s/>/\$>\$/g;
|
---|
231 | $item =~ s/~/\$\\tilde{}\$/;
|
---|
232 |
|
---|
233 | # parse the arglist
|
---|
234 | /\((.*)\)(.*)/;
|
---|
235 | $arglist = $1;
|
---|
236 | $_ = $2;
|
---|
237 |
|
---|
238 | # take care of special characters in arglist
|
---|
239 | $arglist =~ s/&/\\&/g;
|
---|
240 | $arglist =~ s/</\$<\$/g;
|
---|
241 | $arglist =~ s/>/\$>\$/g;
|
---|
242 | $arglist =~ s/_/\\_/g;
|
---|
243 |
|
---|
244 | # make sure there is whitespace after commas (for better formatting).
|
---|
245 | $arglist =~ s/,\s*/, /g;
|
---|
246 |
|
---|
247 | # parse the constness of calling object
|
---|
248 | $constobject = 0;
|
---|
249 | if (/^[ \t]*const(.*)/) {
|
---|
250 | $constobject = 1;
|
---|
251 | $_ = $1;
|
---|
252 | }
|
---|
253 |
|
---|
254 | # parse the pure virtual qualifier
|
---|
255 | $pure = 0;
|
---|
256 | if (/[ \t]*=[ \t]*0(.*)/) {
|
---|
257 | $pure = 1;
|
---|
258 | $_ = $1;
|
---|
259 | }
|
---|
260 |
|
---|
261 | # construct the table entry
|
---|
262 |
|
---|
263 | $qualifiers = '';
|
---|
264 | if ($constobject) {
|
---|
265 | $qualifiers = "$qualifiers const";
|
---|
266 | }
|
---|
267 | if ($pure) {
|
---|
268 | $qualifiers = "$qualifiers pure";
|
---|
269 | }
|
---|
270 | elsif ($virtual) {
|
---|
271 | $qualifiers = "$qualifiers virtual";
|
---|
272 | }
|
---|
273 | elsif ($static) {
|
---|
274 | $qualifiers = "$qualifiers static";
|
---|
275 | }
|
---|
276 | $_ = $qualifiers;
|
---|
277 | /[ \t]*(.*)[ \t]*/;
|
---|
278 | $qualifiers = $1;
|
---|
279 |
|
---|
280 | #$item = "\@b{$membername}($arglist)";
|
---|
281 | $item = "$item($arglist)";
|
---|
282 | if ($qualifiers ne '') {
|
---|
283 | $item = "$item $qualifiers";
|
---|
284 | }
|
---|
285 | if ($typename ne 'void') {
|
---|
286 | $item = "$item \$\\rightarrow\$ {\\bfseries $typename}";
|
---|
287 | }
|
---|
288 |
|
---|
289 | return "$item";
|
---|
290 | }
|
---|
291 |
|
---|
292 | sub get_doc {
|
---|
293 | $doc = $_[0];
|
---|
294 | $members = '';
|
---|
295 | $indoc = 1;
|
---|
296 | while (<>) {
|
---|
297 | if ($indoc && /^\s*\/\/(\.)?(\s*.*)/) {
|
---|
298 | $doc = "$doc\n$2";
|
---|
299 | }
|
---|
300 | elsif (/^\s*template <(.*)>\s*class\s+([a-zA-Z_][a-zA-Z0-9_]*)/) {
|
---|
301 | do new_class($2,$1,'');
|
---|
302 | }
|
---|
303 | elsif (/^\s*template <(.*)>\s*$/) {
|
---|
304 | $tmp_template_param = $1;
|
---|
305 | while (<>) { last; }
|
---|
306 | if (/^\s*class\s+([a-zA-Z_][a-zA-Z0-9_]*)/) {
|
---|
307 | while(<>) { last; }
|
---|
308 | do new_class($1,$tmp_template_param,'');
|
---|
309 | last;
|
---|
310 | }
|
---|
311 | }
|
---|
312 | elsif (/^\s*class\s+([a-zA-Z_][a-zA-Z0-9_]*)/) {
|
---|
313 | while(<>) { last; }
|
---|
314 | do new_class($1,'',$doc);
|
---|
315 | last;
|
---|
316 | }
|
---|
317 | elsif (/^\s*((~\s*)?[A-Za-z_].*,)\s*$/) {
|
---|
318 | $indoc = 0;
|
---|
319 | $member = $1;
|
---|
320 | $remainder = &read_member_continuation;
|
---|
321 | $member = "$member$remainder";
|
---|
322 | print "CASE 1: MEM=$member\n" if ($printmembercase);
|
---|
323 | $member = &beautify_member($member);
|
---|
324 | $members = "$members\\item[$member]\\mbox{}\\\\\n";
|
---|
325 | }
|
---|
326 | elsif (/^\s*((~\s*)?[A-Za-z_].*)\s*{/) {
|
---|
327 | $indoc = 0;
|
---|
328 | print "CASE 2: MEM=$1\n" if ($printmembercase);
|
---|
329 | $member = &beautify_member($1);
|
---|
330 | $members = "$members\\item[$member]\\mbox{}\\\\\n";
|
---|
331 | # attempt to skip over simple routines
|
---|
332 | &skip_inlined_routine("{$'");
|
---|
333 | }
|
---|
334 | elsif (/^\s*((~\s*)?[A-Za-z_].*);\s*/) {
|
---|
335 | $indoc = 0;
|
---|
336 | print "CASE 3: MEM=$1\n" if ($printmembercase);
|
---|
337 | $member = &beautify_member($1);
|
---|
338 | $members = "$members\\item[$member]\\mbox{}\\\\\n";
|
---|
339 | }
|
---|
340 | elsif (/^\s*((~\s*)?[A-Za-z_].*)\s*/) {
|
---|
341 | $indoc = 0;
|
---|
342 | $member = $1;
|
---|
343 | if (! /\)/) {
|
---|
344 | # the member is not complete--finish it
|
---|
345 | $remainder = &read_member_continuation;
|
---|
346 | $member = "$member$remainder";
|
---|
347 | }
|
---|
348 | print "CASE 4: MEM=$member\n" if ($printmembercase);
|
---|
349 | $member = &beautify_member($member);
|
---|
350 | $members = "$members\\item[$member]\\mbox{}\\\\\n";
|
---|
351 | }
|
---|
352 | elsif (/^\s*{/) {
|
---|
353 | $indoc = 0;
|
---|
354 | &skip_inlined_routine("{$'");
|
---|
355 | }
|
---|
356 | else {
|
---|
357 | $item{$interface} = "$item{$interface}$members$doc\n\n";
|
---|
358 | last;
|
---|
359 | }
|
---|
360 | }
|
---|
361 | }
|
---|
362 |
|
---|
363 | sub skip_inlined_routine {
|
---|
364 | local($_) = $_[0];
|
---|
365 | local($nbracket) = &count_brackets($_);
|
---|
366 | return if ($nbracket == 0);
|
---|
367 | while (<>) {
|
---|
368 | $nbracket = $nbracket + &count_brackets($_);
|
---|
369 | return if ($nbracket == 0);
|
---|
370 | }
|
---|
371 | }
|
---|
372 |
|
---|
373 | sub count_brackets {
|
---|
374 | local($_) = $_[0];
|
---|
375 | local($n) = 0;
|
---|
376 | s/"[^\"]*"//g;
|
---|
377 | local(@chars) = split(//,$_);
|
---|
378 | foreach (@chars) {
|
---|
379 | if ($_ eq "{") {
|
---|
380 | $n++;
|
---|
381 | }
|
---|
382 | elsif ($_ eq "}") {
|
---|
383 | $n--;
|
---|
384 | }
|
---|
385 | }
|
---|
386 | return $n;
|
---|
387 | }
|
---|
388 |
|
---|
389 | sub read_member_continuation {
|
---|
390 | local($member) = "";
|
---|
391 | while (<>) {
|
---|
392 | if (/^\s*(.*,)\s*$/) {
|
---|
393 | $member = "$member$1";
|
---|
394 | }
|
---|
395 | elsif (/^\s*(.*){\s*/) {
|
---|
396 | $member = "$member$1";
|
---|
397 | # attempt to skip over simple routines
|
---|
398 | &skip_inlined_routine("{$'");
|
---|
399 | last;
|
---|
400 | }
|
---|
401 | elsif (/^\s*(.*);\s*/) {
|
---|
402 | $member = "$member$1";
|
---|
403 | last;
|
---|
404 | }
|
---|
405 | elsif (/};/) {
|
---|
406 | last;
|
---|
407 | }
|
---|
408 | else {
|
---|
409 | printf "BAD MEMBER CONTINUATION: $_\n";
|
---|
410 | }
|
---|
411 | }
|
---|
412 | return $member;
|
---|
413 | }
|
---|