]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/SWIG/newdoc.cxx
Since I have made several changes to SWIG over the years to accomodate
[wxWidgets.git] / wxPython / wxSWIG / SWIG / newdoc.cxx
1 /*******************************************************************************
2 * Simplified Wrapper and Interface Generator (SWIG)
3 *
4 * Author : David Beazley
5 *
6 * Department of Computer Science
7 * University of Chicago
8 * 1100 E 58th Street
9 * Chicago, IL 60637
10 * beazley@cs.uchicago.edu
11 *
12 * Please read the file LICENSE for the copyright and terms by which SWIG
13 * can be used and distributed.
14 *******************************************************************************/
15 /***********************************************************************
16 * $Header$
17 *
18 * newdoc.cxx
19 *
20 * SWIG Documentation system. (2nd attempt)
21 *
22 * SWIG organizes documentation as a tree structure where each node is a
23 * documentation entry (DocEntry) of some kind. To generate documentation,
24 * we simply traverse the tree and call output methods.
25 *
26 * A sample documentation tree looks something like the following :
27 *
28 * TITLE ----> SECTION 1 ----> func1
29 * ----> func2
30 * ----> func3
31 * ----> class ---> func1
32 * ---> func2
33 * ---> var1
34 * ----> func4
35 *
36 * ----> SECTION 2 ----> func1
37 * ----> var1
38 *
39 * and so on.
40 *
41 * This structure makes it possible to organize C++ classes and more
42 * complicated structures. Hopefully this will provide enough structure
43 * for later versions of SWIG.
44 *
45 *************************************************************************/
46
47 #include "internal.h"
48 #include <ctype.h>
49
50 extern char *get_time();
51 static char *last_name = 0;
52
53 DocEntry *DocEntry::dead_entries = 0;
54
55 // Utility function for converting a string to upper case
56
57 static void str_toupper(char *str) {
58 char *c;
59 c = str;
60 while (*c) {
61 *c = toupper(*c);
62 c++;
63 }
64 }
65
66 // --------------------------------------------------------------------
67 // DocEntry::~DocEntry
68 //
69 // Destroy a documentation entry. Destroys this entry and all of
70 // its children.
71 // --------------------------------------------------------------------
72
73 DocEntry::~DocEntry() {
74 DocEntry *de, *de1;
75
76 if (name) delete name;
77
78 // Now kill all of the children (well, figuratively speaking)
79
80 de = child;
81 while (de) {
82 de1 = de->next;
83 delete de;
84 de = de1;
85 }
86 }
87
88 // --------------------------------------------------------------------
89 // void DocEntry::sort_children()
90 //
91 // Sort children by name (not height). This function gathers all
92 // of the children up into an array of pointers. Then we do an
93 // insertion sort on it and place the children back in order.
94 // --------------------------------------------------------------------
95
96 void DocEntry::sort_children() {
97
98 int count = 0;
99 int i,j;
100 DocEntry *d;
101 DocEntry **list;
102 DocEntry *v;
103
104 if (!child) return; // Nothing to sort
105
106 d = child;
107 while (d) {
108 count++;
109 d = d->next;
110 }
111
112 // allocate a temporary array for sorting everything
113
114 list = new DocEntry *[count+2];
115
116 // Now put pointers into list
117
118 d = child;
119 i = 0;
120 while (d) {
121 list[i] = d;
122 d = d->next;
123 i++;
124 }
125
126 // Do an insertion sort by name
127
128 for (i = 1; i < count; i++) {
129 v = list[i];
130 j = i;
131 while((j > 0) && (strcmp(list[j-1]->name,v->name) > 0)) {
132 list[j] = list[j-1];
133 j--;
134 }
135 list[j] = v;
136 }
137
138 // Now, we're going to reorganize the children in order
139
140 list[count] = 0;
141 child = list[0]; // Our child is the first one in the list
142 d = child;
143 for (i = 0; i < count; i++) {
144 d->next = list[i+1];
145 d = d->next;
146 }
147 delete list;
148 }
149
150 // --------------------------------------------------------------------
151 // void DocEntry::output()
152 //
153 // Output this entry
154 // --------------------------------------------------------------------
155
156 void DocEntry::output(Documentation *) {
157 fprintf(stderr,"SWIG (internal) : No output method defined for DocEntry.\n");
158 }
159
160 // --------------------------------------------------------------------
161 // DocEntry::add(DocEntry *de)
162 //
163 // Adds a new DocEntry as a sibling. Basically we just walk down the
164 // linked list and append ourselves to the end. The documentation
165 // Entry we're adding may, in fact, have siblings too, but this function
166 // Should still work.
167 // --------------------------------------------------------------------
168
169 void DocEntry::add(DocEntry *de) {
170 DocEntry *d,*d1;
171 d = next;
172 d1 = this;
173 while (d) {
174 d1 = d;
175 d = d->next;
176 }
177 d1->next = de;
178 de->previous = d1; // Set up the previous list member
179 }
180
181
182 // --------------------------------------------------------------------
183 // DocEntry::addchild(DocEntry *de)
184 //
185 // Adds a new DocEntry as a child. If we're in Ignore mode, the
186 // documentation entry is still created, but we simply abandon it.
187 // --------------------------------------------------------------------
188
189 void DocEntry::addchild(DocEntry *de) {
190 if (!IgnoreDoc) {
191 if (child) child->add(de);
192 else child = de;
193 } else {
194 if (dead_entries) dead_entries->add(de);
195 else dead_entries = de;
196 }
197 }
198
199 // -------------------------------------------------------------------
200 // DocEntry::remove()
201 //
202 // Removes a documentation entry from the tree and places it on
203 // the dead_entries list
204 // -------------------------------------------------------------------
205
206 void DocEntry::remove() {
207
208 if (previous) {
209 if (next)
210 previous->next = next; // Take out of the linked list
211 else
212 previous->next = 0;
213 } else { // Make sure our parent isn't pointing to us
214 if (parent)
215 parent->child = next;
216 }
217
218 previous = 0;
219 next = 0;
220
221 if (!dead_entries) dead_entries = this;
222 else dead_entries->add(this);
223
224 }
225
226 // -------------------------------------------------------------------
227 // void DocEntry::style(char *name, char *value)
228 //
229 // Set style parameters of a documentation entry
230 // -------------------------------------------------------------------
231
232 void DocEntry::style(char *pname, char *) {
233 if (strcmp(pname,"sort") == 0) {
234 sorted = 1;
235 } else if (strcmp(pname,"nosort") == 0) {
236 sorted = 0;
237 } else if (strcmp(pname,"info") == 0) {
238 print_info = 1;
239 } else if (strcmp(pname,"noinfo") == 0) {
240 print_info = 0;
241 } else if (strcmp(pname,"pre") == 0) {
242 format = 0;
243 } else if (strcmp(pname,"format") == 0) {
244 format = 1;
245 }
246 }
247
248 // -------------------------------------------------------------------
249 // void DocEntry::parse_args(int argc, char **argv)
250 //
251 // Take command line options and process them. This really only
252 // applies to the top-level documentation entry.
253 // -------------------------------------------------------------------
254
255 static char *doc_usage = "\
256 Documentation Processing : \n\
257 -Sformat - Reformat comment text\n\
258 -Sinfo - Print C formatting information (the default)\n\
259 -Snoinfo - Omit C formatting information.\n\
260 -Snosort - Print everything in order (the default)\n\
261 -Spre - Assume comments are pre-formatted (the default)\n\
262 -Ssort - Sort documentation alphabetically\n\n";
263
264 void DocEntry::parse_args(int argc, char **argv) {
265 int i;
266 for (i = 1; i < argc; i++) {
267 if (argv[i]) {
268 if (strcmp(argv[i],"-Ssort") == 0) {
269 this->style("sort",0);
270 mark_arg(i);
271 } else if (strcmp(argv[i],"-Snosort") == 0) {
272 this->style("nosort",0);
273 mark_arg(i);
274 } else if (strcmp(argv[i],"-Sinfo") == 0) {
275 this->style("info",0);
276 mark_arg(i);
277 } else if (strcmp(argv[i],"-Snoinfo") == 0) {
278 this->style("noinfo",0);
279 mark_arg(i);
280 } else if (strcmp(argv[i],"-Spre") == 0) {
281 this->style("pre",0);
282 mark_arg(i);
283 } else if (strcmp(argv[i],"-Sformat") == 0) {
284 this->style("format",0);
285 mark_arg(i);
286 } else if (strcmp(argv[i],"-help") == 0) {
287 fputs(doc_usage,stderr);
288 }
289 }
290 }
291 }
292
293
294 // -------------------------------------------------------------------
295 // DocTitle::DocTitle(char *title, DocEntry *_parent);
296 //
297 // Create a new title documentation entry. The name of the entry
298 // is the title.
299 //
300 // The body text is optional, but may be filled in with a description
301 // as well.
302 // -------------------------------------------------------------------
303
304 DocTitle::DocTitle(char *title, DocEntry *_parent) {
305 name = copy_string(title);
306 str_toupper(name);
307 parent = _parent;
308 child = 0;
309 next = 0;
310 previous = 0;
311 usage << title << "\n";
312 counter = 1;
313 is_separator = 1;
314 line_number = ::start_line;
315 end_line = ::line_number;
316 file = copy_string(input_file);
317 if (_parent) {
318 sorted = _parent->sorted;
319 format = _parent->format;
320 print_info = _parent->print_info;
321 } else {
322 sorted = SWIGDEFAULT_SORT;
323 format = SWIGDEFAULT_FORMAT;
324 print_info = SWIGDEFAULT_INFO;
325 }
326 comment_handler->set_entry(this);
327 if (last_name) delete last_name;
328 last_name = 0;
329 }
330 // --------------------------------------------------------------------
331 // DocTitle::output(Documentation *d)
332 //
333 // Output a title to the Documentation module
334 // --------------------------------------------------------------------
335
336 void DocTitle::output(Documentation *d) {
337 DocEntry *de;
338
339 d->title(this);
340 if (sorted) {
341 sort_children();
342 }
343
344 // Now output my children
345
346 de = child;
347 while (de) {
348 de->output(d);
349 de = de->next;
350 }
351 }
352
353 // -------------------------------------------------------------------
354 // DocSection::DocSection(char *section, DocEntry *_parent);
355 //
356 // Create a new documentation section. The name and description is
357 // set to the name of the section. The text field is optional
358 // but could contain a more complete description.
359 //
360 // The sorted field indicates whether members of this section are
361 // sorted or not.
362 // -------------------------------------------------------------------
363
364 DocSection::DocSection(char *section, DocEntry *_parent) {
365 name = copy_string(section);
366 str_toupper(name);
367 parent = _parent;
368 child = 0;
369 next = 0;
370 previous = 0;
371 usage << section;
372 counter = 1;
373 is_separator = 1;
374 if (_parent) _parent->addchild(this);
375 line_number = ::start_line;
376 end_line = ::line_number;
377 file = copy_string(input_file);
378 if (_parent) {
379 sorted = _parent->sorted;
380 format = _parent->format;
381 print_info = _parent->print_info;
382 } else {
383 sorted = SWIGDEFAULT_SORT;
384 format = SWIGDEFAULT_FORMAT;
385 print_info = SWIGDEFAULT_INFO;
386 }
387 comment_handler->set_entry(this);
388 if (last_name) delete last_name;
389 last_name = 0;
390 }
391
392 // --------------------------------------------------------------------
393 // DocSection::output(Documentation *d)
394 //
395 // Output a section to the documentation module
396 // --------------------------------------------------------------------
397
398 void DocSection::output(Documentation *d) {
399 DocEntry *de;
400
401 // Make a new section
402
403 d->newsection(this,this->parent->counter++); // Make a new section
404
405 // Sort the children if necessary
406
407 if (sorted) {
408 sort_children();
409 }
410
411 // Now output my children
412
413 de = child;
414 while (de) {
415 de->output(d);
416 de = de->next;
417 }
418
419 // End this section
420
421 d->endsection();
422
423 }
424
425
426 // -------------------------------------------------------------------
427 // DocDecl::DocDecl(char *fname, DocEntry *_parent);
428 //
429 // Create documentation for a function declaration.
430 // -------------------------------------------------------------------
431
432 DocDecl::DocDecl(char *fname, DocEntry *_parent) {
433 name = copy_string(fname);
434 str_toupper(name);
435 parent = _parent;
436 child = 0;
437 next = 0;
438 previous = 0;
439 is_separator = 0;
440 if (_parent) _parent->addchild(this);
441 line_number = ::start_line;
442 end_line = ::line_number;
443 file = copy_string(input_file);
444 if (_parent) {
445 sorted = _parent->sorted;
446 format = _parent->format;
447 print_info = _parent->print_info;
448 } else {
449 sorted = SWIGDEFAULT_SORT;
450 format = SWIGDEFAULT_FORMAT;
451 print_info = SWIGDEFAULT_INFO;
452 }
453 comment_handler->set_entry(this);
454 if (last_name) delete last_name;
455 last_name = copy_string(name);
456 }
457
458
459 // --------------------------------------------------------------------
460 // DocDecl::DocDecl(DocEntry *de, DocEntry *_parent)
461 //
462 // Make a new declaration entry, but copy attributes from someone else
463 // --------------------------------------------------------------------
464
465 DocDecl::DocDecl(DocEntry *de, DocEntry *_parent) {
466 name = copy_string(de->name);
467 usage = de->usage.get();
468 cinfo = de->cinfo.get();
469 text = de->text.get();
470 line_number = de->line_number;
471 end_line = de->end_line;
472 file = copy_string(de->file);
473 print_info = de->print_info;
474 format = de->format;
475 if (_parent) {
476 _parent->addchild(this);
477 }
478 }
479
480 // --------------------------------------------------------------------
481 // DocDecl::output(Documentation *d)
482 //
483 // Output a function to the documentation module
484 // --------------------------------------------------------------------
485
486 void DocDecl::output(Documentation *d) {
487 d->print_decl(this);
488 }
489
490 // -------------------------------------------------------------------
491 // DocClass::DocClass(char *classname, DocEntry *_parent);
492 //
493 // Create a new class section. Classes are created as funny sorts of
494 // sections.
495 //
496 // The sorted field indicates whether members of this section are
497 // sorted or not.
498 // -------------------------------------------------------------------
499
500 DocClass::DocClass(char *classname, DocEntry *_parent) {
501 name = copy_string(classname);
502 str_toupper(name);
503 parent = _parent;
504 child = 0;
505 next = 0;
506 previous = 0;
507 usage << classname<< "\n";
508 counter = 1;
509 is_separator = 1;
510 if (_parent) _parent->addchild(this);
511 line_number = ::start_line;
512 end_line = ::line_number;
513 file = copy_string(input_file);
514 if (_parent) {
515 sorted = _parent->sorted;
516 format = _parent->format;
517 print_info = _parent->print_info;
518 } else {
519 sorted = SWIGDEFAULT_SORT;
520 format = SWIGDEFAULT_FORMAT;
521 print_info = SWIGDEFAULT_INFO;
522 }
523 comment_handler->set_entry(this);
524 if (last_name) delete last_name;
525 last_name = copy_string(name);
526
527 }
528
529 // --------------------------------------------------------------------
530 // DocClass::output(Documentation *d)
531 //
532 // Output a section to the documentation module
533 // --------------------------------------------------------------------
534
535 void DocClass::output(Documentation *d) {
536 DocEntry *de;
537
538 // Make a new section
539
540 d->newsection(this,this->parent->counter++); // Make a subsection for this
541
542 // Sort the children if necessary
543
544 if (sorted) {
545 sort_children();
546 }
547
548 // Now output my children
549
550 de = child;
551 while (de) {
552 de->output(d);
553 de = de->next;
554 }
555
556 // End this section
557
558 d->endsection();
559
560 // We now check to see if the next thing is a separator. If not, we'll
561 // emit a separator
562
563 if (next) {
564 if (!next->is_separator)
565 d->separator();
566 }
567 }
568
569 // -------------------------------------------------------------------
570 // DocText::DocText(char *_text, DocEntry *_parent);
571 //
572 // Create documentation for a function declaration.
573 // -------------------------------------------------------------------
574
575 DocText::DocText(char *_text, DocEntry *_parent) {
576 if (!last_name)
577 name = copy_string(""); // There is no name for text
578 else
579 name = copy_string(last_name);
580 parent = _parent;
581 child = 0;
582 next = 0;
583 previous = 0;
584 text << _text;
585 is_separator = 0;
586 if (_parent) _parent->addchild(this);
587 if (_parent) {
588 sorted = _parent->sorted;
589 format = _parent->format;
590 print_info = _parent->print_info;
591 } else {
592 sorted = SWIGDEFAULT_SORT;
593 format = SWIGDEFAULT_FORMAT;
594 print_info = SWIGDEFAULT_INFO;
595 }
596 }
597
598 // --------------------------------------------------------------------
599 // DocText::output(Documentation *d)
600 //
601 // Output a function to the documentation module
602 // --------------------------------------------------------------------
603
604 void DocText::output(Documentation *d) {
605 d->print_text(this);
606 }
607