1 /*=========================================================================
3 Program: Visualization Toolkit
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
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.
14 =========================================================================*/
16 #include "vtkWrapText.h"
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 */
29 const char *vtkWrapText_QuoteString(
30 const char *comment, size_t maxlen)
32 static char *result = 0;
33 static size_t oldmaxlen = 0;
36 if (maxlen > oldmaxlen)
42 result = (char *)malloc((size_t)(maxlen+1));
54 for (i = 0; i < n; i++)
56 if (comment[i] == '\"')
58 strcpy(&result[j],"\\\"");
61 else if (comment[i] == '\\')
63 strcpy(&result[j],"\\\\");
66 else if (comment[i] == '\n')
68 strcpy(&result[j],"\\n");
71 else if ((comment[i] & 0x80) != 0 || isprint(comment[i]))
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];
81 sprintf(&result[j],"\\%3.3o",comment[i]);
86 sprintf(&result[j]," ...\\n [Truncated]\\n");
87 j += (int)strlen(" ...\\n [Truncated]\\n");
96 /* -------------------------------------------------------------------- */
97 /* A simple string that grows as necessary. */
106 /* -- append ---------- */
107 static void vtkWPString_Append(
108 struct vtkWPString *str, const char *text)
110 size_t n = strlen(text);
112 if (str->len + n + 1 > str->maxlen)
114 str->maxlen = (str->len + n + 1 + 2*str->maxlen);
115 str->str = (char *)realloc(str->str, str->maxlen);
118 strncpy(&str->str[str->len], text, n);
120 str->str[str->len] = '\0';
123 /* -- add a char ---------- */
124 static void vtkWPString_PushChar(
125 struct vtkWPString *str, char c)
127 if (str->len + 2 > str->maxlen)
129 str->maxlen = (str->len + 2 + 2*str->maxlen);
130 str->str = (char *)realloc(str->str, str->maxlen);
133 str->str[str->len++] = c;
134 str->str[str->len] = '\0';
137 /* -- strip any of the given chars from the end ---------- */
138 static void vtkWPString_Strip(
139 struct vtkWPString *str, const char *trailers)
148 n = strlen(trailers);
150 while (k > 0 && j < n)
152 for (j = 0; j < n; j++)
154 if (cp[k-1] == trailers[j])
167 /* -- Return the last char ---------- */
168 static char vtkWPString_LastChar(
169 struct vtkWPString *str)
171 if (str->str && str->len > 0)
173 return str->str[str->len-1];
178 /* -- do a linebreak on a method declaration ---------- */
179 static void vtkWPString_BreakSignatureLine(
180 struct vtkWPString *str, size_t *linestart, size_t indentation)
184 size_t j = *linestart;
187 char *text = str->str;
195 while (l > j && text[l-1] != '\n' && text[l-1] != ',' &&
196 text[l-1] != '(' && text[l-1] != ')')
198 /* treat each string as a unit */
199 if (l > 4 && (text[l-1] == '\'' || text[l-1] == '\"'))
203 while (l > 3 && (text[l-1] != delim || text[l-3] == '\\'))
206 if (text[l-1] == '\\')
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')
228 /* Append some chars to guarantee size */
229 vtkWPString_PushChar(str, '\n');
230 vtkWPString_PushChar(str, '\n');
231 for (i = 0; i < indentation; i++)
233 vtkWPString_PushChar(str, ' ');
235 /* re-get the char pointer, it may have been reallocated */
241 while (m < indentation+2 && text[l+m] == ' ')
245 memmove(&text[l+indentation+2-m], &text[l], k-l);
246 k += indentation+2-m;
252 text[l++] = '\\'; text[l++] = 'n';
254 for (i = 0; i < indentation; i++)
262 /* return the new line start position */
266 /* -- do a linebreak on regular text ---------- */
267 static void vtkWPString_BreakCommentLine(
268 struct vtkWPString *str, size_t *linestart, size_t indent)
271 size_t j = *linestart;
273 char *text = str->str;
280 /* try to break the line at a word */
281 while (l > 0 && text[l-1] != ' ' && text[l-1] != '\n')
285 if (l > 0 && text[l-1] != '\n' && l-j > indent)
287 /* replace space with newline */
291 /* Append some chars to guarantee size */
292 vtkWPString_PushChar(str, '\n');
293 vtkWPString_PushChar(str, '\n');
294 for (i = 0; i < indent; i++)
296 vtkWPString_PushChar(str, ' ');
298 /* re-get the char pointer, it may have been reallocated */
300 str->len -= indent+2;
302 if (str->len > l && indent > 0)
304 memmove(&text[l+indent], &text[l], str->len-l);
305 memset(&text[l], ' ', indent);
311 /* long word, just split the word */
312 vtkWPString_PushChar(str, '\n');
314 for (i = 0; i < indent; i++)
316 vtkWPString_PushChar(str, ' ');
320 /* return the new line start position */
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)
329 static struct vtkWPString staticString = { NULL, 0, 0 };
330 struct vtkWPString *text;
332 const char *cp = signature;
334 size_t lastSigStart = 0;
337 text = &staticString;
348 while (cp[i] != '\0')
350 while (text->len - j < width && cp[i] != '\n' && cp[i] != '\0')
353 if (cp[i] == '\"' || cp[i] == '\'')
356 vtkWPString_PushChar(text, '\\');
357 vtkWPString_PushChar(text, cp[i++]);
358 while (cp[i] != delim && cp[i] != '\0')
362 vtkWPString_PushChar(text, '\\');
364 vtkWPString_PushChar(text, cp[i++]);
368 vtkWPString_PushChar(text, '\\');
369 vtkWPString_PushChar(text, cp[i++]);
372 /* remove items that trail the closing parenthesis */
373 else if (cp[i] == ')')
375 vtkWPString_PushChar(text, cp[i++]);
376 if (strncmp(&cp[i], " const", 6) == 0)
380 if (strncmp(&cp[i], " = 0", 4) == 0)
392 vtkWPString_PushChar(text, cp[i++]);
396 /* break the line (try to break after a comma) */
397 if (cp[i] != '\n' && cp[i] != '\0')
399 vtkWPString_BreakSignatureLine(text, &j, 4);
401 /* reached end of line: do next signature */
404 vtkWPString_Strip(text, " \r\t");
408 /* if sig count is even, check length against maxlen */
409 if ((sigCount & 1) == 0)
411 n = strlen(text->str);
420 vtkWPString_PushChar(text, '\\');
421 vtkWPString_PushChar(text, 'n');
423 /* mark the position of the start of the line */
428 vtkWPString_Strip(text, " \r\t");
430 if (strlen(text->str) >= maxlen)
432 /* terminate before the current signature */
433 text->str[lastSigStart] = '\0';
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
447 const char *vtkWrapText_FormatComment(
448 const char *comment, size_t width)
450 static struct vtkWPString staticString = { NULL, 0, 0 };
451 struct vtkWPString *text;
458 text = &staticString;
470 /* skip any leading whitespace */
471 while (cp[i] == '\n' || cp[i] == '\r' ||
472 cp[i] == '\t' || cp[i] == ' ')
477 while (cp[i] != '\0')
479 /* Add characters until the output line is complete */
480 while (cp[i] != '\0' && text->len-j < width)
482 /* if the end of the line was found, see how next line begins */
485 /* eat the leading space */
491 /* skip ahead to find any interesting first characters */
493 while (cp[l] == ' ' || cp[l] == '\t' || cp[l] == '\r')
498 /* check for new section */
499 if (cp[l] == '.' && strncmp(&cp[l], ".SECTION", 8) == 0)
501 vtkWPString_Strip(text, "\n");
504 vtkWPString_PushChar(text, '\n');
505 vtkWPString_PushChar(text, '\n');
508 while (cp[i] == '\r' || cp[i] == '\t' || cp[i] == ' ')
512 while (cp[i] != '\n' && cp[i] != '\0')
514 vtkWPString_PushChar(text, cp[i++]);
516 vtkWPString_Strip(text, " \t\r");
518 if (vtkWPString_LastChar(text) != ':')
520 vtkWPString_PushChar(text, ':');
522 vtkWPString_PushChar(text, '\n');
523 vtkWPString_PushChar(text, '\n');
534 /* handle doxygen tags that appear at start of line */
535 if (cp[l] == '\\' || cp[l] == '@')
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)
550 if (text->len > 0 && vtkWPString_LastChar(text) != '\n')
552 vtkWPString_PushChar(text, '\n');
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] == ' '))
565 while (indent < 3 && cp[l+indent] != ' ')
570 if (text->len > 0 && vtkWPString_LastChar(text) != '\n')
572 vtkWPString_PushChar(text, '\n');
578 /* keep paragraph breaks */
579 else if (cp[l] == '\n')
582 vtkWPString_Strip(text, "\n");
585 vtkWPString_PushChar(text, '\n');
586 vtkWPString_PushChar(text, '\n');
595 /* add newline if nojoin is not set */
597 (cp[i] == ' ' && !indent))
604 vtkWPString_PushChar(text, '\n');
608 /* do line joining */
609 else if (text->len > 0 && vtkWPString_LastChar(text) != '\n')
612 vtkWPString_PushChar(text, ' ');
620 size_t r = text->len;
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')
627 vtkWPString_PushChar(text, cp[i++]);
629 /* if line ended before quote did, then reset */
636 else if (cp[i] == '\'')
639 size_t r = text->len;
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')
646 vtkWPString_PushChar(text, cp[i++]);
648 /* if line ended before quote did, then reset */
656 /* handle simple html tags */
657 else if (cp[i] == '<')
660 if (cp[l] == '/') { l++; }
661 while ((cp[l] >= 'a' && cp[l] <= 'z') ||
662 (cp[l] >= 'a' && cp[l] <= 'z')) { l++; }
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'))
669 vtkWPString_Strip(text, " \n");
670 vtkWPString_PushChar(text, '\n');
671 vtkWPString_PushChar(text, '\n');
676 while (cp[i] == '\r' || cp[i] == '\t' || cp[i] == ' ')
682 else if (cp[i] == '\\' || cp[i] == '@')
684 /* handle simple doxygen tags */
685 if (strncmp(&cp[i+1], "em ", 3) == 0)
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)
698 if (i > 0 && cp[i-1] != ' ')
700 vtkWPString_PushChar(text, ' ');
706 vtkWPString_PushChar(text, '$');
710 vtkWPString_PushChar(text, '\\');
711 vtkWPString_PushChar(text, cp[i+2]);
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] == '\"')
722 else if (cp[i+1] == 'n')
724 vtkWPString_Strip(text, " \n");
725 vtkWPString_PushChar(text, '\n');
726 vtkWPString_PushChar(text, '\n');
731 else if (strncmp(&cp[i+1], "code", 4) == 0)
735 while (cp[i] == ' ' || cp[i] == '\r' ||
736 cp[i] == '\t' || cp[i] == '\n')
741 else if (strncmp(&cp[i+1], "endcode", 7) == 0)
746 while (cp[l] == ' ' || cp[l] == '\t' || cp[l] == '\r')
753 vtkWPString_PushChar(text, '\n');
757 else if (strncmp(&cp[i+1], "verbatim", 8) == 0)
760 while (cp[i] != '\0' && ((cp[i] != '@' && cp[i] != '\\') ||
761 strncmp(&cp[i+1], "endverbatim", 11) != 0))
765 vtkWPString_PushChar(text, cp[i]);
780 /* search for newline */
783 while (cp[l] == ' ' || cp[l] == '\t' || cp[l] == '\r')
794 else if (cp[i] != '\0')
796 vtkWPString_PushChar(text, cp[i++]);
799 } /* while (cp[i] != '\0' && text->len-j < width) */
806 vtkWPString_BreakCommentLine(text, &j, indent);
809 /* remove any trailing blank lines */
810 vtkWPString_Strip(text, "\n");
811 vtkWPString_PushChar(text, '\n');
816 /* -------------------------------------------------------------------- */
817 /* Create a signature for the python version of a method. */
819 static void vtkWrapText_PythonTypeSignature(
820 struct vtkWPString *result, const char *delims[2], ValueInfo *arg);
822 static void vtkWrapText_PythonArraySignature(
823 struct vtkWPString *result, const char *classname,
824 const char *delims[2], int ndim, const char **dims);
826 const char *vtkWrapText_PythonSignature(
827 FunctionInfo *currentFunction)
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] = { "[", "]" };
838 n = vtkWrap_CountWrappedParameters(currentFunction);
840 result = &staticString;
843 /* print out the name of the method */
844 vtkWPString_Append(result, "V.");
845 vtkWPString_Append(result, currentFunction->Name);
847 /* print the arg list */
848 vtkWPString_Append(result, "(");
850 for (i = 0; i < n; i++)
852 arg = currentFunction->Parameters[i];
856 vtkWPString_Append(result, ", ");
860 if (!vtkWrap_IsConst(arg) &&
861 !vtkWrap_IsSetVectorMethod(currentFunction))
866 vtkWrapText_PythonTypeSignature(result, delims, arg);
869 vtkWPString_Append(result, ")");
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)
876 vtkWPString_Append(result, " -> ");
878 vtkWrapText_PythonTypeSignature(result, parens, ret);
881 if (currentFunction->Signature)
883 vtkWPString_Append(result, "\nC++: ");
884 vtkWPString_Append(result, currentFunction->Signature);
890 static void vtkWrapText_PythonTypeSignature(
891 struct vtkWPString *result, const char *braces[2], ValueInfo *arg)
894 const char *dimension;
895 const char *classname = "";
897 if (vtkWrap_IsVoid(arg))
901 else if (vtkWrap_IsObject(arg))
903 classname = arg->Class;
905 else if (vtkWrap_IsFunction(arg))
907 classname = "function";
909 else if (vtkWrap_IsString(arg) || vtkWrap_IsCharPointer(arg))
911 classname = "string";
912 if ((arg->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_UNICODE_STRING)
914 classname = "unicode";
917 else if (vtkWrap_IsChar(arg))
921 else if (vtkWrap_IsBool(arg))
925 else if (vtkWrap_IsRealNumber(arg))
929 else if (vtkWrap_IsInteger(arg))
934 if ((vtkWrap_IsArray(arg) && arg->CountHint) ||
935 vtkWrap_IsPODPointer(arg))
937 vtkWPString_Append(result, braces[0]);
938 vtkWPString_Append(result, classname);
939 vtkWPString_Append(result, ", ...");
940 vtkWPString_Append(result, braces[1]);
942 else if (vtkWrap_IsArray(arg))
944 sprintf(text, "%d", arg->Count);
946 vtkWrapText_PythonArraySignature(result, classname, braces,
949 else if (vtkWrap_IsNArray(arg))
951 vtkWrapText_PythonArraySignature(result, classname, braces,
952 arg->NumberOfDimensions, arg->Dimensions);
956 vtkWPString_Append(result, classname);
960 static void vtkWrapText_PythonArraySignature(
961 struct vtkWPString *result, const char *classname,
962 const char *braces[2], int ndim, const char **dims)
966 vtkWPString_Append(result, braces[0]);
967 n = (int)strtoul(dims[0], 0, 0);
970 for (j = 0; j < n; j++)
972 if (j != 0) { vtkWPString_Append(result, ", "); }
973 vtkWrapText_PythonArraySignature(result, classname,
974 braces, ndim-1, dims+1);
979 for (j = 0; j < n; j++)
981 if (j != 0) { vtkWPString_Append(result, ", "); }
982 vtkWPString_Append(result, classname);
985 vtkWPString_Append(result, braces[1]);