File: matlab.cxx

package info (click to toggle)
swig 1.1p5-2
  • links: PTS
  • area: main
  • in suites: slink
  • size: 9,428 kB
  • ctags: 5,025
  • sloc: cpp: 21,599; ansic: 13,333; yacc: 3,297; python: 2,794; makefile: 2,182; perl: 1,984; tcl: 1,583; sh: 736; lisp: 201; objc: 143
file content (350 lines) | stat: -rw-r--r-- 10,663 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
// ------------------------------------------------------------------------
// 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;
  }
}