Salome HOME
CMake: porting module to the new CMake procedure.
[modules/paravis.git] / src / VTKWrapping / ParaView / vtkWrapText.c
1 /*=========================================================================
2
3   Program:   Visualization Toolkit
4   Module:    vtkWrapText.c
5
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 #include "vtkWrapText.h"
17 #include "vtkWrap.h"
18 #include <string.h>
19 #include <ctype.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 /* -------------------------------------------------------------------- */
24 /* Convert special characters in a string into their escape codes
25  * so that the string can be quoted in a source file.  The specified
26  * maxlen must be at least 32 chars, and should not be over 2047 since
27  * that is the maximum length of a string literal on some systems */
28
29 const char *vtkWrapText_QuoteString(
30   const char *comment, size_t maxlen)
31 {
32   static char *result = 0;
33   static size_t oldmaxlen = 0;
34   size_t i, j, n;
35
36   if (maxlen > oldmaxlen)
37     {
38     if (result)
39       {
40       free(result);
41       }
42     result = (char *)malloc((size_t)(maxlen+1));
43     oldmaxlen = maxlen;
44     }
45
46   if (comment == NULL)
47     {
48     return "";
49     }
50
51   j = 0;
52
53   n = strlen(comment);
54   for (i = 0; i < n; i++)
55     {
56     if (comment[i] == '\"')
57       {
58       strcpy(&result[j],"\\\"");
59       j += 2;
60       }
61     else if (comment[i] == '\\')
62       {
63       strcpy(&result[j],"\\\\");
64       j += 2;
65       }
66     else if (comment[i] == '\n')
67       {
68       strcpy(&result[j],"\\n");
69       j += 2;
70       }
71     else if ((comment[i] & 0x80) != 0 || isprint(comment[i]))
72       {
73       // all characters in extended-ASCII set are printable. Some compilers (VS
74       // 2010, in debug mode) asserts when isprint() is passed a negative value.
75       // Hence, we simply skip the check.
76       result[j] = comment[i];
77       j++;
78       }
79     else
80       {
81       sprintf(&result[j],"\\%3.3o",comment[i]);
82       j += 4;
83       }
84     if (j >= maxlen - 21)
85       {
86       sprintf(&result[j]," ...\\n [Truncated]\\n");
87       j += (int)strlen(" ...\\n [Truncated]\\n");
88       break;
89       }
90     }
91   result[j] = '\0';
92
93   return result;
94 }
95
96 /* -------------------------------------------------------------------- */
97 /* A simple string that grows as necessary. */
98
99 struct vtkWPString
100 {
101   char *str;
102   size_t len;
103   size_t maxlen;
104 };
105
106 /* -- append ---------- */
107 static void vtkWPString_Append(
108   struct vtkWPString *str, const char *text)
109 {
110   size_t n = strlen(text);
111
112   if (str->len + n + 1 > str->maxlen)
113     {
114     str->maxlen = (str->len + n + 1 + 2*str->maxlen);
115     str->str = (char *)realloc(str->str, str->maxlen);
116     }
117
118   strncpy(&str->str[str->len], text, n);
119   str->len += n;
120   str->str[str->len] = '\0';
121 }
122
123 /* -- add a char ---------- */
124 static void vtkWPString_PushChar(
125   struct vtkWPString *str, char c)
126 {
127   if (str->len + 2 > str->maxlen)
128     {
129     str->maxlen = (str->len + 2 + 2*str->maxlen);
130     str->str = (char *)realloc(str->str, str->maxlen);
131     }
132
133   str->str[str->len++] = c;
134   str->str[str->len] = '\0';
135 }
136
137 /* -- strip any of the given chars from the end ---------- */
138 static void vtkWPString_Strip(
139   struct vtkWPString *str, const char *trailers)
140 {
141   size_t k = str->len;
142   char *cp = str->str;
143   size_t j = 0;
144   size_t n;
145
146   if (cp)
147     {
148     n = strlen(trailers);
149
150     while (k > 0 && j < n)
151       {
152       for (j = 0; j < n; j++)
153         {
154         if (cp[k-1] == trailers[j])
155           {
156           k--;
157           break;
158           }
159         }
160       }
161
162     str->len = k;
163     str->str[k] = '\0';
164     }
165 }
166
167 /* -- Return the last char ---------- */
168 static char vtkWPString_LastChar(
169   struct vtkWPString *str)
170 {
171   if (str->str && str->len > 0)
172     {
173     return str->str[str->len-1];
174     }
175   return '\0';
176 }
177
178 /* -- do a linebreak on a method declaration ---------- */
179 static void vtkWPString_BreakSignatureLine(
180   struct vtkWPString *str, size_t *linestart, size_t indentation)
181 {
182   size_t i = 0;
183   size_t m = 0;
184   size_t j = *linestart;
185   size_t l = str->len;
186   size_t k = str->len;
187   char *text = str->str;
188   char delim;
189
190   if (!text)
191     {
192     return;
193     }
194
195   while (l > j && text[l-1] != '\n' && text[l-1] != ',' &&
196     text[l-1] != '(' && text[l-1] != ')')
197     {
198     /* treat each string as a unit */
199     if (l > 4 && (text[l-1] == '\'' || text[l-1] == '\"'))
200       {
201       delim = text[l-1];
202       l -= 2;
203       while (l > 3 && (text[l-1] != delim || text[l-3] == '\\'))
204         {
205         l--;
206         if (text[l-1] == '\\')
207           {
208           l--;
209           }
210         }
211       l -= 2;
212       }
213     else
214       {
215       l--;
216       }
217     }
218
219   /* if none of these chars was found, split is impossible */
220   if (text[l-1] != ',' && text[l-1] != '(' &&
221       text[l-1] != ')' && text[l-1] != '\n')
222     {
223     j++;
224     }
225
226   else
227     {
228     /* Append some chars to guarantee size */
229     vtkWPString_PushChar(str, '\n');
230     vtkWPString_PushChar(str, '\n');
231     for (i = 0; i < indentation; i++)
232       {
233       vtkWPString_PushChar(str, ' ');
234       }
235     /* re-get the char pointer, it may have been reallocated */
236     text = str->str;
237
238     if (k > l)
239       {
240       m = 0;
241       while (m < indentation+2 && text[l+m] == ' ')
242         {
243         m++;
244         }
245       memmove(&text[l+indentation+2-m], &text[l], k-l);
246       k += indentation+2-m;
247       }
248     else
249       {
250       k += indentation+2;
251       }
252     text[l++] = '\\'; text[l++] = 'n';
253     j = l;
254     for (i = 0; i < indentation; i++)
255       {
256       text[l++] = ' ';
257       }
258     }
259
260   str->len = k;
261
262   /* return the new line start position */
263   *linestart = j;
264 }
265
266 /* -- do a linebreak on regular text ---------- */
267 static void vtkWPString_BreakCommentLine(
268   struct vtkWPString *str, size_t *linestart, size_t indent)
269 {
270   size_t i = 0;
271   size_t j = *linestart;
272   size_t l = str->len;
273   char *text = str->str;
274
275   if (!text)
276     {
277     return;
278     }
279
280   /* try to break the line at a word */
281   while (l > 0 && text[l-1] != ' ' && text[l-1] != '\n')
282     {
283     l--;
284     }
285   if (l > 0 && text[l-1] != '\n' && l-j > indent)
286     {
287     /* replace space with newline */
288     text[l-1] = '\n';
289     j = l;
290
291     /* Append some chars to guarantee size */
292     vtkWPString_PushChar(str, '\n');
293     vtkWPString_PushChar(str, '\n');
294     for (i = 0; i < indent; i++)
295       {
296       vtkWPString_PushChar(str, ' ');
297       }
298     /* re-get the char pointer, it may have been reallocated */
299     text = str->str;
300     str->len -= indent+2;
301
302     if (str->len > l && indent > 0)
303       {
304       memmove(&text[l+indent], &text[l], str->len-l);
305       memset(&text[l], ' ', indent);
306       str->len += indent;
307       }
308     }
309   else
310     {
311     /* long word, just split the word */
312     vtkWPString_PushChar(str, '\n');
313     j = str->len;
314     for (i = 0; i < indent; i++)
315       {
316       vtkWPString_PushChar(str, ' ');
317       }
318     }
319
320   /* return the new line start position */
321   *linestart = j;
322 }
323
324 /* -------------------------------------------------------------------- */
325 /* Format a signature to a 70 char linewidth and char limit */
326 const char *vtkWrapText_FormatSignature(
327   const char *signature, size_t width, size_t maxlen)
328 {
329   static struct vtkWPString staticString = { NULL, 0, 0 };
330   struct vtkWPString *text;
331   size_t i, j, n;
332   const char *cp = signature;
333   char delim;
334   size_t lastSigStart = 0;
335   size_t sigCount = 0;
336
337   text = &staticString;
338   text->len = 0;
339
340   if (signature == 0)
341     {
342     return "";
343     }
344
345   i = 0;
346   j = 0;
347
348   while (cp[i] != '\0')
349     {
350     while (text->len - j < width && cp[i] != '\n' && cp[i] != '\0')
351       {
352       /* escape quotes */
353       if (cp[i] == '\"' || cp[i] == '\'')
354         {
355         delim = cp[i];
356         vtkWPString_PushChar(text, '\\');
357         vtkWPString_PushChar(text, cp[i++]);
358         while (cp[i] != delim && cp[i] != '\0')
359           {
360           if (cp[i] == '\\')
361             {
362             vtkWPString_PushChar(text, '\\');
363             }
364           vtkWPString_PushChar(text, cp[i++]);
365           }
366         if (cp[i] == delim)
367           {
368           vtkWPString_PushChar(text, '\\');
369           vtkWPString_PushChar(text, cp[i++]);
370           }
371         }
372       /* remove items that trail the closing parenthesis */
373       else if (cp[i] == ')')
374         {
375         vtkWPString_PushChar(text, cp[i++]);
376         if (strncmp(&cp[i], " const", 6) == 0)
377           {
378           i += 6;
379           }
380         if (strncmp(&cp[i], " = 0", 4) == 0)
381           {
382           i += 4;
383           }
384         if (cp[i] == ';')
385           {
386           i++;
387           }
388         }
389       /* anything else */
390       else
391         {
392         vtkWPString_PushChar(text, cp[i++]);
393         }
394       }
395
396     /* break the line (try to break after a comma) */
397     if (cp[i] != '\n' && cp[i] != '\0')
398       {
399       vtkWPString_BreakSignatureLine(text, &j, 4);
400       }
401     /* reached end of line: do next signature */
402     else
403       {
404       vtkWPString_Strip(text, " \r\t");
405       if (cp[i] != '\0')
406         {
407         sigCount++;
408         /* if sig count is even, check length against maxlen */
409         if ((sigCount & 1) == 0)
410           {
411           n = strlen(text->str);
412           if (n >= maxlen)
413             {
414             break;
415             }
416           lastSigStart = n;
417           }
418
419         i++;
420         vtkWPString_PushChar(text, '\\');
421         vtkWPString_PushChar(text, 'n');
422         }
423       /* mark the position of the start of the line */
424       j = text->len;
425       }
426     }
427
428   vtkWPString_Strip(text, " \r\t");
429
430   if (strlen(text->str) >= maxlen)
431     {
432     /* terminate before the current signature */
433     text->str[lastSigStart] = '\0';
434     }
435
436   return text->str;
437 }
438
439 /* -------------------------------------------------------------------- */
440 /* Format a comment to a 70 char linewidth, in several steps:
441  * 1) remove html tags, convert <p> and <br> into breaks
442  * 2) remove doxygen tags like \em
443  * 3) remove extra whitespace (except paragraph breaks)
444  * 4) re-break the lines
445  */
446
447 const char *vtkWrapText_FormatComment(
448   const char *comment, size_t width)
449 {
450   static struct vtkWPString staticString = { NULL, 0, 0 };
451   struct vtkWPString *text;
452   const char *cp;
453   size_t i, j, l;
454   size_t indent = 0;
455   int nojoin = 0;
456   int start;
457
458   text = &staticString;
459   text->len = 0;
460
461   if (comment == 0)
462     {
463     return "";
464     }
465
466   i = 0; j = 0; l = 0;
467   start = 1;
468   cp = comment;
469
470   /* skip any leading whitespace */
471   while (cp[i] == '\n' || cp[i] == '\r' ||
472          cp[i] == '\t' || cp[i] == ' ')
473     {
474     i++;
475     }
476
477   while (cp[i] != '\0')
478     {
479     /* Add characters until the output line is complete */
480     while (cp[i] != '\0' && text->len-j < width)
481       {
482       /* if the end of the line was found, see how next line begins */
483       if (start)
484         {
485         /* eat the leading space */
486         if (cp[i] == ' ')
487           {
488           i++;
489           }
490
491         /* skip ahead to find any interesting first characters */
492         l = i;
493         while (cp[l] == ' ' || cp[l] == '\t' || cp[l] == '\r')
494           {
495           l++;
496           }
497
498         /* check for new section */
499         if (cp[l] == '.' && strncmp(&cp[l], ".SECTION", 8) == 0)
500           {
501           vtkWPString_Strip(text, "\n");
502           if (text->len > 0)
503             {
504             vtkWPString_PushChar(text, '\n');
505             vtkWPString_PushChar(text, '\n');
506             }
507           i = l+8;
508           while (cp[i] == '\r' || cp[i] == '\t' || cp[i] == ' ')
509             {
510             i++;
511             }
512           while (cp[i] != '\n' && cp[i] != '\0')
513             {
514             vtkWPString_PushChar(text, cp[i++]);
515             }
516           vtkWPString_Strip(text, " \t\r");
517
518           if (vtkWPString_LastChar(text) != ':')
519             {
520             vtkWPString_PushChar(text, ':');
521             }
522           vtkWPString_PushChar(text, '\n');
523           vtkWPString_PushChar(text, '\n');
524           j = text->len;
525           indent = 0;
526           if (cp[i] == '\n')
527             {
528             i++;
529             }
530           start = 1;
531           continue;
532           }
533
534         /* handle doxygen tags that appear at start of line */
535         if (cp[l] == '\\' || cp[l] == '@')
536           {
537           if (strncmp(&cp[l+1], "brief", 5) == 0 ||
538               strncmp(&cp[l+1], "short", 5) == 0 ||
539               strncmp(&cp[l+1], "pre", 3) == 0 ||
540               strncmp(&cp[l+1], "post", 4) == 0 ||
541               strncmp(&cp[l+1], "param", 5) == 0 ||
542               strncmp(&cp[l+1], "tparam", 6) == 0 ||
543               strncmp(&cp[l+1], "cmdparam", 8) == 0 ||
544               strncmp(&cp[l+1], "exception", 9) == 0 ||
545               strncmp(&cp[l+1], "return", 6) == 0 ||
546               strncmp(&cp[l+1], "li", 2) == 0)
547             {
548             nojoin = 2;
549             indent = 4;
550             if (text->len > 0 && vtkWPString_LastChar(text) != '\n')
551               {
552               vtkWPString_PushChar(text, '\n');
553               }
554             j = text->len;
555             i = l;
556             }
557           }
558
559         /* handle bullets and numbering */
560         else if (cp[l] == '-' || cp[l] == '*' || cp[l] == '#' ||
561                  (cp[l] >= '0' && cp[l] <= '9' &&
562                   (cp[l+1] == ')' || cp[l+1] == '.') && cp[l+2] == ' '))
563           {
564           indent = 0;
565           while (indent < 3 && cp[l+indent] != ' ')
566             {
567             indent++;
568             }
569           indent++;
570           if (text->len > 0 && vtkWPString_LastChar(text) != '\n')
571             {
572             vtkWPString_PushChar(text, '\n');
573             }
574           j = text->len;
575           i = l;
576           }
577
578         /* keep paragraph breaks */
579         else if (cp[l] == '\n')
580           {
581           i = l+1;
582           vtkWPString_Strip(text, "\n");
583           if (text->len > 0)
584             {
585             vtkWPString_PushChar(text, '\n');
586             vtkWPString_PushChar(text, '\n');
587             }
588           nojoin = 0;
589           indent = 0;
590           j = text->len;
591           start = 1;
592           continue;
593           }
594
595         /* add newline if nojoin is not set */
596         else if (nojoin ||
597                 (cp[i] == ' ' && !indent))
598           {
599           if (nojoin == 2)
600             {
601             nojoin = 0;
602             indent = 0;
603             }
604           vtkWPString_PushChar(text, '\n');
605           j = text->len;
606           }
607
608         /* do line joining */
609         else if (text->len > 0 && vtkWPString_LastChar(text) != '\n')
610           {
611           i = l;
612           vtkWPString_PushChar(text, ' ');
613           }
614         }
615
616       /* handle quotes */
617       if (cp[i] == '\"')
618         {
619         size_t q = i;
620         size_t r = text->len;
621
622         /* try to keep the quote whole */
623         vtkWPString_PushChar(text, cp[i++]);
624         while (cp[i] != '\"' && cp[i] != '\r' &&
625                cp[i] != '\n' && cp[i] != '\0')
626           {
627           vtkWPString_PushChar(text, cp[i++]);
628           }
629         /* if line ended before quote did, then reset */
630         if (cp[i] != '\"')
631           {
632           i = q;
633           text->len = r;
634           }
635         }
636       else if (cp[i] == '\'')
637         {
638         size_t q = i;
639         size_t r = text->len;
640
641         /* try to keep the quote whole */
642         vtkWPString_PushChar(text, cp[i++]);
643         while (cp[i] != '\'' && cp[i] != '\r' &&
644                cp[i] != '\n' && cp[i] != '\0')
645           {
646           vtkWPString_PushChar(text, cp[i++]);
647           }
648         /* if line ended before quote did, then reset */
649         if (cp[i] != '\'')
650           {
651           i = q;
652           text->len = r;
653           }
654         }
655
656       /* handle simple html tags */
657       else if (cp[i] == '<')
658         {
659         l = i+1;
660         if (cp[l] == '/') { l++; }
661         while ((cp[l] >= 'a' && cp[l] <= 'z') ||
662                (cp[l] >= 'a' && cp[l] <= 'z')) { l++; }
663         if (cp[l] == '>')
664           {
665           if (cp[i+1] == 'p' || cp[i+1] == 'P' ||
666               (cp[i+1] == 'b' && cp[i+2] == 'r') ||
667               (cp[i+1] == 'B' && cp[i+2] == 'R'))
668             {
669             vtkWPString_Strip(text, " \n");
670             vtkWPString_PushChar(text, '\n');
671             vtkWPString_PushChar(text, '\n');
672             j = text->len;
673             indent = 0;
674             }
675           i = l+1;
676           while (cp[i] == '\r' || cp[i] == '\t' || cp[i] == ' ')
677             {
678             i++;
679             }
680           }
681         }
682       else if (cp[i] == '\\' || cp[i] == '@')
683         {
684         /* handle simple doxygen tags */
685         if (strncmp(&cp[i+1], "em ", 3) == 0)
686           {
687           i += 4;
688           }
689         else if (strncmp(&cp[i+1], "a ", 2) == 0 ||
690                  strncmp(&cp[i+1], "e ", 2) == 0 ||
691                  strncmp(&cp[i+1], "c ", 2) == 0 ||
692                  strncmp(&cp[i+1], "b ", 2) == 0 ||
693                  strncmp(&cp[i+1], "p ", 2) == 0 ||
694                  strncmp(&cp[i+1], "f$", 2) == 0 ||
695                  strncmp(&cp[i+1], "f[", 2) == 0 ||
696                  strncmp(&cp[i+1], "f]", 2) == 0)
697           {
698           if (i > 0 && cp[i-1] != ' ')
699             {
700             vtkWPString_PushChar(text, ' ');
701             }
702           if (cp[i+1] == 'f')
703             {
704             if (cp[i+2] == '$')
705               {
706               vtkWPString_PushChar(text, '$');
707               }
708             else
709               {
710               vtkWPString_PushChar(text, '\\');
711               vtkWPString_PushChar(text, cp[i+2]);
712               }
713             }
714           i += 3;
715           }
716         else if (cp[i+1] == '&' || cp[i+1] == '$' || cp[i+1] == '#' ||
717                  cp[i+1] == '<' || cp[i+1] == '>' || cp[i+1] == '%' ||
718                  cp[i+1] == '@' || cp[i+1] == '\\' || cp[i+1] == '\"')
719           {
720           i++;
721           }
722         else if (cp[i+1] == 'n')
723           {
724           vtkWPString_Strip(text, " \n");
725           vtkWPString_PushChar(text, '\n');
726           vtkWPString_PushChar(text, '\n');
727           indent = 0;
728           i += 2;
729           j = text->len;
730           }
731         else if (strncmp(&cp[i+1], "code", 4) == 0)
732           {
733           nojoin = 1;
734           i += 5;
735           while (cp[i] == ' ' || cp[i] == '\r' ||
736                  cp[i] == '\t' || cp[i] == '\n')
737             {
738             i++;
739             }
740           }
741         else if (strncmp(&cp[i+1], "endcode", 7) == 0)
742           {
743           nojoin = 0;
744           i += 8;
745           l = i;
746           while (cp[l] == ' ' || cp[l] == '\t' || cp[l] == '\r')
747             {
748             l++;
749             }
750           if (cp[l] == '\n')
751             {
752             i = l;
753             vtkWPString_PushChar(text, '\n');
754             j = text->len;
755             }
756           }
757         else if (strncmp(&cp[i+1], "verbatim", 8) == 0)
758           {
759           i += 9;
760           while (cp[i] != '\0' && ((cp[i] != '@' && cp[i] != '\\') ||
761                  strncmp(&cp[i+1], "endverbatim", 11) != 0))
762             {
763             if (cp[i] != '\r')
764               {
765               vtkWPString_PushChar(text, cp[i]);
766               }
767             if (cp[i] == '\n')
768               {
769               j = text->len;
770               }
771             i++;
772             }
773           if (cp[i] != '\0')
774             {
775             i += 12;
776             }
777           }
778         }
779
780       /* search for newline */
781       start = 0;
782       l = i;
783       while (cp[l] == ' ' || cp[l] == '\t' || cp[l] == '\r')
784         {
785         l++;
786         }
787       if (cp[l] == '\n')
788         {
789         i = l+1;
790         start = 1;
791         }
792
793       /* append */
794       else if (cp[i] != '\0')
795         {
796         vtkWPString_PushChar(text, cp[i++]);
797         }
798
799       } /* while (cp[i] != '\0' && text->len-j < width) */
800
801     if (cp[i] == '\0')
802       {
803       break;
804       }
805
806     vtkWPString_BreakCommentLine(text, &j, indent);
807     }
808
809   /* remove any trailing blank lines */
810   vtkWPString_Strip(text, "\n");
811   vtkWPString_PushChar(text, '\n');
812
813   return text->str;
814 }
815
816 /* -------------------------------------------------------------------- */
817 /* Create a signature for the python version of a method. */
818
819 static void vtkWrapText_PythonTypeSignature(
820   struct vtkWPString *result, const char *delims[2], ValueInfo *arg);
821
822 static void vtkWrapText_PythonArraySignature(
823   struct vtkWPString *result, const char *classname,
824   const char *delims[2], int ndim, const char **dims);
825
826 const char *vtkWrapText_PythonSignature(
827   FunctionInfo *currentFunction)
828 {
829   /* string is intentionally not freed until the program exits */
830   static struct vtkWPString staticString = { NULL, 0, 0 };
831   struct vtkWPString *result;
832   ValueInfo *arg, *ret;
833   const char *parens[2] = { "(", ")" };
834   const char *braces[2] = { "[", "]" };
835   const char **delims;
836   int i, n;
837
838   n = vtkWrap_CountWrappedArgs(currentFunction);
839
840   result = &staticString;
841   result->len = 0;
842
843   /* print out the name of the method */
844   vtkWPString_Append(result, "V.");
845   vtkWPString_Append(result, currentFunction->Name);
846
847   /* print the arg list */
848   vtkWPString_Append(result, "(");
849
850   for (i = 0; i < n; i++)
851     {
852     arg = currentFunction->Arguments[i];
853
854     if (i != 0)
855       {
856       vtkWPString_Append(result, ", ");
857       }
858
859     delims = parens;
860     if (!vtkWrap_IsConst(arg) &&
861         !vtkWrap_IsSetVectorMethod(currentFunction))
862       {
863       delims = braces;
864       }
865
866     vtkWrapText_PythonTypeSignature(result, delims, arg);
867     }
868
869   vtkWPString_Append(result, ")");
870
871   /* if this is a void method, we are finished */
872   /* otherwise, print "->" and the return type */
873   ret = currentFunction->ReturnValue;
874   if (ret && (ret->Type & VTK_PARSE_UNQUALIFIED_TYPE) != VTK_PARSE_VOID)
875     {
876     vtkWPString_Append(result, " -> ");
877
878     vtkWrapText_PythonTypeSignature(result, parens, ret);
879     }
880
881   if (currentFunction->Signature)
882     {
883     vtkWPString_Append(result, "\nC++: ");
884     vtkWPString_Append(result, currentFunction->Signature);
885     }
886
887   return result->str;
888 }
889
890 static void vtkWrapText_PythonTypeSignature(
891   struct vtkWPString *result, const char *braces[2], ValueInfo *arg)
892 {
893   char text[32];
894   const char *dimension;
895   const char *classname = "";
896
897   if (vtkWrap_IsVoid(arg))
898     {
899     classname = "void";
900     }
901   else if (vtkWrap_IsObject(arg))
902     {
903     classname = arg->Class;
904     }
905   else if (vtkWrap_IsFunction(arg))
906     {
907     classname = "function";
908     }
909   else if (vtkWrap_IsString(arg) || vtkWrap_IsCharPointer(arg))
910     {
911     classname = "string";
912     if ((arg->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_UNICODE_STRING)
913       {
914       classname = "unicode";
915       }
916     }
917   else if (vtkWrap_IsChar(arg))
918     {
919     classname = "char";
920     }
921   else if (vtkWrap_IsBool(arg))
922     {
923     classname = "bool";
924     }
925   else if (vtkWrap_IsRealNumber(arg))
926     {
927     classname = "float";
928     }
929   else if (vtkWrap_IsInteger(arg))
930     {
931     classname = "int";
932     }
933
934   if (vtkWrap_IsArray(arg))
935     {
936     if (arg->CountHint)
937       {
938       vtkWPString_Append(result, braces[0]);
939       vtkWPString_Append(result, classname);
940       vtkWPString_Append(result, ", ...");
941       vtkWPString_Append(result, braces[1]);
942       }
943     else
944       {
945       sprintf(text, "%d", arg->Count);
946       dimension = text;
947       vtkWrapText_PythonArraySignature(result, classname, braces,
948         1, &dimension);
949       }
950     }
951   else if (vtkWrap_IsNArray(arg))
952     {
953     vtkWrapText_PythonArraySignature(result, classname, braces,
954       arg->NumberOfDimensions, arg->Dimensions);
955     }
956   else
957     {
958     vtkWPString_Append(result, classname);
959     }
960 }
961
962 static void vtkWrapText_PythonArraySignature(
963   struct vtkWPString *result, const char *classname,
964   const char *braces[2], int ndim, const char **dims)
965 {
966   int j, n;
967
968   vtkWPString_Append(result, braces[0]);
969   n = (int)strtoul(dims[0], 0, 0);
970   if (ndim > 1)
971     {
972     for (j = 0; j < n; j++)
973       {
974       if (j != 0) { vtkWPString_Append(result, ", "); }
975       vtkWrapText_PythonArraySignature(result, classname,
976         braces, ndim-1, dims+1);
977       }
978     }
979   else
980     {
981     for (j = 0; j < n; j++)
982       {
983       if (j != 0) { vtkWPString_Append(result, ", "); }
984       vtkWPString_Append(result, classname);
985       }
986     }
987   vtkWPString_Append(result, braces[1]);
988 }