]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wxSWIG/SWIG/comment.cxx
download clarification
[wxWidgets.git] / wxPython / wxSWIG / SWIG / comment.cxx
CommitLineData
c90f71dd
RD
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#include "internal.h"
17
18/*******************************************************************************
19 * $Header$
20 *
21 * File : comment.cxx
22 *
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
26 * correctly.
27 *
28 * Here's the general idea :
29 *
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).
33 *
34 * 2. We maintain separate lists of comments and documentation
35 * entries.
36 *
37 * 3. Periodically, we go through the list of documentation entries
38 * and see if we can associate any comments.
39 *
40 * 4. Upon completion of parsing, it's critical that we cleanup
41 * the lists using the cleanup() method.
42 *
43 *******************************************************************************/
44
45// -----------------------------------------------------------------------------
46// struct Comment
47//
48// Structure used to maintain a linked list of comments for later use.
49// -----------------------------------------------------------------------------
50
51class Comment {
52public:
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
61
62 Comment(char *t, int line, int col, char *f);
63 ~Comment();
64 static Comment *find(DocEntry *de, CommentHandler *ch);
65 void attach(DocEntry *de, CommentHandler *ch);
66};
67
68
69// -----------------------------------------------------------------------
70// Create a new comment. Automatically puts it on the linked list
71// -----------------------------------------------------------------------
72Comment::Comment(char *t, int line, int col, char *f) {
73 int nlines = 0;
74 char *c;
75
76 text = new String(t);
77 c = t;
78 while (*c) {
79 if (*c == '\n') nlines++;
80 c++;
81 }
82 first_line = line;
83 column = col;
84 last_line = line + nlines - 1;
85 file = copy_string(f);
86 if (comment_list) {
87 comment_list->prev = this;
88 }
89 next = comment_list;
90 comment_list = this;
91 prev = 0;
92}
93
94// -----------------------------------------------------------------------
95// Destroy a comment
96// -----------------------------------------------------------------------
97Comment::~Comment() {
98 delete text;
99 delete file;
100 // Remove from linked list (if applicable)
101 if (prev) {
102 prev->next = next;
103 }
104 if (next) {
105 next->prev = prev;
106 }
107 if (this == comment_list) comment_list = next;
108}
109// -----------------------------------------------------------------------
110// find(DocEntry *de, CommentHandler *ch)
111//
112// This function tries to a find a comment matching the search criteria
113// of a given comment handler and documentation entry.
114// -----------------------------------------------------------------------
115
116Comment *Comment::find(DocEntry *de, CommentHandler *ch) {
117 Comment *c;
118
119 c = comment_list;
120
121 // Start walking down our list of stored comments
122
123 while (c) {
124 // printf("Searching %x : %s\n", c, c->text->get());
125 if (strcmp(de->file,c->file) == 0) {
126
127 // At least comment is in the right file. Now check line numbers
128
129 if (ch->location == BEFORE) {
130
131 // Check to see if the last line of the comment is close
132 // enough to our declaration.
133
134 if ((c->last_line <= de->line_number) &&
135 ((de->line_number - c->last_line) <= ch->skip_lines)) {
136 return c;
137 }
138 } else { // AFTER mode
139 // Check to see if the first line of the comment is close
140 // enough to our declaration.
141
142 if ((c->first_line >= de->end_line) &&
143 ((c->first_line - de->end_line) <= ch->skip_lines)) {
144 return c;
145 }
146 }
147 // Check to see if the line numbers are too small. Comments
148 // are processed in order so there's no sense in checking
149 // all entries.
150
151 if (c->last_line < de->line_number)
152 return 0;
153
154 }
155 c = c->next;
156 }
157 return 0;
158}
159
160// -----------------------------------------------------------------------
161// void attach(DocEntry *de, CommentHandler *ch)
162//
163// This function attachs a comment to a documentation entry and applies
164// all of the style information in the comment handler.
165// -----------------------------------------------------------------------
166void Comment::attach(DocEntry *de, CommentHandler *ch) {
167 int nlines = 0;
168 char **split = 0;
169 char *c;
170 int i,lnum,el;
171 if (!de) return;
172
173 // If we're ignoring comments, forget it
174 if (ch->ignore) {
175 return;
176 }
177
178 // If the comment is formatted, no style processing is applied
179
180 if (de->format) {
181 de->text << *text;
182 return;
183 }
184
185 // Untabify the comment
186
187 if (ch->untabify) text->untabify();
188
189 // Count how many lines we have
190
191 c = text->get();
192 while (*c) {
193 if (*c == '\n') nlines++;
194 c++;
195 }
196
197 if (nlines == 0) return;
198
199 // Tokenize the documentation string into lines
200
201 split = new char*[nlines+1];
202 c = text->get();
203 i = 0;
204 split[i] = c;
205 while (*c) {
206 if (*c == '\n') {
207 *(c++) = 0;
208 split[++i] = c;
209 } else c++;
210 }
211 lnum = 0;
212
213 // Now process the chop_top and chop_bottom values
214 // if nlines < (chop_top + chop_bottom), then we do nothing
215
216 if (nlines > (ch->chop_top + ch->chop_bottom)) {
217 lnum += ch->chop_top;
218 el = nlines-ch->chop_bottom;
219 } else {
220 el = nlines;
221 }
222
223 // Now process in-between lines
224
225 while (lnum < el) {
226 /* Chop line */
227 if (split[lnum]) {
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];
232 }
233 }
234 lnum++;
235 de->text << "\n";
236 }
237
238 // printf("*** ATTACHING %s : %s\n", de->usage.get(), de->text.get());
239 delete split;
240}
241
242
243CommentHandler *comment_handler = 0;
244Comment *Comment::comment_list = 0;
245
246// ------------------------------------------------------------------------
247// struct DocEntryList
248//
249// This structure manages a linked list of documentation entries that
250// haven't had comments attached to them yet.
251//
252// As a general rule, this list tends to remain rather short.
253// ------------------------------------------------------------------------
254
255struct DocEntryList {
256 DocEntry *de;
257 CommentHandler *ch;
258 DocEntryList *next;
259 DocEntryList *prev;
260 static DocEntryList *doc_list;
261
262 // -----------------------------------------------------------------------
263 // Create a new list entry
264 // -----------------------------------------------------------------------
265 DocEntryList(DocEntry *d, CommentHandler *c) {
266
267 de = d;
268 ch = c;
269 next = doc_list;
270 prev = 0;
271 if (doc_list)
272 doc_list->prev = this;
273 doc_list = this;
274
275 // Only allow a few doc entries to survive
276
277 if (this->next) {
278 if (this->next->next) {
279 delete this->next->next;
280 }
281 }
282 }
283
284 // -----------------------------------------------------------------------
285 // Destroy a list entry
286 // -----------------------------------------------------------------------
287 ~DocEntryList() {
288 if (prev) {
289 prev->next = next;
290 }
291 if (next) {
292 next->prev = prev;
293 }
294 if (this == doc_list) doc_list = next;
295 };
296
297 // -----------------------------------------------------------------------
298 // static check()
299 //
300 // Checks the list of documentation entries to see if any can be associated.
301 // -----------------------------------------------------------------------
302
303 static void check() {
304
305 DocEntryList *dl, *dl_temp;
306 Comment *cmt;
307
308 // printf ("Checking\n");
309 dl = doc_list;
310 while (dl) {
311 cmt = Comment::find(dl->de,dl->ch);
312 if (cmt) {
313 // Okay, we found a matching comment. Attach it to this
314 // documentation entry.
315 cmt->attach(dl->de,dl->ch);
316
317 // Destroy the comment and doc list entry
318 delete cmt;
319
320 // Declarations are always coming in order so we're going
321 // to blow away all of them past this point
322
323 dl_temp = dl->next;
324 delete dl;
325 dl = dl_temp;
326 } else {
327 dl = dl->next;
328 }
329 }
330 }
331};
332
333
334DocEntryList *DocEntryList::doc_list = 0;
335
336// -----------------------------------------------------------------------------
337// CommentHandler::CommentHandler()
338//
339// Constructor. Creates a new comment handler. Sets up some default values
340// for comment handling.
341//
342// Inputs : None
343//
344// Output : New CommentHandler object.
345//
346// Side Effects : Sets default comment handling parameters.
347// -----------------------------------------------------------------------------
348
349CommentHandler::CommentHandler() {
350 skip_lines = 1;
351 location = AFTER;
352 chop_top = 0;
353 chop_bottom = 0;
354 chop_left = 3;
355 chop_right = 0;
356 untabify = 1;
357 ignore = 0;
358}
359
360// -----------------------------------------------------------------------------
361// CommentHandler::CommentHandler(CommentHandler *c)
362//
363// Constructor. Creates a new comment handler, but copies attributes from
364// another handler.
365//
366// Inputs :
367// c = A different comment handler.
368//
369// Output : A new CommentHandler object.
370//
371// Side Effects : None
372// -----------------------------------------------------------------------------
373
374CommentHandler::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;
382 ignore = c->ignore;
383}
384
385// -----------------------------------------------------------------------------
386// CommentHandler::~CommentHandler()
387//
388// Destructor. Destroys a comment handler. Does nothing interesting at the
389// moment.
390//
391// Inputs : None
392//
393// Output : None
394//
395// Side Effects : None
396// -----------------------------------------------------------------------------
397
398CommentHandler::~CommentHandler() {
399}
400
401// -----------------------------------------------------------------------------
402// void CommentHandler::add_comment(char *text, int line_num, int col, char *file)
403//
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)
406//
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.
410//
411// 2. If a new comment appears, we simply create a new one
412//
413// Inputs :
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.
418//
419// Output : None
420//
421// Side Effects :
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// -----------------------------------------------------------------------------
427
428void CommentHandler::add_comment(char *text, int line_num, int col, char *file) {
429
430 char *c;
431 int nlines = 0;
432 Comment *cmt;
433
434 // printf("line_num = %d, %s\n", line_num,text);
435
436 // Count up how many lines are in this comment
437
438 c = text;
439 while (*c) {
440 if (*c == '\n') nlines++;
441 c++;
442 }
443
444 // Check to see if this comment is in a successive line to the last one
445
446 cmt = Comment::comment_list;
447
448 if (cmt) {
449
450 // Check for column alignment
451 if ((cmt->column == col) && (line_num == (cmt->last_line + 1)) &&
452 (nlines <= 1)) {
453 *(cmt->text) << text;
454 cmt->last_line = line_num + nlines - 1;
455 } else {
456 // This is a new comment, add it to our list
457 cmt = new Comment(text,line_num,col,file);
458 }
459 } else {
460 cmt = new Comment(text,line_num,col,file);
461 }
462}
463
464// -----------------------------------------------------------------------------
465// void CommentHanlder::set_entry(DocEntry *d)
466//
467// This grabs a DocEntry and hangs onto it.
468//
469// We will place the doc entry into our documentation list and then
470// check it to see if any comments are sitting around.
471//
472// Inputs : d = Documentation Entry
473//
474// Output : None
475//
476// Side Effects :
477// May attach comments to the documentation entry. In this case,
478// comments and DocEntries may be removed from internal lists.
479// -----------------------------------------------------------------------------
480
481void CommentHandler::set_entry(DocEntry *d) {
482
483 // printf("Set entry : file: %s, line %d, %s\n", d->file, d->line_number, d->usage.get());
484
485 // Create a new list entry and save it
486
487 new DocEntryList(d,this);
488
489 // Check all of the documentation entries to see if they can be placed
490
491 DocEntryList::check();
492
493}
494
495// -----------------------------------------------------------------------------
496// static void CommentHandler::cleanup()
497//
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
500// of parsing.
501//
502// Inputs : None
503//
504// Output : None
505//
506// Side Effects :
507// Removes documentation entries and comments from internal lists.
508//
509// -----------------------------------------------------------------------------
510
511void CommentHandler::cleanup() {
512 int nc, nd;
513 Comment *c;
514 DocEntryList *d;
515
516 DocEntryList::check();
517
518 // Figure out how bad we're doing on memory
519
520 nc = 0;
521 nd = 0;
522 c = Comment::comment_list;
523 while (c) {
524 nc++;
525 c = c->next;
526 }
527
528 d = DocEntryList::doc_list;
529 while(d) {
530 nd++;
531 d = d->next;
532 }
533
534 if (Verbose) {
535 printf("%d unprocessed comments, %d unprocessed doc entries.\n",nc,nd);
536 }
537}
538
539// -----------------------------------------------------------------------------
540// void CommentHandler::style(char *name, char *value)
541//
542// Processes comment handling style parameters. The following parameters
543// are available :
544//
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
556//
557// Inputs :
558// name - Name of style parameter
559// value - Optional parameter value
560//
561// Output : None
562//
563// Side Effects : Changes style of comment handler object.
564//
565// -----------------------------------------------------------------------------
566
567void CommentHandler::style(char *name, char *value) {
568
569 if (strcmp(name,"before") == 0) {
570 location = BEFORE;
571 } else if (strcmp(name,"after") == 0) {
572 location = AFTER;
573 } else if (strcmp(name,"skip") == 0) {
574 if (value)
575 skip_lines = atoi(value);
576 } else if (strcmp(name,"chop_top") == 0) {
577 if (value)
578 chop_top = atoi(value);
579 } else if (strcmp(name,"chop_bottom") == 0) {
580 if (value)
581 chop_bottom = atoi(value);
582 } else if (strcmp(name,"chop_left") == 0) {
583 if (value)
584 chop_left = atoi(value);
585 } else if (strcmp(name,"chop_right") == 0) {
586 if (value)
587 chop_right = atoi(value);
588 } else if (strcmp(name,"tabify") == 0) {
589 untabify = 0;
590 } else if (strcmp(name,"untabify") == 0) {
591 untabify = 1;
592 } else if (strcmp(name,"ignore") == 0) {
593 ignore = 1;
594 } else if (strcmp(name,"enable") == 0) {
595 ignore = 0;
596 }
597}
598
599// -----------------------------------------------------------------------------
600// void CommentHandler::parse_args(int argc, char **argv)
601//
602// Function for processing command line options given on the SWIG command line.
603// See the help string below for available options.
604//
605// Inputs :
606// argc = Argument count
607// argv = Argument strings
608//
609// Output : None
610//
611// Side Effects :
612// Changes various style parameters for the top-level CommentHandler.
613// -----------------------------------------------------------------------------
614
615static char *comment_usage = "\
616Comment 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";
627
628void CommentHandler::parse_args(int argc, char **argv) {
629 int i;
630
631 for (i = 1; i < argc; i++) {
632 if (argv[i]) {
633 if (strcmp(argv[i],"-Sbefore") == 0) {
634 this->style("before",0);
635 mark_arg(i);
636 } else if (strcmp(argv[i],"-Safter") == 0) {
637 this->style("after",0);
638 mark_arg(i);
639 } else if (strcmp(argv[i],"-Schop_top") == 0) {
640 if (argv[i+1]) {
641 this->style("chop_top",argv[i+1]);
642 mark_arg(i);
643 mark_arg(i+1);
644 i++;
645 } else {
646 arg_error();
647 }
648 } else if (strcmp(argv[i],"-Schop_bottom") == 0) {
649 if (argv[i+1]) {
650 this->style("chop_bottom",argv[i+1]);
651 mark_arg(i);
652 mark_arg(i+1);
653 i++;
654 } else {
655 arg_error();
656 }
657 } else if (strcmp(argv[i],"-Schop_left") == 0) {
658 if (argv[i+1]) {
659 this->style("chop_left",argv[i+1]);
660 mark_arg(i);
661 mark_arg(i+1);
662 i++;
663 } else {
664 arg_error();
665 }
666 } else if (strcmp(argv[i],"-Schop_right") == 0) {
667 if (argv[i+1]) {
668 this->style("chop_right",argv[i+1]);
669 mark_arg(i);
670 mark_arg(i+1);
671 i++;
672 } else {
673 arg_error();
674 }
675 } else if (strcmp(argv[i],"-Sskip") == 0) {
676 if (argv[i+1]) {
677 this->style("skip",argv[i+1]);
678 mark_arg(i);
679 mark_arg(i+1);
680 i++;
681 } else {
682 arg_error();
683 }
684 } else if (strcmp(argv[i],"-Suntabify") == 0) {
685 this->style("untabify",0);
686 mark_arg(i);
687 } else if (strcmp(argv[i],"-Stabify") == 0) {
688 this->style("tabify",0);
689 mark_arg(i);
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);
694 }
695 }
696 }
697}