// ------------------------------------------------------------------------
// Experimental MATLAB Language module
//
// Produces wrappers for MATLAB 4.x/5.0
// ------------------------------------------------------------------------
#include "swig.h"
#include "matlab.h"
static char *usage = "\
MATLAB Options\n\
-module name - Set name of module\n\n";
static String constants;
// ---------------------------------------------------------------------
// MATLAB::parse_args(int argc, char *argv[])
//
// Parse my command line options and initialize by variables.
// ---------------------------------------------------------------------
void MATLAB::parse_args(int argc, char *argv[]) {
// Look for certain command line options
for (int i = 1; i < argc; i++) {
if (argv[i]) {
if (strcmp(argv[i],"-module") == 0) {
if (argv[i+1]) {
set_module(argv[i+1],0);
mark_arg(i);
mark_arg(i+1);
i++;
} else {
arg_error();
}
} else if (strcmp(argv[i],"-help") == 0) {
fprintf(stderr,"%s\n", usage);
}
}
}
// Set location of SWIG library
strcpy(LibDir,"matlab");
// Add a symbol to the parser for conditional compilation
add_symbol("SWIGMATLAB",0,0);
// Add typemap definitions
typemap_lang = "matlab";
}
// ---------------------------------------------------------------------
// void MATLAB::parse()
//
// Start parsing an interface file for MATLAB.
// ---------------------------------------------------------------------
void MATLAB::parse() {
fprintf(stderr,"Making wrappers for MATLAB (Experimental)\n");
headers(); // Emit header files and other supporting code
// Tell the parser to first include a typemap definition file
if (include_file("matlab.map") == -1) {
fprintf(stderr,"Unable to find matlab.map!\n");
SWIG_exit(1);
}
yyparse(); // Run the SWIG parser
}
// ---------------------------------------------------------------------
// MATLAB::set_module(char *mod_name,char **mod_list)
//
// Sets the module name. Does nothing if it's already set (so it can
// be overriddent as a command line option).
//
// mod_list is a NULL-terminated list of additional modules. This
// is really only useful when building static executables.
//----------------------------------------------------------------------
void MATLAB::set_module(char *mod_name, char **mod_list) {
if (module) return;
module = new char[strlen(mod_name)+1];
strcpy(module,mod_name);
}
// ---------------------------------------------------------------------
// MATLAB::headers(void)
//
// Generate the appropriate header files for MATLAB interface.
// ----------------------------------------------------------------------
void MATLAB::headers(void)
{
emit_banner(f_header); // Print the SWIG banner message
fprintf(f_header,"/* Implementation : MATLAB */\n\n");
// Include header file code fragment into the output
if (insert_file("mlheader.swg",f_header) == -1) {
fprintf(stderr,"Fatal Error. Unable to locate 'mlheader.swg'.\n");
SWIG_exit(1);
}
// Emit the default SWIG pointer type-checker (for strings)
if (insert_file("swigptr.swg",f_header) == -1) {
fprintf(stderr,"Fatal Error. Unable to locate 'swigptr.swg'.\n");
SWIG_exit(1);
}
}
// --------------------------------------------------------------------
// MATLAB::initialize(void)
//
// Produces an initialization function. Assumes that the init function
// name has already been specified.
// ---------------------------------------------------------------------
void MATLAB::initialize() {
if (!module) module = "swig";
// Start generating the initialization function
if (insert_file("mlinit.swg",f_init) == -1) {
fprintf(stderr,"Fatal Error. Unabled to locate 'mlinit.swg'.\n");
SWIG_exit(1);
}
}
// ---------------------------------------------------------------------
// MATLAB::close(void)
//
// Wrap things up. Close initialization function.
// ---------------------------------------------------------------------
void MATLAB::close(void) {
// Dump the pointer equivalency table
fprintf(f_wrappers,"void initialize_module() { \n");
fprintf(f_wrappers,"mexPrintf(\"Initializing module %s\\n\");\n", module);
fprintf(f_wrappers,"%s", constants.get());
emit_ptr_equivalence(f_wrappers);
fprintf(f_wrappers,"}\n");
// Finish off our init function and print it to the init file
fprintf(f_init,"\t mexErrMsgTxt(\"Unknown method.\");\n");
fprintf(f_init,"}\n");
}
// ----------------------------------------------------------------------
// MATLAB::create_command(char *cname, char *iname)
//
// Creates a MATLAB command from a C function. Really, we just do a
// string compare in the init function and call to the real function
// ----------------------------------------------------------------------
void MATLAB::create_command(char *cname, char *iname) {
char *wname;
wname = name_wrapper(cname,"");
fprintf(f_init,"\t if (strcmp(command,\"%s\") == 0) {\n", iname);
fprintf(f_init,"\t\t%s(nlhs,plhs,nrhs-1,&prhs[1]);\n",wname);
fprintf(f_init,"\t\treturn;\n");
fprintf(f_init,"\t}\n");
}
// ----------------------------------------------------------------------
// MATLAB::create_function(char *name, char *iname, DataType *d, ParmList *l)
//
// Create a function declaration and register it with the interpreter.
// ----------------------------------------------------------------------
void MATLAB::create_function(char *name, char *iname, DataType *t, ParmList *l)
{
String source, target;
char *tm;
String cleanup, outarg;
// A new wrapper function object
WrapperFunction f;
// Make a wrapper name for this function
char *wname = name_wrapper(iname,"");
// Now write the wrapper function itself....this is pretty ugly
f.def << "static void " << wname << "(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { \n";
// Emit all of the local variables for holding arguments.
int pcount = emit_args(t,l,f);
// Get number of optional/default arguments
int numopt = l->numopt();
// Emit count to check the number of arguments
f.code << tab4 << "if ((nrhs < " << (pcount-numopt) << ") || (nrhs > " << l->numarg() << ")) {\n"
<< tab8 << "mexErrMsgTxt(\"" << iname << ". Wrong # args.\");\n"
<< tab8 << "return;\n"
<< tab4 << "}\n";
// Now walk the function parameter list and generate code to get arguments
int j = 0; // Total number of non-optional arguments
for (int i = 0; i < pcount ; i++) {
Parm &p = (*l)[i]; // Get the ith argument
source = "";
target = "";
// Produce string representation of source and target arguments
source << "prhs[" << j << "]";
target << "_arg" << i;
if (!p.ignore) {
if (j >= (pcount-numopt)) // Check if parsing an optional argument
f.code << tab4 << "if (nrhs >" << j << ") {\n";
// Get typemap for this argument
tm = typemap_lookup("in",typemap_lang,p.t,p.name,source,target,&f);
if (tm) {
f.code << tm << "\n";
f.code.replace("$arg",source); // Perform a variable replacement
} else {
fprintf(stderr,"%s : Line %d. No typemapping for datatype %s\n",
input_file,line_number, p.t->print_type());
}
if (j >= (pcount-numopt))
f.code << tab4 << "} \n";
j++;
}
// Check to see if there was any sort of a constaint typemap
if ((tm = typemap_lookup("check",typemap_lang,p.t,p.name,source,target))) {
// Yep. Use it instead of the default
f.code << tm << "\n";
f.code.replace("$arg",source);
}
// Check if there was any cleanup code (save it for later)
if ((tm = typemap_lookup("freearg",typemap_lang,p.t,p.name,target,"plhs[0]"))) {
// Yep. Use it instead of the default
cleanup << tm << "\n";
cleanup.replace("$arg",source);
}
if ((tm = typemap_lookup("argout",typemap_lang,p.t,p.name,target,"plhs[0]"))) {
// Yep. Use it instead of the default
outarg << tm << "\n";
outarg.replace("$arg",source);
}
}
// Now write code to make the function call
emit_func_call(name,t,l,f);
// Return value if necessary
if ((t->type != T_VOID) || (t->is_pointer)) {
if ((tm = typemap_lookup("out",typemap_lang,t,name,"_result","plhs[0]"))) {
// Yep. Use it instead of the default
f.code << tm << "\n";
} else {
fprintf(stderr,"%s : Line %d. No return typemap for datatype %s\n",
input_file,line_number,t->print_type());
}
}
// Dump argument output code;
f.code << outarg;
// Dump the argument cleanup code
f.code << cleanup;
// Look for any remaining cleanup
if (NewObject) {
if ((tm = typemap_lookup("newfree",typemap_lang,t,iname,"_result",""))) {
f.code << tm << "\n";
}
}
if ((tm = typemap_lookup("ret",typemap_lang,t,name,"_result",""))) {
f.code << tm << "\n";
}
// Wrap things up (in a manner of speaking)
f.code << tab4 << "return;\n}";
// Substitute the cleanup code (some exception handlers like to have this)
f.code.replace("$cleanup",cleanup);
// Emit the function
f.print(f_wrappers);
// Now register the function with the language
create_command(name,iname);
// If there's a documentation entry, produce a usage string
if (doc_entry) {
static DocEntry *last_doc_entry = 0;
// Use usage as description
doc_entry->usage << iname;
// Set the cinfo field to specific a return type
if (last_doc_entry != doc_entry) {
doc_entry->cinfo << "returns " << t->print_type();
last_doc_entry = doc_entry;
}
}
}
// -----------------------------------------------------------------------
// MATLAB::link_variable(char *name, char *iname, DataType *t)
//
// Create a MATLAB link to a C variable.
// -----------------------------------------------------------------------
void MATLAB::link_variable(char *name, char *iname, DataType *t)
{
emit_set_get(name,iname,t);
}
// -----------------------------------------------------------------------
// MATLAB::declare_const(char *name, char *iname, DataType *type, char *value)
//
// Makes a constant. A quick trick is to make a variable and create a
// link to it.
// ------------------------------------------------------------------------
void MATLAB::declare_const(char *name, char *iname, DataType *type, char *value) {
// Returns a constant value
char *tm;
tm = typemap_lookup("const",typemap_lang, type, name, name, iname);
if (tm) {
String str = tm;
str.replace("$value",value);
constants << str;
}
}
syntax highlighted by Code2HTML, v. 0.9.1