]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/SWIG/comment.cxx
1 /*******************************************************************************
2 * Simplified Wrapper and Interface Generator (SWIG)
4 * Author : David Beazley
6 * Department of Computer Science
7 * University of Chicago
10 * beazley@cs.uchicago.edu
12 * Please read the file LICENSE for the copyright and terms by which SWIG
13 * can be used and distributed.
14 *******************************************************************************/
18 /*******************************************************************************
23 * This is a semi-magical module for associating C/C++ comments with
24 * documentation entries. While this sounds like it might be easy,
25 * there are a number of subtle problems getting things to associate
28 * Here's the general idea :
30 * 1. The parser and scanner feed both C comments and documentation
31 * entries to this class. These may show up in really bizarre
32 * orders (not necessarily the order seen in an interface file).
34 * 2. We maintain separate lists of comments and documentation
37 * 3. Periodically, we go through the list of documentation entries
38 * and see if we can associate any comments.
40 * 4. Upon completion of parsing, it's critical that we cleanup
41 * the lists using the cleanup() method.
43 *******************************************************************************/
45 // -----------------------------------------------------------------------------
48 // Structure used to maintain a linked list of comments for later use.
49 // -----------------------------------------------------------------------------
53 String
*text
; // Text of the comment
54 int first_line
; // First line of the comment
55 int last_line
; // Last line of the comment
56 int column
; // First column of comment
57 char *file
; // Name of the file that it was in
58 Comment
*next
; // Next comment (when in a linked list)
59 Comment
*prev
; // Previous comment
60 static Comment
*comment_list
; // List of all comments
62 Comment(char *t
, int line
, int col
, char *f
);
64 static Comment
*find(DocEntry
*de
, CommentHandler
*ch
);
65 void attach(DocEntry
*de
, CommentHandler
*ch
);
69 // -----------------------------------------------------------------------
70 // Create a new comment. Automatically puts it on the linked list
71 // -----------------------------------------------------------------------
72 Comment::Comment(char *t
, int line
, int col
, char *f
) {
79 if (*c
== '\n') nlines
++;
84 last_line
= line
+ nlines
- 1;
85 file
= copy_string(f
);
87 comment_list
->prev
= this;
94 // -----------------------------------------------------------------------
96 // -----------------------------------------------------------------------
100 // Remove from linked list (if applicable)
107 if (this == comment_list
) comment_list
= next
;
109 // -----------------------------------------------------------------------
110 // find(DocEntry *de, CommentHandler *ch)
112 // This function tries to a find a comment matching the search criteria
113 // of a given comment handler and documentation entry.
114 // -----------------------------------------------------------------------
116 Comment
*Comment::find(DocEntry
*de
, CommentHandler
*ch
) {
121 // Start walking down our list of stored comments
124 // printf("Searching %x : %s\n", c, c->text->get());
125 if (strcmp(de
->file
,c
->file
) == 0) {
127 // At least comment is in the right file. Now check line numbers
129 if (ch
->location
== BEFORE
) {
131 // Check to see if the last line of the comment is close
132 // enough to our declaration.
134 if ((c
->last_line
<= de
->line_number
) &&
135 ((de
->line_number
- c
->last_line
) <= ch
->skip_lines
)) {
138 } else { // AFTER mode
139 // Check to see if the first line of the comment is close
140 // enough to our declaration.
142 if ((c
->first_line
>= de
->end_line
) &&
143 ((c
->first_line
- de
->end_line
) <= ch
->skip_lines
)) {
147 // Check to see if the line numbers are too small. Comments
148 // are processed in order so there's no sense in checking
151 if (c
->last_line
< de
->line_number
)
160 // -----------------------------------------------------------------------
161 // void attach(DocEntry *de, CommentHandler *ch)
163 // This function attachs a comment to a documentation entry and applies
164 // all of the style information in the comment handler.
165 // -----------------------------------------------------------------------
166 void Comment::attach(DocEntry
*de
, CommentHandler
*ch
) {
173 // If we're ignoring comments, forget it
178 // If the comment is formatted, no style processing is applied
185 // Untabify the comment
187 if (ch
->untabify
) text
->untabify();
189 // Count how many lines we have
193 if (*c
== '\n') nlines
++;
197 if (nlines
== 0) return;
199 // Tokenize the documentation string into lines
201 split
= new char*[nlines
+1];
213 // Now process the chop_top and chop_bottom values
214 // if nlines < (chop_top + chop_bottom), then we do nothing
216 if (nlines
> (ch
->chop_top
+ ch
->chop_bottom
)) {
217 lnum
+= ch
->chop_top
;
218 el
= nlines
-ch
->chop_bottom
;
223 // Now process in-between lines
228 if (strlen(split
[lnum
]) > (unsigned) (ch
->chop_left
+ch
->chop_right
)) {
229 if (ch
->chop_right
> 0)
230 split
[lnum
][strlen(split
[lnum
]) - ch
->chop_right
] = 0;
231 de
->text
<< &split
[lnum
][ch
->chop_left
];
238 // printf("*** ATTACHING %s : %s\n", de->usage.get(), de->text.get());
243 CommentHandler
*comment_handler
= 0;
244 Comment
*Comment::comment_list
= 0;
246 // ------------------------------------------------------------------------
247 // struct DocEntryList
249 // This structure manages a linked list of documentation entries that
250 // haven't had comments attached to them yet.
252 // As a general rule, this list tends to remain rather short.
253 // ------------------------------------------------------------------------
255 struct DocEntryList
{
260 static DocEntryList
*doc_list
;
262 // -----------------------------------------------------------------------
263 // Create a new list entry
264 // -----------------------------------------------------------------------
265 DocEntryList(DocEntry
*d
, CommentHandler
*c
) {
272 doc_list
->prev
= this;
275 // Only allow a few doc entries to survive
278 if (this->next
->next
) {
279 delete this->next
->next
;
284 // -----------------------------------------------------------------------
285 // Destroy a list entry
286 // -----------------------------------------------------------------------
294 if (this == doc_list
) doc_list
= next
;
297 // -----------------------------------------------------------------------
300 // Checks the list of documentation entries to see if any can be associated.
301 // -----------------------------------------------------------------------
303 static void check() {
305 DocEntryList
*dl
, *dl_temp
;
308 // printf ("Checking\n");
311 cmt
= Comment::find(dl
->de
,dl
->ch
);
313 // Okay, we found a matching comment. Attach it to this
314 // documentation entry.
315 cmt
->attach(dl
->de
,dl
->ch
);
317 // Destroy the comment and doc list entry
320 // Declarations are always coming in order so we're going
321 // to blow away all of them past this point
334 DocEntryList
*DocEntryList::doc_list
= 0;
336 // -----------------------------------------------------------------------------
337 // CommentHandler::CommentHandler()
339 // Constructor. Creates a new comment handler. Sets up some default values
340 // for comment handling.
344 // Output : New CommentHandler object.
346 // Side Effects : Sets default comment handling parameters.
347 // -----------------------------------------------------------------------------
349 CommentHandler::CommentHandler() {
360 // -----------------------------------------------------------------------------
361 // CommentHandler::CommentHandler(CommentHandler *c)
363 // Constructor. Creates a new comment handler, but copies attributes from
367 // c = A different comment handler.
369 // Output : A new CommentHandler object.
371 // Side Effects : None
372 // -----------------------------------------------------------------------------
374 CommentHandler::CommentHandler(CommentHandler
*c
) {
375 skip_lines
= c
->skip_lines
;
376 location
= c
->location
;
377 chop_top
= c
->chop_top
;
378 chop_bottom
= c
->chop_bottom
;
379 chop_left
= c
->chop_left
;
380 chop_right
= c
->chop_right
;
381 untabify
= c
->untabify
;
385 // -----------------------------------------------------------------------------
386 // CommentHandler::~CommentHandler()
388 // Destructor. Destroys a comment handler. Does nothing interesting at the
395 // Side Effects : None
396 // -----------------------------------------------------------------------------
398 CommentHandler::~CommentHandler() {
401 // -----------------------------------------------------------------------------
402 // void CommentHandler::add_comment(char *text, int line_num, int col, char *file)
404 // This function takes a character string as comment text and appends
405 // it to the current comment string (which is held in Comment::comment_list)
407 // 1. If two comments appear in successive lines, they are
408 // concatenated. This is to handle C++ style comments like the
409 // one surrounding this text.
411 // 2. If a new comment appears, we simply create a new one
414 // text = Text of the comment
415 // line_num = Starting line number of the comment
416 // col = Starting column of the comment
417 // file = File in which the comment was located.
422 // Saves the comment in an internal linked list.
423 // If multiple comments appear in succession, some may end up
424 // in our comment list permanently (ie. never attached to any
425 // particular declaration).
426 // -----------------------------------------------------------------------------
428 void CommentHandler::add_comment(char *text
, int line_num
, int col
, char *file
) {
434 // printf("line_num = %d, %s\n", line_num,text);
436 // Count up how many lines are in this comment
440 if (*c
== '\n') nlines
++;
444 // Check to see if this comment is in a successive line to the last one
446 cmt
= Comment::comment_list
;
450 // Check for column alignment
451 if ((cmt
->column
== col
) && (line_num
== (cmt
->last_line
+ 1)) &&
453 *(cmt
->text
) << text
;
454 cmt
->last_line
= line_num
+ nlines
- 1;
456 // This is a new comment, add it to our list
457 cmt
= new Comment(text
,line_num
,col
,file
);
460 cmt
= new Comment(text
,line_num
,col
,file
);
464 // -----------------------------------------------------------------------------
465 // void CommentHanlder::set_entry(DocEntry *d)
467 // This grabs a DocEntry and hangs onto it.
469 // We will place the doc entry into our documentation list and then
470 // check it to see if any comments are sitting around.
472 // Inputs : d = Documentation Entry
477 // May attach comments to the documentation entry. In this case,
478 // comments and DocEntries may be removed from internal lists.
479 // -----------------------------------------------------------------------------
481 void CommentHandler::set_entry(DocEntry
*d
) {
483 // printf("Set entry : file: %s, line %d, %s\n", d->file, d->line_number, d->usage.get());
485 // Create a new list entry and save it
487 new DocEntryList(d
,this);
489 // Check all of the documentation entries to see if they can be placed
491 DocEntryList::check();
495 // -----------------------------------------------------------------------------
496 // static void CommentHandler::cleanup()
498 // Checks all documentation entries and sees if there are any comments available.
499 // If so, they are attached. This function is usually only called upon completion
507 // Removes documentation entries and comments from internal lists.
509 // -----------------------------------------------------------------------------
511 void CommentHandler::cleanup() {
516 DocEntryList::check();
518 // Figure out how bad we're doing on memory
522 c
= Comment::comment_list
;
528 d
= DocEntryList::doc_list
;
535 printf("%d unprocessed comments, %d unprocessed doc entries.\n",nc
,nd
);
539 // -----------------------------------------------------------------------------
540 // void CommentHandler::style(char *name, char *value)
542 // Processes comment handling style parameters. The following parameters
545 // after - Comments appear after a declaration
546 // before - Comments appear before a declaration
547 // skip - Number of blank lines between comment and decl.
548 // chop_top - Number of lines to chop from top of a comment
549 // chop_bottom - Number of lines to chop from bottom of a comment
550 // chop_left - Number of characters to chop from left
551 // chop_right - Number of characters to chop from right
552 // tabify - Leave tabs in comment text
553 // untabify - Strip tabs and convert them into spaces.
554 // ignore - Ignore comments
555 // enable - Enable comments
558 // name - Name of style parameter
559 // value - Optional parameter value
563 // Side Effects : Changes style of comment handler object.
565 // -----------------------------------------------------------------------------
567 void CommentHandler::style(char *name
, char *value
) {
569 if (strcmp(name
,"before") == 0) {
571 } else if (strcmp(name
,"after") == 0) {
573 } else if (strcmp(name
,"skip") == 0) {
575 skip_lines
= atoi(value
);
576 } else if (strcmp(name
,"chop_top") == 0) {
578 chop_top
= atoi(value
);
579 } else if (strcmp(name
,"chop_bottom") == 0) {
581 chop_bottom
= atoi(value
);
582 } else if (strcmp(name
,"chop_left") == 0) {
584 chop_left
= atoi(value
);
585 } else if (strcmp(name
,"chop_right") == 0) {
587 chop_right
= atoi(value
);
588 } else if (strcmp(name
,"tabify") == 0) {
590 } else if (strcmp(name
,"untabify") == 0) {
592 } else if (strcmp(name
,"ignore") == 0) {
594 } else if (strcmp(name
,"enable") == 0) {
599 // -----------------------------------------------------------------------------
600 // void CommentHandler::parse_args(int argc, char **argv)
602 // Function for processing command line options given on the SWIG command line.
603 // See the help string below for available options.
606 // argc = Argument count
607 // argv = Argument strings
612 // Changes various style parameters for the top-level CommentHandler.
613 // -----------------------------------------------------------------------------
615 static char *comment_usage
= "\
616 Comment Style Options : \n\
617 -Safter - Use comments after a declaration.\n\
618 -Sbefore - Use comments before a declaration.\n\
619 -Schop_bottom n - Chop n lines from bottom of comments.\n\
620 -Schop_left n - Chop n characters from left of a comment.\n\
621 -Schop_right n - Chop n characters from right of a comment.\n\
622 -Schop_top n - Chop n lines from top of comments.\n\
623 -Signore - Ignore comments.\n\
624 -Sskip n - Max lines between comment and declaration.\n\
625 -Stabify - Do not convert tabs.\n\
626 -Suntabify - Convert tabs into spaces (the default).\n\n";
628 void CommentHandler::parse_args(int argc
, char **argv
) {
631 for (i
= 1; i
< argc
; i
++) {
633 if (strcmp(argv
[i
],"-Sbefore") == 0) {
634 this->style("before",0);
636 } else if (strcmp(argv
[i
],"-Safter") == 0) {
637 this->style("after",0);
639 } else if (strcmp(argv
[i
],"-Schop_top") == 0) {
641 this->style("chop_top",argv
[i
+1]);
648 } else if (strcmp(argv
[i
],"-Schop_bottom") == 0) {
650 this->style("chop_bottom",argv
[i
+1]);
657 } else if (strcmp(argv
[i
],"-Schop_left") == 0) {
659 this->style("chop_left",argv
[i
+1]);
666 } else if (strcmp(argv
[i
],"-Schop_right") == 0) {
668 this->style("chop_right",argv
[i
+1]);
675 } else if (strcmp(argv
[i
],"-Sskip") == 0) {
677 this->style("skip",argv
[i
+1]);
684 } else if (strcmp(argv
[i
],"-Suntabify") == 0) {
685 this->style("untabify",0);
687 } else if (strcmp(argv
[i
],"-Stabify") == 0) {
688 this->style("tabify",0);
690 } else if (strcmp(argv
[i
],"-Signore") == 0) {
691 this->style("ignore",0);
692 } else if (strcmp(argv
[i
],"-help") == 0) {
693 fputs(comment_usage
,stderr
);