]>
Commit | Line | Data |
---|---|---|
c90f71dd RD |
1 | /******************************************************************************* |
2 | * Simplified Wrapper and Interface Generator (SWIG) | |
3 | * | |
4 | * Author : David Beazley | |
5 | * | |
6 | * Department of Computer Science | |
7 | * University of Chicago | |
8 | * 1100 E 58th Street | |
9 | * Chicago, IL 60637 | |
10 | * beazley@cs.uchicago.edu | |
11 | * | |
12 | * Please read the file LICENSE for the copyright and terms by which SWIG | |
13 | * can be used and distributed. | |
14 | *******************************************************************************/ | |
15 | ||
16 | /*********************************************************************** | |
17 | * $Header$ | |
18 | * | |
19 | * perl5.c | |
20 | * | |
21 | * Definitions for adding functions to Perl 5 | |
22 | * | |
23 | * How to extend perl5 (note : this is totally different in Perl 4) : | |
24 | * | |
25 | * 1. Variable linkage | |
26 | * | |
27 | * Must declare two functions : | |
28 | * | |
29 | * _var_set(SV *sv, MAGIC *mg); | |
30 | * _var_get(SV *sv, MAGIC *mg); | |
31 | * | |
32 | * These functions must set/get the values of a variable using | |
33 | * Perl5 internals. | |
34 | * | |
35 | * To add these to Perl5 (which isn't entirely clear), need to | |
36 | * do the following : | |
37 | * | |
38 | * SV *sv; | |
39 | * MAGIC *m; | |
40 | * sv = perl_get_sv("varname",TRUE); | |
41 | * sv_magic(sv,sv, 'U', "varname", strlen("varname)); | |
42 | * m = mg_find(sv, 'U'); | |
43 | * m->mg_virtual = (MGVTBL *) malloc(sizeof(MGVTBL)); | |
44 | * m->mg_virtual.svt_get = _var_set; | |
45 | * m->mg_virtual.svt_set = _var_get; | |
46 | * m->mg_virtual.svt_len = 0; | |
47 | * m->mg_virtual.svt_free = 0; | |
48 | * m->mg_virtual.svt_clear = 0; | |
49 | * | |
50 | * | |
51 | * 2. Function extension | |
52 | * | |
53 | * Functions are declared as : | |
54 | * XS(_wrap_func) { | |
55 | * dXSARGS; | |
56 | * if (items != parmcount) { | |
57 | * croak("Usage :"); | |
58 | * } | |
59 | * ... get arguments ... | |
60 | * | |
61 | * ... call function ... | |
62 | * ... set return value in ST(0) | |
63 | * XSRETURN(1); | |
64 | * } | |
65 | * To extract function arguments, use the following : | |
66 | * _arg = (int) SvIV(ST(0)) | |
67 | * _arg = (double) SvNV(ST(0)) | |
68 | * _arg = (char *) SvPV(ST(0),na); | |
69 | * | |
70 | * For return values, use : | |
71 | * ST(0) = sv_newmortal(); | |
72 | * sv_setiv(ST(0), (IV) RETVAL); // Integers | |
73 | * sv_setnv(ST(0), (double) RETVAL); // Doubles | |
74 | * sv_setpv((SV*) ST(0), RETVAL); // Strings | |
75 | * | |
76 | * New functions are added using | |
77 | * newXS("name", _wrap_func, file) | |
78 | * | |
79 | * | |
80 | * 3. Compilation. | |
81 | * | |
82 | * Code should be compiled into an object file for dynamic | |
83 | * loading into Perl. | |
84 | ***********************************************************************/ | |
85 | ||
86 | #include "swig.h" | |
87 | #include "perl5.h" | |
88 | ||
89 | static String pragma_include; | |
90 | ||
91 | static char *usage = "\ | |
92 | Perl5 Options (available with -perl5)\n\ | |
93 | -module name - Set module name\n\ | |
94 | -package name - Set package prefix\n\ | |
95 | -static - Omit code related to dynamic loading.\n\ | |
96 | -shadow - Create shadow classes.\n\ | |
97 | -compat - Compatibility mode.\n\ | |
98 | -alt-header file- Use an alternate header.\n\n"; | |
99 | ||
100 | static char *import_file = 0; | |
101 | static char *smodule = 0; | |
102 | static int compat = 0; | |
103 | ||
104 | // --------------------------------------------------------------------- | |
105 | // PERL5::parse_args(int argc, char *argv[]) | |
106 | // | |
107 | // Parse command line options. | |
108 | // --------------------------------------------------------------------- | |
109 | ||
110 | void | |
111 | PERL5::parse_args(int argc, char *argv[]) { | |
112 | ||
113 | int i = 1; | |
114 | ||
115 | export_all = 0; | |
116 | sprintf(LibDir,"%s", perl_path); | |
117 | ||
118 | // Look for certain command line options | |
119 | ||
120 | // Get options | |
121 | for (i = 1; i < argc; i++) { | |
122 | if (argv[i]) { | |
123 | if(strcmp(argv[i],"-package") == 0) { | |
124 | if (argv[i+1]) { | |
125 | package = new char[strlen(argv[i+1])+1]; | |
126 | strcpy(package, argv[i+1]); | |
127 | mark_arg(i); | |
128 | mark_arg(i+1); | |
129 | i++; | |
130 | } else { | |
131 | arg_error(); | |
132 | } | |
133 | } else if (strcmp(argv[i],"-module") == 0) { | |
134 | if (argv[i+1]) { | |
135 | module = new char[strlen(argv[i+1])+1]; | |
136 | strcpy(module, argv[i+1]); | |
137 | cmodule = module; | |
138 | cmodule.replace(":","_"); | |
139 | mark_arg(i); | |
140 | mark_arg(i+1); | |
141 | i++; | |
142 | } else { | |
143 | arg_error(); | |
144 | } | |
145 | } else if (strcmp(argv[i],"-exportall") == 0) { | |
146 | export_all = 1; | |
147 | mark_arg(i); | |
148 | } else if (strcmp(argv[i],"-static") == 0) { | |
149 | is_static = 1; | |
150 | mark_arg(i); | |
151 | } else if (strcmp(argv[i],"-shadow") == 0) { | |
152 | blessed = 1; | |
153 | mark_arg(i); | |
154 | } else if (strcmp(argv[i],"-alt-header") == 0) { | |
155 | if (argv[i+1]) { | |
156 | alt_header = copy_string(argv[i+1]); | |
157 | mark_arg(i); | |
158 | mark_arg(i+1); | |
159 | i++; | |
160 | } else { | |
161 | arg_error(); | |
162 | } | |
163 | } else if (strcmp(argv[i],"-compat") == 0) { | |
164 | compat = 1; | |
165 | mark_arg(i); | |
166 | } else if (strcmp(argv[i],"-help") == 0) { | |
167 | fputs(usage,stderr); | |
168 | } | |
169 | } | |
170 | } | |
171 | // Add a symbol for this module | |
172 | ||
173 | add_symbol("SWIGPERL",0,0); | |
174 | add_symbol("SWIGPERL5",0,0); | |
175 | ||
176 | // Set name of typemaps | |
177 | ||
178 | typemap_lang = "perl5"; | |
179 | ||
180 | } | |
181 | ||
182 | // ------------------------------------------------------------------ | |
183 | // PERL5::parse() | |
184 | // | |
185 | // Parse an interface file | |
186 | // ------------------------------------------------------------------ | |
187 | ||
188 | void | |
189 | PERL5::parse() { | |
190 | ||
191 | ||
192 | printf("Generating wrappers for Perl 5\n"); | |
193 | ||
194 | // Print out PERL5 specific headers | |
195 | ||
196 | headers(); | |
197 | ||
198 | // Run the parser | |
199 | ||
200 | yyparse(); | |
201 | fputs(vinit.get(),f_wrappers); | |
202 | } | |
203 | ||
204 | ||
205 | // --------------------------------------------------------------------- | |
206 | // PERL5::set_module(char *mod_name, char **mod_list) | |
207 | // | |
208 | // Sets the module name. | |
209 | // Does nothing if it's already set (so it can be overridden as a command | |
210 | // line option). | |
211 | // | |
212 | //---------------------------------------------------------------------- | |
213 | static String modinit, modextern; | |
214 | ||
215 | void PERL5::set_module(char *mod_name, char **mod_list) { | |
216 | int i; | |
217 | if (import_file) { | |
218 | if (!(strcmp(import_file,input_file+strlen(input_file)-strlen(import_file)))) { | |
219 | if (blessed) { | |
220 | fprintf(f_pm,"require %s;\n", mod_name); | |
221 | } | |
222 | delete [] import_file; | |
223 | import_file = 0; | |
224 | } | |
225 | } | |
226 | ||
227 | if (module) return; | |
228 | ||
229 | module = new char[strlen(mod_name)+1]; | |
230 | strcpy(module,mod_name); | |
231 | ||
232 | // if there was a mod_list specified, make this big hack | |
233 | if (mod_list) { | |
234 | modinit << "#define SWIGMODINIT "; | |
235 | modextern << "#ifdef __cplusplus\n" | |
236 | << "extern \"C\" {\n" | |
237 | << "#endif\n"; | |
238 | i = 0; | |
239 | while(mod_list[i]) { | |
240 | modinit << "newXS(\"" << mod_list[i] << "::boot_" << mod_list[i] << "\", boot_" << mod_list[i] << ", file);\\\n"; | |
241 | modextern << "extern void boot_" << mod_list[i] << "(CV *);\n"; | |
242 | i++; | |
243 | } | |
244 | modextern << "#ifdef __cplusplus\n" | |
245 | << "}\n" | |
246 | << "#endif\n"; | |
247 | modinit << "/* End of extern module initialization */\n"; | |
248 | } | |
249 | ||
250 | // Create a C module name and put it in 'cmodule' | |
251 | ||
252 | cmodule = module; | |
253 | cmodule.replace(":","_"); | |
254 | } | |
255 | ||
256 | // --------------------------------------------------------------------- | |
257 | // PERL5::set_init(char *iname) | |
258 | // | |
259 | // Sets the initialization function name. | |
260 | // Does nothing if it's already set | |
261 | // | |
262 | //---------------------------------------------------------------------- | |
263 | ||
264 | void PERL5::set_init(char *iname) { | |
265 | set_module(iname,0); | |
266 | } | |
267 | ||
268 | // --------------------------------------------------------------------- | |
269 | // PERL5::headers(void) | |
270 | // | |
271 | // Generate the appropriate header files for PERL5 interface. | |
272 | // ---------------------------------------------------------------------- | |
273 | ||
274 | void PERL5::headers(void) | |
275 | { | |
276 | ||
277 | emit_banner(f_header); | |
278 | ||
279 | if (!alt_header) { | |
280 | if (insert_file("headers.swg", f_header) == -1) { | |
281 | fprintf(stderr,"Perl5 : Fatal error. Unable to locate headers.swg. Possible installation problem.\n"); | |
282 | SWIG_exit(1); | |
283 | } | |
284 | } else { | |
285 | if (insert_file(alt_header, f_header) == -1) { | |
286 | fprintf(stderr,"SWIG : Fatal error. Unable to locate %s.\n",alt_header); | |
287 | SWIG_exit(1); | |
288 | } | |
289 | } | |
290 | ||
291 | if (NoInclude) { | |
292 | fprintf(f_header,"#define SWIG_NOINCLUDE\n"); | |
293 | } | |
294 | ||
295 | // Get special SWIG related declarations | |
296 | if (insert_file("perl5.swg", f_header) == -1) { | |
297 | fprintf(stderr,"SWIG : Fatal error. Unable to locate 'perl5.swg' in SWIG library.\n"); | |
298 | SWIG_exit(1); | |
299 | } | |
300 | ||
301 | // Get special SWIG related declarations | |
302 | if (insert_file("perl5mg.swg", f_header) == -1) { | |
303 | fprintf(stderr,"SWIG : Fatal error. Unable to locate 'perl5mg.swg' in SWIG library.\n"); | |
304 | SWIG_exit(1); | |
305 | } | |
306 | ||
307 | } | |
308 | ||
309 | // -------------------------------------------------------------------- | |
310 | // PERL5::initialize() | |
311 | // | |
312 | // Output initialization code that registers functions with the | |
313 | // interface. | |
314 | // --------------------------------------------------------------------- | |
315 | ||
316 | void PERL5::initialize() | |
317 | { | |
318 | ||
319 | char filen[256]; | |
320 | ||
321 | if (!module){ | |
322 | module = "swig"; | |
323 | fprintf(stderr,"SWIG : *** Warning. No module name specified.\n"); | |
324 | } | |
325 | ||
326 | if (!package) { | |
327 | package = new char[strlen(module)+1]; | |
328 | strcpy(package,module); | |
329 | } | |
330 | ||
331 | // If we're in blessed mode, change the package name to "packagec" | |
332 | ||
333 | if (blessed) { | |
334 | char *newpackage = new char[strlen(package)+2]; | |
335 | sprintf(newpackage,"%sc",package); | |
336 | realpackage = package; | |
337 | package = newpackage; | |
338 | } else { | |
339 | realpackage = package; | |
340 | } | |
341 | ||
342 | // Create a .pm file | |
343 | // Need to strip off any prefixes that might be found in | |
344 | // the module name | |
345 | ||
346 | { | |
347 | char *m = module + strlen(module); | |
348 | while (m != module) { | |
349 | if (*m == ':') { | |
350 | m++; | |
351 | break; | |
352 | } | |
353 | m--; | |
354 | } | |
355 | sprintf(filen,"%s%s.pm", output_dir,m); | |
356 | if ((f_pm = fopen(filen,"w")) == 0) { | |
357 | fprintf(stderr,"Unable to open %s\n", filen); | |
358 | SWIG_exit(0); | |
359 | } | |
360 | } | |
361 | if (!blessed) { | |
362 | smodule = module; | |
363 | } else if (is_static) { | |
364 | smodule = new char[strlen(module)+2]; | |
365 | strcpy(smodule,module); | |
366 | strcat(smodule,"c"); | |
367 | cmodule << "c"; | |
368 | } else { | |
369 | smodule = module; | |
370 | } | |
371 | ||
372 | fprintf(f_header,"#define SWIG_init boot_%s\n\n", cmodule.get()); | |
373 | fprintf(f_header,"#define SWIG_name \"%s::boot_%s\"\n", package, cmodule.get()); | |
374 | fprintf(f_header,"#define SWIG_varinit \"%s::var_%s_init();\"\n", package, cmodule.get()); | |
375 | fprintf(f_header,"#ifdef __cplusplus\n"); | |
376 | fprintf(f_header,"extern \"C\"\n"); | |
377 | fprintf(f_header,"#endif\n"); | |
378 | fprintf(f_header,"#ifndef PERL_OBJECT\n"); | |
379 | fprintf(f_header,"SWIGEXPORT(void) boot_%s(CV* cv);\n", cmodule.get()); | |
380 | fprintf(f_header,"#else\n"); | |
381 | fprintf(f_header,"SWIGEXPORT(void) boot_%s(CV *cv, CPerlObj *);\n",cmodule.get()); | |
382 | fprintf(f_header,"#endif\n"); | |
383 | fprintf(f_init,"#ifdef __cplusplus\n"); | |
384 | fprintf(f_init,"extern \"C\"\n"); | |
385 | fprintf(f_init,"#endif\n"); | |
386 | fprintf(f_init,"XS(boot_%s) {\n", cmodule.get()); | |
387 | fprintf(f_init,"\t dXSARGS;\n"); | |
388 | fprintf(f_init,"\t char *file = __FILE__;\n"); | |
389 | fprintf(f_init,"\t cv = cv; items = items;\n"); | |
390 | fprintf(f_init,"\t newXS(\"%s::var_%s_init\", _wrap_perl5_%s_var_init, file);\n",package,cmodule.get(), cmodule.get()); | |
391 | vinit << "XS(_wrap_perl5_" << cmodule << "_var_init) {\n" | |
392 | << tab4 << "dXSARGS;\n" | |
393 | << tab4 << "SV *sv;\n" | |
394 | << tab4 << "cv = cv; items = items;\n"; | |
395 | ||
396 | fprintf(f_pm,"# This file was automatically generated by SWIG\n"); | |
397 | fprintf(f_pm,"package %s;\n",module); | |
398 | fprintf(f_pm,"require Exporter;\n"); | |
399 | if (!is_static) { | |
400 | fprintf(f_pm,"require DynaLoader;\n"); | |
401 | fprintf(f_pm,"@ISA = qw(Exporter DynaLoader);\n"); | |
402 | } else { | |
403 | fprintf(f_pm,"@ISA = qw(Exporter);\n"); | |
404 | } | |
405 | ||
406 | // Start creating magic code | |
407 | ||
408 | ||
409 | magic << "#ifdef PERL_OBJECT\n" | |
410 | << "#define MAGIC_CLASS _wrap_" << module << "_var::\n" | |
411 | << "class _wrap_" << module << "_var : public CPerlObj {\n" | |
412 | << "public:\n" | |
413 | << "#else\n" | |
414 | << "#define MAGIC_CLASS\n" | |
415 | << "#endif\n" | |
416 | << "SWIGCLASS_STATIC int swig_magic_readonly(SV *sv, MAGIC *mg) {\n" | |
417 | << tab4 << "MAGIC_PPERL\n" | |
418 | << tab4 << "sv = sv; mg = mg;\n" | |
419 | << tab4 << "croak(\"Value is read-only.\");\n" | |
420 | << tab4 << "return 0;\n" | |
421 | << "}\n"; // Dump out external module declarations | |
422 | ||
423 | /* Process additional initialization files here */ | |
424 | ||
425 | if (strlen(modinit.get()) > 0) { | |
426 | fprintf(f_header,"%s\n",modinit.get()); | |
427 | } | |
428 | if (strlen(modextern.get()) > 0) { | |
429 | fprintf(f_header,"%s\n",modextern.get()); | |
430 | } | |
431 | } | |
432 | ||
433 | // --------------------------------------------------------------------- | |
434 | // PERL5::import(char *filename) | |
435 | // | |
436 | // Import directive | |
437 | // --------------------------------------------------------------------- | |
438 | ||
439 | void PERL5::import(char *filename) { | |
440 | if (import_file) delete [] import_file; | |
441 | import_file = copy_string(filename); | |
442 | } | |
443 | ||
444 | ||
445 | // --------------------------------------------------------------------- | |
446 | // PERL5::close(void) | |
447 | // | |
448 | // Wrap things up. Close initialization function. | |
449 | // --------------------------------------------------------------------- | |
450 | ||
451 | void PERL5::close(void) | |
452 | { | |
453 | String base; | |
454 | ||
455 | // Dump out variable wrappers | |
456 | ||
457 | magic << "\n\n#ifdef PERL_OBJECT\n" | |
458 | << "};\n" | |
459 | << "#endif\n"; | |
460 | ||
461 | fprintf(f_header,"%s\n", magic.get()); | |
462 | ||
463 | emit_ptr_equivalence(f_init); | |
464 | ||
465 | fprintf(f_init,"\t ST(0) = &PL_sv_yes;\n"); | |
466 | fprintf(f_init,"\t XSRETURN(1);\n"); | |
467 | fprintf(f_init,"}\n"); | |
468 | ||
469 | vinit << tab4 << "XSRETURN(1);\n" | |
470 | << "}\n"; | |
471 | ||
472 | fprintf(f_pm,"package %s;\n", package); | |
473 | ||
474 | if (!is_static) { | |
475 | fprintf(f_pm,"bootstrap %s;\n", smodule); | |
476 | } else { | |
477 | fprintf(f_pm,"boot_%s();\n", smodule); | |
478 | } | |
479 | fprintf(f_pm,"var_%s_init();\n", cmodule.get()); | |
480 | fprintf(f_pm,"%s",pragma_include.get()); | |
481 | fprintf(f_pm,"package %s;\n", realpackage); | |
482 | fprintf(f_pm,"@EXPORT = qw(%s );\n",exported.get()); | |
483 | ||
484 | if (blessed) { | |
485 | ||
486 | base << "\n# ---------- BASE METHODS -------------\n\n" | |
487 | << "package " << realpackage << ";\n\n"; | |
488 | ||
489 | // Write out the TIE method | |
490 | ||
491 | base << "sub TIEHASH {\n" | |
492 | << tab4 << "my ($classname,$obj) = @_;\n" | |
493 | << tab4 << "return bless $obj, $classname;\n" | |
494 | << "}\n\n"; | |
495 | ||
496 | // Output a CLEAR method. This is just a place-holder, but by providing it we | |
497 | // can make declarations such as | |
498 | // %$u = ( x => 2, y=>3, z =>4 ); | |
499 | // | |
500 | // Where x,y,z are the members of some C/C++ object. | |
501 | ||
502 | base << "sub CLEAR { }\n\n"; | |
503 | ||
504 | // Output default firstkey/nextkey methods | |
505 | ||
506 | base << "sub FIRSTKEY { }\n\n"; | |
507 | base << "sub NEXTKEY { }\n\n"; | |
508 | ||
509 | // Output a 'this' method | |
510 | ||
511 | base << "sub this {\n" | |
512 | << tab4 << "my $ptr = shift;\n" | |
513 | << tab4 << "return tied(%$ptr);\n" | |
514 | << "}\n\n"; | |
515 | ||
516 | fprintf(f_pm,"%s",base.get()); | |
517 | ||
518 | // Emit function stubs for stand-alone functions | |
519 | ||
520 | fprintf(f_pm,"\n# ------- FUNCTION WRAPPERS --------\n\n"); | |
521 | fprintf(f_pm,"package %s;\n\n",realpackage); | |
522 | fprintf(f_pm,"%s",func_stubs.get()); | |
523 | ||
524 | ||
525 | // Emit package code for different classes | |
526 | ||
527 | fprintf(f_pm,"%s",pm.get()); | |
528 | ||
529 | // Emit variable stubs | |
530 | ||
531 | fprintf(f_pm,"\n# ------- VARIABLE STUBS --------\n\n"); | |
532 | fprintf(f_pm,"package %s;\n\n",realpackage); | |
533 | fprintf(f_pm,"%s",var_stubs.get()); | |
534 | ||
535 | } | |
536 | ||
537 | fprintf(f_pm,"1;\n"); | |
538 | fclose(f_pm); | |
539 | ||
540 | // Patch up documentation title | |
541 | ||
542 | if ((doc_entry) && (module)) { | |
543 | doc_entry->cinfo << "Module : " << module << ", " | |
544 | << "Package : " << realpackage; | |
545 | } | |
546 | ||
547 | } | |
548 | ||
549 | // ---------------------------------------------------------------------- | |
550 | // char *PERL5::type_mangle(DataType *t) | |
551 | // | |
552 | // Mangles a datatype into a Perl5 name compatible with xsubpp type | |
553 | // T_PTROBJ. | |
554 | // ---------------------------------------------------------------------- | |
555 | ||
556 | char * | |
557 | PERL5::type_mangle(DataType *t) { | |
558 | static char result[128]; | |
559 | int i; | |
560 | char *r, *c; | |
561 | ||
562 | if (blessed) { | |
563 | ||
564 | // Check to see if we've blessed this datatype | |
565 | ||
566 | if ((classes.lookup(t->name)) && (t->is_pointer <= 1)) { | |
567 | ||
568 | // This is a blessed class. Return just the type-name | |
569 | strcpy(result,(char *) classes.lookup(t->name)); | |
570 | return result; | |
571 | } | |
572 | } | |
573 | ||
574 | r = result; | |
575 | c = t->name; | |
576 | ||
577 | for ( c = t->name; *c; c++,r++) { | |
578 | *r = *c; | |
579 | } | |
580 | for (i = 0; i < (t->is_pointer-t->implicit_ptr); i++, r++) { | |
581 | strcpy(r,"Ptr"); | |
582 | r+=2; | |
583 | } | |
584 | *r = 0; | |
585 | return result; | |
586 | } | |
587 | ||
588 | // ---------------------------------------------------------------------- | |
589 | // PERL5::get_pointer(char *iname, char *srcname, char *src, char *target, | |
590 | // DataType *t, String &f, char *ret) | |
591 | // | |
592 | // Emits code to get a pointer from a parameter and do type checking. | |
593 | // ---------------------------------------------------------------------- | |
594 | ||
595 | void PERL5::get_pointer(char *iname, char *srcname, char *src, char *dest, | |
596 | DataType *t, String &f, char *ret) { | |
597 | ||
598 | // Now get the pointer value from the string and save in dest | |
599 | ||
600 | f << tab4 << "if (SWIG_GetPtr(" << src << ",(void **) &" << dest << ","; | |
601 | ||
602 | // If we're passing a void pointer, we give the pointer conversion a NULL | |
603 | // pointer, otherwise pass in the expected type. | |
604 | ||
605 | if (t->type == T_VOID) f << "(char *) 0 )) {\n"; | |
606 | else | |
607 | f << "\"" << t->print_mangle() << "\")) {\n"; | |
608 | ||
609 | // This part handles the type checking according to three different | |
610 | // levels. 0 = no checking, 1 = warning message, 2 = strict. | |
611 | ||
612 | switch(TypeStrict) { | |
613 | case 0: // No type checking | |
614 | f << tab4 << "}\n"; | |
615 | break; | |
616 | ||
617 | case 1: // Warning message only | |
618 | ||
619 | // Change this part to how you want to handle a type-mismatch warning. | |
620 | // By default, it will just print to stderr. | |
621 | ||
622 | f << tab8 << "fprintf(stderr,\"Warning : type mismatch in " << srcname | |
623 | << " of " << iname << ". Expected " << t->print_mangle() | |
624 | << ", received %s\\n\"," << src << ");\n" | |
625 | << tab4 << "}\n"; | |
626 | ||
627 | break; | |
628 | case 2: // Super strict mode. | |
629 | ||
630 | // Change this part to return an error. | |
631 | ||
632 | f << tab8 << "croak(\"Type error in " << srcname | |
633 | << " of " << iname << ". Expected " << t->print_mangle() << ".\");\n" | |
634 | << tab8 << ret << ";\n" | |
635 | << tab4 << "}\n"; | |
636 | ||
637 | break; | |
638 | ||
639 | default : | |
640 | fprintf(stderr,"SWIG Error. Unknown strictness level\n"); | |
641 | break; | |
642 | } | |
643 | } | |
644 | ||
645 | // ---------------------------------------------------------------------- | |
646 | // PERL5::create_command(char *cname, char *iname) | |
647 | // | |
648 | // Create a command and register it with the interpreter | |
649 | // ---------------------------------------------------------------------- | |
650 | ||
651 | void PERL5::create_command(char *cname, char *iname) { | |
652 | fprintf(f_init,"\t newXS(\"%s::%s\", %s, file);\n", package, iname, name_wrapper(cname,"")); | |
653 | if (export_all) { | |
654 | exported << iname << " "; | |
655 | } | |
656 | } | |
657 | ||
658 | // ---------------------------------------------------------------------- | |
659 | // PERL5::create_function(char *name, char *iname, DataType *d, | |
660 | // ParmList *l) | |
661 | // | |
662 | // Create a function declaration and register it with the interpreter. | |
663 | // ---------------------------------------------------------------------- | |
664 | ||
665 | void PERL5::create_function(char *name, char *iname, DataType *d, ParmList *l) | |
666 | { | |
667 | Parm *p; | |
668 | int pcount,i,j; | |
669 | char *wname; | |
670 | char *usage = 0; | |
671 | WrapperFunction f; | |
672 | char source[256],target[256],temp[256], argnum[32]; | |
673 | char *tm; | |
674 | String cleanup,outarg,build; | |
675 | int numopt = 0; | |
676 | int need_save, num_saved = 0; // Number of saved arguments. | |
677 | int have_build = 0; | |
678 | ||
679 | // Make a wrapper name for this | |
680 | ||
681 | wname = name_wrapper(iname,""); | |
682 | ||
683 | // Now write the wrapper function itself....this is pretty ugly | |
684 | ||
685 | f.def << "XS(" << wname << ") {\n"; | |
686 | f.code << tab4 << "cv = cv;\n"; | |
687 | ||
688 | pcount = emit_args(d, l, f); | |
689 | numopt = l->numopt(); | |
690 | ||
691 | f.add_local("int","argvi = 0"); | |
692 | ||
693 | // Check the number of arguments | |
694 | ||
695 | usage = usage_func(iname,d,l); | |
696 | f.code << tab4 << "if ((items < " << (pcount-numopt) << ") || (items > " << l->numarg() << ")) \n" | |
697 | << tab8 << "croak(\"Usage: " << usage << "\");\n"; | |
698 | ||
699 | // Write code to extract parameters. | |
700 | // This section should be able to extract virtually any kind | |
701 | // parameter, represented as a string | |
702 | ||
703 | i = 0; | |
704 | j = 0; | |
705 | p = l->get_first(); | |
706 | while (p != 0) { | |
707 | // Produce string representation of source and target arguments | |
708 | sprintf(source,"ST(%d)",j); | |
709 | sprintf(target,"_arg%d",i); | |
710 | sprintf(argnum,"%d",j+1); | |
711 | ||
712 | // Check to see if this argument is being ignored | |
713 | ||
714 | if (!p->ignore) { | |
715 | ||
716 | // If there are optional arguments, check for this | |
717 | ||
718 | if (j>= (pcount-numopt)) | |
719 | f.code << tab4 << "if (items > " << j << ") {\n"; | |
720 | ||
721 | // See if there is a type-map | |
722 | if ((tm = typemap_lookup("in","perl5",p->t,p->name,source,target,&f))) { | |
723 | f.code << tm << "\n"; | |
724 | f.code.replace("$argnum",argnum); | |
725 | f.code.replace("$arg",source); | |
726 | } else { | |
727 | ||
728 | if (!p->t->is_pointer) { | |
729 | ||
730 | // Extract a parameter by "value" | |
731 | ||
732 | switch(p->t->type) { | |
733 | ||
734 | // Integers | |
735 | ||
736 | case T_BOOL: | |
737 | case T_INT : | |
738 | case T_SHORT : | |
739 | case T_LONG : | |
740 | case T_SINT : | |
741 | case T_SSHORT: | |
742 | case T_SLONG: | |
743 | case T_SCHAR: | |
744 | case T_UINT: | |
745 | case T_USHORT: | |
746 | case T_ULONG: | |
747 | case T_UCHAR: | |
748 | f.code << tab4 << "_arg" << i << " = " << p->t->print_cast() | |
749 | << "SvIV(ST(" << j << "));\n"; | |
750 | break; | |
751 | case T_CHAR : | |
752 | ||
753 | ||
754 | ||
755 | f.code << tab4 << "_arg" << i << " = (char) *SvPV(ST(" << j << "),PL_na);\n"; | |
756 | break; | |
757 | ||
758 | // Doubles | |
759 | ||
760 | case T_DOUBLE : | |
761 | case T_FLOAT : | |
762 | f.code << tab4 << "_arg" << i << " = " << p->t->print_cast() | |
763 | << " SvNV(ST(" << j << "));\n"; | |
764 | break; | |
765 | ||
766 | // Void.. Do nothing. | |
767 | ||
768 | case T_VOID : | |
769 | break; | |
770 | ||
771 | // User defined. This is invalid here. Note, user-defined types by | |
772 | // value are handled in the parser. | |
773 | ||
774 | case T_USER: | |
775 | ||
776 | // Unsupported data type | |
777 | ||
778 | default : | |
779 | fprintf(stderr,"%s : Line %d. Unable to use type %s as a function argument.\n",input_file, line_number, p->t->print_type()); | |
780 | break; | |
781 | } | |
782 | } else { | |
783 | ||
784 | // Argument is a pointer type. Special case is for char * | |
785 | // since that is usually a string. | |
786 | ||
787 | if ((p->t->type == T_CHAR) && (p->t->is_pointer == 1)) { | |
788 | f.code << tab4 << "if (! SvOK((SV*) ST(" << j << "))) { " | |
789 | << "_arg" << i << " = 0; }\n"; | |
790 | f.code << tab4 << "else { _arg" | |
791 | << i << " = (char *) SvPV(ST(" << j << "),PL_na); }\n"; | |
792 | } else { | |
793 | ||
794 | // Have a generic pointer type here. Read it in as a swig | |
795 | // typed pointer. | |
796 | ||
797 | sprintf(temp,"argument %d", i+1); | |
798 | get_pointer(iname,temp,source,target, p->t, f.code, "XSRETURN(1)"); | |
799 | } | |
800 | } | |
801 | } | |
802 | // The source is going to be an array of saved values. | |
803 | ||
804 | sprintf(temp,"_saved[%d]",num_saved); | |
805 | if (j>= (pcount-numopt)) | |
806 | f.code << tab4 << "} \n"; | |
807 | j++; | |
808 | } else { | |
809 | temp[0] = 0; | |
810 | } | |
811 | // Check to see if there is any sort of "build" typemap (highly complicated) | |
812 | ||
813 | if ((tm = typemap_lookup("build","perl5",p->t,p->name,source,target))) { | |
814 | build << tm << "\n"; | |
815 | have_build = 1; | |
816 | } | |
817 | ||
818 | // Check if there is any constraint code | |
819 | if ((tm = typemap_lookup("check","perl5",p->t,p->name,source,target))) { | |
820 | f.code << tm << "\n"; | |
821 | f.code.replace("$argnum",argnum); | |
822 | } | |
823 | need_save = 0; | |
824 | ||
825 | if ((tm = typemap_lookup("freearg","perl5",p->t,p->name,target,temp))) { | |
826 | cleanup << tm << "\n"; | |
827 | cleanup.replace("$argnum",argnum); | |
828 | cleanup.replace("$arg",temp); | |
829 | need_save = 1; | |
830 | } | |
831 | if ((tm = typemap_lookup("argout","perl5",p->t,p->name,target,"ST(argvi)"))) { | |
832 | String tempstr; | |
833 | tempstr = tm; | |
834 | tempstr.replace("$argnum",argnum); | |
835 | tempstr.replace("$arg",temp); | |
836 | outarg << tempstr << "\n"; | |
837 | need_save = 1; | |
838 | } | |
839 | // If we needed a saved variable, we need to emit to emit some code for that | |
840 | // This only applies if the argument actually existed (not ignore) | |
841 | if ((need_save) && (!p->ignore)) { | |
842 | f.code << tab4 << temp << " = " << source << ";\n"; | |
843 | num_saved++; | |
844 | } | |
845 | p = l->get_next(); | |
846 | i++; | |
847 | } | |
848 | ||
849 | // If there were any saved arguments, emit a local variable for them | |
850 | ||
851 | if (num_saved) { | |
852 | sprintf(temp,"_saved[%d]",num_saved); | |
853 | f.add_local("SV *",temp); | |
854 | } | |
855 | ||
856 | // If there was a "build" typemap, we need to go in and perform a serious hack | |
857 | ||
858 | if (have_build) { | |
859 | char temp1[32]; | |
860 | char temp2[256]; | |
861 | l->sub_parmnames(build); // Replace all parameter names | |
862 | j = 1; | |
863 | for (i = 0; i < l->nparms; i++) { | |
864 | p = l->get(i); | |
865 | if (strlen(p->name) > 0) { | |
866 | sprintf(temp1,"_in_%s", p->name); | |
867 | } else { | |
868 | sprintf(temp1,"_in_arg%d", i); | |
869 | } | |
870 | sprintf(temp2,"argv[%d]",j); | |
871 | build.replaceid(temp1,temp2); | |
872 | if (!p->ignore) | |
873 | j++; | |
874 | } | |
875 | f.code << build; | |
876 | } | |
877 | ||
878 | // Now write code to make the function call | |
879 | ||
880 | emit_func_call(name,d,l,f); | |
881 | ||
882 | // See if there was a typemap | |
883 | ||
884 | if ((tm = typemap_lookup("out","perl5",d,iname,"_result","ST(argvi)"))) { | |
885 | // Yep. Use it instead of the default | |
886 | f.code << tm << "\n"; | |
887 | } else if ((d->type != T_VOID) || (d->is_pointer)) { | |
888 | if (!d->is_pointer) { | |
889 | ||
890 | // Function returns a "value" | |
891 | f.code << tab4 << "ST(argvi) = sv_newmortal();\n"; | |
892 | switch(d->type) { | |
893 | case T_INT: case T_BOOL: case T_SINT: case T_UINT: | |
894 | case T_SHORT: case T_SSHORT: case T_USHORT: | |
895 | case T_LONG : case T_SLONG : case T_ULONG: | |
896 | case T_SCHAR: case T_UCHAR : | |
897 | f.code << tab4 << "sv_setiv(ST(argvi++),(IV) _result);\n"; | |
898 | break; | |
899 | case T_DOUBLE : | |
900 | case T_FLOAT : | |
901 | f.code << tab4 << "sv_setnv(ST(argvi++), (double) _result);\n"; | |
902 | break; | |
903 | case T_CHAR : | |
904 | f.add_local("char", "_ctemp[2]"); | |
905 | f.code << tab4 << "_ctemp[0] = _result;\n" | |
906 | << tab4 << "_ctemp[1] = 0;\n" | |
907 | << tab4 << "sv_setpv((SV*)ST(argvi++),_ctemp);\n"; | |
908 | break; | |
909 | ||
910 | // Return a complex type by value | |
911 | ||
912 | case T_USER: | |
913 | d->is_pointer++; | |
914 | f.code << tab4 << "sv_setref_pv(ST(argvi++),\"" << d->print_mangle() | |
915 | << "\", (void *) _result);\n"; | |
916 | d->is_pointer--; | |
917 | break; | |
918 | ||
919 | default : | |
920 | fprintf(stderr,"%s: Line %d. Unable to use return type %s in function %s.\n", input_file, line_number, d->print_type(), name); | |
921 | break; | |
922 | } | |
923 | } else { | |
924 | ||
925 | // Is a pointer return type | |
926 | f.code << tab4 << "ST(argvi) = sv_newmortal();\n"; | |
927 | if ((d->type == T_CHAR) && (d->is_pointer == 1)) { | |
928 | ||
929 | // Return a character string | |
930 | f.code << tab4 << "sv_setpv((SV*)ST(argvi++),(char *) _result);\n"; | |
931 | ||
932 | } else { | |
933 | // Is an ordinary pointer type. | |
934 | f.code << tab4 << "sv_setref_pv(ST(argvi++),\"" << d->print_mangle() | |
935 | << "\", (void *) _result);\n"; | |
936 | } | |
937 | } | |
938 | } | |
939 | ||
940 | // If there were any output args, take care of them. | |
941 | ||
942 | f.code << outarg; | |
943 | ||
944 | // If there was any cleanup, do that. | |
945 | ||
946 | f.code << cleanup; | |
947 | ||
948 | if (NewObject) { | |
949 | if ((tm = typemap_lookup("newfree","perl5",d,iname,"_result",""))) { | |
950 | f.code << tm << "\n"; | |
951 | } | |
952 | } | |
953 | ||
954 | if ((tm = typemap_lookup("ret","perl5",d,iname,"_result",""))) { | |
955 | // Yep. Use it instead of the default | |
956 | f.code << tm << "\n"; | |
957 | } | |
958 | ||
959 | // Wrap things up (in a manner of speaking) | |
960 | ||
961 | f.code << tab4 << "XSRETURN(argvi);\n}\n"; | |
962 | ||
963 | // Add the dXSARGS last | |
964 | ||
965 | f.add_local("dXSARGS",""); | |
966 | ||
967 | // Substitute the cleanup code | |
968 | f.code.replace("$cleanup",cleanup); | |
969 | f.code.replace("$name",iname); | |
970 | ||
971 | // Dump this function out | |
972 | ||
973 | f.print(f_wrappers); | |
974 | ||
975 | // Create a first crack at a documentation entry | |
976 | ||
977 | if (doc_entry) { | |
978 | static DocEntry *last_doc_entry = 0; | |
979 | doc_entry->usage << usage; | |
980 | if (last_doc_entry != doc_entry) { | |
981 | doc_entry->cinfo << "returns " << d->print_type(); | |
982 | last_doc_entry = doc_entry; | |
983 | } | |
984 | } | |
985 | ||
986 | // Now register the function | |
987 | ||
988 | fprintf(f_init,"\t newXS(\"%s::%s\", %s, file);\n", package, iname, wname); | |
989 | ||
990 | if (export_all) { | |
991 | exported << iname << " "; | |
992 | } | |
993 | ||
994 | ||
995 | // -------------------------------------------------------------------- | |
996 | // Create a stub for this function, provided it's not a member function | |
997 | // | |
998 | // Really we only need to create a stub if this function involves | |
999 | // complex datatypes. If it does, we'll make a small wrapper to | |
1000 | // process the arguments. If it doesn't, we'll just make a symbol | |
1001 | // table entry. | |
1002 | // -------------------------------------------------------------------- | |
1003 | ||
1004 | if ((blessed) && (!member_func)) { | |
1005 | int need_stub = 0; | |
1006 | String func; | |
1007 | ||
1008 | // We'll make a stub since we may need it anyways | |
1009 | ||
1010 | func << "sub " << iname << " {\n" | |
1011 | << tab4 << "my @args = @_;\n"; | |
1012 | ||
1013 | ||
1014 | // Now we have to go through and patch up the argument list. If any | |
1015 | // arguments to our function correspond to other Perl objects, we | |
1016 | // need to extract them from a tied-hash table object. | |
1017 | ||
1018 | Parm *p = l->get_first(); | |
1019 | int i = 0; | |
1020 | while(p) { | |
1021 | ||
1022 | if (!p->ignore) { | |
1023 | // Look up the datatype name here | |
1024 | ||
1025 | if ((classes.lookup(p->t->name)) && (p->t->is_pointer <= 1)) { | |
1026 | if (i >= (pcount - numopt)) | |
1027 | func << tab4 << "if (scalar(@args) >= " << i << ") {\n" << tab4; | |
1028 | ||
1029 | func << tab4 << "$args[" << i << "] = tied(%{$args[" << i << "]});\n"; | |
1030 | ||
1031 | if (i >= (pcount - numopt)) | |
1032 | func << tab4 << "}\n"; | |
1033 | ||
1034 | need_stub = 1; | |
1035 | } | |
1036 | i++; | |
1037 | } | |
1038 | p = l->get_next(); | |
1039 | } | |
1040 | ||
1041 | func << tab4 << "my $result = " << package << "::" << iname << "(@args);\n"; | |
1042 | ||
1043 | // Now check to see what kind of return result was found. | |
1044 | // If this function is returning a result by 'value', SWIG did an | |
1045 | // implicit malloc/new. We'll mark the object like it was created | |
1046 | // in Perl so we can garbage collect it. | |
1047 | ||
1048 | if ((classes.lookup(d->name)) && (d->is_pointer <=1)) { | |
1049 | ||
1050 | func << tab4 << "return undef if (!defined($result));\n"; | |
1051 | ||
1052 | // If we're returning an object by value, put it's reference | |
1053 | // into our local hash table | |
1054 | ||
1055 | if ((d->is_pointer == 0) || ((d->is_pointer == 1) && NewObject)) { | |
1056 | func << tab4 << "$" << (char *) classes.lookup(d->name) << "::OWNER{$result} = 1;\n"; | |
1057 | } | |
1058 | ||
1059 | // We're returning a Perl "object" of some kind. Turn it into | |
1060 | // a tied hash | |
1061 | ||
1062 | func << tab4 << "my %resulthash;\n" | |
1063 | /* << tab4 << "tie %resulthash, \"" << (char *) classes.lookup(d->name) << "\", $result;\n" | |
1064 | << tab4 << "return bless \\%resulthash, \"" << (char *) classes.lookup(d->name) << "\";\n" | |
1065 | */ | |
1066 | << tab4 << "tie %resulthash, ref($result), $result;\n" | |
1067 | << tab4 << "return bless \\%resulthash, ref($result);\n" | |
1068 | << "}\n"; | |
1069 | ||
1070 | need_stub = 1; | |
1071 | } else { | |
1072 | ||
1073 | // Hmmm. This doesn't appear to be anything I know about so just | |
1074 | // return it unmolested. | |
1075 | ||
1076 | func << tab4 <<"return $result;\n" | |
1077 | << "}\n"; | |
1078 | ||
1079 | } | |
1080 | ||
1081 | // Now check if we needed the stub. If so, emit it, otherwise | |
1082 | // Emit code to hack Perl's symbol table instead | |
1083 | ||
1084 | if (need_stub) { | |
1085 | func_stubs << func; | |
1086 | } else { | |
1087 | func_stubs << "*" << iname << " = *" << package << "::" << iname << ";\n"; | |
1088 | } | |
1089 | } | |
1090 | } | |
1091 | ||
1092 | // ----------------------------------------------------------------------- | |
1093 | // PERL5::link_variable(char *name, char *iname, DataType *d) | |
1094 | // | |
1095 | // Create a link to a C variable. | |
1096 | // ----------------------------------------------------------------------- | |
1097 | ||
1098 | void PERL5::link_variable(char *name, char *iname, DataType *t) | |
1099 | { | |
1100 | char set_name[256]; | |
1101 | char val_name[256]; | |
1102 | WrapperFunction getf, setf; | |
1103 | char *tm; | |
1104 | sprintf(set_name,"_wrap_set_%s",iname); | |
1105 | sprintf(val_name,"_wrap_val_%s",iname); | |
1106 | ||
1107 | // Create a new scalar that we will attach magic to | |
1108 | ||
1109 | vinit << tab4 << "sv = perl_get_sv(\"" << package << "::" << iname << "\",TRUE | 0x2);\n"; | |
1110 | ||
1111 | // Create a Perl function for setting the variable value | |
1112 | ||
1113 | if (!(Status & STAT_READONLY)) { | |
1114 | setf.def << "SWIGCLASS_STATIC int " << set_name << "(SV* sv, MAGIC *mg) {\n"; | |
1115 | ||
1116 | setf.code << tab4 << "MAGIC_PPERL\n"; | |
1117 | setf.code << tab4 << "mg = mg;\n"; | |
1118 | ||
1119 | /* Check for a few typemaps */ | |
1120 | if ((tm = typemap_lookup("varin","perl5",t,"","sv",name))) { | |
1121 | setf.code << tm << "\n"; | |
1122 | } else if ((tm = typemap_lookup("in","perl5",t,"","sv",name))) { | |
1123 | setf.code << tm << "\n"; | |
1124 | } else { | |
1125 | if (!t->is_pointer) { | |
1126 | ||
1127 | // Set the value to something | |
1128 | ||
1129 | switch(t->type) { | |
1130 | case T_INT : case T_BOOL: case T_SINT : case T_UINT: | |
1131 | case T_SHORT : case T_SSHORT : case T_USHORT: | |
1132 | case T_LONG : case T_SLONG : case T_ULONG: | |
1133 | case T_UCHAR: case T_SCHAR: | |
1134 | setf.code << tab4 << name << " = " << t->print_cast() << " SvIV(sv);\n"; | |
1135 | break; | |
1136 | case T_DOUBLE : | |
1137 | case T_FLOAT : | |
1138 | setf.code << tab4 << name << " = " << t->print_cast() << " SvNV(sv);\n"; | |
1139 | break; | |
1140 | case T_CHAR : | |
1141 | setf.code << tab4 << name << " = (char) *SvPV(sv,PL_na);\n"; | |
1142 | break; | |
1143 | ||
1144 | case T_USER: | |
1145 | ||
1146 | // Add support for User defined type here | |
1147 | // Get as a pointer value | |
1148 | ||
1149 | t->is_pointer++; | |
1150 | setf.add_local("void","*_temp"); | |
1151 | get_pointer(iname,"value","sv","_temp", t, setf.code, "return(1)"); | |
1152 | setf.code << tab4 << name << " = *(" << t->print_cast() << " _temp);\n"; | |
1153 | t->is_pointer--; | |
1154 | break; | |
1155 | ||
1156 | default : | |
1157 | fprintf(stderr,"%s : Line %d. Unable to link with datatype %s (ignored).\n", input_file, line_number, t->print_type()); | |
1158 | return; | |
1159 | } | |
1160 | } else { | |
1161 | // Have some sort of pointer type here, Process it differently | |
1162 | if ((t->type == T_CHAR) && (t->is_pointer == 1)) { | |
1163 | setf.add_local("char","*_a"); | |
1164 | setf.code << tab4 << "_a = (char *) SvPV(sv,PL_na);\n"; | |
1165 | ||
1166 | if (CPlusPlus) | |
1167 | setf.code << tab4 << "if (" << name << ") delete [] " << name << ";\n" | |
1168 | << tab4 << name << " = new char[strlen(_a)+1];\n"; | |
1169 | else | |
1170 | setf.code << tab4 << "if (" << name << ") free(" << name << ");\n" | |
1171 | << tab4 << name << " = (char *) malloc(strlen(_a)+1);\n"; | |
1172 | setf.code << "strcpy(" << name << ",_a);\n"; | |
1173 | } else { | |
1174 | // Set the value of a pointer | |
1175 | ||
1176 | setf.add_local("void","*_temp"); | |
1177 | get_pointer(iname,"value","sv","_temp", t, setf.code, "return(1)"); | |
1178 | setf.code << tab4 << name << " = " << t->print_cast() << " _temp;\n"; | |
1179 | } | |
1180 | } | |
1181 | } | |
1182 | setf.code << tab4 << "return 1;\n" | |
1183 | << "}\n"; | |
1184 | ||
1185 | setf.code.replace("$name",iname); | |
1186 | setf.print(magic); | |
1187 | ||
1188 | } | |
1189 | ||
1190 | // Now write a function to evaluate the variable | |
1191 | ||
1192 | getf.def << "SWIGCLASS_STATIC int " << val_name << "(SV *sv, MAGIC *mg) {\n"; | |
1193 | getf.code << tab4 << "MAGIC_PPERL\n"; | |
1194 | getf.code << tab4 << "mg = mg;\n"; | |
1195 | ||
1196 | // Check for a typemap | |
1197 | ||
1198 | if ((tm = typemap_lookup("varout","perl5",t,"",name, "sv"))) { | |
1199 | getf.code << tm << "\n"; | |
1200 | } else if ((tm = typemap_lookup("out","perl5",t,"",name,"sv"))) { | |
1201 | setf.code << tm << "\n"; | |
1202 | } else { | |
1203 | if (!t->is_pointer) { | |
1204 | switch(t->type) { | |
1205 | case T_INT : case T_BOOL: case T_SINT: case T_UINT: | |
1206 | case T_SHORT : case T_SSHORT: case T_USHORT: | |
1207 | case T_LONG : case T_SLONG : case T_ULONG: | |
1208 | case T_UCHAR: case T_SCHAR: | |
1209 | getf.code << tab4 << "sv_setiv(sv, (IV) " << name << ");\n"; | |
1210 | vinit << tab4 << "sv_setiv(sv,(IV)" << name << ");\n"; | |
1211 | break; | |
1212 | case T_DOUBLE : | |
1213 | case T_FLOAT : | |
1214 | getf.code << tab4 << "sv_setnv(sv, (double) " << name << ");\n"; | |
1215 | vinit << tab4 << "sv_setnv(sv,(double)" << name << ");\n"; | |
1216 | break; | |
1217 | case T_CHAR : | |
1218 | getf.add_local("char","_ptemp[2]"); | |
1219 | getf.code << tab4 << "_ptemp[0] = " << name << ";\n" | |
1220 | << tab4 << "_ptemp[1] = 0;\n" | |
1221 | << tab4 << "sv_setpv((SV*) sv, _ptemp);\n"; | |
1222 | break; | |
1223 | case T_USER: | |
1224 | t->is_pointer++; | |
1225 | getf.code << tab4 << "rsv = SvRV(sv);\n" | |
1226 | << tab4 << "sv_setiv(rsv,(IV) &" << name << ");\n"; | |
1227 | ||
1228 | // getf.code << tab4 << "sv_setref_pv((SV*) sv,\"" << t->print_mangle() | |
1229 | // << "\", (void *) &" << name << ");\n"; | |
1230 | ||
1231 | getf.add_local("SV","*rsv"); | |
1232 | vinit << tab4 << "sv_setref_pv(sv,\"" << t->print_mangle() << "\",(void *) &" << name << ");\n"; | |
1233 | t->is_pointer--; | |
1234 | ||
1235 | break; | |
1236 | default : | |
1237 | break; | |
1238 | } | |
1239 | } else { | |
1240 | ||
1241 | // Have some sort of arbitrary pointer type. Return it as a string | |
1242 | ||
1243 | if ((t->type == T_CHAR) && (t->is_pointer == 1)) | |
1244 | getf.code << tab4 << "sv_setpv((SV*) sv, " << name << ");\n"; | |
1245 | else { | |
1246 | getf.code << tab4 << "rsv = SvRV(sv);\n" | |
1247 | << tab4 << "sv_setiv(rsv,(IV) " << name << ");\n"; | |
1248 | getf.add_local("SV","*rsv"); | |
1249 | vinit << tab4 << "sv_setref_pv(sv,\"" << t->print_mangle() << "\",(void *) 1);\n"; | |
1250 | ||
1251 | //getf.code << tab4 << "sv_setref_pv((SV*) sv,\"" << t->print_mangle() | |
1252 | // << "\", (void *) " << name << ");\n"; | |
1253 | } | |
1254 | } | |
1255 | } | |
1256 | getf.code << tab4 << "return 1;\n" | |
1257 | << "}\n"; | |
1258 | ||
1259 | getf.code.replace("$name",iname); | |
1260 | getf.print(magic); | |
1261 | ||
1262 | // Now add symbol to the PERL interpreter | |
1263 | if (Status & STAT_READONLY) { | |
1264 | vinit << tab4 << "swig_create_magic(sv,\"" << package << "::" << iname << "\",MAGIC_CAST MAGIC_CLASS swig_magic_readonly, MAGIC_CAST MAGIC_CLASS " << val_name << ");\n"; | |
1265 | } else { | |
1266 | vinit << tab4 << "swig_create_magic(sv,\"" << package << "::" << iname << "\", MAGIC_CAST MAGIC_CLASS " << set_name << ", MAGIC_CAST MAGIC_CLASS " << val_name << ");\n"; | |
1267 | } | |
1268 | // Add a documentation entry | |
1269 | ||
1270 | if (doc_entry) { | |
1271 | doc_entry->usage << usage_var(iname,t); | |
1272 | doc_entry->cinfo << "Global : " << t->print_type() << " " << name; | |
1273 | } | |
1274 | ||
1275 | // If we're blessed, try to figure out what to do with the variable | |
1276 | // 1. If it's a Perl object of some sort, create a tied-hash | |
1277 | // around it. | |
1278 | // 2. Otherwise, just hack Perl's symbol table | |
1279 | ||
1280 | if (blessed) { | |
1281 | if ((classes.lookup(t->name)) && (t->is_pointer <= 1)) { | |
1282 | var_stubs << "\nmy %__" << iname << "_hash;\n" | |
1283 | << "tie %__" << iname << "_hash,\"" << (char *) classes.lookup(t->name) << "\", $" | |
1284 | << package << "::" << iname << ";\n" | |
1285 | << "$" << iname << "= \\%__" << iname << "_hash;\n" | |
1286 | << "bless $" << iname << ", " << (char *) classes.lookup(t->name) << ";\n"; | |
1287 | } else { | |
1288 | var_stubs << "*" << iname << " = *" << package << "::" << iname << ";\n"; | |
1289 | } | |
1290 | if (export_all) | |
1291 | exported << "$" << name << " "; | |
1292 | } | |
1293 | } | |
1294 | ||
1295 | // ----------------------------------------------------------------------- | |
1296 | // PERL5::declare_const(char *name, char *iname, DataType *type, char *value) | |
1297 | // | |
1298 | // Makes a constant. Really just creates a variable and creates a read-only | |
1299 | // link to it. | |
1300 | // ------------------------------------------------------------------------ | |
1301 | ||
1302 | // Functions used to create constants | |
1303 | ||
1304 | static const char *setiv = "#ifndef PERL_OBJECT\ | |
1305 | \n#define swig_setiv(a,b) _swig_setiv(a,b)\ | |
1306 | \nstatic void _swig_setiv(char *name, long value) { \ | |
1307 | \n#else\ | |
1308 | \n#define swig_setiv(a,b) _swig_setiv(pPerl,a,b)\ | |
1309 | \nstatic void _swig_setiv(CPerlObj *pPerl, char *name, long value) { \ | |
1310 | \n#endif\ | |
1311 | \n SV *sv; \ | |
1312 | \n sv = perl_get_sv(name,TRUE | 0x2);\ | |
1313 | \n sv_setiv(sv, (IV) value);\ | |
1314 | \n SvREADONLY_on(sv);\ | |
1315 | \n}\n"; | |
1316 | ||
1317 | static const char *setnv = "#ifndef PERL_OBJECT\ | |
1318 | \n#define swig_setnv(a,b) _swig_setnv(a,b)\ | |
1319 | \nstatic void _swig_setnv(char *name, double value) { \ | |
1320 | \n#else\ | |
1321 | \n#define swig_setnv(a,b) _swig_setnv(pPerl,a,b)\ | |
1322 | \nstatic void _swig_setnv(CPerlObj *pPerl, char *name, double value) { \ | |
1323 | \n#endif\ | |
1324 | \n SV *sv; \ | |
1325 | \n sv = perl_get_sv(name,TRUE | 0x2);\ | |
1326 | \n sv_setnv(sv, value);\ | |
1327 | \n SvREADONLY_on(sv);\ | |
1328 | \n}\n"; | |
1329 | ||
1330 | static const char *setpv = "#ifndef PERL_OBJECT\ | |
1331 | \n#define swig_setpv(a,b) _swig_setpv(a,b)\ | |
1332 | \nstatic void _swig_setpv(char *name, char *value) { \ | |
1333 | \n#else\ | |
1334 | \n#define swig_setpv(a,b) _swig_setpv(pPerl,a,b)\ | |
1335 | \nstatic void _swig_setpv(CPerlObj *pPerl, char *name, char *value) { \ | |
1336 | \n#endif\ | |
1337 | \n SV *sv; \ | |
1338 | \n sv = perl_get_sv(name,TRUE | 0x2);\ | |
1339 | \n sv_setpv(sv, value);\ | |
1340 | \n SvREADONLY_on(sv);\ | |
1341 | \n}\n"; | |
1342 | ||
1343 | static const char *setrv = "#ifndef PERL_OBJECT\ | |
1344 | \n#define swig_setrv(a,b,c) _swig_setrv(a,b,c)\ | |
1345 | \nstatic void _swig_setrv(char *name, void *value, char *type) { \ | |
1346 | \n#else\ | |
1347 | \n#define swig_setrv(a,b,c) _swig_setrv(pPerl,a,b,c)\ | |
1348 | \nstatic void _swig_setrv(CPerlObj *pPerl, char *name, void *value, char *type) { \ | |
1349 | \n#endif\ | |
1350 | \n SV *sv; \ | |
1351 | \n sv = perl_get_sv(name,TRUE | 0x2);\ | |
1352 | \n sv_setref_pv(sv, type, value);\ | |
1353 | \n SvREADONLY_on(sv);\ | |
1354 | \n}\n"; | |
1355 | ||
1356 | void | |
1357 | PERL5::declare_const(char *name, char *, DataType *type, char *value) | |
1358 | { | |
1359 | ||
1360 | char *tm; | |
1361 | static int have_int_func = 0; | |
1362 | static int have_double_func = 0; | |
1363 | static int have_char_func = 0; | |
1364 | static int have_ref_func = 0; | |
1365 | ||
1366 | if ((tm = typemap_lookup("const","perl5",type,name,value,name))) { | |
1367 | fprintf(f_init,"%s\n",tm); | |
1368 | } else { | |
1369 | if ((type->type == T_USER) && (!type->is_pointer)) { | |
1370 | fprintf(stderr,"%s : Line %d. Unsupported constant value.\n", input_file, line_number); | |
1371 | return; | |
1372 | } | |
1373 | // Generate a constant | |
1374 | // vinit << tab4 << "sv = perl_get_sv(\"" << package << "::" << name << "\",TRUE);\n"; | |
1375 | if (type->is_pointer == 0) { | |
1376 | switch(type->type) { | |
1377 | case T_INT:case T_SINT: case T_UINT: case T_BOOL: | |
1378 | case T_SHORT: case T_SSHORT: case T_USHORT: | |
1379 | case T_LONG: case T_SLONG: case T_ULONG: | |
1380 | case T_SCHAR: case T_UCHAR: | |
1381 | if (!have_int_func) { | |
1382 | fprintf(f_header,"%s\n",setiv); | |
1383 | have_int_func = 1; | |
1384 | } | |
1385 | vinit << tab4 << "swig_setiv(\"" << package << "::" << name << "\", (long) " << value << ");\n"; | |
1386 | break; | |
1387 | case T_DOUBLE: | |
1388 | case T_FLOAT: | |
1389 | if (!have_double_func) { | |
1390 | fprintf(f_header,"%s\n",setnv); | |
1391 | have_double_func = 1; | |
1392 | } | |
1393 | vinit << tab4 << "swig_setnv(\"" << package << "::" << name << "\", (double) (" << value << "));\n"; | |
1394 | break; | |
1395 | case T_CHAR : | |
1396 | if (!have_char_func) { | |
1397 | fprintf(f_header,"%s\n",setpv); | |
1398 | have_char_func = 1; | |
1399 | } | |
1400 | vinit << tab4 << "swig_setpv(\"" << package << "::" << name << "\", \"" << value << "\");\n"; | |
1401 | break; | |
1402 | default: | |
1403 | fprintf(stderr,"%s : Line %d. Unsupported constant value.\n", input_file, line_number); | |
1404 | break; | |
1405 | } | |
1406 | } else { | |
1407 | if ((type->type == T_CHAR) && (type->is_pointer == 1)) { | |
1408 | if (!have_char_func) { | |
1409 | fprintf(f_header,"%s\n",setpv); | |
1410 | have_char_func = 1; | |
1411 | } | |
1412 | vinit << tab4 << "swig_setpv(\"" << package << "::" << name << "\", \"" << value << "\");\n"; | |
1413 | } else { | |
1414 | // A user-defined type. We're going to munge it into a string pointer value | |
1415 | if (!have_ref_func) { | |
1416 | fprintf(f_header,"%s\n",setrv); | |
1417 | have_ref_func = 1; | |
1418 | } | |
1419 | vinit << tab4 << "swig_setrv(\"" << package << "::" << name << "\", (void *) " << value << ", \"" | |
1420 | << type->print_mangle() << "\");\n"; | |
1421 | } | |
1422 | } | |
1423 | } | |
1424 | ||
1425 | // Patch up the documentation entry | |
1426 | ||
1427 | if (doc_entry) { | |
1428 | doc_entry->usage = ""; | |
1429 | doc_entry->usage << usage_const(name,type,value); | |
1430 | doc_entry->cinfo = ""; | |
1431 | doc_entry->cinfo << "Constant: " << type->print_type(); | |
1432 | } | |
1433 | ||
1434 | if (blessed) { | |
1435 | if ((classes.lookup(type->name)) && (type->is_pointer <= 1)) { | |
1436 | var_stubs << "\nmy %__" << name << "_hash;\n" | |
1437 | << "tie %__" << name << "_hash,\"" << (char *) classes.lookup(type->name) << "\", $" | |
1438 | << package << "::" << name << ";\n" | |
1439 | << "$" << name << "= \\%__" << name << "_hash;\n" | |
1440 | << "bless $" << name << ", " << (char *) classes.lookup(type->name) << ";\n"; | |
1441 | } else { | |
1442 | var_stubs << "*" << name << " = *" << package << "::" << name << ";\n"; | |
1443 | } | |
1444 | } | |
1445 | if (export_all) | |
1446 | exported << "$" << name << " "; | |
1447 | } | |
1448 | ||
1449 | // ---------------------------------------------------------------------- | |
1450 | // PERL5::usage_var(char *iname, DataType *t) | |
1451 | // | |
1452 | // Produces a usage string for a Perl 5 variable. | |
1453 | // ---------------------------------------------------------------------- | |
1454 | ||
1455 | char *PERL5::usage_var(char *iname, DataType *) { | |
1456 | ||
1457 | static char temp[1024]; | |
1458 | char *c; | |
1459 | ||
1460 | sprintf(temp,"$%s", iname); | |
1461 | c = temp + strlen(temp); | |
1462 | return temp; | |
1463 | } | |
1464 | ||
1465 | // --------------------------------------------------------------------------- | |
1466 | // char *PERL5::usage_func(pkg, char *iname, DataType *t, ParmList *l) | |
1467 | // | |
1468 | // Produces a usage string for a function in Perl | |
1469 | // --------------------------------------------------------------------------- | |
1470 | ||
1471 | char *PERL5::usage_func(char *iname, DataType *, ParmList *l) { | |
1472 | ||
1473 | static String temp; | |
1474 | Parm *p; | |
1475 | int i; | |
1476 | ||
1477 | temp = ""; | |
1478 | temp << iname << "("; | |
1479 | ||
1480 | /* Now go through and print parameters */ | |
1481 | ||
1482 | p = l->get_first(); | |
1483 | i = 0; | |
1484 | while (p != 0) { | |
1485 | if (!p->ignore) { | |
1486 | /* If parameter has been named, use that. Otherwise, just print a type */ | |
1487 | ||
1488 | if ((p->t->type != T_VOID) || (p->t->is_pointer)) { | |
1489 | if (strlen(p->name) > 0) { | |
1490 | temp << p->name; | |
1491 | } else { | |
1492 | temp << p->t->print_type(); | |
1493 | } | |
1494 | } | |
1495 | i++; | |
1496 | p = l->get_next(); | |
1497 | if (p) | |
1498 | if (!p->ignore) | |
1499 | temp << ","; | |
1500 | } else { | |
1501 | p = l->get_next(); | |
1502 | if (p) | |
1503 | if ((i>0) && (!p->ignore)) | |
1504 | temp << ","; | |
1505 | } | |
1506 | } | |
1507 | temp << ");"; | |
1508 | return temp.get(); | |
1509 | } | |
1510 | ||
1511 | // ---------------------------------------------------------------------- | |
1512 | // PERL5::usage_const(char *iname, DataType *type, char *value) | |
1513 | // | |
1514 | // Produces a usage string for a Perl 5 constant | |
1515 | // ---------------------------------------------------------------------- | |
1516 | ||
1517 | char *PERL5::usage_const(char *iname, DataType *, char *value) { | |
1518 | ||
1519 | static char temp[1024]; | |
1520 | if (value) { | |
1521 | sprintf(temp,"$%s = %s", iname, value); | |
1522 | } else { | |
1523 | sprintf(temp,"$%s", iname); | |
1524 | } | |
1525 | return temp; | |
1526 | } | |
1527 | ||
1528 | // ----------------------------------------------------------------------- | |
1529 | // PERL5::add_native(char *name, char *funcname) | |
1530 | // | |
1531 | // Add a native module name to Perl5. | |
1532 | // ----------------------------------------------------------------------- | |
1533 | ||
1534 | void PERL5::add_native(char *name, char *funcname) { | |
1535 | fprintf(f_init,"\t newXS(\"%s::%s\", %s, file);\n", package,name, funcname); | |
1536 | if (export_all) | |
1537 | exported << name << " "; | |
1538 | if (blessed) { | |
1539 | func_stubs << "*" << name << " = *" << package << "::" << name << ";\n"; | |
1540 | } | |
1541 | } | |
1542 | ||
1543 | /**************************************************************************** | |
1544 | *** OBJECT-ORIENTED FEATURES | |
1545 | **************************************************************************** | |
1546 | *** These extensions provide a more object-oriented interface to C++ | |
1547 | *** classes and structures. The code here is based on extensions | |
1548 | *** provided by David Fletcher and Gary Holt. | |
1549 | *** | |
1550 | *** I have generalized these extensions to make them more general purpose | |
1551 | *** and to resolve object-ownership problems. | |
1552 | *** | |
1553 | *** The approach here is very similar to the Python module : | |
1554 | *** 1. All of the original methods are placed into a single | |
1555 | *** package like before except that a 'c' is appended to the | |
1556 | *** package name. | |
1557 | *** | |
1558 | *** 2. All methods and function calls are wrapped with a new | |
1559 | *** perl function. While possibly inefficient this allows | |
1560 | *** us to catch complex function arguments (which are hard to | |
1561 | *** track otherwise). | |
1562 | *** | |
1563 | *** 3. Classes are represented as tied-hashes in a manner similar | |
1564 | *** to Gary Holt's extension. This allows us to access | |
1565 | *** member data. | |
1566 | *** | |
1567 | *** 4. Stand-alone (global) C functions are modified to take | |
1568 | *** tied hashes as arguments for complex datatypes (if | |
1569 | *** appropriate). | |
1570 | *** | |
1571 | *** 5. Global variables involving a class/struct is encapsulated | |
1572 | *** in a tied hash. | |
1573 | *** | |
1574 | *** 6. Object ownership is maintained by having a hash table | |
1575 | *** within in each package called "this". It is unlikely | |
1576 | *** that C++ program will use this so it's a somewhat | |
1577 | *** safe variable name. | |
1578 | *** | |
1579 | ****************************************************************************/ | |
1580 | ||
1581 | static int class_renamed = 0; | |
1582 | static String fullclassname; | |
1583 | ||
1584 | // -------------------------------------------------------------------------- | |
1585 | // PERL5::cpp_open_class(char *classname, char *rname, int strip) | |
1586 | // | |
1587 | // Opens a new C++ class or structure. Basically, this just records | |
1588 | // the class name and clears a few variables. | |
1589 | // -------------------------------------------------------------------------- | |
1590 | ||
1591 | void PERL5::cpp_open_class(char *classname, char *rname, char *ctype, int strip) { | |
1592 | ||
1593 | char temp[256]; | |
1594 | extern void typeeq_addtypedef(char *, char *); | |
1595 | ||
1596 | // Register this with the default class handler | |
1597 | ||
1598 | this->Language::cpp_open_class(classname, rname, ctype, strip); | |
1599 | ||
1600 | if (blessed) { | |
1601 | have_constructor = 0; | |
1602 | have_destructor = 0; | |
1603 | have_data_members = 0; | |
1604 | ||
1605 | // If the class is being renamed to something else, use the renaming | |
1606 | ||
1607 | if (rname) { | |
1608 | class_name = copy_string(rname); | |
1609 | class_renamed = 1; | |
1610 | // Now things get even more hideous. Need to register an equivalence | |
1611 | // between the renamed name and the new name. Yuck! | |
1612 | // printf("%s %s\n", classname, rname); | |
1613 | typeeq_addtypedef(classname,rname); | |
1614 | typeeq_addtypedef(rname,classname); | |
1615 | /* | |
1616 | fprintf(f_init,"\t SWIG_RegisterMapping(\"%s\",\"%s\",0);\n",classname,rname); | |
1617 | fprintf(f_init,"\t SWIG_RegisterMapping(\"%s\",\"%s\",0);\n",rname,classname); | |
1618 | */ | |
1619 | } else { | |
1620 | class_name = copy_string(classname); | |
1621 | class_renamed = 0; | |
1622 | } | |
1623 | ||
1624 | // A highly experimental feature. This is the fully qualified | |
1625 | // name of the Perl class | |
1626 | ||
1627 | if (!compat) { | |
1628 | fullclassname = realpackage; | |
1629 | fullclassname << "::" << class_name; | |
1630 | } else { | |
1631 | fullclassname = class_name; | |
1632 | } | |
1633 | ||
1634 | fullclassname = class_name; | |
1635 | ||
1636 | real_classname = copy_string(classname); | |
1637 | if (base_class) delete base_class; | |
1638 | base_class = 0; | |
1639 | class_type = copy_string(ctype); | |
1640 | pcode = new String(); | |
1641 | blessedmembers = new String(); | |
1642 | member_keys = new String(); | |
1643 | ||
1644 | // Add some symbols to the hash tables | |
1645 | ||
1646 | // classes.add(real_classname,copy_string(class_name)); /* Map original classname to class */ | |
1647 | classes.add(real_classname,copy_string(fullclassname)); /* Map original classname to class */ | |
1648 | ||
1649 | // Add full name of datatype to the hash table just in case the user uses it | |
1650 | ||
1651 | sprintf(temp,"%s %s", class_type, fullclassname.get()); | |
1652 | // classes.add(temp,copy_string(class_name)); /* Map full classname to classs */ | |
1653 | } | |
1654 | } | |
1655 | ||
1656 | // ------------------------------------------------------------------------------- | |
1657 | // PERL5::cpp_close_class() | |
1658 | // | |
1659 | // These functions close a class definition. | |
1660 | // | |
1661 | // This also sets up the hash table of classes we've seen go by. | |
1662 | // ------------------------------------------------------------------------------- | |
1663 | ||
1664 | void PERL5::cpp_close_class() { | |
1665 | ||
1666 | // We need to check to make sure we got constructors, and other | |
1667 | // stuff here. | |
1668 | ||
1669 | if (blessed) { | |
1670 | pm << "\n############# Class : " << fullclassname << " ##############\n"; | |
1671 | pm << "\npackage " << fullclassname << ";\n"; | |
1672 | ||
1673 | // If we are inheriting from a base class, set that up | |
1674 | ||
1675 | if (strcmp(class_name,realpackage)) | |
1676 | pm << "@ISA = qw( " << realpackage; | |
1677 | else | |
1678 | pm << "@ISA = qw( "; | |
1679 | ||
1680 | if (base_class) { | |
1681 | pm << " " << *base_class; | |
1682 | } | |
1683 | pm << " );\n"; | |
1684 | ||
1685 | // Dump out a hash table containing the pointers that we own | |
1686 | ||
1687 | pm << "%OWNER = ();\n"; | |
1688 | if (have_data_members) { | |
1689 | pm << "%BLESSEDMEMBERS = (\n" | |
1690 | << blessedmembers->get() | |
1691 | << ");\n\n"; | |
1692 | } | |
1693 | if (have_data_members || have_destructor) | |
1694 | pm << "%ITERATORS = ();\n"; | |
1695 | ||
1696 | ||
1697 | // Dump out the package methods | |
1698 | ||
1699 | pm << *pcode; | |
1700 | delete pcode; | |
1701 | ||
1702 | // Output methods for managing ownership | |
1703 | ||
1704 | pm << "sub DISOWN {\n" | |
1705 | << tab4 << "my $self = shift;\n" | |
1706 | << tab4 << "my $ptr = tied(%$self);\n" | |
1707 | << tab4 << "delete $OWNER{$ptr};\n" | |
1708 | << tab4 << "};\n\n" | |
1709 | << "sub ACQUIRE {\n" | |
1710 | << tab4 << "my $self = shift;\n" | |
1711 | << tab4 << "my $ptr = tied(%$self);\n" | |
1712 | << tab4 << "$OWNER{$ptr} = 1;\n" | |
1713 | << tab4 << "};\n\n"; | |
1714 | ||
1715 | // Only output the following methods if a class has member data | |
1716 | ||
1717 | if (have_data_members) { | |
1718 | ||
1719 | // Output a FETCH method. This is actually common to all classes | |
1720 | pm << "sub FETCH {\n" | |
1721 | << tab4 << "my ($self,$field) = @_;\n" | |
1722 | << tab4 << "my $member_func = \"" << package << "::" << name_get(name_member("${field}",class_name,AS_IS),AS_IS) << "\";\n" | |
1723 | << tab4 << "my $val = &$member_func($self);\n" | |
1724 | << tab4 << "if (exists $BLESSEDMEMBERS{$field}) {\n" | |
1725 | << tab8 << "return undef if (!defined($val));\n" | |
1726 | << tab8 << "my %retval;\n" | |
1727 | << tab8 << "tie %retval,$BLESSEDMEMBERS{$field},$val;\n" | |
1728 | << tab8 << "return bless \\%retval, $BLESSEDMEMBERS{$field};\n" | |
1729 | << tab4 << "}\n" | |
1730 | << tab4 << "return $val;\n" | |
1731 | << "}\n\n"; | |
1732 | ||
1733 | // Output a STORE method. This is also common to all classes (might move to base class) | |
1734 | ||
1735 | pm << "sub STORE {\n" | |
1736 | << tab4 << "my ($self,$field,$newval) = @_;\n" | |
1737 | << tab4 << "my $member_func = \"" << package << "::" << name_set(name_member("${field}",class_name,AS_IS),AS_IS) << "\";\n" | |
1738 | << tab4 << "if (exists $BLESSEDMEMBERS{$field}) {\n" | |
1739 | << tab8 << "&$member_func($self,tied(%{$newval}));\n" | |
1740 | << tab4 << "} else {\n" | |
1741 | << tab8 << "&$member_func($self,$newval);\n" | |
1742 | << tab4 << "}\n" | |
1743 | << "}\n\n"; | |
1744 | ||
1745 | // Output a FIRSTKEY method. This is to allow iteration over a structure's keys. | |
1746 | ||
1747 | pm << "sub FIRSTKEY {\n" | |
1748 | << tab4 << "my $self = shift;\n" | |
1749 | << tab4 << "$ITERATORS{$self} = [" << member_keys->get() << "];\n" | |
1750 | << tab4 << "my $first = shift @{$ITERATORS{$self}};\n" | |
1751 | << tab4 << "return $first;\n" | |
1752 | << "}\n\n"; | |
1753 | ||
1754 | // Output a NEXTKEY method. This is the iterator so that each and keys works | |
1755 | ||
1756 | pm << "sub NEXTKEY {\n" | |
1757 | << tab4 << "my $self = shift;\n" | |
1758 | << tab4 << "$nelem = scalar @{$ITERATORS{$self}};\n" | |
1759 | << tab4 << "if ($nelem > 0) {\n" | |
1760 | << tab8 << "my $member = shift @{$ITERATORS{$self}};\n" | |
1761 | << tab8 << "return $member;\n" | |
1762 | << tab4 << "} else {\n" | |
1763 | << tab8 << "$ITERATORS{$self} = [" << member_keys->get() << "];\n" | |
1764 | << tab8 << "return ();\n" | |
1765 | << tab4 << "}\n" | |
1766 | << "}\n\n"; | |
1767 | } | |
1768 | } | |
1769 | } | |
1770 | ||
1771 | // -------------------------------------------------------------------------- | |
1772 | // PERL5::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) | |
1773 | // | |
1774 | // Handles a C++ member function. This basically does the same thing as | |
1775 | // the non-C++ version, but we set up a few status variables that affect | |
1776 | // the function generation function. | |
1777 | // | |
1778 | // -------------------------------------------------------------------------- | |
1779 | ||
1780 | void PERL5::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) { | |
1781 | ||
1782 | String func; | |
1783 | char *realname; | |
1784 | Parm *p; | |
1785 | int i; | |
1786 | String cname = "perl5:"; | |
1787 | int pcount, numopt; | |
1788 | ||
1789 | // First emit normal member function | |
1790 | ||
1791 | member_func = 1; | |
1792 | this->Language::cpp_member_func(name,iname,t,l); | |
1793 | member_func = 0; | |
1794 | ||
1795 | if (!blessed) return; | |
1796 | ||
1797 | // Now emit a Perl wrapper function around our member function, we might need | |
1798 | // to patch up some arguments along the way | |
1799 | ||
1800 | if (!iname) | |
1801 | realname = name; | |
1802 | else | |
1803 | realname = iname; | |
1804 | ||
1805 | cname << class_name << "::" << realname; | |
1806 | if (add_symbol(cname.get(),0,0)) { | |
1807 | return; // Forget it, we saw this function already | |
1808 | } | |
1809 | ||
1810 | func << "sub " << realname << " {\n" | |
1811 | << tab4 << "my @args = @_;\n" | |
1812 | << tab4 << "$args[0] = tied(%{$args[0]});\n"; | |
1813 | ||
1814 | // Now we have to go through and patch up the argument list. If any | |
1815 | // arguments to our function correspond to other Perl objects, we | |
1816 | // need to extract them from a tied-hash table object. | |
1817 | ||
1818 | p = l->get_first(); | |
1819 | pcount = l->nparms; | |
1820 | numopt = l->numopt(); | |
1821 | i = 1; | |
1822 | while(p) { | |
1823 | if (!p->ignore) { | |
1824 | ||
1825 | // Look up the datatype name here | |
1826 | if ((classes.lookup(p->t->name)) && (p->t->is_pointer <= 1)) { | |
1827 | // Yep. This smells alot like an object, patch up the arguments | |
1828 | ||
1829 | if (i >= (pcount - numopt)) | |
1830 | func << tab4 << "if (scalar(@args) >= " << i << ") {\n"; | |
1831 | ||
1832 | func << tab4 << "$args[" << i << "] = tied(%{$args[" << i << "]});\n"; | |
1833 | ||
1834 | if (i >= (pcount - numopt)) | |
1835 | func << tab4 << "}\n"; | |
1836 | } | |
1837 | i++; | |
1838 | } | |
1839 | p = l->get_next(); | |
1840 | } | |
1841 | ||
1842 | // Okay. We've made argument adjustments, now call into the package | |
1843 | ||
1844 | func << tab4 << "my $result = " << package << "::" << name_member(realname,class_name) | |
1845 | << "(@args);\n"; | |
1846 | ||
1847 | // Now check to see what kind of return result was found. | |
1848 | // If this function is returning a result by 'value', SWIG did an | |
1849 | // implicit malloc/new. We'll mark the object like it was created | |
1850 | // in Perl so we can garbage collect it. | |
1851 | ||
1852 | if ((classes.lookup(t->name)) && (t->is_pointer <=1)) { | |
1853 | ||
1854 | func << tab4 << "return undef if (!defined($result));\n"; | |
1855 | ||
1856 | // If we're returning an object by value, put it's reference | |
1857 | // into our local hash table | |
1858 | ||
1859 | if ((t->is_pointer == 0) || ((t->is_pointer == 1) && NewObject)) { | |
1860 | func << tab4 << "$" << (char *) classes.lookup(t->name) << "::OWNER{$result} = 1;\n"; | |
1861 | } | |
1862 | ||
1863 | // We're returning a Perl "object" of some kind. Turn it into | |
1864 | // a tied hash | |
1865 | ||
1866 | func << tab4 << "my %resulthash;\n" | |
1867 | /* << tab4 << "tie %resulthash, \"" << (char *) classes.lookup(t->name) << "\", $result;\n" | |
1868 | << tab4 << "return bless \\%resulthash, \"" << (char *) classes.lookup(t->name) << "\";\n" */ | |
1869 | << tab4 << "tie %resulthash, ref($result), $result;\n" | |
1870 | << tab4 << "return bless \\%resulthash, ref($result);\n" | |
1871 | ||
1872 | << "}\n"; | |
1873 | ||
1874 | } else { | |
1875 | ||
1876 | // Hmmm. This doesn't appear to be anything I know about so just | |
1877 | // return it unmolested. | |
1878 | ||
1879 | func << tab4 <<"return $result;\n" | |
1880 | << "}\n"; | |
1881 | ||
1882 | } | |
1883 | ||
1884 | // Append our function to the pcode segment | |
1885 | ||
1886 | *pcode << func; | |
1887 | ||
1888 | // Create a new kind of documentation entry for the shadow class | |
1889 | ||
1890 | if (doc_entry) { | |
1891 | doc_entry->usage = ""; // Blow away whatever was there before | |
1892 | doc_entry->usage << usage_func(realname,t,l); | |
1893 | } | |
1894 | } | |
1895 | ||
1896 | // -------------------------------------------------------------------------------- | |
1897 | // PERL5::cpp_variable(char *name, char *iname, DataType *t) | |
1898 | // | |
1899 | // Adds an instance member. This is a little hairy because data members are | |
1900 | // really added with a tied-hash table that is attached to the object. | |
1901 | // | |
1902 | // On the low level, we will emit a pair of get/set functions to retrieve | |
1903 | // values just like before. These will then be encapsulated in a FETCH/STORE | |
1904 | // method associated with the tied-hash. | |
1905 | // | |
1906 | // In the event that a member is an object that we have already wrapped, then | |
1907 | // we need to retrieve the data a tied-hash as opposed to what SWIG normally | |
1908 | // returns. To determine this, we build an internal hash called 'BLESSEDMEMBERS' | |
1909 | // that contains the names and types of tied data members. If a member name | |
1910 | // is in the list, we tie it, otherwise, we just return the normal SWIG value. | |
1911 | // -------------------------------------------------------------------------------- | |
1912 | ||
1913 | void PERL5::cpp_variable(char *name, char *iname, DataType *t) { | |
1914 | ||
1915 | char *realname; | |
1916 | String cname = "perl5:"; | |
1917 | ||
1918 | // Emit a pair of get/set functions for the variable | |
1919 | ||
1920 | member_func = 1; | |
1921 | this->Language::cpp_variable(name, iname, t); | |
1922 | member_func = 0; | |
1923 | ||
1924 | if (iname) realname = iname; | |
1925 | else realname = name; | |
1926 | ||
1927 | if (blessed) { | |
1928 | cname << class_name << "::" << realname; | |
1929 | if (add_symbol(cname.get(),0,0)) { | |
1930 | return; // Forget it, we saw this already | |
1931 | } | |
1932 | ||
1933 | // Store name of key for future reference | |
1934 | ||
1935 | *member_keys << "'" << realname << "', "; | |
1936 | ||
1937 | // Now we need to generate a little Perl code for this | |
1938 | ||
1939 | if ((classes.lookup(t->name)) && (t->is_pointer <= 1)) { | |
1940 | ||
1941 | // This is a Perl object that we have already seen. Add an | |
1942 | // entry to the members list | |
1943 | ||
1944 | *blessedmembers << tab4 << realname << " => '" << (char *) classes.lookup(t->name) << "',\n"; | |
1945 | ||
1946 | } | |
1947 | ||
1948 | // Patch up the documentation entry | |
1949 | ||
1950 | if (doc_entry) { | |
1951 | doc_entry->usage = ""; | |
1952 | doc_entry->usage << "$this->{" << realname << "}"; | |
1953 | } | |
1954 | } | |
1955 | have_data_members++; | |
1956 | } | |
1957 | ||
1958 | ||
1959 | // ----------------------------------------------------------------------------- | |
1960 | // void PERL5::cpp_constructor(char *name, char *iname, ParmList *l) | |
1961 | // | |
1962 | // Emits a blessed constructor for our class. In addition to our construct | |
1963 | // we manage a Perl hash table containing all of the pointers created by | |
1964 | // the constructor. This prevents us from accidentally trying to free | |
1965 | // something that wasn't necessarily allocated by malloc or new | |
1966 | // ----------------------------------------------------------------------------- | |
1967 | ||
1968 | void PERL5::cpp_constructor(char *name, char *iname, ParmList *l) { | |
1969 | Parm *p; | |
1970 | int i; | |
1971 | char *realname; | |
1972 | String cname="perl5:constructor:"; | |
1973 | ||
1974 | // Emit an old-style constructor for this class | |
1975 | ||
1976 | member_func = 1; | |
1977 | this->Language::cpp_constructor(name, iname, l); | |
1978 | ||
1979 | if (blessed) { | |
1980 | ||
1981 | if (iname) | |
1982 | realname = iname; | |
1983 | else { | |
1984 | if (class_renamed) realname = class_name; | |
1985 | else realname = class_name; | |
1986 | } | |
1987 | ||
1988 | cname << class_name << "::" << realname; | |
1989 | if (add_symbol(cname.get(),0,0)) { | |
1990 | return; // Forget it, we saw this already | |
1991 | } | |
1992 | if ((strcmp(realname,class_name) == 0) || ((!iname) && (ObjCClass)) ){ | |
1993 | ||
1994 | // Emit a blessed constructor | |
1995 | ||
1996 | *pcode << "sub new {\n"; | |
1997 | ||
1998 | } else { | |
1999 | ||
2000 | // Constructor doesn't match classname so we'll just use the normal name | |
2001 | ||
2002 | *pcode << "sub " << name_construct(realname) << " () {\n"; | |
2003 | ||
2004 | } | |
2005 | ||
2006 | *pcode << tab4 << "my $self = shift;\n" | |
2007 | << tab4 << "my @args = @_;\n"; | |
2008 | ||
2009 | // We are going to need to patch up arguments here if necessary | |
2010 | // Now we have to go through and patch up the argument list. If any | |
2011 | // arguments to our function correspond to other Perl objects, we | |
2012 | // need to extract them from a tied-hash table object. | |
2013 | ||
2014 | p = l->get_first(); | |
2015 | i = 0; | |
2016 | while(p) { | |
2017 | ||
2018 | // Look up the datatype name here | |
2019 | ||
2020 | if ((classes.lookup(p->t->name)) && (p->t->is_pointer <= 1)) { | |
2021 | ||
2022 | // Yep. This smells alot like an object, patch up the arguments | |
2023 | *pcode << tab4 << "$args[" << i << "] = tied(%{$args[" << i << "]});\n"; | |
2024 | } | |
2025 | p = l->get_next(); | |
2026 | i++; | |
2027 | } | |
2028 | ||
2029 | *pcode << tab4 << "$self = " << package << "::" << name_construct(realname) << "(@args);\n" | |
2030 | << tab4 << "return undef if (!defined($self));\n" | |
2031 | << tab4 << "bless $self, \"" << fullclassname << "\";\n" | |
2032 | << tab4 << "$OWNER{$self} = 1;\n" | |
2033 | << tab4 << "my %retval;\n" | |
2034 | << tab4 << "tie %retval, \"" << fullclassname << "\", $self;\n" | |
2035 | << tab4 << "return bless \\%retval,\"" << fullclassname << "\";\n" | |
2036 | << "}\n\n"; | |
2037 | have_constructor = 1; | |
2038 | ||
2039 | // Patch up the documentation entry | |
2040 | ||
2041 | if (doc_entry) { | |
2042 | doc_entry->usage = ""; | |
2043 | doc_entry->usage << usage_func("new",0,l); | |
2044 | } | |
2045 | } | |
2046 | member_func = 0; | |
2047 | } | |
2048 | ||
2049 | ||
2050 | // ------------------------------------------------------------------------------ | |
2051 | // void PERL5::cpp_destructor(char *name, char *newname) | |
2052 | // | |
2053 | // Creates a destructor for a blessed object | |
2054 | // ------------------------------------------------------------------------------ | |
2055 | ||
2056 | void PERL5::cpp_destructor(char *name, char *newname) { | |
2057 | ||
2058 | char *realname; | |
2059 | member_func = 1; | |
2060 | this->Language::cpp_destructor(name, newname); | |
2061 | ||
2062 | if (blessed) { | |
2063 | if (newname) realname = newname; | |
2064 | else { | |
2065 | if (class_renamed) realname = class_name; | |
2066 | else realname = name; | |
2067 | } | |
2068 | ||
2069 | // Emit a destructor for this object | |
2070 | ||
2071 | *pcode << "sub DESTROY {\n" | |
2072 | << tab4 << "my $self = tied(%{$_[0]});\n" | |
2073 | << tab4 << "delete $ITERATORS{$self};\n" | |
2074 | << tab4 << "if (exists $OWNER{$self}) {\n" | |
2075 | << tab8 << package << "::" << name_destroy(realname) << "($self);\n" | |
2076 | << tab8 << "delete $OWNER{$self};\n" | |
2077 | << tab4 << "}\n}\n\n"; | |
2078 | ||
2079 | have_destructor = 1; | |
2080 | ||
2081 | if (doc_entry) { | |
2082 | doc_entry->usage = "DESTROY"; | |
2083 | doc_entry->cinfo = "Destructor"; | |
2084 | } | |
2085 | } | |
2086 | member_func = 0; | |
2087 | } | |
2088 | // ----------------------------------------------------------------------------- | |
2089 | // void PERL5::cpp_static_func(char *name, char *iname, DataType *t, ParmList *l) | |
2090 | // | |
2091 | // Emits a wrapper for a static class function. Basically, we just call the | |
2092 | // appropriate method in the module package. | |
2093 | // ------------------------------------------------------------------------------ | |
2094 | void PERL5::cpp_static_func(char *name, char *iname, DataType *t, ParmList *l) { | |
2095 | this->Language::cpp_static_func(name,iname,t,l); | |
2096 | char *realname; | |
2097 | if (iname) realname = name; | |
2098 | else realname = iname; | |
2099 | ||
2100 | if (blessed) { | |
2101 | *pcode << "*" << realname << " = *" << realpackage << "::" << name_member(realname,class_name) << ";\n"; | |
2102 | } | |
2103 | } | |
2104 | ||
2105 | // ------------------------------------------------------------------------------ | |
2106 | // void PERL5::cpp_inherit(char **baseclass, int mode) | |
2107 | // | |
2108 | // This sets the Perl5 baseclass (if possible). | |
2109 | // ------------------------------------------------------------------------------ | |
2110 | ||
2111 | void PERL5::cpp_inherit(char **baseclass, int) { | |
2112 | ||
2113 | char *bc; | |
2114 | int i = 0, have_first = 0; | |
2115 | if (!blessed) { | |
2116 | this->Language::cpp_inherit(baseclass); | |
2117 | return; | |
2118 | } | |
2119 | ||
2120 | // Inherit variables and constants from base classes, but not | |
2121 | // functions (since Perl can handle that okay). | |
2122 | ||
2123 | this->Language::cpp_inherit(baseclass, INHERIT_CONST | INHERIT_VAR); | |
2124 | ||
2125 | // Now tell the Perl5 module that we're inheriting from base classes | |
2126 | ||
2127 | base_class = new String; | |
2128 | while (baseclass[i]) { | |
2129 | // See if this is a class we know about | |
2130 | bc = (char *) classes.lookup(baseclass[i]); | |
2131 | if (bc) { | |
2132 | if (have_first) *base_class << " "; | |
2133 | *base_class << bc; | |
2134 | have_first = 1; | |
2135 | } | |
2136 | i++; | |
2137 | } | |
2138 | if (!have_first) { | |
2139 | delete base_class; | |
2140 | base_class = 0; | |
2141 | } | |
2142 | } | |
2143 | ||
2144 | // -------------------------------------------------------------------------------- | |
2145 | // PERL5::cpp_declare_const(char *name, char *iname, DataType *type, char *value) | |
2146 | // | |
2147 | // Add access to a C++ constant. We can really just do this by hacking | |
2148 | // the symbol table | |
2149 | // -------------------------------------------------------------------------------- | |
2150 | ||
2151 | void PERL5::cpp_declare_const(char *name, char *iname, DataType *type, char *value) { | |
2152 | char *realname; | |
2153 | int oldblessed = blessed; | |
2154 | String cname; | |
2155 | ||
2156 | // Create a normal constant | |
2157 | blessed = 0; | |
2158 | this->Language::cpp_declare_const(name, iname, type, value); | |
2159 | blessed = oldblessed; | |
2160 | ||
2161 | if (blessed) { | |
2162 | if (!iname) | |
2163 | realname = name; | |
2164 | else | |
2165 | realname = iname; | |
2166 | ||
2167 | cname << class_name << "::" << realname; | |
2168 | if (add_symbol(cname.get(),0,0)) { | |
2169 | return; // Forget it, we saw this already | |
2170 | } | |
2171 | ||
2172 | // Create a symbol table entry for it | |
2173 | *pcode << "*" << realname << " = *" << package << "::" << name_member(realname,class_name) << ";\n"; | |
2174 | ||
2175 | // Fix up the documentation entry | |
2176 | ||
2177 | if (doc_entry) { | |
2178 | doc_entry->usage = ""; | |
2179 | doc_entry->usage << realname; | |
2180 | if (value) { | |
2181 | doc_entry->usage << " = " << value; | |
2182 | } | |
2183 | } | |
2184 | } | |
2185 | } | |
2186 | ||
2187 | // ----------------------------------------------------------------------- | |
2188 | // PERL5::cpp_class_decl(char *name, char *rename, char *type) | |
2189 | // | |
2190 | // Treatment of an empty class definition. Used to handle | |
2191 | // shadow classes across modules. | |
2192 | // ----------------------------------------------------------------------- | |
2193 | ||
2194 | void PERL5::cpp_class_decl(char *name, char *rename, char *type) { | |
2195 | char temp[256]; | |
2196 | if (blessed) { | |
2197 | classes.add(name,copy_string(rename)); | |
2198 | // Add full name of datatype to the hash table | |
2199 | if (strlen(type) > 0) { | |
2200 | sprintf(temp,"%s %s", type, name); | |
2201 | classes.add(temp,copy_string(rename)); | |
2202 | } | |
2203 | } | |
2204 | } | |
2205 | ||
2206 | // -------------------------------------------------------------------------------- | |
2207 | // PERL5::add_typedef(DataType *t, char *name) | |
2208 | // | |
2209 | // This is called whenever a typedef is encountered. When shadow classes are | |
2210 | // used, this function lets us discovered hidden uses of a class. For example : | |
2211 | // | |
2212 | // struct FooBar { | |
2213 | // ... | |
2214 | // } | |
2215 | // | |
2216 | // typedef FooBar *FooBarPtr; | |
2217 | // | |
2218 | // -------------------------------------------------------------------------------- | |
2219 | ||
2220 | void PERL5::add_typedef(DataType *t, char *name) { | |
2221 | ||
2222 | if (!blessed) return; | |
2223 | ||
2224 | // First check to see if there aren't too many pointers | |
2225 | ||
2226 | if (t->is_pointer > 1) return; | |
2227 | ||
2228 | if (classes.lookup(name)) return; // Already added | |
2229 | ||
2230 | // Now look up the datatype in our shadow class hash table | |
2231 | ||
2232 | if (classes.lookup(t->name)) { | |
2233 | ||
2234 | // Yep. This datatype is in the hash | |
2235 | ||
2236 | // Put this types 'new' name into the hash | |
2237 | ||
2238 | classes.add(name,copy_string((char *) classes.lookup(t->name))); | |
2239 | } | |
2240 | } | |
2241 | ||
2242 | ||
2243 | // -------------------------------------------------------------------------------- | |
2244 | // PERL5::pragma(char *, char *, char *) | |
2245 | // | |
2246 | // Pragma directive. | |
2247 | // | |
2248 | // %pragma(perl5) code="String" # Includes a string in the .pm file | |
2249 | // %pragma(perl5) include="file.pl" # Includes a file in the .pm file | |
2250 | // | |
2251 | // -------------------------------------------------------------------------------- | |
2252 | ||
2253 | void PERL5::pragma(char *lang, char *code, char *value) { | |
2254 | if (strcmp(lang,"perl5") == 0) { | |
2255 | if (strcmp(code,"code") == 0) { | |
2256 | // Dump the value string into the .pm file | |
2257 | if (value) { | |
2258 | pragma_include << value << "\n"; | |
2259 | } | |
2260 | } else if (strcmp(code,"include") == 0) { | |
2261 | // Include a file into the .pm file | |
2262 | if (value) { | |
2263 | if (get_file(value,pragma_include) == -1) { | |
2264 | fprintf(stderr,"%s : Line %d. Unable to locate file %s\n", input_file, line_number,value); | |
2265 | } | |
2266 | } | |
2267 | } else { | |
2268 | fprintf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file,line_number); | |
2269 | } | |
2270 | } | |
2271 | } |