/* Create the docstring for a class, and print it to fp */ void vtkWrapPython_ClassDoc( FILE *fp, FileInfo *file_info, ClassInfo *data, HierarchyInfo *hinfo, int is_vtkobject) { char pythonname[1024]; const char *supername; char *cp; const char *ccp = NULL; size_t i, n; size_t briefmax = 255; int j; char temp[500]; char *comment; if (data == file_info->MainClass && file_info->NameComment) { /* use the old VTK-style class description */ fprintf(fp, " \"%s\\n\",\n", vtkWrapText_QuoteString( vtkWrapText_FormatComment(file_info->NameComment, 70), 500)); } else if (data->Comment) { strncpy(temp, data->Name, briefmax); temp[briefmax] = '\0'; i = strlen(temp); temp[i++] = ' '; temp[i++] = '-'; if (data->Comment[0] != ' ') { temp[i++] = ' '; } /* extract the brief comment, if present */ ccp = data->Comment; while (i < briefmax && *ccp != '\0') { /* a blank line ends the brief comment */ if (ccp[0] == '\n' && ccp[1] == '\n') { break; } /* fuzzy: capital letter or a new command on next line ends brief */ if (ccp[0] == '\n' && ccp[1] == ' ' && ((ccp[2] >= 'A' && ccp[2] <= 'Z') || ccp[2] == '@' || ccp[2] == '\\')) { break; } temp[i] = *ccp; /* a sentence-ending period ends the brief comment */ if (ccp[0] == '.' && (ccp[1] == ' ' || ccp[1] == '\n')) { i++; ccp++; while (*ccp == ' ') { ccp++; } break; } ccp++; i++; } /* skip all blank lines */ while (*ccp == '\n') { ccp++; } if (*ccp == '\0') { ccp = NULL; } temp[i] = '\0'; fprintf(fp, " \"%s\\n\",\n", vtkWrapText_QuoteString( vtkWrapText_FormatComment(temp, 70), 500)); } else { fprintf(fp, " \"%s - no description provided.\\n\\n\",\n", vtkWrapText_QuoteString(data->Name, 500)); } /* only consider superclasses that are wrapped */ supername = vtkWrapPython_GetSuperClass(data, hinfo); if (supername) { vtkWrapPython_PyTemplateName(supername, pythonname); fprintf(fp, " \"Superclass: %s\\n\\n\",\n", vtkWrapText_QuoteString(pythonname, 500)); } if (data == file_info->MainClass && (file_info->Description || file_info->Caveats || file_info->SeeAlso)) { n = 100; if (file_info->Description) { n += strlen(file_info->Description); } if (file_info->Caveats) { n += strlen(file_info->Caveats); } if (file_info->SeeAlso) { n += strlen(file_info->SeeAlso); } comment = (char *)malloc(n); cp = comment; *cp = '\0'; if (file_info->Description) { strcpy(cp, file_info->Description); cp += strlen(cp); *cp++ = '\n'; *cp++ = '\n'; *cp = '\0'; } if (file_info->Caveats) { sprintf(cp, ".SECTION Caveats\n\n"); cp += strlen(cp); strcpy(cp, file_info->Caveats); cp += strlen(cp); *cp++ = '\n'; *cp++ = '\n'; *cp = '\0'; } if (file_info->SeeAlso) { sprintf(cp, ".SECTION See Also\n\n"); cp += strlen(cp); strcpy(cp, file_info->SeeAlso); cp += strlen(cp); *cp = '\0'; } ccp = vtkWrapText_FormatComment(comment, 70); free(comment); } else if (ccp) { ccp = vtkWrapText_FormatComment(ccp, 70); } if (ccp) { n = (strlen(ccp) + 400-1)/400; for (i = 0; i < n; i++) { strncpy(temp, &ccp[400*i], 400); temp[400] = '\0'; if (i < n-1) { fprintf(fp, " \"%s\",\n", vtkWrapText_QuoteString(temp, 500)); } else { /* just for the last time */ fprintf(fp, " \"%s\\n\",\n", vtkWrapText_QuoteString(temp, 500)); } } } /* for special objects, add constructor signatures to the doc */ if (!is_vtkobject && !data->Template && !data->IsAbstract) { for (j = 0; j < data->NumberOfFunctions; j++) { if (vtkWrapPython_MethodCheck(data, data->Functions[j], hinfo) && vtkWrap_IsConstructor(data, data->Functions[j])) { fprintf(fp," \"%s\\n\",\n", vtkWrapText_FormatSignature( data->Functions[j]->Signature, 70, 2000)); } } } }
/* convert a C++ templated type to pythonic dict form */ size_t vtkWrapPython_PyTemplateName(const char *name, char *pname) { unsigned int ctype = 0; const char *ptype = NULL; size_t i, j, n, m; /* skip const, volatile qualifiers */ for (;;) { if (strncmp(name, "const ", 6) == 0) { name += 6; } else if (strncmp(name, "volatile ", 9) == 0) { name += 9; } else { break; } } /* convert basic types to their VTK_PARSE constants */ n = vtkParse_BasicTypeFromString(name, &ctype, NULL, NULL); /* convert to pythonic equivalents (borrowed from numpy) */ switch (ctype & VTK_PARSE_BASE_TYPE) { case VTK_PARSE_BOOL: ptype = "bool"; break; case VTK_PARSE_CHAR: ptype = "char"; break; case VTK_PARSE_SIGNED_CHAR: ptype = "int8"; break; case VTK_PARSE_UNSIGNED_CHAR: ptype = "uint8"; break; case VTK_PARSE_SHORT: ptype = "int16"; break; case VTK_PARSE_UNSIGNED_SHORT: ptype = "uint16"; break; case VTK_PARSE_INT: ptype = "int32"; break; case VTK_PARSE_UNSIGNED_INT: ptype = "uint32"; break; case VTK_PARSE_LONG: ptype = "int"; /* python int is C long */ break; case VTK_PARSE_UNSIGNED_LONG: ptype = "uint"; break; case VTK_PARSE_LONG_LONG: case VTK_PARSE___INT64: ptype = "int64"; break; case VTK_PARSE_UNSIGNED_LONG_LONG: case VTK_PARSE_UNSIGNED___INT64: ptype = "uint64"; break; case VTK_PARSE_FLOAT: ptype = "float32"; break; case VTK_PARSE_DOUBLE: ptype = "float64"; break; } /* if type was a simple type, then we're done */ if (ptype) { strcpy(pname, ptype); return n; } /* look for VTK types that become common python types */ if ((n == 12 && strncmp(name, "vtkStdString", n) == 0) || (n == 11 && strncmp(name, "std::string", n) == 0) #ifndef VTK_LEGACY_REMOVE || (n == 14 && strncmp(name, "vtkstd::string", n) == 0) #endif ) { strcpy(pname, "str"); return n; } else if (n == 16 && strncmp(name, "vtkUnicodeString", n) == 0) { strcpy(pname, "unicode"); return n; } /* check whether name is templated */ for (i = 0; i < n; i++) { if (name[i] == '<') { break; } } strncpy(pname, name, i); if (name[i] != '<') { pname[i] = '\0'; return i; } /* if templated, subst '[' for '<' */ pname[i++] = '['; j = i; m = 1; while (i < n && m != 0 && name[i] != '>') { if (name[i] >= '0' && name[i] <= '9') { /* incomplete: only does decimal integers */ do { pname[j++] = name[i++]; } while (name[i] >= '0' && name[i] <= '9'); while (name[i] == 'u' || name[i] == 'l' || name[i] == 'U' || name[i] == 'L') { i++; } } else { m = vtkWrapPython_PyTemplateName(&name[i], &pname[j]); i += m; j = strlen(pname); } while (name[i] == ' ' || name[i] == '\t') { i++; } if (name[i] == ',') { pname[j++] = name[i++]; } while (name[i] == ' ' || name[i] == '\t') { i++; } } if (name[i] == '>') { i++; pname[j++] = ']'; } pname[j] = '\0'; return i; }
/* Create the docstring for a class, and print it to fp */ void vtkWrapPython_ClassDoc( FILE *fp, FileInfo *file_info, ClassInfo *data, HierarchyInfo *hinfo, int is_vtkobject) { char pythonname[1024]; const char *supername; char *cp; const char *ccp; size_t i, n; int j; char temp[500]; char *comment; if (file_info->NameComment) { fprintf(fp, " \"%s\\n\",\n", vtkWrapText_QuoteString( vtkWrapText_FormatComment(file_info->NameComment, 70), 500)); } else { fprintf(fp, " \"%s - no description provided.\\n\\n\",\n", vtkWrapText_QuoteString(data->Name, 500)); } /* only consider superclasses that are wrapped */ supername = vtkWrapPython_GetSuperClass(data, hinfo); if (supername) { vtkWrapPython_PyTemplateName(supername, pythonname); fprintf(fp, " \"Superclass: %s\\n\\n\",\n", vtkWrapText_QuoteString(pythonname, 500)); } n = 100; if (file_info->Description) { n += strlen(file_info->Description); } if (file_info->Caveats) { n += strlen(file_info->Caveats); } if (file_info->SeeAlso) { n += strlen(file_info->SeeAlso); } comment = (char *)malloc(n); cp = comment; *cp = '\0'; if (file_info->Description) { strcpy(cp, file_info->Description); cp += strlen(cp); *cp++ = '\n'; *cp++ = '\n'; *cp = '\0'; } if (file_info->Caveats) { sprintf(cp, ".SECTION Caveats\n\n"); cp += strlen(cp); strcpy(cp, file_info->Caveats); cp += strlen(cp); *cp++ = '\n'; *cp++ = '\n'; *cp = '\0'; } if (file_info->SeeAlso) { sprintf(cp, ".SECTION See Also\n\n"); cp += strlen(cp); strcpy(cp, file_info->SeeAlso); cp += strlen(cp); *cp = '\0'; } ccp = vtkWrapText_FormatComment(comment, 70); free(comment); n = (strlen(ccp) + 400-1)/400; for (i = 0; i < n; i++) { strncpy(temp, &ccp[400*i], 400); temp[400] = '\0'; if (i < n-1) { fprintf(fp, " \"%s\",\n", vtkWrapText_QuoteString(temp, 500)); } else { /* just for the last time */ fprintf(fp, " \"%s\\n\",\n", vtkWrapText_QuoteString(temp, 500)); } } /* for special objects, add constructor signatures to the doc */ if (!is_vtkobject && !data->Template && !data->IsAbstract) { for (j = 0; j < data->NumberOfFunctions; j++) { if (vtkWrapPython_MethodCheck(data, data->Functions[j], hinfo) && vtkWrap_IsConstructor(data, data->Functions[j])) { fprintf(fp," \"%s\\n\",\n", vtkWrapText_FormatSignature( data->Functions[j]->Signature, 70, 2000)); } } } }
/* Wrap a templated class */ int vtkWrapPython_WrapTemplatedClass( FILE *fp, ClassInfo *data, FileInfo *file_info, HierarchyInfo *hinfo) { char classname[1024]; const char *instantiations[1024]; int ninstantiations = 0; int i, j, k, nargs; ClassInfo *sdata; ValueInfo *tdef; HierarchyEntry *entry; const char *name; char *cp; const char **args; const char **defaults; const char *modulename; const char *name_with_args; int is_vtkobject = 0; const char **types; /* do not directly wrap vtkTypeTemplate */ if (strcmp(data->Name, "vtkTypeTemplate") == 0) { return 0; } if (hinfo == 0) { return 0; } entry = vtkParseHierarchy_FindEntry(hinfo, data->Name); if (entry == 0) { return 0; } modulename = entry->Module; defaults = entry->TemplateDefaults; /* find all instantiations from derived classes */ for (j = 0; j < hinfo->NumberOfEntries; j++) { entry = &hinfo->Entries[j]; classname[0] = '\0'; /* skip enum entries */ if (entry->IsEnum) { continue; } /* look for typedefs of template instantiations */ if (entry->IsTypedef) { tdef = entry->Typedef; if ((tdef->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_OBJECT && entry->NumberOfTemplateParameters == 0) { if (tdef->Class && tdef->Class[0] != '\0' && tdef->Class[strlen(tdef->Class) - 1] == '>') { strcpy(classname, tdef->Class); entry = vtkParseHierarchy_FindEntry(hinfo, classname); } } if (!entry || entry->IsTypedef || entry->IsEnum) { continue; } } nargs = entry->NumberOfTemplateParameters; args = entry->TemplateParameters; if (strcmp(entry->Module, modulename) == 0 && (entry->NumberOfSuperClasses == 1 || strcmp(entry->Name, data->Name) == 0)) { types = NULL; /* only do these classes directly */ if (strcmp(entry->Name, "vtkDenseArray") == 0 || strcmp(entry->Name, "vtkSparseArray") == 0) { types = vtkParse_GetArrayTypes(); } else if (strcmp(entry->Name, "vtkTuple") == 0) { static const char *tuple_types[13] = { "unsigned char, 2", "unsigned char, 3", "unsigned char, 4", "int, 2", "int, 3", "int, 4", "float, 2", "float, 3", "float, 4", "double, 2", "double, 3", "double, 4", NULL }; types = tuple_types; } /* do all other templated classes indirectly */ else if (nargs > 0) { continue; } for (i = 0; i == 0 || (types && types[i] != NULL); i++) { /* make the classname, with template args if present */ if (classname[0] == '\0') { if (nargs == 0) { sprintf(classname, "%s", entry->Name); } else { sprintf(classname, "%s<%s>", entry->Name, types[i]); } } name_with_args = NULL; if (strcmp(data->Name, entry->Name) == 0) { /* entry is the same as data */ cp = (char *)malloc(strlen(classname) + 1); strcpy(cp, classname); name_with_args = cp; } else { /* entry is not data, see if it is a subclass, and if so, * what template args of 'data' it corresponds to */ vtkParseHierarchy_IsTypeOfTemplated( hinfo, entry, classname, data->Name, &name_with_args); } if (name_with_args) { /* append to the list of instantiations if not present yet */ for (k = 0; k < ninstantiations; k++) { if (strcmp(name_with_args, instantiations[k]) == 0) { break; } } if (k == ninstantiations) { instantiations[ninstantiations++] = name_with_args; } else { free((char *)name_with_args); } } classname[0] = '\0'; } } } if (ninstantiations) { for (k = 0; k < ninstantiations; k++) { entry = vtkParseHierarchy_FindEntry(hinfo, instantiations[k]); is_vtkobject = vtkParseHierarchy_IsTypeOfTemplated( hinfo, entry, instantiations[k], "vtkObjectBase", NULL); nargs = data->Template->NumberOfParameters; vtkParse_DecomposeTemplatedType(instantiations[k], &name, nargs, &args, defaults); sdata = (ClassInfo *)malloc(sizeof(ClassInfo)); vtkParse_CopyClass(sdata, data); vtkParse_InstantiateClassTemplate(sdata, file_info->Strings, nargs, args); vtkWrapText_PythonName(instantiations[k], classname); vtkWrapPython_WrapOneClass( fp, modulename, classname, sdata, file_info, hinfo, is_vtkobject); vtkParse_FreeClass(sdata); vtkParse_FreeTemplateDecomposition(name, nargs, args); } /* the docstring for the templated class */ fprintf(fp, "static const char *Py%s_Doc[] = {\n", data->Name); vtkWrapPython_ClassDoc(fp, file_info, data, hinfo, is_vtkobject); fprintf(fp, " \"\\nProvided Types:\\n\\n\",\n"); for (k = 0; k < ninstantiations; k++) { vtkWrapPython_PyTemplateName(instantiations[k], classname); fprintf(fp, " \" %s => %s\\n\",\n", classname, instantiations[k]); } fprintf(fp, " NULL\n" "};\n" "\n"); fprintf(fp, "PyObject *Py%s_TemplateNew()\n" "{\n" " PyObject *o;\n" "\n" " PyObject *temp = PyVTKTemplate_New(\"%sPython.%s\",\n" " Py%s_Doc);\n" "\n", data->Name, modulename, data->Name, data->Name); for (k = 0; k < ninstantiations; k++) { vtkWrapText_PythonName(instantiations[k], classname); entry = vtkParseHierarchy_FindEntry(hinfo, instantiations[k]); if (vtkParseHierarchy_IsTypeOfTemplated( hinfo, entry, instantiations[k], "vtkObjectBase", NULL)) { fprintf(fp, " o = Py%s_ClassNew();\n", classname); } else { fprintf(fp, " o = Py%s_TypeNew();\n", classname); } fprintf(fp, " if (o && PyVTKTemplate_AddItem(temp, o) != 0)\n" " {\n" " Py_DECREF(o);\n" " }\n" "\n"); free((char *)instantiations[k]); } fprintf(fp, " return temp;\n" "}\n" "\n"); return 1; } return 0; }