]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/Modules/tcl.cxx
1 /*******************************************************************************
2 * Simplified Wrapper and Interface Generator (SWIG)
4 * Author : David Beazley
6 * Department of Computer Science
7 * University of Chicago
10 * beazley@cs.uchicago.edu
12 * Please read the file LICENSE for the copyright and terms by which SWIG
13 * can be used and distributed.
14 *******************************************************************************/
16 /***********************************************************************
21 * Definitions for creating a simple, stand-alone TCL implementation.
23 ***********************************************************************/
29 static char *Tcl_config
="swigtcl.swg";
30 static char *usage
= "\
31 Tcl Options (available with -tcl)\n\
32 -module name - Set name of module\n\
33 -prefix name - Set a prefix to be appended to all names\n\
34 -namespace - Build module into a Tcl8 namespace. \n\
35 -noobject - Omit code for object oriented interface.\n\
36 -old - Use old SWIG interface (same as -noobject).\n\n";
39 static char *ns_name
= 0;
40 static String mod_init
;
41 static String mod_extern
;
43 // ---------------------------------------------------------------------
44 // TCL::parse_args(int argc, char *argv[])
46 // Parse tcl specific command line options
47 // ---------------------------------------------------------------------
49 void TCL::parse_args(int argc
, char *argv
[]) {
52 sprintf(LibDir
,"%s",tcl_path
);
54 // Look for certain command line options
56 for (i
= 1; i
< argc
; i
++) {
58 if (strcmp(argv
[i
],"-prefix") == 0) {
60 prefix
= new char[strlen(argv
[i
+1])+2];
61 strcpy(prefix
, argv
[i
+1]);
68 } else if (strcmp(argv
[i
],"-module") == 0) {
70 set_module(argv
[i
+1],0);
77 } else if (strcmp(argv
[i
],"-namespace") == 0) {
80 } else if (strcmp(argv
[i
],"-old") == 0) {
83 } else if (strcmp(argv
[i
],"-noobject") == 0) {
86 } else if (strcmp(argv
[i
],"-help") == 0) {
92 // If a package has been specified, make sure it ends with a '_'
95 ns_name
= copy_string(prefix
);
96 if (prefix
[strlen(prefix
)] != '_') {
97 prefix
[strlen(prefix
)+1] = 0;
98 prefix
[strlen(prefix
)] = '_';
103 // Create a symbol SWIGTCL
105 add_symbol("SWIGTCL",0,0);
106 typemap_lang
= "tcl";
108 // Attempt to load up the C++ configuration files
110 get_file("delcmd.swg",delcmd
);
111 get_file("methodcmd.swg",methodcmd
);
112 get_file("objcmd.swg",objcmd
);
116 // ---------------------------------------------------------------------
119 // Start parsing an interface file for Tcl.
120 // ---------------------------------------------------------------------
124 fprintf(stderr
,"Making wrappers for Tcl\n");
126 // Print out TCL specific headers
136 // ---------------------------------------------------------------------
137 // TCL::set_module(char *mod_name,char **mod_list)
139 // Sets the module name.
140 // Does nothing if it's already set (so it can be overridden as a command
143 // mod_list is a NULL-terminated list of additional modules. This
144 // is really only useful when building static executables and other
146 //----------------------------------------------------------------------
148 void TCL::set_module(char *mod_name
, char **mod_list
) {
155 module = new char[strlen(mod_name
)+1];
156 strcpy(module,mod_name
);
158 // Fix capitalization for Tcl
162 *c
= (char) tolower(*c
);
166 // Now create an initialization function
168 sprintf(temp
,"%s_Init", module);
169 init_name
= new char[strlen(temp
) + 1];
170 strcpy(init_name
, temp
);
171 *init_name
= toupper(*init_name
);
173 if (!ns_name
) ns_name
= copy_string(module);
175 // If namespaces have been specified, set the prefix to the module name
177 if ((nspace
) && (strlen(prefix
) < 1)) {
178 prefix
= new char[strlen(module)+2];
179 strcpy(prefix
,module);
180 prefix
[strlen(module)] = '_';
181 prefix
[strlen(module)+1] = 0;
184 // If additional modules have been specified, create some code for
185 // initializing them.
189 while (mod_list
[i
]) {
192 *c
= (char) tolower(*c
);
195 sprintf(temp
,"%s_Init",mod_list
[i
]);
196 temp
[0] = toupper(temp
[0]);
198 // Dump out some initialization code
200 mod_init
<< tab4
<< "if (" << temp
<< "(" << interp_name
<< ") == TCL_ERROR) {\n"
201 << tab8
<< "return TCL_ERROR;\n"
203 mod_extern
<< "extern int " << temp
<< "(Tcl_Interp *);\n";
210 // ---------------------------------------------------------------------
211 // TCL::set_init(char *iname)
213 // Sets the initialization function name.
214 // Does nothing if it's already set
216 //----------------------------------------------------------------------
218 void TCL::set_init(char *iname
) {
220 if (init_name
) return;
222 init_name
= new char[strlen(iname
)+1];
223 strcpy(init_name
, iname
);
227 // ---------------------------------------------------------------------
228 // TCL::headers(void)
230 // Generate the appropriate header files for TCL interface.
231 // ----------------------------------------------------------------------
233 void TCL::headers(void)
236 emit_banner(f_header
);
237 fprintf(f_header
,"/* Implementation : TCL 7.x */\n\n");
238 fprintf(f_header
,"#include <tcl.h>\n");
239 fprintf(f_header
,"#include <string.h>\n");
240 fprintf(f_header
,"#include <stdlib.h>\n");
241 fprintf(f_header
,"#define SWIGTCL\n");
244 fprintf(f_header
,"#define SWIG_NOINCLUDE\n");
247 if (insert_file("swigtcl.swg", f_header
) == -1) {
248 fprintf(stderr
,"Unable to find 'swigtcl.swg'. Possible installation problem.\n");
253 // --------------------------------------------------------------------
254 // TCL::initialize(void)
256 // Produces an initialization function. Assumes that the init function
257 // name has already been specified.
258 // ---------------------------------------------------------------------
260 void TCL::initialize()
263 if ((!ns_name
) && (nspace
)) {
264 fprintf(stderr
,"Tcl error. Must specify a namespace.\n");
269 init_name
= "Swig_Init";
270 fprintf(stderr
,"SWIG : *** Warning. No module name specified.\n");
273 fprintf(f_header
,"#define SWIG_init %s\n", init_name
);
274 if (!module) module = "swig";
275 fprintf(f_header
,"#define SWIG_name \"%s\"\n", module);
277 fprintf(f_header
,"#define SWIG_prefix \"%s::\"\n", ns_name
);
278 fprintf(f_header
,"#define SWIG_namespace \"%s\"\n\n", ns_name
);
280 fprintf(f_header
,"#define SWIG_prefix \"%s\"\n", prefix
);
281 fprintf(f_header
,"#define SWIG_namespace \"\"\n\n");
283 fprintf(f_header
,"#ifdef __cplusplus\n");
284 fprintf(f_header
,"extern \"C\" {\n");
285 fprintf(f_header
,"#endif\n");
286 fprintf(f_header
,"#ifdef MAC_TCL\n");
287 fprintf(f_header
,"#pragma export on\n");
288 fprintf(f_header
,"#endif\n");
289 fprintf(f_header
,"SWIGEXPORT(int) %s(Tcl_Interp *);\n", init_name
);
290 fprintf(f_header
,"#ifdef MAC_TCL\n");
291 fprintf(f_header
,"#pragma export off\n");
292 fprintf(f_header
,"#endif\n");
293 fprintf(f_header
,"#ifdef __cplusplus\n");
294 fprintf(f_header
,"}\n");
295 fprintf(f_header
,"#endif\n");
297 fprintf(f_init
,"SWIGEXPORT(int) %s(Tcl_Interp *%s) {\n", init_name
, interp_name
);
299 fprintf(f_init
,"\t if (%s == 0) \n", interp_name
);
300 fprintf(f_init
,"\t\t return TCL_ERROR;\n");
302 /* Check to see if other initializations need to be performed */
304 if (strlen(mod_extern
.get())) {
305 fprintf(f_init
,"%s\n",mod_init
.get());
306 fprintf(f_header
,"#ifdef __cplusplus\n");
307 fprintf(f_header
,"extern \"C\" {\n");
308 fprintf(f_header
,"#endif\n");
309 fprintf(f_header
,"%s\n",mod_extern
.get());
310 fprintf(f_header
,"#ifdef __cplusplus\n");
311 fprintf(f_header
,"}\n");
312 fprintf(f_header
,"#endif\n");
315 /* Check to see if we're adding support for Tcl8 nspaces */
317 fprintf(f_init
,"#if (TCL_MAJOR_VERSION >= 8)\n");
318 fprintf(f_init
,"\t Tcl_Eval(%s,\"namespace eval %s { }\");\n", interp_name
, ns_name
);
319 fprintf(f_init
,"#endif\n");
323 // ---------------------------------------------------------------------
326 // Wrap things up. Close initialization function.
327 // ---------------------------------------------------------------------
329 void TCL::close(void)
332 // Dump the pointer equivalency table
334 emit_ptr_equivalence(f_init
);
336 // Close the init file and quit
337 fprintf(f_init
,"%s",postinit
.get());
338 fprintf(f_init
,"\t return TCL_OK;\n");
339 fprintf(f_init
,"}\n");
342 // ----------------------------------------------------------------------
343 // TCL::get_pointer(char *iname, char *srcname, char *src, char *dest,
344 // DataType *t, String &f, char *ret)
346 // iname = name of function or variable
347 // srcname = name of source
348 // src = source variable in wrapper code
349 // dest = destination variable in wrapper code
351 // f = String where output is going to go
352 // ret = Return action
353 // ----------------------------------------------------------------------
355 void TCL::get_pointer(char *iname
, char *srcname
, char *src
, char *dest
,
356 DataType
*t
, String
&f
, char *ret
) {
358 // Pointers are read as hex-strings with encoded type information
360 f
<< tab4
<< "if (SWIG_GetPtr(" << src
<< ",(void **) &" << dest
<< ",";
362 if (t
->type
== T_VOID
) f
<< "(char *) 0)) {\n";
364 f
<< "\"" << t
->print_mangle() << "\")) {\n";
366 // Now emit code according to the level of strictness desired
369 case 0: // No type checking
372 case 1: // Warning message only
373 f
<< tab8
<< "fprintf(stderr,\"Warning : type mismatch in " << srcname
374 << " of " << iname
<< ". Expected " << t
->print_mangle()
375 << ", received %s\\n\"," << src
<< ");\n"
377 case 2: // Super strict mode.
378 f
<< tab8
<< "Tcl_SetResult(interp, \"Type error in " << srcname
<< " of " << iname
379 << ". Expected " << t
->print_mangle() << ", received \", TCL_STATIC);\n"
380 << tab8
<< "Tcl_AppendResult(interp, " << src
<< ", (char *) NULL);\n"
381 << tab8
<< ret
<< ";\n"
385 fprintf(stderr
,"Unknown strictness level\n");
390 // ----------------------------------------------------------------------
391 // TCL::create_command(char *cname, char *iname)
393 // Creates a Tcl command from a C function.
394 // ----------------------------------------------------------------------
396 void TCL::create_command(char *cname
, char *iname
) {
399 char *wname
= name_wrapper(cname
,prefix
);
401 fprintf(f_init
,"\t Tcl_CreateCommand(%s,SWIG_prefix \"%s\",%s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n", interp_name
, iname
, wname
);
403 // Add interpreter name to repeatcmd hash table. This hash is used in C++ code
404 // generation to try and find repeated wrapper functions.
406 repeatcmd
.add(iname
,copy_string(wname
));
409 // ----------------------------------------------------------------------
410 // TCL::create_function(char *name, char *iname, DataType *d, ParmList *l)
412 // Create a function declaration and register it with the interpreter.
413 // ----------------------------------------------------------------------
415 void TCL::create_function(char *name
, char *iname
, DataType
*d
, ParmList
*l
)
421 char source
[256], target
[256], argnum
[32], *tm
;
422 String cleanup
, outarg
;
424 int have_build
= 0; // Status indicating build typemap
429 // Make a wrapper name for this function
431 wname
= name_wrapper(iname
,prefix
);
433 // Now write the wrapper function itself....this is pretty ugly
435 f
.def
<< "static int " << wname
<< "(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) {\n";
436 f
.code
<< tab4
<< "clientData = clientData; argv = argv;\n";
438 // Print out variables for storing arguments.
440 pcount
= emit_args(d
, l
, f
);
442 // Get number of optional arguments
444 numopt
= l
->numopt();
446 // Check the number of arguments
448 usage
= usage_func(iname
,d
,l
); // Create a usage string
449 f
.code
<< tab4
<< "if ((argc < " << (pcount
-numopt
) +1 << ") || (argc > " << l
->numarg()+1 << ")) {\n"
450 << tab8
<< "Tcl_SetResult(interp, \"Wrong # args. " << usage
<< "\",TCL_STATIC);\n"
451 << tab8
<< "return TCL_ERROR;\n"
454 // Extract parameters. This case statement should be used to extract
455 // Function parameters. Add more cases if you want to do more.
461 // Produce string representations of the source and target arguments
462 sprintf(source
,"argv[%d]",j
+1);
463 sprintf(target
,"_arg%d",i
);
464 sprintf(argnum
,"%d",j
+1);
466 // See if this argument is being ignored
469 if (j
>= (pcount
-numopt
))
470 f
.code
<< tab4
<< "if (argc >" << j
+1 << ") { \n";
472 // See if there is a type-mapping
474 if ((tm
= typemap_lookup("in","tcl",p
->t
,p
->name
,source
,target
,&f
))) {
475 // Yep. Use it instead of the default
476 f
.code
<< tm
<< "\n";
477 f
.code
.replace("$argnum",argnum
);
478 f
.code
.replace("$arg",source
);
481 if (!p
->t
->is_pointer
) {
483 // Extract a parameter by value.
497 f
.code
<< tab4
<< "_arg" << i
<< " = " << p
->t
->print_cast() << " atol(argv[" << j
+1 << "]);\n";
506 f
.code
<< tab4
<< "_arg" << i
<< " = " << p
->t
->print_cast() << " strtoul(argv[" << j
+1
507 << "],(char **) NULL,0);\n";
514 f
.code
<< tab4
<< "_arg" << i
<< " = " << p
->t
->print_cast() << " atof(argv[" << j
+1 << "]);\n";
517 // A single character
520 f
.code
<< tab4
<< "_arg" << i
<< " = *argv[" << j
+1 << "];\n";
523 // Void.. Do nothing.
528 // User defined. This is an error.
532 // Unsupported data type
535 fprintf(stderr
,"%s : Line %d: Unable to use type %s as a function argument.\n",
536 input_file
, line_number
, p
->t
->print_type());
539 } else { /* Pointer type */
541 // Function argument is some sort of pointer
542 // Look for a string. Otherwise, just pull off a pointer.
544 if ((p
->t
->type
== T_CHAR
) && (p
->t
->is_pointer
== 1)) {
545 f
.code
<< tab4
<< "_arg" << i
<< " = argv[" << j
+1 << "];\n";
548 // Have a generic pointer type here. Read it in as
552 sprintf(arg_temp
,"argument %d",j
+1);
553 get_pointer(iname
,arg_temp
,source
,target
,p
->t
,f
.code
,"return TCL_ERROR");
557 if (j
>= (pcount
-numopt
))
558 f
.code
<< tab4
<< "} \n";
562 // Check to see if there is any sort of "build" typemap (highly complicated)
564 if ((tm
= typemap_lookup("build","tcl",p
->t
,p
->name
,source
,target
))) {
569 // Check to see if there was any sort of a constaint typemap
570 if ((tm
= typemap_lookup("check","tcl",p
->t
,p
->name
,source
,target
))) {
571 // Yep. Use it instead of the default
572 f
.code
<< tm
<< "\n";
573 f
.code
.replace("$argnum",argnum
);
574 f
.code
.replace("$arg",source
);
577 // Check if there was any cleanup code (save it for later)
578 if ((tm
= typemap_lookup("freearg","tcl",p
->t
,p
->name
,target
,"interp->result"))) {
579 // Yep. Use it instead of the default
580 cleanup
<< tm
<< "\n";
581 cleanup
.replace("$argnum",argnum
);
582 cleanup
.replace("$arg",source
);
584 if ((tm
= typemap_lookup("argout","tcl",p
->t
,p
->name
,target
,"interp->result"))) {
585 // Yep. Use it instead of the default
586 outarg
<< tm
<< "\n";
587 outarg
.replace("$argnum",argnum
);
588 outarg
.replace("$arg",source
);
590 p
= l
->get_next(); // Get next parameter and continue
594 // If there was a "build" typemap, we need to go in and perform a serious hack
599 l
->sub_parmnames(build
); // Replace all parameter names
601 for (i
= 0; i
< l
->nparms
; i
++) {
603 if (strlen(p
->name
) > 0) {
604 sprintf(temp1
,"_in_%s", p
->name
);
606 sprintf(temp1
,"_in_arg%d", i
);
608 sprintf(temp2
,"argv[%d]",j
);
609 build
.replaceid(temp1
,temp2
);
616 // Now write code to make the function call
618 emit_func_call(name
,d
,l
,f
);
620 // Return value if necessary
622 if ((tm
= typemap_lookup("out","tcl",d
,name
,"_result","interp->result"))) {
623 // Yep. Use it instead of the default
624 f
.code
<< tm
<< "\n";
625 } else if ((d
->type
!= T_VOID
) || (d
->is_pointer
)) {
626 // Normal SWIG mappings
628 if (!d
->is_pointer
) {
630 // Function returns a "value"
633 // Is a signed integer
642 f
.code
<< tab4
<< "sprintf(interp->result,\"%ld\", (long) _result);\n";
645 // Is an unsigned integer
650 f
.code
<< tab4
<< "sprintf(interp->result,\"%lu\", (unsigned long) _result);\n";
653 // Is a single character. Assume we return it as a string
655 f
.code
<< tab4
<< "sprintf(interp->result,\"%c\", _result);\n";
658 // Floating point number
661 f
.code
<< tab4
<< "Tcl_PrintDouble(interp,(double) _result, interp->result);\n";
662 //sprintf(interp->result,\"%0.17f\",(double) _result);\n";
668 // Okay. We're returning malloced memory at this point.
669 // Probably dangerous, but what the hell
672 f
.code
<< tab4
<< "SWIG_MakePtr(interp->result, (void *) _result,\"" << d
->print_mangle()
679 fprintf(stderr
,"%s : Line %d: Unable to use return type %s in function %s.\n",
680 input_file
, line_number
, d
->print_type(), name
);
685 // Is a pointer return type
687 if ((d
->type
== T_CHAR
) && (d
->is_pointer
== 1)) {
688 // Return a character string
689 f
.code
<< tab4
<< "Tcl_SetResult(interp, (char *) _result, " << char_result
<< ");\n";
691 f
.code
<< tab4
<< "SWIG_MakePtr(interp->result, (void *) _result,\"" << d
->print_mangle() << "\");\n";
696 // Dump argument output code;
699 // Dump the argument cleanup code
702 // Look for any remaining cleanup
705 if ((tm
= typemap_lookup("newfree","tcl",d
,iname
,"_result",""))) {
706 f
.code
<< tm
<< "\n";
710 if ((tm
= typemap_lookup("ret","tcl",d
,name
,"_result",""))) {
711 // Yep. Use it instead of the default
712 f
.code
<< tm
<< "\n";
715 // Wrap things up (in a manner of speaking)
717 f
.code
<< tab4
<< "return TCL_OK;\n}";
719 // Substitute the cleanup code
720 f
.code
.replace("$cleanup",cleanup
);
721 f
.code
.replace("$name",iname
);
723 // Dump out the function
727 // Add interpreter name to repeatcmd hash table. This hash is used in C++ code
728 // generation to try and find repeated wrapper functions.
730 fprintf(f_init
,"\t Tcl_CreateCommand(%s, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n", interp_name
, iname
, wname
);
732 // If there's a documentation entry, produce a usage string
736 static DocEntry
*last_doc_entry
= 0;
738 // Use usage as description
739 doc_entry
->usage
<< usage
;
741 // Set the cinfo field to specific a return type
743 if (last_doc_entry
!= doc_entry
) {
744 doc_entry
->cinfo
<< "returns " << d
->print_type();
745 last_doc_entry
= doc_entry
;
750 // -----------------------------------------------------------------------
751 // TCL::link_variable(char *name, char *iname, DataType *t,
754 // Create a TCL link to a variable.
755 // -----------------------------------------------------------------------
757 void TCL::link_variable(char *name
, char *iname
, DataType
*t
)
765 // See if there were any typemaps
767 tm
= typemap_lookup("varin","tcl",t
,name
,"","");
768 tm1
= typemap_lookup("varout","tcl",t
,name
,"","");
770 fprintf(stderr
,"%s : Line %d. Warning. varin/varout typemap methods not supported.",
771 input_file
, line_number
);
774 // Check the datatype. Must be a valid Tcl type (there aren't many)
776 if (((t
->type
== T_INT
) && (!t
->is_pointer
)) ||
777 ((t
->type
== T_UINT
) && (!t
->is_pointer
)) ||
778 ((t
->type
== T_SINT
) && (!t
->is_pointer
)) ||
779 ((t
->type
== T_DOUBLE
) && (!t
->is_pointer
)) ||
780 ((t
->type
== T_BOOL
) && (!t
->is_pointer
)) ||
781 ((t
->type
== T_CHAR
) && (t
->is_pointer
== 1))) {
783 // This is a valid TCL type.
785 if (t
->type
== T_UINT
)
786 fprintf(stderr
,"%s : Line %d : ** Warning. Linkage of unsigned type may be unsafe.\n",
787 input_file
, line_number
);
789 // Now add symbol to the TCL interpreter
794 // Is an array. We have to do something different
795 fprintf(f_wrappers
,"static char *tclvar%s = %s;\n",name
,name
);
796 s
<< "(char *) &tclvar" << name
<< ", TCL_LINK_STRING";
798 s
<< "(char *) &" << name
<< ", TCL_LINK_STRING";
805 s
<< "(char *) &" << name
<< ", TCL_LINK_INT";
808 s
<< "(char *) &" << name
<< ", TCL_LINK_DOUBLE";
811 fprintf(f_init
,"Fatal error. Internal error (Tcl:link_variable)\n");
815 if (Status
& STAT_READONLY
)
816 s
<< " | TCL_LINK_READ_ONLY);\n";
820 fprintf(f_init
,"\t Tcl_LinkVar(%s, SWIG_prefix \"%s\", %s",interp_name
, iname
, s
.get());
822 // Make a usage string for it
825 doc_entry
->usage
<< usage_var(iname
,t
);
826 doc_entry
->cinfo
= "";
827 doc_entry
->cinfo
<< "Global : " << t
->print_type() << " " << name
;
831 // Have some sort of "other" type.
832 // We're going to emit some functions to set/get it's value instead
834 emit_set_get(name
,iname
, t
);
836 doc_entry
->cinfo
= "";
837 doc_entry
->cinfo
<< "Global : " << t
->print_type() << " " << iname
;
840 // If shadow classes are enabled and we have a user-defined type
841 // that we know about, create a command for it.
844 if ((t
->type
== T_USER
) && (t
->is_pointer
< 1)) {
845 // See if the datatype is in our hash table
846 if (hash
.lookup(t
->name
)) {
847 // Yep. Try to create a command for it
848 // postinit << tab4 << "Tcl_CreateCommand(interp, SWIG_prefix \"" << iname << "\",Tcl" << (char *) hash.lookup(t->name)
849 // << "MethodCmd, (ClientData)";
851 postinit
<< tab4
<< "{\n"
852 << tab8
<< "char cmd[] = \""
853 << (char *) hash
.lookup(t
->name
) << " " << iname
<< " -this ["
854 << iname
<< "_get ]\";\n"
855 << tab8
<< "Tcl_GlobalEval(interp,cmd);\n"
858 // postinit << tab4 << "Tcl_GlobalEval(interp,\"set " << iname << " [" << iname << "_get ];"
859 // << (char *) hash.lookup(t->name) << " -this $" << iname << "\");\n";
867 // -----------------------------------------------------------------------
868 // TCL::declare_const(char *name, char *iname, DataType *type, char *value)
870 // Makes a constant. Really just creates a variable and links to it.
871 // Tcl variable linkage allows read-only variables so we'll use that
872 // instead of just creating a Tcl variable.
873 // ------------------------------------------------------------------------
875 void TCL::declare_const(char *name
, char *, DataType
*type
, char *value
) {
877 int OldStatus
= Status
; // Save old status flags
883 Status
= STAT_READONLY
; // Enable readonly mode.
885 // Make a static variable;
887 sprintf(var_name
,"_wrap_const_%s",name
);
889 // See if there's a typemap
892 if ((type
->type
== T_CHAR
) && (type
->is_pointer
== 1)) {
896 if ((type
->type
== T_CHAR
) && (type
->is_pointer
== 0)) {
900 if ((tm
= typemap_lookup("const","tcl",type
,name
,rvalue
.get(),name
))) {
901 // Yep. Use it instead of the default
902 fprintf(f_init
,"%s\n",tm
);
905 // Create variable and assign it a value
907 if (type
->is_pointer
== 0) {
909 case T_BOOL
: case T_INT
: case T_SINT
: case T_DOUBLE
:
910 fprintf(f_header
,"static %s %s = %s;\n", type
->print_type(), var_name
, value
);
911 link_variable(var_name
,name
,type
);
918 fprintf(f_header
,"static %s %s = %s;\n", type
->print_type(), var_name
, value
);
919 fprintf(f_header
,"static char *%s_char;\n", var_name
);
921 fprintf(f_init
,"\t %s_char = new char[32];\n",var_name
);
923 fprintf(f_init
,"\t %s_char = (char *) malloc(32);\n",var_name
);
925 fprintf(f_init
,"\t sprintf(%s_char,\"%%ld\", (long) %s);\n", var_name
, var_name
);
926 sprintf(var_name
,"%s_char",var_name
);
927 t
= new DataType(T_CHAR
);
929 link_variable(var_name
,name
,t
);
936 fprintf(f_header
,"static %s %s = %s;\n", type
->print_type(), var_name
, value
);
937 fprintf(f_header
,"static char *%s_char;\n", var_name
);
939 fprintf(f_init
,"\t %s_char = new char[32];\n",var_name
);
941 fprintf(f_init
,"\t %s_char = (char *) malloc(32);\n",var_name
);
943 fprintf(f_init
,"\t sprintf(%s_char,\"%%lu\", (unsigned long) %s);\n", var_name
, var_name
);
944 sprintf(var_name
,"%s_char",var_name
);
945 t
= new DataType(T_CHAR
);
947 link_variable(var_name
,name
,t
);
951 type
->type
= T_DOUBLE
;
952 strcpy(type
->name
,"double");
953 fprintf(f_header
,"static %s %s = %s (%s);\n", type
->print_type(), var_name
, type
->print_cast(), value
);
954 link_variable(var_name
,name
,type
);
959 fprintf(f_header
,"static %s %s = \"%s\";\n", type
->print_type(), var_name
, value
);
960 link_variable(var_name
,name
,type
);
964 fprintf(stderr
,"%s : Line %d. Unsupported constant value.\n", input_file
, line_number
);
968 // Have some sort of pointer value here
969 if ((type
->type
== T_CHAR
) && (type
->is_pointer
== 1)) {
971 fprintf(f_header
,"static %s %s = \"%s\";\n", type
->print_type(), var_name
, value
);
972 link_variable(var_name
,name
,type
);
974 // Something else. Some sort of pointer value
975 fprintf(f_header
,"static %s %s = %s;\n", type
->print_type(), var_name
, value
);
976 fprintf(f_header
,"static char *%s_char;\n", var_name
);
978 fprintf(f_init
,"\t %s_char = new char[%d];\n",var_name
,(int) strlen(type
->print_mangle())+ 20);
980 fprintf(f_init
,"\t %s_char = (char *) malloc(%d);\n",var_name
,(int) strlen(type
->print_mangle())+ 20);
982 t
= new DataType(T_CHAR
);
984 fprintf(f_init
,"\t SWIG_MakePtr(%s_char, (void *) %s,\"%s\");\n",
985 var_name
, var_name
, type
->print_mangle());
986 sprintf(var_name
,"%s_char",var_name
);
987 link_variable(var_name
,name
,t
);
993 // Create a documentation entry for this
996 doc_entry
->usage
= ""; // Destroy any previous information from linking
997 doc_entry
->usage
<< usage_const(name
, type
, value
);
998 doc_entry
->cinfo
= "";
999 doc_entry
->cinfo
<< "Constant : " << type
->print_type();
1004 // ----------------------------------------------------------------------
1005 // TCL::usage_var(char *iname, DataType *t, char **s)
1007 // Produces a usage string for a tcl variable. Stores it in s
1008 // ----------------------------------------------------------------------
1010 char *TCL::usage_var(char *iname
, DataType
*t
) {
1016 temp
<< "$" << prefix
<< iname
;
1018 temp
<< ns_name
<< "::" << iname
;
1020 if (!(((t
->type
== T_INT
) && (!t
->is_pointer
)) ||
1021 ((t
->type
== T_UINT
) && (!t
->is_pointer
)) ||
1022 ((t
->type
== T_DOUBLE
) && (!t
->is_pointer
)) ||
1023 ((t
->type
== T_BOOL
) && (!t
->is_pointer
)) ||
1024 ((t
->type
== T_CHAR
) && (t
->is_pointer
)))) {
1025 /* We emitted a pair of set/get functions instead. Doc will be generated for that */
1032 // ---------------------------------------------------------------------------
1033 // char *TCL::usage_string(char *iname, DataType *t, ParmList *l),
1035 // Generates a generic usage string for a Tcl function.
1036 // ---------------------------------------------------------------------------
1038 char * TCL::usage_string(char *iname
, DataType
*, ParmList
*l
) {
1042 int i
, numopt
,pcount
;
1045 temp
<< iname
<< " ";
1047 /* Now go through and print parameters */
1050 numopt
= l
->numopt();
1054 // Only print an argument if not ignored
1056 if (!typemap_check("ignore","tcl",p
->t
,p
->name
)) {
1057 if (i
>= (pcount
-numopt
))
1060 /* If parameter has been named, use that. Otherwise, just print a type */
1062 if ((p
->t
->type
!= T_VOID
) || (p
->t
->is_pointer
)) {
1063 if (strlen(p
->name
) > 0) {
1067 temp
<< "{ " << p
->t
->print_type() << " }";
1070 if (i
>= (pcount
-numopt
))
1080 // ---------------------------------------------------------------------------
1081 // char *TCL::usage_func(char *iname, DataType *t, ParmList *l),
1083 // Produces a usage string for a function in Tcl
1084 // ---------------------------------------------------------------------------
1086 char * TCL::usage_func(char *iname
, DataType
*t
, ParmList
*l
) {
1091 temp
<< ns_name
<< "::" << iname
;
1093 temp
<< prefix
<< iname
;
1095 return usage_string(temp
,t
,l
);
1098 // -----------------------------------------------------------------
1099 // TCL::usage_const(char *name, DataType *type, char *value)
1102 // Makes a usage string and returns it
1103 // -----------------------------------------------------------------
1105 char *TCL::usage_const(char *name
, DataType
*, char *value
) {
1109 temp
<< ns_name
<< "::" << name
<< " = " << value
;
1111 temp
<< "$" << prefix
<< name
<< " = " << value
;
1116 // -------------------------------------------------------------------
1117 // TCL::add_native(char *name, char *funcname)
1119 // This adds an already written Tcl wrapper function to our
1120 // initialization function.
1121 // -------------------------------------------------------------------
1124 void TCL::add_native(char *name
, char *funcname
) {
1126 fprintf(f_init
,"\t Tcl_CreateCommand(%s, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",interp_name
, name
, funcname
);
1130 doc_entry
->usage
<< ns_name
<< "::" << name
<< " args";
1132 doc_entry
->usage
<< prefix
<< name
<< " args";
1134 doc_entry
->cinfo
<< "Native method : " << funcname
;
1139 // -------------------------------------------------------------------
1140 // TCL::pragma(char *lname, char *name, char *value)
1142 // This is an experimental %pragma handler. Officially unsupported
1143 // in this release, but requested in e-mail.
1144 // --------------------------------------------------------------------
1146 void TCL::pragma(char *lname
, char *name
, char *) {
1148 if (strcmp(lname
,"tcl") == 0) {
1149 if (strcmp(name
,"dynamic") == 0) {
1150 char_result
= "TCL_DYNAMIC";
1151 } else if (strcmp(name
,"static") == 0) {
1152 char_result
= "TCL_STATIC";
1153 } else if (strcmp(name
,"volatile") == 0) {
1154 char_result
= "TCL_VOLATILE";
1160 // ---------------------------------------------------------------------
1163 // The following functions provide some support for C++ classes and
1165 // ---------------------------------------------------------------------
1167 void TCL::cpp_open_class(char *classname
, char *rename
, char *ctype
, int strip
) {
1169 this->Language::cpp_open_class(classname
,rename
,ctype
,strip
);
1177 config_options
= "";
1180 have_constructor
= 0;
1181 have_destructor
= 0;
1187 class_name
= copy_string(rename
);
1189 class_name
= copy_string(classname
);
1191 base_class
= (char *) 0;
1193 class_type
= new char[strlen(ctype
)+2];
1194 sprintf(class_type
,"%s ", ctype
);
1198 real_classname
= copy_string(classname
);
1200 // Build up the hash table
1202 hash
.add(real_classname
,copy_string(class_name
));
1203 sprintf(temp
,"%s %s", class_type
, real_classname
);
1204 hash
.add(temp
,copy_string(class_name
));
1208 void TCL::cpp_close_class() {
1213 this->Language::cpp_close_class();
1217 sprintf(t
->name
,"%s%s", class_type
, real_classname
);
1221 // Note : The object oriented interface is defined by three files
1222 // delcmd.swg - Object deletion wrapper
1223 // methodcmd.swg - Method invocation command
1224 // objcmd.swg - Command to create a new object
1226 // These files are located in the SWIG library. This module
1227 // grabs the files and performs marker replacements to
1228 // build the wrapper function.
1230 // Generate a Tcl function for object destruction
1232 if (have_destructor
) {
1236 // Dump out method code
1239 // Dump out object creation command
1242 // Now perform marker replacements
1243 code
.replace("@CLASS@",class_name
);
1245 temp
<< name_destroy(class_name
);
1246 code
.replace("@DESTRUCTOR@",temp
);
1247 code
.replace("@CLASSTYPE@",t
->print_type());
1248 "configure " >> methodnames
;
1249 "cget " >> methodnames
;
1250 code
.replace("@METHODLIST@", methodnames
);
1251 code
.replace("@CLASSMANGLE@",t
->print_mangle());
1252 code
.replace("@METHODS@",methods
);
1253 code
.replace("@CONFIGMETHODS@",config
);
1254 code
.replace("@CGETMETHODS@",cget
);
1255 if (have_constructor
) {
1257 temp
<< name_wrapper(name_construct(class_name
),prefix
);
1261 code
.replace("@TCLCONSTRUCTOR@",temp
);
1262 code
.replace("@CONFIGLIST@",config_options
);
1263 code
.replace("@CGETLIST@",options
);
1264 if (have_destructor
) {
1270 code
.replace("@TCLDESTRUCTOR@",temp
);
1271 fprintf(f_wrappers
,"%s\n", code
.get());
1272 fprintf(f_init
,"\t Tcl_CreateCommand(interp, SWIG_prefix \"%s\",Tcl%sCmd, (ClientData) NULL, NULL);\n", class_name
, class_name
);
1276 void TCL::cpp_member_func(char *name
, char *iname
, DataType
*t
, ParmList
*l
) {
1282 this->Language::cpp_member_func(name
,iname
,t
,l
);
1290 // Add stubs for this member to our class handler function
1293 methods
<< tab4
<< "else ";
1297 // Try to figure out if there is a wrapper for this function
1300 temp
<< name_member(realname
,class_name
);
1302 rname
= (char *) repeatcmd
.lookup(temp
);
1305 rname
= name_wrapper(temp
.get(),prefix
);
1307 methods
<< "if (strcmp(argv[1],\"" << realname
<< "\") == 0) {\n"
1308 << tab4
<< tab4
<< "cmd = " << rname
<< ";\n"
1312 methodnames
<< realname
<< " ";
1315 doc_entry
->usage
= "";
1316 doc_entry
->usage
<< usage_string(realname
,t
,l
);
1321 void TCL::cpp_variable(char *name
, char *iname
, DataType
*t
) {
1326 this->Language::cpp_variable(name
, iname
, t
);
1334 // Write config code
1336 char *bc
= class_name
;
1338 if (!(Status
& STAT_READONLY
)) {
1340 config
<< tab8
<< tab8
;
1346 temp
<< name_set(name_member(realname
,bc
));
1347 rname
= (char *) repeatcmd
.lookup(temp
);
1349 rname
= name_wrapper(temp
.get(),prefix
);
1351 config
<< "if (strcmp(argv[i],\"-" << realname
<< "\") == 0) {\n"
1352 << tab8
<< tab8
<< tab4
<< "cmd = " << rname
<< ";\n"
1353 << tab8
<< tab8
<< "} ";
1361 cget
<< tab8
<< tab8
;
1366 // Try to figure out if there is a wrapper for this function
1368 temp
<< name_get(name_member(realname
,bc
));
1369 rname
= (char *) repeatcmd
.lookup(temp
);
1371 rname
= name_wrapper(temp
.get(),prefix
);
1373 cget
<< "if (strcmp(argv[2],\"-" << realname
<< "\") == 0) {\n"
1374 << tab8
<< tab8
<< tab4
<< "cmd = " << rname
<< ";\n"
1375 << tab8
<< tab8
<< "} ";
1378 options
<< "-" << realname
<< " ";
1379 if (!(Status
& STAT_READONLY
)) {
1380 config_options
<< "-" << realname
<< " ";
1383 doc_entry
->usage
= "";
1384 doc_entry
->usage
<< "-" << realname
<< "\n";
1389 void TCL::cpp_constructor(char *name
, char *iname
, ParmList
*l
) {
1390 this->Language::cpp_constructor(name
,iname
,l
);
1393 if ((!have_constructor
) && (doc_entry
)) {
1394 doc_entry
->usage
= "";
1395 doc_entry
->usage
<< class_name
<< usage_string(" name",0,l
);
1397 have_constructor
= 1;
1400 void TCL::cpp_destructor(char *name
, char *newname
) {
1401 this->Language::cpp_destructor(name
,newname
);
1403 if (!have_destructor
) {
1405 doc_entry
->usage
= "rename obj {}";
1408 have_destructor
= 1;
1412 void TCL::cpp_inherit(char **baseclass
, int) {
1413 this->Language::cpp_inherit(baseclass
);
1416 void TCL::cpp_declare_const(char *name
, char *iname
, DataType
*type
, char *value
) {
1417 this->Language::cpp_declare_const(name
,iname
,type
,value
);
1421 // --------------------------------------------------------------------------------
1422 // TCL::add_typedef(DataType *t, char *name)
1424 // This is called whenever a typedef is encountered. When shadow classes are
1425 // used, this function lets us discovered hidden uses of a class. For example :
1431 // typedef FooBar *FooBarPtr;
1433 // --------------------------------------------------------------------------------
1435 void TCL::add_typedef(DataType
*t
, char *name
) {
1437 if (!shadow
) return;
1439 // First check to see if there aren't too many pointers
1441 if (t
->is_pointer
> 1) return;
1442 if (hash
.lookup(name
)) return; // Already added
1444 // Now look up the datatype in our shadow class hash table
1446 if (hash
.lookup(t
->name
)) {
1448 // Yep. This datatype is in the hash
1449 // Put this types 'new' name into the hash
1450 hash
.add(name
,copy_string((char *) hash
.lookup(t
->name
)));
1454 // -----------------------------------------------------------------------
1455 // TCL::cpp_class_decl(char *name, char *rename, char *type)
1457 // Treatment of an empty class definition. Used to handle
1458 // shadow classes across modules.
1459 // -----------------------------------------------------------------------
1461 void TCL::cpp_class_decl(char *name
, char *rename
, char *type
) {
1463 this->Language::cpp_class_decl(name
,rename
, type
);
1465 hash
.add(name
,copy_string(rename
));
1466 // Add full name of datatype to the hash table
1467 if (strlen(type
) > 0) {
1468 sprintf(temp
,"%s %s", type
, name
);
1469 hash
.add(temp
,copy_string(rename
));