/* ---------------------------------------------------------------------------- * This file is part of SWIG, which is licensed as a whole under version 3 * (or any later version) of the GNU General Public License. Some additional * terms also apply to certain portions of SWIG. The full details of the SWIG * license and copyrights can be found in the LICENSE and COPYRIGHT files * included with the SWIG source code as distributed by the SWIG developers * and at https://www.swig.org/legal.html. * * scilab.cxx * * Scilab language module for SWIG. * --------------------------------------------------------------------------*/ #include "swigmod.h" #include #include static const int SCILAB_IDENTIFIER_NAME_CHAR_MAX = 24; static const char *usage = (char *) " \ Scilab options (available with -scilab)\n \ -builder - Generate a Scilab builder script\n \ -buildercflags - Add to the builder compiler flags\n \ -builderflagscript - Set the Scilab script to use by builder to configure the build flags\n \ -builderldflags - Add to the builder linker flags\n \ -buildersources - Add the (comma separated) files to the builder sources\n \ -builderverbositylevel - Set the builder verbosity level to (default 0: off, 2: high)\n \ -gatewayxml - Generate gateway xml with the given \n \ \n"; class SCILAB:public Language { protected: /* General objects used for holding the strings */ File *beginSection; File *runtimeSection; File *headerSection; File *wrappersSection; File *initSection; String *variablesCode; bool generateBuilder; File *builderFile; String *builderCode; String *builderCode5; String *builderCode6; int builderFunctionCount; List *sourceFileList; List *cflags; List *ldflags; String *verboseBuildLevel; String *buildFlagsScript; String *gatewayHeader; String *gatewayHeaderV5; String *gatewayHeaderV6; bool createGatewayXML; File *gatewayXMLFile; String *gatewayXML; String *gatewayID; int primitiveID; bool createLoader; File *loaderFile; String *loaderScript; String *loaderScript5; String *loaderScript6; int loaderFunctionCount; public: /* ------------------------------------------------------------------------ * main() * ----------------------------------------------------------------------*/ virtual void main(int argc, char *argv[]) { generateBuilder = false; sourceFileList = NewList(); cflags = NewList(); ldflags = NewList(); verboseBuildLevel = NULL; buildFlagsScript = NULL; gatewayHeader = NULL; gatewayHeaderV5 = NULL; gatewayHeaderV6 = NULL; createGatewayXML = false; gatewayXML = NULL; gatewayXMLFile = NULL; gatewayID = NULL; createLoader = true; loaderFile = NULL; loaderScript = NULL; /* Manage command line arguments */ for (int argIndex = 1; argIndex < argc; argIndex++) { if (argv[argIndex] != NULL) { if (strcmp(argv[argIndex], "-help") == 0) { Printf(stdout, "%s\n", usage); } else if (strcmp(argv[argIndex], "-builder") == 0) { Swig_mark_arg(argIndex); generateBuilder = true; createLoader = false; } else if (strcmp(argv[argIndex], "-buildersources") == 0) { if (argv[argIndex + 1] != NULL) { Swig_mark_arg(argIndex); char *sourceFile = strtok(argv[argIndex + 1], ","); while (sourceFile != NULL) { Insert(sourceFileList, Len(sourceFileList), sourceFile); sourceFile = strtok(NULL, ","); } Swig_mark_arg(argIndex + 1); } } else if (strcmp(argv[argIndex], "-buildercflags") == 0) { Swig_mark_arg(argIndex); if (argv[argIndex + 1] != NULL) { Insert(cflags, Len(cflags), argv[argIndex + 1]); Swig_mark_arg(argIndex + 1); } } else if (strcmp(argv[argIndex], "-builderldflags") == 0) { Swig_mark_arg(argIndex); if (argv[argIndex + 1] != NULL) { Insert(ldflags, Len(ldflags), argv[argIndex + 1]); Swig_mark_arg(argIndex + 1); } } else if (strcmp(argv[argIndex], "-builderverbositylevel") == 0) { Swig_mark_arg(argIndex); verboseBuildLevel = NewString(argv[argIndex + 1]); Swig_mark_arg(argIndex + 1); } else if (strcmp(argv[argIndex], "-builderflagscript") == 0) { Swig_mark_arg(argIndex); buildFlagsScript = NewString(argv[argIndex + 1]); Swig_mark_arg(argIndex + 1); } else if (strcmp(argv[argIndex], "-gatewayxml") == 0) { Swig_mark_arg(argIndex); createGatewayXML = true; gatewayID = NewString(argv[argIndex + 1]); Swig_mark_arg(argIndex + 1); } } } if (verboseBuildLevel == NULL) { verboseBuildLevel = NewString("0"); } /* Set language-specific subdirectory in SWIG library */ SWIG_library_directory("scilab"); /* Add a symbol to the parser for conditional compilation */ Preprocessor_define("SWIGSCILAB 1", 0); /* Set scilab configuration file */ SWIG_config_file("scilab.swg"); /* Set typemap for scilab */ SWIG_typemap_lang("scilab"); allow_overloading(); } /* ------------------------------------------------------------------------ * top() * ----------------------------------------------------------------------*/ virtual int top(Node *node) { /* Get the module name */ String *gatewayName = Getattr(node, "name"); // Set library name String *gatewayLibraryName = NewStringf("lib%s", gatewayName); /* Get the output file name */ String *outputFilename = Getattr(node, "outfile"); /* Initialize I/O */ beginSection = NewFile(outputFilename, "w", SWIG_output_files()); if (!beginSection) { FileErrorDisplay(outputFilename); Exit(EXIT_FAILURE); } runtimeSection = NewString(""); initSection = NewString(""); headerSection = NewString(""); wrappersSection = NewString(""); /* Register file targets with the SWIG file handler */ Swig_register_filebyname("begin", beginSection); Swig_register_filebyname("header", headerSection); Swig_register_filebyname("wrapper", wrappersSection); Swig_register_filebyname("runtime", runtimeSection); Swig_register_filebyname("init", initSection); /* Output module initialization code */ Swig_banner(beginSection); Swig_obligatory_macros(runtimeSection, "SCILAB"); // Gateway header source merged with wrapper source in nobuilder mode if (!generateBuilder) startGatewayHeader(gatewayLibraryName); // Create builder file if required if (generateBuilder) { createBuilderFile(outputFilename); } // Create gateway XML if required if (createGatewayXML) { createGatewayXMLFile(gatewayName); } // Create loader script if required if (createLoader) { createLoaderFile(gatewayLibraryName); } // Module initialization function String *smallFunctionName = createSmallIdentifierName(gatewayName, SCILAB_IDENTIFIER_NAME_CHAR_MAX - 5); String *gatewayInitFunctionName = NewStringf("%s_Init", gatewayName); String *gatewayInitSmallFunctionName = NewStringf("%s_Init", smallFunctionName); String *wrapperFunctionName = NewStringf("SWIG_%s_Init", gatewayName); /* Add initialization function to builder table */ addFunctionToScilab(gatewayInitFunctionName, gatewayInitSmallFunctionName, wrapperFunctionName); // Add helper functions to builder table addHelperFunctions(); // Open Scilab wrapper variables creation function variablesCode = NewString(""); Printf(variablesCode, "int SWIG_CreateScilabVariables(void *_pvApiCtx) {"); /* Emit code for children */ if (CPlusPlus) { Printf(wrappersSection, "extern \"C\" {\n"); } Language::top(node); if (CPlusPlus) { Printf(wrappersSection, "}\n"); } // Close Scilab wrapper variables creation function Printf(variablesCode, " return SWIG_OK;\n}\n"); // Add Builder footer code and save if (generateBuilder) { saveBuilderFile(gatewayLibraryName); } /* Close the init function and rename with module name */ Printf(initSection, "return 0;\n}\n"); Replaceall(initSection, "", gatewayName); /* Write all to the wrapper file */ SwigType_emit_type_table(runtimeSection, wrappersSection); // Declare pointer types, ... (Ex: SWIGTYPE_p_p_double) // Gateway header source merged with wrapper source in nobuilder mode if (!generateBuilder) { terminateGatewayHeader(gatewayLibraryName); Printv(initSection, gatewayHeader, NIL); } Dump(runtimeSection, beginSection); Dump(headerSection, beginSection); Dump(wrappersSection, beginSection); Dump(variablesCode, beginSection); Wrapper_pretty_print(initSection, beginSection); if (createGatewayXML) { saveGatewayXMLFile(); } if (createLoader) { saveLoaderFile(gatewayLibraryName); } /* Cleanup files */ Delete(runtimeSection); Delete(headerSection); Delete(wrappersSection); Delete(initSection); Delete(beginSection); Delete(sourceFileList); Delete(cflags); Delete(ldflags); return SWIG_OK; } /* ------------------------------------------------------------------------ * emitBanner() * ----------------------------------------------------------------------*/ void emitBanner(File *f) { Printf(f, "// ----------------------------------------------------------------------------\n"); Swig_banner_target_lang(f, "// "); Printf(f, "// ----------------------------------------------------------------------------- */\n\n"); } /* ------------------------------------------------------------------------ * functionWrapper() * ----------------------------------------------------------------------*/ virtual int functionWrapper(Node *node) { /* Get some useful attributes of this function */ String *functionName = Getattr(node, "sym:name"); String *smallFunctionName = createSmallIdentifierName(functionName); SwigType *functionReturnType = Getattr(node, "type"); ParmList *functionParamsList = Getattr(node, "parms"); int paramIndex = 0; // Used for loops over ParmsList Parm *param = NULL; // Used for loops over ParamsList /* Create the wrapper object */ Wrapper *wrapper = NewWrapper(); /* Create the function wrapper name */ String *wrapperName = Swig_name_wrapper(functionName); /* Deal with overloading */ String *overloadedName = Copy(wrapperName); /* Determine whether the function is overloaded or not */ bool isOverloaded = ! !Getattr(node, "sym:overloaded"); /* Determine whether the function is the last overloaded */ bool isLastOverloaded = isOverloaded && !Getattr(node, "sym:nextSibling"); if (!isOverloaded && !addSymbol(functionName, node)) { DelWrapper(wrapper); return SWIG_ERROR; } if (isOverloaded) { Append(overloadedName, Getattr(node, "sym:overname")); } /* Write the wrapper function definition (standard Scilab gateway function prototype) */ Printv(wrapper->def, "SWIGEXPORT int ", overloadedName, "(SWIG_GatewayParameters) {", NIL); /* Emit all of the local variables for holding arguments */ // E.g.: double arg1; emit_parameter_variables(functionParamsList, wrapper); /* Attach typemaps to the parameter list */ // Add local variables used in typemaps (iRows, iCols, ...) emit_attach_parmmaps(functionParamsList, wrapper); Setattr(node, "wrap:parms", functionParamsList); /* Check input/output arguments count */ int maxInputArguments = emit_num_arguments(functionParamsList); int minInputArguments = emit_num_required(functionParamsList); int minOutputArguments = 0; int maxOutputArguments = 1; if (!emit_isvarargs(functionParamsList)) { Printf(wrapper->code, "SWIG_CheckInputArgument(pvApiCtx, $mininputarguments, $maxinputarguments);\n"); } else { Printf(wrapper->code, "SWIG_CheckInputArgumentAtLeast(pvApiCtx, $mininputarguments-1);\n"); } Printf(wrapper->code, "SWIG_CheckOutputArgument(pvApiCtx, $minoutputarguments, $maxoutputarguments);\n"); /* Set context */ Printf(wrapper->code, "SWIG_Scilab_SetFuncName(fname);\n"); Printf(wrapper->code, "SWIG_Scilab_SetApiContext(pvApiCtx);\n"); /* Write typemaps(in) */ for (paramIndex = 0, param = functionParamsList; paramIndex < maxInputArguments; ++paramIndex) { // Ignore parameter if the typemap specifies numinputs=0 while (checkAttribute(param, "tmap:in:numinputs", "0")) { param = Getattr(param, "tmap:in:next"); } SwigType *paramType = Getattr(param, "type"); String *paramTypemap = Getattr(param, "tmap:in"); if (paramTypemap) { // Replace $input by the position on Scilab stack String *source = NewString(""); Printf(source, "%d", paramIndex + 1); Setattr(param, "emit:input", source); Replaceall(paramTypemap, "$input", Getattr(param, "emit:input")); if (Getattr(param, "wrap:disown") || (Getattr(param, "tmap:in:disown"))) { Replaceall(paramTypemap, "$disown", "SWIG_POINTER_DISOWN"); } else { Replaceall(paramTypemap, "$disown", "0"); } if (paramIndex >= minInputArguments) { /* Optional input argument management */ Printf(wrapper->code, "if (SWIG_NbInputArgument(pvApiCtx) > %d) {\n%s\n}\n", paramIndex, paramTypemap); } else { Printf(wrapper->code, "%s\n", paramTypemap); } param = Getattr(param, "tmap:in:next"); } else { Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(paramType, 0)); break; } } /* TODO write constraints */ Setattr(node, "wrap:name", overloadedName); /* Emit the function call */ Swig_director_emit_dynamic_cast(node, wrapper); String *functionActionCode = emit_action(node); /* Insert the return variable */ emit_return_variable(node, functionReturnType, wrapper); /* Return the function value if necessary */ String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, Swig_cresult_name(), wrapper, functionActionCode); if (functionReturnTypemap) { // Result is actually the position of output value on stack if (Len(functionReturnTypemap) > 0) { Printf(wrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1); } Replaceall(functionReturnTypemap, "$result", "1"); if (GetFlag(node, "feature:new")) { Replaceall(functionReturnTypemap, "$owner", "1"); } else { Replaceall(functionReturnTypemap, "$owner", "0"); } Printf(wrapper->code, "%s\n", functionReturnTypemap); /* If the typemap is not empty, the function return one more argument than the typemaps gives */ if (Len(functionReturnTypemap) > 0) { minOutputArguments++; maxOutputArguments++; } Delete(functionReturnTypemap); } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(functionReturnType, 0), functionName); } /* Write typemaps(out) */ for (param = functionParamsList; param;) { String *paramTypemap = Getattr(param, "tmap:argout"); if (paramTypemap) { minOutputArguments++; maxOutputArguments++; Printf(wrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", minOutputArguments); String *result = NewString(""); Printf(result, "%d", minOutputArguments); Replaceall(paramTypemap, "$result", result); Printf(wrapper->code, "%s\n", paramTypemap); Delete(paramTypemap); param = Getattr(param, "tmap:argout:next"); } else { param = nextSibling(param); } } /* Add cleanup code */ for (param = functionParamsList; param;) { String *tm; if ((tm = Getattr(param, "tmap:freearg"))) { if (tm && (Len(tm) != 0)) { Printf(wrapper->code, "%s\n", tm); } param = Getattr(param, "tmap:freearg:next"); } else { param = nextSibling(param); } } /* See if there is any return cleanup code */ String *tm; if ((tm = Swig_typemap_lookup("ret", node, Swig_cresult_name(), 0))) { Printf(wrapper->code, "%s\n", tm); Delete(tm); } /* Close the function(ok) */ Printv(wrapper->code, "return SWIG_OK;\n", NIL); Printv(wrapper->code, "}\n", NIL); /* Add the failure cleanup code */ /* TODO */ /* Final substitutions if applicable */ Replaceall(wrapper->code, "$symname", functionName); /* Set CheckInputArgument and CheckOutputArgument input arguments */ if (maxOutputArguments < 1) { maxOutputArguments = 1; } if (minOutputArguments == 1) { minOutputArguments = 0; } String *argnumber = NewString(""); Printf(argnumber, "%d", minInputArguments); Replaceall(wrapper->code, "$mininputarguments", argnumber); argnumber = NewString(""); Printf(argnumber, "%d", maxInputArguments); Replaceall(wrapper->code, "$maxinputarguments", argnumber); argnumber = NewString(""); Printf(argnumber, "%d", minOutputArguments); Replaceall(wrapper->code, "$minoutputarguments", argnumber); argnumber = NewString(""); Printf(argnumber, "%d", maxOutputArguments); Replaceall(wrapper->code, "$maxoutputarguments", argnumber); /* Dump the function out */ Wrapper_print(wrapper, wrappersSection); /* Update builder.sce contents */ if (isLastOverloaded) { addFunctionToScilab(functionName, smallFunctionName, wrapperName); dispatchFunction(node); } if (!isOverloaded) { addFunctionToScilab(functionName, smallFunctionName, wrapperName); } /* tidy up */ Delete(overloadedName); Delete(wrapperName); DelWrapper(wrapper); return SWIG_OK; } /* ----------------------------------------------------------------------- * dispatchFunction() * ----------------------------------------------------------------------- */ void dispatchFunction(Node *node) { Wrapper *wrapper = NewWrapper(); String *functionName = Getattr(node, "sym:name"); String *wrapperName = Swig_name_wrapper(functionName); int maxargs = 0; /* Generate the dispatch function */ String *dispatch = Swig_overload_dispatch(node, "return %s(SWIG_GatewayArguments);", &maxargs); String *tmp = NewString(""); Printv(wrapper->def, "SWIGEXPORT int ", wrapperName, "(SWIG_GatewayParameters) {\n", NIL); /* Get the number of the parameters */ Wrapper_add_local(wrapper, "argc", "int argc = SWIG_NbInputArgument(pvApiCtx)"); Printf(tmp, "int argv[%d] = {", maxargs); for (int j = 0; j < maxargs; ++j) { Printf(tmp, "%s%d", j ? "," : " ", j + 1); } Printf(tmp, "}"); Wrapper_add_local(wrapper, "argv", tmp); Printf(wrapper->code, "SWIG_Scilab_SetApiContext(pvApiCtx);\n"); /* Dump the dispatch function */ Printv(wrapper->code, dispatch, "\n", NIL); Printf(wrapper->code, "Scierror(999, _(\"No matching function for overload\"));\n"); Printf(wrapper->code, "return SWIG_ERROR;\n"); Printv(wrapper->code, "}\n", NIL); Wrapper_print(wrapper, wrappersSection); Delete(tmp); DelWrapper(wrapper); Delete(dispatch); Delete(wrapperName); } /* ----------------------------------------------------------------------- * variableWrapper() * ----------------------------------------------------------------------- */ virtual int variableWrapper(Node *node) { /* Get information about variable */ String *origVariableName = Getattr(node, "name"); // Ex: Shape::nshapes String *variableName = Getattr(node, "sym:name"); // Ex; Shape_nshapes (can be used for function names, ...) String *smallVariableName = createSmallIdentifierName(variableName, SCILAB_IDENTIFIER_NAME_CHAR_MAX - 4); /* Manage GET function */ Wrapper *getFunctionWrapper = NewWrapper(); String *getFunctionName = Swig_name_get(NSPACE_TODO, variableName); String *scilabGetFunctionName = Swig_name_get(NSPACE_TODO, variableName); String *scilabGetSmallFunctionName = Swig_name_get(NSPACE_TODO, smallVariableName); Setattr(node, "wrap:name", getFunctionName); Printv(getFunctionWrapper->def, "SWIGEXPORT int ", getFunctionName, "(SWIG_GatewayParameters) {\n", NIL); /* Check the number of input and output */ Printf(getFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 0, 0);\n"); Printf(getFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 0, 1);\n"); Printf(getFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n"); String *varoutTypemap = Swig_typemap_lookup("varout", node, origVariableName, 0); if (varoutTypemap != NULL) { Printf(getFunctionWrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1); Replaceall(varoutTypemap, "$value", origVariableName); Replaceall(varoutTypemap, "$result", "1"); emit_action_code(node, getFunctionWrapper->code, varoutTypemap); Delete(varoutTypemap); } Append(getFunctionWrapper->code, "return SWIG_OK;\n"); Append(getFunctionWrapper->code, "}\n"); Wrapper_print(getFunctionWrapper, wrappersSection); /* Add function to builder table */ addFunctionToScilab(scilabGetFunctionName, scilabGetSmallFunctionName, getFunctionName); /* Manage SET function */ if (is_assignable(node)) { Wrapper *setFunctionWrapper = NewWrapper(); String *setFunctionName = Swig_name_set(NSPACE_TODO, variableName); String *scilabSetFunctionName = Swig_name_set(NSPACE_TODO, variableName); String *scilabSetSmallFunctionName = Swig_name_set(NSPACE_TODO, smallVariableName); Setattr(node, "wrap:name", setFunctionName); Printv(setFunctionWrapper->def, "SWIGEXPORT int ", setFunctionName, "(SWIG_GatewayParameters) {\n", NIL); /* Check the number of input and output */ Printf(setFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 1, 1);\n"); Printf(setFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 0, 1);\n"); Printf(setFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n"); String *varinTypemap = Swig_typemap_lookup("varin", node, origVariableName, 0); if (varinTypemap != NULL) { Replaceall(varinTypemap, "$input", "1"); emit_action_code(node, setFunctionWrapper->code, varinTypemap); Delete(varinTypemap); } Append(setFunctionWrapper->code, "return SWIG_OK;\n"); Append(setFunctionWrapper->code, "}\n"); Wrapper_print(setFunctionWrapper, wrappersSection); /* Add function to builder table */ addFunctionToScilab(scilabSetFunctionName, scilabSetSmallFunctionName, setFunctionName); DelWrapper(setFunctionWrapper); } DelWrapper(getFunctionWrapper); return SWIG_OK; } /* ----------------------------------------------------------------------- * constantWrapper() * ----------------------------------------------------------------------- */ virtual int constantWrapper(Node *node) { /* Get the useful information from the node */ String *nodeName = Getattr(node, "name"); SwigType *type = Getattr(node, "type"); String *constantName = Getattr(node, "sym:name"); String *rawValue = Getattr(node, "rawval"); String *constantValue = rawValue ? rawValue : Getattr(node, "value"); String *constantTypemap = NULL; // If feature scilab:const enabled, constants & enums are wrapped to Scilab variables if (GetFlag(node, "feature:scilab:const")) { bool isConstant = ((SwigType_issimple(type)) || (SwigType_type(type) == T_STRING)); bool isEnum = (Cmp(nodeType(node), "enumitem") == 0); if (isConstant || isEnum) { if (isEnum) { Setattr(node, "type", "double"); constantValue = Getattr(node, "value"); } constantTypemap = Swig_typemap_lookup("scilabconstcode", node, nodeName, 0); if (constantTypemap != NULL) { Setattr(node, "wrap:name", constantName); Replaceall(constantTypemap, "$result", constantName); Replaceall(constantTypemap, "$value", constantValue); emit_action_code(node, variablesCode, constantTypemap); Delete(constantTypemap); return SWIG_OK; } } } /* Create variables for member pointer constants, not supported by typemaps (like Python wrapper does) */ if (SwigType_type(type) == T_MPOINTER) { String *wname = Swig_name_wrapper(constantName); String *str = SwigType_str(type, wname); Printf(headerSection, "static %s = %s;\n", str, constantValue); Delete(str); constantValue = wname; } // Constant names can have SCILAB_VARIABLE_NAME_CHAR_MAX because of suffixes "_get" added to function String *smallConstantName = createSmallIdentifierName(constantName, SCILAB_IDENTIFIER_NAME_CHAR_MAX - 4); /* Create GET function to get the constant value */ Wrapper *getFunctionWrapper = NewWrapper(); String *getFunctionName = Swig_name_get(NSPACE_TODO, constantName); String *scilabGetSmallFunctionName = Swig_name_get(NSPACE_TODO, smallConstantName); Setattr(node, "wrap:name", getFunctionName); Setattr(node, "wrap:name", getFunctionName); Printv(getFunctionWrapper->def, "SWIGEXPORT int ", getFunctionName, "(SWIG_GatewayParameters) {\n", NIL); /* Check the number of input and output */ Printf(getFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 0, 0);\n"); Printf(getFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 0, 1);\n"); Printf(getFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n"); constantTypemap = Swig_typemap_lookup("constcode", node, nodeName, 0); if (constantTypemap != NULL) { Printf(getFunctionWrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1); Replaceall(constantTypemap, "$value", constantValue); Replaceall(constantTypemap, "$result", "1"); emit_action_code(node, getFunctionWrapper->code, constantTypemap); Delete(constantTypemap); } /* Dump the wrapper function */ Append(getFunctionWrapper->code, "return SWIG_OK;\n"); Append(getFunctionWrapper->code, "}\n"); Wrapper_print(getFunctionWrapper, wrappersSection); /* Add the function to Scilab */ addFunctionToScilab(getFunctionName, scilabGetSmallFunctionName, getFunctionName); DelWrapper(getFunctionWrapper); return SWIG_OK; } /* --------------------------------------------------------------------- * enumvalueDeclaration() * --------------------------------------------------------------------- */ virtual int enumvalueDeclaration(Node *node) { static int iPreviousEnumValue = 0; if (GetFlag(node, "feature:scilab:const")) { // Compute the "absolute" value of enum if needed // (most of time enum values are a linked list of relative values) String *enumValue = Getattr(node, "enumvalue"); String *enumValueEx = Getattr(node, "enumvalueex"); // First enum value ? String *firstenumitem = Getattr(node, "firstenumitem"); if (firstenumitem) { if (enumValue) { // Value is in 'enumvalue' iPreviousEnumValue = atoi(Char(enumValue)); } else if (enumValueEx) { // Or value is in 'enumValueEx' iPreviousEnumValue = atoi(Char(enumValueEx)); enumValue = NewString(""); Printf(enumValue, "%d", iPreviousEnumValue); Setattr(node, "enumvalue", enumValue); } } else if (!enumValue && enumValueEx) { // Value is not specified, set it by incrementing last value enumValue = NewString(""); Printf(enumValue, "%d", ++iPreviousEnumValue); Setattr(node, "enumvalue", enumValue); } // Enums in Scilab are mapped to double Setattr(node, "type", "double"); } return Language::enumvalueDeclaration(node); } /* ----------------------------------------------------------------------- * addHelperFunctions() * ----------------------------------------------------------------------- */ void addHelperFunctions() { addFunctionToScilab("SWIG_this", "SWIG_this", "SWIG_this"); addFunctionToScilab("SWIG_ptr", "SWIG_ptr", "SWIG_ptr"); } /* ----------------------------------------------------------------------- * addFunctionToScilab() * Declare a wrapped function in Scilab (builder, gateway, XML, ...) * ----------------------------------------------------------------------- */ void addFunctionToScilab(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr scilabSmallFunctionName, const_String_or_char_ptr wrapperFunctionName) { if (!generateBuilder) addFunctionInGatewayHeader(scilabFunctionName, scilabSmallFunctionName, wrapperFunctionName); if (generateBuilder) { addFunctionInScriptTable(scilabFunctionName, scilabSmallFunctionName, wrapperFunctionName, builderCode5, builderCode6); } if (createLoader) { addFunctionInLoader(scilabFunctionName, scilabSmallFunctionName); } if (gatewayXMLFile) { Printf(gatewayXML, "\n", gatewayID, primitiveID++, scilabSmallFunctionName); } } /* ----------------------------------------------------------------------- * createBuilderCode() * ----------------------------------------------------------------------- */ void createBuilderFile(String *outputFilename) { String *builderFilename = NewStringf("builder.sce"); builderFile = NewFile(builderFilename, "w", SWIG_output_files()); if (!builderFile) { FileErrorDisplay(builderFilename); Exit(EXIT_FAILURE); } emitBanner(builderFile); builderFunctionCount = 0; builderCode = NewString(""); builderCode5 = NewString(""); builderCode6 = NewString(""); Printf(builderCode, "mode(-1);\n"); Printf(builderCode, "lines(0);\n"); /* Useful for automatic tests */ // Scilab needs to be in the build directory Printf(builderCode, "originaldir = pwd();\n"); Printf(builderCode, "builddir = get_absolute_file_path('builder.sce');\n"); Printf(builderCode, "cd(builddir);\n"); Printf(builderCode, "ilib_verbose(%s);\n", verboseBuildLevel); Printf(builderCode, "libs = [];\n"); // Flags from command line arguments Printf(builderCode, "cflags = \"\";\n"); for (int i = 0; i < Len(cflags); i++) { String *cflag = Getitem(cflags, i); Printf(builderCode, "cflags = cflags + \" %s\";\n", cflag); } if (Len(ldflags) > 0) { for (int i = 0; i < Len(ldflags); i++) { String *ldflag = Getitem(ldflags, i); if (i == 0) { Printf(builderCode, "ldflags = \"%s\";\n", ldflag); } else { Printf(builderCode, "ldflags = ldflags + \" %s\";\n", ldflag); } } } else { Printf(builderCode, "ldflags = \"\";\n"); } // External script to set flags if (buildFlagsScript) { Printf(builderCode, "exec(\"%s\");\n", buildFlagsScript); Printf(builderCode, "cflags = cflags + getCompilationFlags();\n"); Printf(builderCode, "ldflags = ldflags + getLinkFlags();\n"); } // Additional sources Insert(sourceFileList, 0, outputFilename); for (int i = 0; i < Len(sourceFileList); i++) { String *sourceFile = Getitem(sourceFileList, i); if (i == 0) { Printf(builderCode, "files = \"%s\";\n", sourceFile); } else { Printf(builderCode, "files($ + 1) = \"%s\";\n", sourceFile); } } Printf(builderCode5, "table = [ ..\n"); Printf(builderCode6, "table = [ ..\n"); } /* ----------------------------------------------------------------------- * addFunctionInBuilderCode() * Add a function wrapper in the function table of generated builder script * ----------------------------------------------------------------------- */ void addFunctionInScriptTable(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr scilabSmallFunctionName, const_String_or_char_ptr wrapperFunctionName, String *scriptCode5, String *scriptCode6) { if (++builderFunctionCount % 10 == 0) { Printf(scriptCode5, "];\ntable = [table; ..\n"); Printf(scriptCode6, "];\ntable = [table; ..\n"); } Printf(scriptCode5, "\"%s\",\"%s\"; ..\n", scilabSmallFunctionName, wrapperFunctionName); Printf(scriptCode6, "\"%s\",\"%s\"; ..\n", scilabFunctionName, wrapperFunctionName); } /* ----------------------------------------------------------------------- * saveBuilderFile() * ----------------------------------------------------------------------- */ void saveBuilderFile(String *gatewayName) { Printf(builderCode5, "];\n"); Printf(builderCode6, "];\n"); if (Equal(builderCode5, builderCode6)) { Append(builderCode, builderCode6); } else { Printf(builderCode, "ver = getversion('scilab');\n"); Printf(builderCode, "if ver(1) < 6 then\n"); Printf(builderCode, " // version is less or equal to 5.5.2\n"); Printf(builderCode, " \n"); Append(builderCode, builderCode5); Printf(builderCode, " \n"); Printf(builderCode, "else\n"); Printf(builderCode, " // version is 6.0.0 or more\n"); Printf(builderCode, " \n"); Append(builderCode, builderCode6); Printf(builderCode, " \n"); Printf(builderCode, "end\n"); } Printf(builderCode, "ierr = 0;\n"); Printf(builderCode, "if ~isempty(table) then\n"); Printf(builderCode, " ierr = execstr(\"ilib_build(''%s'', table, files, libs, [], ldflags, cflags);\", 'errcatch');\n", gatewayName); Printf(builderCode, " if ierr <> 0 then\n"); Printf(builderCode, " err_msg = lasterror();\n"); Printf(builderCode, " end\n"); Printf(builderCode, "end\n"); Printf(builderCode, "cd(originaldir);\n"); Printf(builderCode, "if ierr <> 0 then\n"); Printf(builderCode, " error(ierr, err_msg);\n"); Printf(builderCode, "end\n"); Printv(builderFile, builderCode, NIL); Delete(builderCode); Delete(builderFile); } /* ----------------------------------------------------------------------- * createGatewayXMLFile() * This XML file is used by Scilab in the context of internal modules * ----------------------------------------------------------------------- */ void createGatewayXMLFile(String *gatewayName) { String *gatewayXMLFilename = NewStringf("%s_gateway.xml", gatewayName); gatewayXMLFile = NewFile(gatewayXMLFilename, "w", SWIG_output_files()); if (!gatewayXMLFile) { FileErrorDisplay(gatewayXMLFilename); Exit(EXIT_FAILURE); } // Add a slightly modified SWIG banner to the gateway XML ("--modify" is illegal in XML) gatewayXML = NewString(""); Printf(gatewayXML, "\n"); Printf(gatewayXML, "\n"); Printf(gatewayXML, "\n", gatewayName); primitiveID = 1; } /* ----------------------------------------------------------------------- * saveGatewayXMLFile() * ----------------------------------------------------------------------- */ void saveGatewayXMLFile() { Printf(gatewayXML, "\n"); Printv(gatewayXMLFile, gatewayXML, NIL); Delete(gatewayXMLFile); } /* ----------------------------------------------------------------------- * startGatewayHeader() * Start the gateway header * ----------------------------------------------------------------------- */ void startGatewayHeader(String *gatewayLibraryName) { gatewayHeader = NewString(""); Printf(gatewayHeader, "\n"); gatewayHeaderV6 = NewString(""); Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); Printf(gatewayHeaderV6, "extern \"C\" {\n"); Printf(gatewayHeaderV6, "#endif\n"); Printf(gatewayHeaderV6, "#include \"c_gateway_prototype.h\"\n"); Printf(gatewayHeaderV6, "#include \"addfunction.h\"\n"); Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); Printf(gatewayHeaderV6, "}\n"); Printf(gatewayHeaderV6, "#endif\n"); Printf(gatewayHeaderV6, "\n"); Printf(gatewayHeaderV6, "#define MODULE_NAME L\"%s\"\n", gatewayLibraryName); Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); Printf(gatewayHeaderV6, "extern \"C\"\n"); Printf(gatewayHeaderV6, "#endif\n"); Printf(gatewayHeaderV6, "SWIGEXPORT int %s(wchar_t *pwstFuncName) {\n", gatewayLibraryName); Printf(gatewayHeaderV6, "\n"); } /* ----------------------------------------------------------------------- * addFunctionInGatewayHeader() * Add a function in the gateway header * ----------------------------------------------------------------------- */ void addFunctionInGatewayHeader(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr scilabSmallFunctionName, const_String_or_char_ptr wrapperFunctionName) { if (gatewayHeaderV5 == NULL) { gatewayHeaderV5 = NewString(""); Printf(gatewayHeaderV5, "static GenericTable Tab[] = {\n"); } else Printf(gatewayHeaderV5, ",\n"); Printf(gatewayHeaderV5, " {(Myinterfun)sci_gateway, (GT)%s, (char *)\"%s\"}", wrapperFunctionName, scilabSmallFunctionName); Printf(gatewayHeaderV6, "if (wcscmp(pwstFuncName, L\"%s\") == 0) { addCStackFunction((wchar_t *)L\"%s\", &%s, (wchar_t *)MODULE_NAME); }\n", scilabFunctionName, scilabFunctionName, wrapperFunctionName); } /* ----------------------------------------------------------------------- * terminateGatewayHeader() * Terminates the gateway header * ----------------------------------------------------------------------- */ void terminateGatewayHeader(String *gatewayLibraryName) { Printf(gatewayHeaderV5, "};\n"); Printf(gatewayHeaderV5, "\n"); Printf(gatewayHeaderV5, "#ifdef __cplusplus\n"); Printf(gatewayHeaderV5, "extern \"C\" {\n"); Printf(gatewayHeaderV5, "#endif\n"); Printf(gatewayHeaderV5, "SWIGEXPORT int C2F(%s)() {\n", gatewayLibraryName); Printf(gatewayHeaderV5, " Rhs = Max(0, Rhs);\n"); Printf(gatewayHeaderV5, " if (*(Tab[Fin-1].f) != NULL) {\n"); Printf(gatewayHeaderV5, " if(pvApiCtx == NULL) {\n"); Printf(gatewayHeaderV5, " pvApiCtx = (StrCtx *)MALLOC(sizeof(StrCtx));\n"); Printf(gatewayHeaderV5, " }\n"); Printf(gatewayHeaderV5, " pvApiCtx->pstName = (char *)Tab[Fin-1].name;\n"); Printf(gatewayHeaderV5, " (*(Tab[Fin-1].f))(Tab[Fin-1].name,(GatefuncH)Tab[Fin-1].F);\n"); Printf(gatewayHeaderV5, " }\n"); Printf(gatewayHeaderV5, " return 0;\n"); Printf(gatewayHeaderV5, "}\n"); Printf(gatewayHeaderV5, "\n"); Printf(gatewayHeaderV5, "#ifdef __cplusplus\n"); Printf(gatewayHeaderV5, "}\n"); Printf(gatewayHeaderV5, "#endif\n"); Printf(gatewayHeaderV6, "return 1;\n"); Printf(gatewayHeaderV6, "};\n"); Printf(gatewayHeader, "#if SWIG_SCILAB_VERSION >= 600\n"); Printv(gatewayHeader, gatewayHeaderV6, NIL); Printf(gatewayHeader, "#else\n"); Printv(gatewayHeader, gatewayHeaderV5, NIL); Printf(gatewayHeader, "#endif\n"); } /* ----------------------------------------------------------------------- * createLoaderScriptFile() * Creates the loader script file (loader.sce) * ----------------------------------------------------------------------- */ void createLoaderFile(String *gatewayLibraryName) { String *loaderFilename = NewString("loader.sce"); loaderFile = NewFile(loaderFilename, "w", SWIG_output_files()); if (!loaderFile) { FileErrorDisplay(loaderFilename); Exit(EXIT_FAILURE); } emitBanner(loaderFile); loaderFunctionCount = 0; loaderScript = NewString("function loader_function()\n"); Printf(loaderScript, " p = get_absolute_file_path('loader.sce');\n", gatewayLibraryName); Printf(loaderScript, " [bOK, ilib] = c_link('%s');\n", gatewayLibraryName); Printf(loaderScript, " if bOK then\n"); Printf(loaderScript, " ulink(ilib);\n"); Printf(loaderScript, " end\n"); loaderScript5 = NewString(" list_functions = [ ..\n"); loaderScript6 = NewString(" list_functions = [ ..\n"); } /* ----------------------------------------------------------------------- * addFunctionInLoaderScript() * Add a function in the loader script table * ----------------------------------------------------------------------- */ void addFunctionInLoader(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr scilabSmallFunctionName) { if (++loaderFunctionCount % 10 == 0) { Printf(loaderScript5, " ];\n list_functions = [list_functions; ..\n"); Printf(loaderScript6, " ];\n list_functions = [list_functions; ..\n"); } Printf(loaderScript5, " '%s'; ..\n", scilabSmallFunctionName); Printf(loaderScript6, " '%s'; ..\n", scilabFunctionName); } /* ----------------------------------------------------------------------- * saveLoaderScriptFile() * Terminates and saves the loader script * ----------------------------------------------------------------------- */ void saveLoaderFile(String *gatewayLibraryName) { Printf(loaderScript5, " ];\n"); Printf(loaderScript6, " ];\n"); if (Equal(loaderScript5, loaderScript6)) { Append(loaderScript, loaderScript6); } else { Printf(loaderScript, " ver = getversion('scilab');\n"); Printf(loaderScript, " if ver(1) < 6 then\n"); Printf(loaderScript, " // version is less or equal to 5.5.2\n"); Printf(loaderScript, " \n"); Append(loaderScript, loaderScript5); Delete(loaderScript5); Printf(loaderScript, " \n"); Printf(loaderScript, " else\n"); Printf(loaderScript, " // version is 6.0.0 or more\n"); Printf(loaderScript, " \n"); Append(loaderScript, loaderScript6); Delete(loaderScript6); Printf(loaderScript, " \n"); Printf(loaderScript, " end\n"); } Printf(loaderScript, " addinter(p + '%s' + getdynlibext(), '%s', list_functions);\n", gatewayLibraryName, gatewayLibraryName); Printf(loaderScript, "endfunction\n"); Printf(loaderScript, "loader_function();\n"); Printf(loaderScript, "clear loader_function;\n"); Printv(loaderFile, loaderScript, NIL); Delete(loaderScript); Delete(loaderFile); } /* ----------------------------------------------------------------------- * createSmallIdentifierName() * Create a Scilab small identifier to be used by Scilab 5 * ----------------------------------------------------------------------- */ String* createSmallIdentifierName(String* name, int outputLen = SCILAB_IDENTIFIER_NAME_CHAR_MAX) { char* s = Char(name); int nameLen = Len(s); // truncate and preserve common suffix if (outputLen > 4 && nameLen > outputLen) { String* smallName = NewStringWithSize(name, outputLen); char* smallNameStr = (char*) Data(smallName); if (s[nameLen-4] == '_' && s[nameLen - 3] == 'g' && s[nameLen - 2] == 'e' && s[nameLen - 1] == 't') { // get memcpy(&smallNameStr[outputLen - 4], &s[nameLen - 4], 4); } else if (s[nameLen-4] == '_' && s[nameLen - 3] == 's' && s[nameLen - 2] == 'e' && s[nameLen - 1] == 't') { // set memcpy(&smallNameStr[outputLen - 4], &s[nameLen - 4], 4); } return smallName; } return name; } }; extern "C" Language *swig_scilab(void) { return new SCILAB(); }