Files
ThirdParty-6/ParaView-5.0.1/Utilities/WrapClientServer/vtkWrapClientServer.c

1385 lines
42 KiB
C

/*=========================================================================
Program: ParaView
Module: vtkWrapClientServer.c
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "vtkParse.h"
#include "vtkParseHierarchy.h"
#include "vtkParseMain.h"
#include "vtkWrap.h"
int numberOfWrappedFunctions = 0;
FunctionInfo *wrappedFunctions[1000];
extern FunctionInfo *currentFunction;
HierarchyInfo *hierarchyInfo = NULL;
/* make a guess about whether a class is wrapped */
static int class_is_wrapped(const char *classname)
{
HierarchyEntry *entry;
if (hierarchyInfo)
{
entry = vtkParseHierarchy_FindEntry(hierarchyInfo, classname);
if (entry)
{
/* only allow non-excluded vtkObjects as args */
if (vtkParseHierarchy_GetProperty(entry, "WRAP_EXCLUDE") ||
!vtkParseHierarchy_IsTypeOf(hierarchyInfo, entry, "vtkObjectBase"))
{
return 0;
}
}
}
return 1;
}
int arg_is_pointer_to_data(unsigned int argType, int count)
{
return
(count == 0 &&
(argType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER && /* T* */
(argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_STRING && /* vtkStdString* */
(argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_VOID && /* void* */
(argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_CHAR && /* char* */
(argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_BOOL && /* bool* */
(argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_UNKNOWN && /* Foo* */
(argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_VTK_OBJECT /* vtkFoo* */);
}
void output_temp(FILE *fp, int i, unsigned int argType, const char *Id,
int count)
{
/* Store whether this is pointer to data. */
int isPointerToData = i != MAX_ARGS && arg_is_pointer_to_data(argType, count);
/* ignore void */
if (((argType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_VOID) &&
((argType & VTK_PARSE_INDIRECT) == 0))
{
return;
}
/* for const * return types prototype with const */
if ((i == MAX_ARGS) && ((argType & VTK_PARSE_CONST) != 0))
{
fprintf(fp," const ");
}
else
{
fprintf(fp," ");
}
/* Handle some objects of known type. */
if(((argType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_VTK_OBJECT) &&
(((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER) ||
((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_REF)) &&
strcmp(Id, "vtkClientServerStream") == 0)
{
fprintf(fp, "vtkClientServerStream temp%i_inst, *temp%i = &temp%i_inst;\n",
i, i, i);
return;
}
/* Start pointer-to-data arguments. */
if(isPointerToData)
{
fprintf(fp, "vtkClientServerStreamDataArg<");
}
if (argType & VTK_PARSE_UNSIGNED)
{
fprintf(fp,"unsigned ");
}
switch ((argType & VTK_PARSE_BASE_TYPE) & ~VTK_PARSE_UNSIGNED)
{
case VTK_PARSE_FLOAT: fprintf(fp,"float "); break;
case VTK_PARSE_DOUBLE: fprintf(fp,"double "); break;
case VTK_PARSE_INT: fprintf(fp,"int "); break;
case VTK_PARSE_SHORT: fprintf(fp,"short "); break;
case VTK_PARSE_LONG: fprintf(fp,"long "); break;
case VTK_PARSE_VOID: fprintf(fp,"void "); break;
case VTK_PARSE_CHAR: fprintf(fp,"char "); break;
case VTK_PARSE_ID_TYPE: fprintf(fp,"vtkIdType "); break;
case VTK_PARSE_LONG_LONG: fprintf(fp,"long long "); break;
case VTK_PARSE___INT64: fprintf(fp,"__int64 "); break;
case VTK_PARSE_SIGNED_CHAR: fprintf(fp,"signed char "); break;
case VTK_PARSE_BOOL: fprintf(fp,"bool "); break;
case VTK_PARSE_VTK_OBJECT: fprintf(fp,"%s ",Id); break;
case VTK_PARSE_STRING:
if (i == MAX_ARGS) { fprintf(fp,"%s ",Id); break; }
else { fprintf(fp,"char *"); } break;
case VTK_PARSE_UNKNOWN: return;
}
/* Finish pointer-to-data arguments. */
if(isPointerToData)
{
fprintf(fp, "> temp%i(msg, 0, %i);\n", i, i+2);
return;
}
/* handle array arguements */
if (count > 1)
{
fprintf(fp,"temp%i[%i];\n",i,count);
return;
}
switch (argType & VTK_PARSE_INDIRECT)
{
case VTK_PARSE_REF:
if (i == MAX_ARGS)
{
fprintf(fp, " *"); /* act " &" */
}
break;
case VTK_PARSE_POINTER: fprintf(fp, " *"); break;
case VTK_PARSE_POINTER_REF: fprintf(fp, "*&"); break;
case VTK_PARSE_POINTER_POINTER: fprintf(fp, "**"); break;
default: fprintf(fp," "); break;
}
fprintf(fp,"temp%i",i);
fprintf(fp,";\n");
}
/* when the cpp file doesn't have enough info use the hint file */
void use_hints(FILE *fp)
{
unsigned int rType = currentFunction->ReturnType;
/* use the hint */
if ((rType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER)
{
switch (rType & VTK_PARSE_BASE_TYPE)
{
case VTK_PARSE_FLOAT: case VTK_PARSE_DOUBLE:
case VTK_PARSE_INT: case VTK_PARSE_SHORT: case VTK_PARSE_LONG:
case VTK_PARSE_ID_TYPE:
case VTK_PARSE_LONG_LONG: case VTK_PARSE___INT64:
case VTK_PARSE_UNSIGNED_CHAR: case VTK_PARSE_SIGNED_CHAR:
case VTK_PARSE_UNSIGNED_INT: case VTK_PARSE_UNSIGNED_SHORT:
case VTK_PARSE_UNSIGNED_LONG: case VTK_PARSE_UNSIGNED_ID_TYPE:
case VTK_PARSE_UNSIGNED_LONG_LONG: case VTK_PARSE_UNSIGNED___INT64:
fprintf(fp,
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Reply << vtkClientServerStream::InsertArray(temp%i,%i) << vtkClientServerStream::End;\n", MAX_ARGS, currentFunction->HintSize);
break;
}
}
}
void return_result(FILE *fp)
{
unsigned int rType = currentFunction->ReturnType;
const char *rClass = currentFunction->ReturnClass;
switch (rType & VTK_PARSE_BASE_TYPE)
{
case VTK_PARSE_VOID:
if ((rType & VTK_PARSE_INDIRECT) == 0)
{
return;
}
break;
case VTK_PARSE_FLOAT: case VTK_PARSE_CHAR: case VTK_PARSE_INT:
case VTK_PARSE_SHORT: case VTK_PARSE_LONG: case VTK_PARSE_DOUBLE:
case VTK_PARSE_ID_TYPE:
case VTK_PARSE_LONG_LONG: case VTK_PARSE___INT64:
case VTK_PARSE_SIGNED_CHAR: case VTK_PARSE_BOOL:
case VTK_PARSE_UNSIGNED_CHAR: case VTK_PARSE_UNSIGNED_INT:
case VTK_PARSE_UNSIGNED_SHORT: case VTK_PARSE_UNSIGNED_LONG:
case VTK_PARSE_UNSIGNED_ID_TYPE:
case VTK_PARSE_UNSIGNED_LONG_LONG: case VTK_PARSE_UNSIGNED___INT64:
case VTK_PARSE_STRING:
if ((rType & VTK_PARSE_INDIRECT) == 0 ||
(((rType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_CHAR) &&
((rType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER)))
{
fprintf(fp,
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Reply << temp%i << vtkClientServerStream::End;\n",
MAX_ARGS);
return;
}
else if ((rType & VTK_PARSE_INDIRECT) == VTK_PARSE_REF)
{
fprintf(fp,
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Reply << *temp%i << vtkClientServerStream::End;\n",
MAX_ARGS);
return;
}
else if ((rType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER)
{
/* handle functions returning vectors */
/* this is done by looking them up in a hint file */
use_hints(fp);
return;
}
break;
case VTK_PARSE_VTK_OBJECT:
/* Handle some objects of known type. */
if(strcmp(rClass, "vtkClientServerStream") == 0)
{
fprintf(fp,
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Reply << *temp%i << vtkClientServerStream::End;\n",
MAX_ARGS);
return;
}
else if ((rType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER)
{
fprintf(fp,
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Reply << (vtkObjectBase *)temp%i << vtkClientServerStream::End;\n",MAX_ARGS);
return;
}
break;
}
/* if we get to here, then the type was not recognized */
fprintf(fp,
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Reply\n"
" << \"unable to return result of type(%#x).\"\n"
" << vtkClientServerStream::End;\n",
(rType & VTK_PARSE_UNQUALIFIED_TYPE));
}
void get_args(FILE *fp, int i)
{
unsigned int argType = currentFunction->ArgTypes[i];
int argCount = currentFunction->ArgCounts[i];
const char *argClass = currentFunction->ArgClasses[i];
int j;
int start_arg = 2;
/* what arg do we start with */
for (j = 0; j < i; j++)
{
start_arg = start_arg +
(currentFunction->ArgCounts[j] ? currentFunction->ArgCounts[j] : 1);
}
/* ignore void */
if (((argType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_VOID) &&
((argType & VTK_PARSE_INDIRECT) == 0))
{
return;
}
switch (argType & VTK_PARSE_BASE_TYPE)
{
case VTK_PARSE_FLOAT:
case VTK_PARSE_DOUBLE:
case VTK_PARSE_INT:
case VTK_PARSE_SHORT:
case VTK_PARSE_LONG:
case VTK_PARSE_ID_TYPE:
case VTK_PARSE_LONG_LONG:
case VTK_PARSE___INT64:
case VTK_PARSE_SIGNED_CHAR:
case VTK_PARSE_BOOL:
case VTK_PARSE_CHAR:
case VTK_PARSE_UNSIGNED_CHAR:
case VTK_PARSE_UNSIGNED_INT:
case VTK_PARSE_UNSIGNED_SHORT:
case VTK_PARSE_UNSIGNED_LONG:
case VTK_PARSE_UNSIGNED_ID_TYPE:
case VTK_PARSE_UNSIGNED_LONG_LONG:
case VTK_PARSE_UNSIGNED___INT64:
case VTK_PARSE_STRING:
if (((argType & VTK_PARSE_INDIRECT) == 0) ||
((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_REF) ||
(((argType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_CHAR) &&
((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER)))
{
fprintf(fp, "msg.GetArgument(0, %i, &temp%i)", i+2, i);
}
else if (((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER) &&
(argCount > 1))
{
fprintf(fp, "msg.GetArgument(0, %i, temp%i, %i)", i+2, i, argCount);
}
else if (((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER) &&
(arg_is_pointer_to_data(argType, argCount)))
{
/* Pointer-to-data arguments are handled by an object
convertible to bool. */
fprintf(fp, "temp%i", i);
}
break;
case VTK_PARSE_VTK_OBJECT:
/* Handle some objects of known type. */
if ((((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_REF) ||
((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER)) &&
strcmp(argClass, "vtkClientServerStream") == 0)
{
fprintf(fp,
"msg.GetArgument(0, %i, temp%i)", i+2, i);
}
else if ((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER)
{
fprintf(fp,
"vtkClientServerStreamGetArgumentObject(msg, 0, %i, &temp%i, \"%s\")",
i+2, i, argClass);
}
break;
case VTK_PARSE_VOID:
case VTK_PARSE_UNKNOWN:
break;
}
}
/* declare these so they can be used in outputFunction */
int managableArguments(FunctionInfo *curFunction);
int notWrappable(FunctionInfo *curFunction);
void outputFunction(FILE *fp, ClassInfo *data)
{
int i;
if (notWrappable(currentFunction))
{
return;
}
/* if the args are OK and it is not a constructor or destructor */
if (managableArguments(currentFunction) &&
strcmp(data->Name,currentFunction->Name) &&
strcmp(data->Name,currentFunction->Name + 1))
{
if(currentFunction->IsLegacy)
{
fprintf(fp,"#if !defined(VTK_LEGACY_REMOVE)\n");
}
fprintf(fp," if (!strcmp(\"%s\",method) && msg.GetNumberOfArguments(0) == %i)\n",
currentFunction->Name, currentFunction->NumberOfArguments+2);
fprintf(fp, " {\n");
/* process the args */
for (i = 0; i < currentFunction->NumberOfArguments; i++)
{
output_temp(fp, i, currentFunction->ArgTypes[i],
currentFunction->ArgClasses[i],
currentFunction->ArgCounts[i]);
}
output_temp(fp, MAX_ARGS,currentFunction->ReturnType,
currentFunction->ReturnClass, 0);
if(currentFunction->NumberOfArguments > 0)
{
const char* amps = " if(";
/* now get the required args from the stack */
for (i = 0; i < currentFunction->NumberOfArguments; i++)
{
fprintf(fp, "%s", amps);
amps = " &&\n ";
get_args(fp,i);
}
fprintf(fp, ")\n");
}
fprintf(fp, " {\n");
if ((currentFunction->ReturnType & VTK_PARSE_UNQUALIFIED_TYPE) ==
VTK_PARSE_VOID)
{
fprintf(fp," op->%s(",currentFunction->Name);
}
else if ((currentFunction->ReturnType & VTK_PARSE_INDIRECT) ==
VTK_PARSE_REF)
{
fprintf(fp," temp%i = &(op)->%s(",MAX_ARGS,currentFunction->Name);
}
else
{
fprintf(fp," temp%i = (op)->%s(",MAX_ARGS,currentFunction->Name);
}
for (i = 0; i < currentFunction->NumberOfArguments; i++)
{
if (i)
{
fprintf(fp,",");
}
if (((currentFunction->ArgTypes[i] & VTK_PARSE_INDIRECT)
== VTK_PARSE_REF) &&
((currentFunction->ArgTypes[i] & VTK_PARSE_BASE_TYPE)
== VTK_PARSE_VTK_OBJECT))
{
fprintf(fp,"*(temp%i)",i);
}
else if ((((currentFunction->ArgTypes[i] & VTK_PARSE_INDIRECT) == 0) ||
((currentFunction->ArgTypes[i] & VTK_PARSE_INDIRECT) ==
VTK_PARSE_REF)) &&
((currentFunction->ArgTypes[i] & VTK_PARSE_BASE_TYPE) ==
VTK_PARSE_STRING))
{
/* explicit construction avoids possible ambiguity */
fprintf(fp,"vtkStdString(temp%i)",i);
}
else
{
fprintf(fp,"temp%i",i);
}
}
fprintf(fp,");\n");
return_result(fp);
fprintf(fp," return 1;\n");
fprintf(fp," }\n");
fprintf(fp," }\n");
if(currentFunction->IsLegacy)
{
fprintf(fp,"#endif\n");
}
wrappedFunctions[numberOfWrappedFunctions] = currentFunction;
numberOfWrappedFunctions++;
}
#if 0
if (!strcmp("vtkObject",data->Name))
{
fprintf(fp," if (!strcmp(\"AddProgressObserver\",method) && msg.NumberOfArguments == 3 &&\n");
fprintf(fp," msg.ArgumentTypes[2] == vtkClietnServerStream::string_value)\n");
fprintf(fp," {\n");
fprintf(fp," vtkClientServerProgressObserver *apo = vtkClientServerProgressObserver::New();\n");
fprintf(fp," vtkObject* obj = arlu->GetObjectFromMessage(msg, 0, 1);\n");
fprintf(fp," apo->SetFilterID(arlu->GetIDFromObject(obj));\n");
fprintf(fp," apo->SetClientServerUtil(arlu);\n");
fprintf(fp," char *temp0 = vtkClientServerInterpreter::GetString(msg,2);\n");
fprintf(fp," op->AddObserver(temp0,apo);\n");
fprintf(fp," apo->Delete();\n");
fprintf(fp," delete [] temp0;\n");
fprintf(fp," return 1;\n");
fprintf(fp," }\n");
}
#endif
}
//--------------------------------------------------------------------------nix
/*
* This structure is used internally to sort+collect individual functions.
* Polymorphed functions will be combined and can be handeled together.
*
*/
typedef struct _UniqueFunctionInfo
{
const char *Name;
int TotalPolymorphTypes;
FunctionInfo *Function[20];
} UniqueFunctionInfo;
//--------------------------------------------------------------------------nix
/*
* This structure is used to collect and hold class information. It is a
* modified version of FileInfo
*
*/
typedef struct _NewClassInfo
{
int HasDelete;
int IsAbstract;
int IsConcrete;
const char *ClassName;
const char *FileName;
const char *OutputFileName;
const char *SuperClasses[10];
int NumberOfSuperClasses;
int NumberOfFunctions;
UniqueFunctionInfo Functions[1000];
const char *NameComment;
const char *Description;
const char *Caveats;
const char *SeeAlso;
} NewClassInfo;
//--------------------------------------------------------------------------nix
/*
* notWrappable returns true if the current-function is not wrappable.
*
* @param curFunction function-info being worked on
*
* @return true if the function is not wrappable
*/
int notWrappable(FunctionInfo *curFunction)
{
return (curFunction->IsOperator ||
curFunction->ArrayFailure ||
!curFunction->IsPublic ||
!curFunction->Name);
}
//--------------------------------------------------------------------------nix
/*
* managableArguments check if the functions arguments are in a form
* which can easily be used for automatic wrapper generation.
*
* @param curFunction the function beign worked on
*
* @return true if the arguments are okay for code generation
*/
int managableArguments(FunctionInfo *curFunction)
{
static unsigned int supported_types[] = {
VTK_PARSE_VOID, VTK_PARSE_BOOL, VTK_PARSE_FLOAT, VTK_PARSE_DOUBLE,
VTK_PARSE_CHAR, VTK_PARSE_UNSIGNED_CHAR, VTK_PARSE_SIGNED_CHAR,
VTK_PARSE_INT, VTK_PARSE_UNSIGNED_INT,
VTK_PARSE_SHORT, VTK_PARSE_UNSIGNED_SHORT,
VTK_PARSE_LONG, VTK_PARSE_UNSIGNED_LONG,
VTK_PARSE_ID_TYPE, VTK_PARSE_UNSIGNED_ID_TYPE,
VTK_PARSE_LONG_LONG, VTK_PARSE_UNSIGNED_LONG_LONG,
VTK_PARSE___INT64, VTK_PARSE_UNSIGNED___INT64,
VTK_PARSE_VTK_OBJECT, VTK_PARSE_STRING,
0
};
int i, j;
int args_ok = 1;
unsigned int returnType = 0;
unsigned int argType = 0;
unsigned int baseType = 0;
/* check to see if we can handle the args */
for (i = 0; i < curFunction->NumberOfArguments; i++)
{
int isPointerToData = arg_is_pointer_to_data(curFunction->ArgTypes[i],
curFunction->ArgCounts[i]);
argType = (curFunction->ArgTypes[i] & VTK_PARSE_UNQUALIFIED_TYPE);
baseType = (argType & VTK_PARSE_BASE_TYPE);
if (curFunction->ArgTypes[i] != VTK_PARSE_FUNCTION)
{
for (j = 0; supported_types[j] != 0; j++)
{
if (baseType == supported_types[j]) { break; }
}
if (supported_types[j] == 0)
{
args_ok = 0;
}
}
/* if its a pointer arg make sure we have the ArgCount */
if (((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER) &&
!isPointerToData &&
((argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_CHAR) &&
((argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_VTK_OBJECT))
{
if (curFunction->NumberOfArguments > 1 ||
curFunction->ArgCounts[i] == 0 ||
((argType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_STRING))
{
args_ok = 0;
}
}
/* if it has a reference arg, don't wrap it */
if ((argType & VTK_PARSE_INDIRECT) == VTK_PARSE_REF)
{
/* make exception for "vtkClientServerStream&" */
if (((argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_VTK_OBJECT) ||
strcmp(curFunction->ArgClasses[i], "vtkClientServerStream"))
{
/* also make exception for "const vtkStdString&" */
if ((argType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_STRING ||
(curFunction->ArgTypes[i] & VTK_PARSE_CONST) == 0)
{
args_ok = 0;
}
}
}
/* if it is a vtk object that isn't a pointer or ref, don't wrap it */
if (((argType & VTK_PARSE_INDIRECT) == 0) &&
((argType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_VTK_OBJECT))
{
args_ok = 0;
}
/* if arg is a vtk object, make sure it is a wrapped object */
if ((argType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_VTK_OBJECT &&
!class_is_wrapped(curFunction->ArgClasses[i]))
{
args_ok = 0;
}
/* if it is "**" or "*&" then don't wrap it */
if (((argType & VTK_PARSE_INDIRECT) != 0) &&
((argType & VTK_PARSE_INDIRECT) != VTK_PARSE_POINTER) &&
((argType & VTK_PARSE_INDIRECT) != VTK_PARSE_REF))
{
args_ok = 0;
}
/* if it is an array of chars, then don't wrap it */
if ((argType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_CHAR &&
curFunction->ArgCounts[i] != 0)
{
args_ok = 0;
}
if ((argType & VTK_PARSE_UNSIGNED) &&
(argType != VTK_PARSE_UNSIGNED_CHAR)&&
(argType != VTK_PARSE_UNSIGNED_INT)&&
(argType != VTK_PARSE_UNSIGNED_SHORT)&&
(argType != VTK_PARSE_UNSIGNED_LONG)&&
(argType != VTK_PARSE_UNSIGNED_ID_TYPE)&&
!isPointerToData)
{
args_ok = 0;
}
}
/* check the return type */
returnType = (curFunction->ReturnType & VTK_PARSE_UNQUALIFIED_TYPE);
baseType = (returnType & VTK_PARSE_BASE_TYPE);
for (j = 0; supported_types[j] != 0; j++)
{
if (baseType == supported_types[j]) { break; }
}
if (supported_types[j] == 0)
{
args_ok = 0;
}
/* if it is a reference, then don't wrap it */
if ((returnType & VTK_PARSE_INDIRECT) == VTK_PARSE_REF)
{
/* make exception for "vtkClientServerStream&" */
if (((returnType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_VTK_OBJECT) ||
strcmp(curFunction->ReturnClass, "vtkClientServerStream"))
{
/* also make exception for "vtkStdString" */
if ((returnType & VTK_PARSE_BASE_TYPE) != VTK_PARSE_STRING)
{
args_ok = 0;
}
}
}
/* if it is a vtk object that isn't a pointer, don't wrap it */
if (((returnType & VTK_PARSE_INDIRECT) == 0) &&
((returnType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_VTK_OBJECT))
{
args_ok = 0;
}
/* if arg is a vtk object, make sure it is a wrapped object */
if ((returnType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_VTK_OBJECT &&
!class_is_wrapped(curFunction->ReturnClass))
{
args_ok = 0;
}
/* if it is "**" or "*&" then don't wrap it */
if (((returnType & VTK_PARSE_INDIRECT) != 0) &&
((returnType & VTK_PARSE_INDIRECT) != VTK_PARSE_POINTER) &&
((returnType & VTK_PARSE_INDIRECT) != VTK_PARSE_REF))
{
args_ok = 0;
}
/* cannot wrap function pointers */
if (curFunction->NumberOfArguments &&
(curFunction->ArgTypes[0] == VTK_PARSE_FUNCTION))
{
args_ok = 0;
}
/* we can't handle void * return types */
if (((returnType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_VOID) &&
((returnType & VTK_PARSE_INDIRECT) != 0))
{
args_ok = 0;
}
/* watch out for functions that dont have enough info */
if ((returnType & VTK_PARSE_INDIRECT) == VTK_PARSE_POINTER)
{
switch (returnType & VTK_PARSE_BASE_TYPE)
{
case VTK_PARSE_FLOAT: case VTK_PARSE_DOUBLE:
case VTK_PARSE_INT: case VTK_PARSE_SHORT:
case VTK_PARSE_LONG: case VTK_PARSE_ID_TYPE:
case VTK_PARSE_LONG_LONG: case VTK_PARSE___INT64:
case VTK_PARSE_SIGNED_CHAR: case VTK_PARSE_UNSIGNED_CHAR:
case VTK_PARSE_UNSIGNED_INT: case VTK_PARSE_UNSIGNED_SHORT:
case VTK_PARSE_UNSIGNED_LONG: case VTK_PARSE_UNSIGNED_ID_TYPE:
case VTK_PARSE_UNSIGNED_LONG_LONG: case VTK_PARSE_UNSIGNED___INT64:
args_ok = curFunction->HaveHint;
break;
case VTK_PARSE_CHAR:
case VTK_PARSE_VTK_OBJECT:
break;
default:
args_ok = 0;
break;
}
}
return args_ok;
}
//--------------------------------------------------------------------------nix
/*
* funCmp is used to compare the function names of two FunInfo data.
* This is used as a utility to the sort function.
*
* @param fun1 first function data which is compared
* @param fun2 second function data which is compared
*
* @return values returned by strcmp
*/
int funCmp(const void *fun1, const void *fun2)
{
FunctionInfo *a = (FunctionInfo*)fun1;
FunctionInfo *b = (FunctionInfo*)fun2;
return strcmp(a->Name,b->Name);
}
//--------------------------------------------------------------------------nix
/*
* copy copies data from the source array to the destination
*
* @param from the source array from which we want to copy data
* @param fromSize the size of the source array
* @param to the destination to which we wanto to copy the data
*
* @return the size of the destination array
*/
/*
int copy(FunctionInfo* from, int fromSize, FunctionInfo* to)
{
int i;
for (i=0 ; i<fromSize;i++)
{
to[i] = from[i];
}
return i;
}
*/
//--------------------------------------------------------------------------nix
/*
* extractWrappable copies data from the source array to the destination
* array and removes unwrappable functions whenever encountered.
* It returns the count of the destination array.
*
* @param from the source array from which we want to extract data
* @param fromSize the size of the source array
* @param to the destination to which we wanto to copy extracted data
*
* @return the size of the destination array (this may not be the size of the source)
*/
int extractWrappable(FunctionInfo* from[],
int fromSize,
FunctionInfo* to[],
const char* ClassName)
{
int i,j;
for (i=0,j=0 ; i<fromSize ;i++)
{
/* if the function is wrappable and
args are OK and
it is not a constructor or destructor */
if(!notWrappable(from[i]) &&
managableArguments(from[i]) &&
strcmp(ClassName,from[i]->Name) && strcmp(ClassName,from[i]->Name + 1))
{
to[j] = from[i];
++j;
}
}
return j;
}
//--------------------------------------------------------------------------nix
/*
* collectUniqueFunctionInfo collects unique function. Polymorphed functions
* are grouped in the UniqueFunctionInfo structure.
*
* @param src source data array with all applicable function info
* @param srcSize the size of the array holding this info
* @param dest the destnation array to store the extracted info
*
* @return the total number of elements in the dest array
*/
int collectUniqueFunctionInfo(FunctionInfo *src[], int srcSize, UniqueFunctionInfo dest[])
{
int i,j,k;
for (i=0; i < srcSize; i++)
{
dest[i].Name = src[i]->Name;
dest[i].TotalPolymorphTypes = 1;
dest[i].Function[0] = src[i];
for(j=i+1; j < srcSize; j++)
{
if(strcmp(dest[i].Name, src[j]->Name) == 0)
{
//printf("%d [%d]> dest = %s :: src = %s\n",i,srcSize, dest[i].Name,src[j].Name);
//printf(" > [SAME]\n");
dest[i].Function[dest[i].TotalPolymorphTypes] = src[j];
dest[i].TotalPolymorphTypes++;
for(k=j; k < srcSize-1; k++)
{
//printf("remaining = %s\n",src[k]->Name);
src[k] = src[k+1];
}
j--;
srcSize--;
}
}
}
return srcSize;
}
//--------------------------------------------------------------------------nix
/*
* This is a format converter function which converts from traditional
* FileInfo format to NewClassInfo format. The NewClassInfo format combines
* polymorphed functions into UniqueFunctionInfo internal format.
*
* @param data hold the collected file data form the parser
* @param classData the form into which we want to convert
*/
void getClassInfo(FileInfo *fileInfo, ClassInfo *data, NewClassInfo* classData)
{
int i;
int TotalUniqueFunctions=0;
int TotalFunctions;
FunctionInfo **tempFun =(FunctionInfo**)malloc
(sizeof(FunctionInfo*)*data->NumberOfFunctions);
/* Collect all the information */
classData->HasDelete = data->HasDelete;
classData->IsAbstract = data->IsAbstract;
classData->IsConcrete = !data->IsAbstract;
classData->ClassName = data->Name;
classData->FileName = fileInfo->FileName;
classData->OutputFileName = "";
classData->NumberOfSuperClasses = data->NumberOfSuperClasses;
for (i = 0; i < data->NumberOfSuperClasses; ++i)
{
classData->SuperClasses[i] = data->SuperClasses[i];
}
classData->NameComment = fileInfo->NameComment;
classData->Description = fileInfo->Description;
classData->Caveats = fileInfo->Caveats;
classData->SeeAlso = fileInfo->SeeAlso;
/* Collect only wrappable functions*/
TotalFunctions = extractWrappable(data->Functions,
data->NumberOfFunctions,
tempFun,
data->Name);
/* Sort the function data. */
//qsort(tempFun,TotalFunctions,sizeof(FunctionInfo),funCmp);
/* for(i=0;i<TotalFunctions;i++) */
/* { */
/* printf("(funargs %s %d)\n",tempFun[i].Name,tempFun[i].NumberOfArguments); */
/* } */
// printf("START\n");
/* Collect unique and group polymorphed functions in UniqueFunctionInfo */
TotalUniqueFunctions = collectUniqueFunctionInfo(tempFun,
TotalFunctions,
classData->Functions);
// printf("END\n");
/* for(i=0;i<TotalUniqueFunctions;i++) */
/* { */
/* printf("(funargs %s %d)\n",tempFun[i].Name,tempFun[i].NumberOfArguments); */
/* } */
classData->NumberOfFunctions = TotalUniqueFunctions;
free(tempFun);
}
//--------------------------------------------------------------------------nix
/*
* Checks if the given string in unique in a list of strings
*
* @param main The main class name which is compared with others
* @param list The list which is compared with
* @param total total number of elements in the list
*
* @return 0 if found and 1 if not
*/
int isUniqueString(const char* main, const char *list[], int total)
{
int i;
for (i = 0; i < total; ++i)
{
if(strcmp(main,list[i])==0)
return 0;
}
return 1;
}
//--------------------------------------------------------------------------nix
/*
* This function takes a list of class names and replaces with a unique list
* The total unique elements is returned
*
* @param classes IN/OUT List to hold the classes
* @param total IN the total number of classes
*
* @return the total list of unique classes
*/
int uniqueClasses(const char *classes[],int total,const char *classSelfName)
{
int i,j=0;
const char *temp[1000];
const char* current_class_name;
for (i = total-1; i>=0; --i)
{
current_class_name = classes[i];
if (strcmp(current_class_name,classSelfName)!=0 &&
// hack
strcmp(current_class_name,"vtkClientServerStream")!=0 &&
isUniqueString(current_class_name,&temp[0],j)
// && strcmp(classes[i],"vtkObjectBase")!=0)
)
{
temp[j]= current_class_name;
++j;
}
}
for(i=0;i<j;++i)
{
classes[i]=temp[i];
}
return j;
}
//--------------------------------------------------------------------------nix
/* Some classes refer to classes that are external to their libraries,
* these used to be handled in a messy way with VTK_WRAP_EXTERN. In the
* future, they will be handled with a vtkWrapHierarchy tool that
* can automatically detect external objects.
*
* @param classname IN -> the referrer class
* @param argclass IN -> the class being referred to
*
* @return true if argclass is external to classname's kit
*/
static int isExternalObject(const char *classname, const char *argclass)
{
static const char *wrapExtern[] = {
"vtkInformation", "vtkDataObject",
"vtkPolyDataSilhouette", "vtkProp3D",
"vtkPolyDataSilhouette", "vtkCamera",
0, 0 };
const char **externCheck;
for (externCheck = wrapExtern; *externCheck != 0; externCheck += 2)
{
if (strcmp(externCheck[0], classname) == 0 &&
strcmp(externCheck[1], argclass) == 0)
{
return 1;
}
}
return 0;
}
//--------------------------------------------------------------------------nix
/*
* This is used to extract all the other classes used. This includes
* superclasses, class data type passed as parameters and class
* data-types returned by the methods.
*
* @param data IN -> to extract a list of other classes used
* @param classes OUT <- the structure to hold the extracted classes
*
* @return the count of the extracted unique classes
*/
int extractOtherClassesUsed(NewClassInfo *data, const char *classes[])
{
int i,j,k;
int count=0;
// Collect all the superclasses
for ( i = 0; i < data->NumberOfSuperClasses; ++i)
classes[i]=data->SuperClasses[i];
count = data->NumberOfSuperClasses;
// return count; // HACK only returns the super classes
// Collect all the functions params and return types
for ( i = 0; i < data->NumberOfFunctions; ++i)
{
for (j = 0; j < data->Functions[i].TotalPolymorphTypes; ++j)
{
for (k=0; k < data->Functions[i].Function[j]->NumberOfArguments; ++k)
{
if((data->Functions[i].Function[j]->ArgTypes[k] & VTK_PARSE_BASE_TYPE)
== VTK_PARSE_VTK_OBJECT)
{
if (!isExternalObject(data->ClassName,
data->Functions[i].Function[j]->ArgClasses[k]))
{
classes[count]=data->Functions[i].Function[j]->ArgClasses[k];
++count;
}
}
}
if((data->Functions[i].Function[j]->ReturnType & VTK_PARSE_BASE_TYPE)
== VTK_PARSE_VTK_OBJECT)
{
if (!isExternalObject(data->ClassName,
data->Functions[i].Function[j]->ReturnClass))
{
classes[count]=data->Functions[i].Function[j]->ReturnClass;
++count;
}
}
}
}
return uniqueClasses(classes,count,data->ClassName);
}
//--------------------------------------------------------------------------nix
/*
* outputs the "Object"_Init(vtkClientServerInterpreter*csi) file. This is
* used to register and initialize the classes and their dependent objects
* to the ClientServerInterpreter. Dependent objects include superclasses
* Objects passed as parameters and object types returned.
*
* @param fp file to write into
* @param data data which will be used to write into file
*/
void output_InitFunction(FILE *fp, NewClassInfo *data)
{
fprintf(fp,"\n");
fprintf(fp,
"\n"
"//-------------------------------------------------------------------------auto\n"
"void VTK_EXPORT %s_Init(vtkClientServerInterpreter* csi)\n"
"{\n"
" static vtkClientServerInterpreter* last = NULL;\n"
" if(last != csi)\n"
" {\n"
" last = csi;\n", data->ClassName);
if(!data->IsAbstract)
fprintf(fp," csi->AddNewInstanceFunction(\"%s\", %sClientServerNewCommand);\n",
data->ClassName,data->ClassName);
fprintf(fp," csi->AddCommandFunction(\"%s\", %sCommand);\n",
data->ClassName,data->ClassName);
fprintf(fp, " }\n}\n");
}
/* check all methods for use of vtkStdString */
int classUsesStdString(ClassInfo *data)
{
int i, j;
FunctionInfo *info;
for (i = 0; i < data->NumberOfFunctions; i++)
{
info = data->Functions[i];
if ((info->ReturnType & VTK_PARSE_BASE_TYPE) == VTK_PARSE_STRING)
{
return 1;
}
for (j = 0; j < info->NumberOfArguments; j++)
{
if ((info->ArgTypes[j] & VTK_PARSE_BASE_TYPE) == VTK_PARSE_STRING)
{
return 1;
}
}
}
return 0;
}
#if defined(_MSC_VER) && _MSC_VER < 1900
# define snprintf _snprintf
#endif
/* print the parsed structures */
int main(int argc, char *argv[])
{
OptionInfo *options;
FileInfo *fileInfo;
ClassInfo *data;
NamespaceInfo *ns;
char nsname[1024];
struct {
NamespaceInfo *ns;
size_t nsnamepos;
int n;
} nsstack[32];
size_t nspos;
FILE *fp;
NewClassInfo *classData;
int i;
/* get command-line args and parse the header file */
fileInfo = vtkParse_Main(argc, argv);
/* get the command-line options */
options = vtkParse_GetCommandLineOptions();
/* get the output file */
fp = fopen(options->OutputFileName, "w");
if (!fp)
{
fprintf(stderr, "Error opening output file %s\n", options->OutputFileName);
exit(1);
}
data = fileInfo->MainClass;
/* Set up the stack. */
nspos = 0;
nsstack[nspos].ns = fileInfo->Contents;
nsstack[nspos].nsnamepos = 0;
nsstack[nspos].n = 0;
nsname[nsstack[nspos].nsnamepos] = '\0';
ns = nsstack[nspos].ns;
while (!data && ns)
{
if (ns->Name)
{
size_t namelen = strlen(nsname);
snprintf(nsname + namelen, sizeof(nsname) - namelen, "::%s", ns->Name);
}
if (ns->NumberOfClasses > 0)
{
data = ns->Classes[0];
break;
}
if (ns->NumberOfNamespaces > nsstack[nspos].n)
{
/* Use the next namespace. */
ns = ns->Namespaces[nsstack[nspos].n];
nsstack[nspos].n++;
/* Go deeper. */
nspos++;
nsstack[nspos].ns = ns;
nsstack[nspos].nsnamepos = strlen(nsname);
nsstack[nspos].n = 0;
}
else
{
if (nspos)
{
--nspos;
/* Reset the namespace name. */
nsname[nsstack[nspos].nsnamepos] = '\0';
/* Go back up the stack. */
ns = nsstack[nspos].ns;
}
else
{
/* Nothing left to search. */
ns = NULL;
}
}
}
if(!data)
{
fclose(fp);
exit(1);
}
/* get the hierarchy info for accurate typing */
if (options->HierarchyFileName)
{
hierarchyInfo = vtkParseHierarchy_ReadFile(options->HierarchyFileName);
if (hierarchyInfo)
{
/* resolve using declarations within the header files */
vtkWrap_ApplyUsingDeclarations(data, fileInfo, hierarchyInfo);
}
}
fprintf(fp,"// ClientServer wrapper for %s object\n//\n",data->Name);
fprintf(fp,"#define VTK_WRAPPING_CXX\n");
if(strcmp("vtkObjectBase", data->Name) != 0)
{
/* Block inclusion of full streams. */
fprintf(fp,"#define VTK_STREAMS_FWD_ONLY\n");
}
fprintf(fp,"#include \"%s.h\"\n",data->Name);
fprintf(fp,"#include \"vtkSystemIncludes.h\"\n");
if (classUsesStdString(data))
{
fprintf(fp,"#include \"vtkStdString.h\"\n");
}
fprintf(fp,"#include \"vtkClientServerInterpreter.h\"\n");
fprintf(fp,"#include \"vtkClientServerStream.h\"\n\n");
#if 0
if (!strcmp("vtkObject",data->Name))
{
fprintf(fp,"#include \"vtkClientServerProgressObserver.h\"\n\n");
}
#endif
if (!strcmp("vtkObjectBase",data->Name))
{
fprintf(fp,"#include <sstream>\n");
}
if (*nsname)
{
fprintf(fp,"using namespace %s;\n", nsname);
}
if (!data->IsAbstract)
{
fprintf(fp,"\nvtkObjectBase *%sClientServerNewCommand(void* /*ctx*/)\n{\n",data->Name);
fprintf(fp," return %s::New();\n}\n\n",data->Name);
}
fprintf(fp,
"\n"
"int VTK_EXPORT"
" %sCommand(vtkClientServerInterpreter *arlu, vtkObjectBase *ob,"
" const char *method, const vtkClientServerStream& msg,"
" vtkClientServerStream& resultStream, void* /*ctx*/)\n"
"{\n",
data->Name);
if(strcmp(data->Name, "vtkObjectBase") == 0)
{
fprintf(fp," %s *op = ob;\n",
data->Name);
}
else
{
fprintf(fp," %s *op = %s::SafeDownCast(ob);\n",
data->Name, data->Name);
fprintf(fp,
" if(!op)\n"
" {\n"
" vtkOStrStreamWrapper vtkmsg;\n"
" vtkmsg << \"Cannot cast \" << ob->GetClassName() << \" object to %s. \"\n"
" << \"This probably means the class specifies the incorrect superclass in vtkTypeMacro.\";\n"
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Error\n"
" << vtkmsg.str() << 0 << vtkClientServerStream::End;\n"
" return 0;\n"
" }\n", data->Name);
}
fprintf(fp, " (void)arlu;\n");
/*fprintf(fp," vtkClientServerStream resultStream;\n");*/
/* insert function handling code here */
for (i = 0; i < data->NumberOfFunctions; i++)
{
currentFunction = data->Functions[i];
outputFunction(fp, data);
}
/* try superclasses */
for (i = 0; i < data->NumberOfSuperClasses; i++)
{
fprintf(fp,
"\n"
" {\n"
" const char* commandName = \"%s\";\n"
" if (arlu->HasCommandFunction(commandName) &&\n"
" arlu->CallCommandFunction(commandName, op, method, msg, resultStream)) { return 1; }\n"
" }\n",
data->SuperClasses[i]);
}
/* Add the Print method to vtkObjectBase. */
if (!strcmp("vtkObjectBase",data->Name))
{
fprintf(fp,
" if (!strcmp(\"Print\",method) && msg.GetNumberOfArguments(0) == 2)\n"
" {\n"
" std::ostringstream buf_with_warning_C4701;\n"
" op->Print(buf_with_warning_C4701);\n"
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Reply\n"
" << buf_with_warning_C4701.str().c_str()\n"
" << vtkClientServerStream::End;\n"
" return 1;\n"
" }\n");
}
/* Add the special form of AddObserver to vtkObject. */
if (!strcmp("vtkObject",data->Name))
{
fprintf(fp,
" if (!strcmp(\"AddObserver\",method) && msg.GetNumberOfArguments(0) == 4)\n"
" {\n"
" const char* event;\n"
" vtkClientServerStream css;\n"
" if(msg.GetArgument(0, 2, &event) && msg.GetArgument(0, 3, &css))\n"
" {\n"
" return arlu->NewObserver(op, event, css);\n"
" }\n"
" }\n");
}
fprintf(fp,
" if(resultStream.GetNumberOfMessages() > 0 &&\n"
" resultStream.GetCommand(0) == vtkClientServerStream::Error &&\n"
" resultStream.GetNumberOfArguments(0) > 1)\n"
" {\n"
" /* A superclass wrapper prepared a special message. */\n"
" return 0;\n"
" }\n"
" vtkOStrStreamWrapper vtkmsg;\n"
" vtkmsg << \"Object type: %s, could not find requested method: \\\"\"\n"
" << method << \"\\\"\\nor the method was called with incorrect arguments.\\n\";\n"
" resultStream.Reset();\n"
" resultStream << vtkClientServerStream::Error\n"
" << vtkmsg.str() << vtkClientServerStream::End;\n"
" vtkmsg.rdbuf()->freeze(0);\n",
data->Name);
fprintf(fp,
" return 0;\n"
"}\n");
classData = (NewClassInfo*)malloc(sizeof(NewClassInfo));
getClassInfo(fileInfo,data,classData);
output_InitFunction(fp,classData);
free(classData);
vtkParse_Free(fileInfo);
fclose(fp);
return 0;
}