]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wxSWIG/Modules/tcl8.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 * Module for creating Tcl 8.0 native wrapper functions. Older SWIG
22 * modules will work with Tcl 8.0, but this one provides a significant
23 * boost in performance.
24 ***********************************************************************/
30 static char *Tcl_config
="swigtcl.swg";
31 static char *usage
= "\
32 Tcl 8.0 Options (available with -tcl)\n\
33 -module name - Set name of module\n\
34 -prefix name - Set a prefix to be appended to all names\n\
35 -namespace - Build module into a Tcl 8 namespace. \n\
36 -noobject - Omit code for object oriented interface.\n\
37 -old - Use old SWIG interface (same as -noobject).\n\n";
39 static char *ns_name
= 0;
41 static String mod_init
;
42 static String mod_extern
;
44 // ---------------------------------------------------------------------
45 // TCL8::parse_args(int argc, char *argv[])
47 // Parse tcl specific command line options
48 // ---------------------------------------------------------------------
50 void TCL8::parse_args(int argc
, char *argv
[]) {
53 sprintf(LibDir
,"%s",tcl_path
);
55 // Look for certain command line options
57 for (i
= 1; i
< argc
; i
++) {
59 if (strcmp(argv
[i
],"-prefix") == 0) {
61 prefix
= new char[strlen(argv
[i
+1])+2];
62 strcpy(prefix
, argv
[i
+1]);
69 } else if (strcmp(argv
[i
],"-module") == 0) {
71 set_module(argv
[i
+1],0);
78 } else if (strcmp(argv
[i
],"-namespace") == 0) {
81 } else if (strcmp(argv
[i
],"-old") == 0) {
84 } else if (strcmp(argv
[i
],"-noobject") == 0) {
87 } else if (strcmp(argv
[i
],"-help") == 0) {
93 // If a package has been specified, make sure it ends with a '_'
96 ns_name
= copy_string(prefix
);
97 if (prefix
[strlen(prefix
)] != '_') {
98 prefix
[strlen(prefix
)+1] = 0;
99 prefix
[strlen(prefix
)] = '_';
104 // Create a symbol SWIGTCL
106 add_symbol("SWIGTCL",0,0);
107 add_symbol("SWIGTCL8",0,0);
109 // Set name of typemaps
111 typemap_lang
= "tcl8";
113 // Attempt to load up the C++ configuration files
115 get_file("delcmd8.swg",delcmd
);
116 get_file("methodcmd8.swg",methodcmd
);
117 get_file("objcmd8.swg",objcmd
);
121 // ---------------------------------------------------------------------
122 // void TCL8::parse()
124 // Start parsing an interface file for Tcl.
125 // ---------------------------------------------------------------------
129 fprintf(stderr
,"Making wrappers for Tcl 8.x\n");
131 // Print out TCL specific headers
141 // ---------------------------------------------------------------------
142 // TCL8::set_module(char *mod_name,char **mod_list)
144 // Sets the module name.
145 // Does nothing if it's already set (so it can be overridden as a command
148 // mod_list is a NULL-terminated list of additional modules. This
149 // is really only useful when building static executables and other
151 //----------------------------------------------------------------------
153 void TCL8::set_module(char *mod_name
, char **mod_list
) {
160 module = new char[strlen(mod_name
)+1];
161 strcpy(module,mod_name
);
163 // Fix capitalization for Tcl
167 *c
= (char) tolower(*c
);
171 // Now create an initialization function
173 sprintf(temp
,"%s_Init", module);
174 init_name
= new char[strlen(temp
) + 1];
175 strcpy(init_name
, temp
);
176 *init_name
= toupper(*init_name
);
178 if (!ns_name
) ns_name
= copy_string(module);
180 // If namespaces have been specified, set the prefix to the module name
182 if ((nspace
) && (strlen(prefix
) < 1)) {
183 prefix
= new char[strlen(module)+2];
184 strcpy(prefix
,module);
185 prefix
[strlen(module)] = '_';
186 prefix
[strlen(module)+1] = 0;
189 // If additional modules have been specified, create some code for
190 // initializing them.
194 while (mod_list
[i
]) {
197 *c
= (char) tolower(*c
);
200 sprintf(temp
,"%s_Init",mod_list
[i
]);
201 temp
[0] = toupper(temp
[0]);
203 // Dump out some initialization code
205 mod_init
<< tab4
<< "if (" << temp
<< "(" << interp_name
<< ") == TCL_ERROR) {\n"
206 << tab8
<< "return TCL_ERROR;\n"
208 mod_extern
<< "extern int " << temp
<< "(Tcl_Interp *);\n";
215 // ---------------------------------------------------------------------
216 // TCL8::set_init(char *iname)
218 // Sets the initialization function name.
219 // Does nothing if it's already set
221 //----------------------------------------------------------------------
223 void TCL8::set_init(char *iname
) {
225 if (init_name
) return;
226 init_name
= new char[strlen(iname
)+1];
227 strcpy(init_name
, iname
);
231 // ---------------------------------------------------------------------
232 // TCL8::headers(void)
234 // Generate the appropriate header files for TCL interface.
235 // ----------------------------------------------------------------------
237 void TCL8::headers(void)
240 emit_banner(f_header
);
241 fprintf(f_header
,"/* Implementation : TCL 8.0 */\n\n");
242 fprintf(f_header
,"#include <tcl.h>\n");
243 fprintf(f_header
,"#include <string.h>\n");
244 fprintf(f_header
,"#include <stdlib.h>\n");
245 fprintf(f_header
,"#define SWIGTCL\n");
246 fprintf(f_header
,"#define SWIGTCL8\n");
248 // Include a Tcl configuration file for Unix,Mac,Wintel.
251 fprintf(f_header
,"#define SWIG_NOINCLUDE\n");
254 if (insert_file("swigtcl8.swg",f_header
) == -1) {
255 fprintf(stderr
,"SWIG : Fatal error. Unable to locate 'swigtcl8.swg' in SWIG library.\n");
260 // --------------------------------------------------------------------
261 // TCL8::initialize(void)
263 // Produces an initialization function. Assumes that the init function
264 // name has already been specified.
265 // ---------------------------------------------------------------------
267 void TCL8::initialize()
270 if ((!ns_name
) && (nspace
)) {
271 fprintf(stderr
,"Tcl error. Must specify a namespace.\n");
276 init_name
= "Swig_Init";
277 fprintf(stderr
,"SWIG : *** Warning. No module name specified.\n");
280 fprintf(f_header
,"#define SWIG_init %s\n", init_name
);
281 if (!module) module = "swig";
282 fprintf(f_header
,"#define SWIG_name \"%s\"\n", module);
284 fprintf(f_header
,"#define SWIG_prefix \"%s::\"\n", ns_name
);
285 fprintf(f_header
,"#define SWIG_namespace \"%s\"\n\n", ns_name
);
287 fprintf(f_header
,"#define SWIG_prefix \"%s\"\n", prefix
);
288 fprintf(f_header
,"#define SWIG_namespace \"\"\n\n");
290 fprintf(f_header
,"#ifdef __cplusplus\n");
291 fprintf(f_header
,"extern \"C\" {\n");
292 fprintf(f_header
,"#endif\n");
293 fprintf(f_header
,"#ifdef MAC_TCL\n");
294 fprintf(f_header
,"#pragma export on\n");
295 fprintf(f_header
,"#endif\n");
296 fprintf(f_header
,"SWIGEXPORT(int) %s(Tcl_Interp *);\n", init_name
);
297 fprintf(f_header
,"#ifdef MAC_TCL\n");
298 fprintf(f_header
,"#pragma export off\n");
299 fprintf(f_header
,"#endif\n");
300 fprintf(f_header
,"#ifdef __cplusplus\n");
301 fprintf(f_header
,"}\n");
302 fprintf(f_header
,"#endif\n");
305 fprintf(f_init
,"SWIGEXPORT(int) %s(Tcl_Interp *%s) {\n", init_name
, interp_name
);
307 fprintf(f_init
,"#ifdef ITCL_NAMESPACES\n");
308 fprintf(f_init
,"\t Itcl_Namespace spaceId;\n");
309 fprintf(f_init
,"#endif\n");
312 fprintf(f_init
,"\t if (%s == 0) \n", interp_name
);
313 fprintf(f_init
,"\t\t return TCL_ERROR;\n");
315 /* Set up SwigPtrType table */
317 fprintf(f_init
,"\t SWIG_RegisterType();\n");
319 /* Check to see if other initializations need to be performed */
321 if (strlen(mod_extern
.get())) {
322 fprintf(f_init
,"%s\n",mod_init
.get());
323 fprintf(f_header
,"#ifdef __cplusplus\n");
324 fprintf(f_header
,"extern \"C\" {\n");
325 fprintf(f_header
,"#endif\n");
326 fprintf(f_header
,"%s\n",mod_extern
.get());
327 fprintf(f_header
,"#ifdef __cplusplus\n");
328 fprintf(f_header
,"}\n");
329 fprintf(f_header
,"#endif\n");
333 /* Check to see if we're adding support for Tcl8 nspaces */
335 fprintf(f_init
,"#if (TCL_MAJOR_VERSION >= 8)\n");
336 fprintf(f_init
,"\t Tcl_Eval(%s,\"namespace eval %s { }\");\n", interp_name
, ns_name
);
337 fprintf(f_init
,"#endif\n");
341 // ---------------------------------------------------------------------
344 // Wrap things up. Close initialization function.
345 // ---------------------------------------------------------------------
347 void TCL8::close(void)
350 // Dump the pointer equivalency table
352 emit_ptr_equivalence(f_init
);
354 // Close the init file and quit
356 fprintf(f_init
,"%s",postinit
.get());
357 fprintf(f_init
,"\t return TCL_OK;\n");
358 fprintf(f_init
,"}\n");
362 // ----------------------------------------------------------------------
363 // TCL8::get_pointer(char *iname, char *srcname, char *src, char *dest,
364 // DataType *t, String &f, char *ret)
366 // iname = name of function or variable
367 // srcname = name of source
368 // src = source variable in wrapper code
369 // dest = destination variable in wrapper code
371 // f = String where output is going to go
372 // ret = Return action
373 // ----------------------------------------------------------------------
375 void TCL8::get_pointer(char *iname
, char *srcname
, char *src
, char *dest
,
376 DataType
*t
, String
&f
, char *ret
) {
378 // Pointers are read as hex-strings with encoded type information
380 f
<< tab4
<< "if ((rettype = SWIG_GetPointerObj(interp," << src
<< ",(void **) &" << dest
<< ",";
382 if (t
->type
== T_VOID
) f
<< "(char *) 0))) {\n";
384 f
<< "\"" << t
->print_mangle() << "\"))) {\n";
386 // Now emit code according to the level of strictness desired
389 case 0: // No type checking
392 case 1: // Warning message only
393 f
<< tab8
<< "fprintf(stderr,\"Warning : type mismatch in " << srcname
394 << " of " << iname
<< ". Expected " << t
->print_mangle()
395 << ", received %s\\n\", rettype);\n"
397 case 2: // Super strict mode.
398 f
<< tab8
<< "Tcl_SetStringObj(tcl_result, \"Type error in " << srcname
<< " of " << iname
399 << ". Expected " << t
->print_mangle() << ", received \", -1);\n"
400 << tab8
<< "Tcl_AppendToObj(tcl_result, rettype, -1);\n"
401 << tab8
<< ret
<< ";\n"
405 fprintf(stderr
,"Unknown strictness level\n");
411 // ----------------------------------------------------------------------
412 // TCL8::create_command(char *cname, char *iname)
414 // Creates a Tcl command from a C function.
415 // ----------------------------------------------------------------------
417 void TCL8::create_command(char *cname
, char *iname
) {
419 char *wname
= name_wrapper(cname
,prefix
);
421 fprintf(f_init
,"\t Tcl_CreateObjCommand(%s, SWIG_prefix \"%s\",%s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n", interp_name
, iname
, wname
);
423 // Add interpreter name to repeatcmd hash table. This hash is used in C++ code
424 // generation to try and find repeated wrapper functions.
426 repeatcmd
.add(iname
,copy_string(wname
));
429 // ----------------------------------------------------------------------
430 // TCL8::create_function(char *name, char *iname, DataType *d, ParmList *l)
432 // Create a function declaration and register it with the interpreter.
433 // ----------------------------------------------------------------------
435 void TCL8::create_function(char *name
, char *iname
, DataType
*d
, ParmList
*l
)
440 char *usage
= 0, *tm
;
445 String cleanup
, outarg
, build
;
449 // Make a wrapper name for this function
451 wname
= name_wrapper(iname
,prefix
);
453 // Now write the wrapper function itself....this is pretty ugly
455 f
.def
<< "static int " << wname
<< "(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {\n";
457 f
.code
<< tab4
<< "clientData = clientData; objv = objv;\n";
459 // Print out variables for storing arguments.
461 pcount
= emit_args(d
, l
, f
);
462 numopt
= l
->numopt();
464 // Create a local variable for holding the interpreter result value
466 f
.add_local("Tcl_Obj *", "tcl_result");
468 // Extract the tcl result object
470 f
.code
<< tab4
<< "tcl_result = Tcl_GetObjResult(interp);\n";
472 // Check the number of arguments
474 usage
= usage_func(iname
,d
,l
); // Create a usage string
475 f
.code
<< tab4
<< "if ((objc < " << (pcount
-numopt
) +1 << ") || (objc > " << l
->numarg()+1 << ")) {\n"
476 << tab8
<< "Tcl_SetStringObj(tcl_result,\"Wrong # args. " << usage
<< "\",-1);\n"
477 << tab8
<< "return TCL_ERROR;\n"
480 // Extract parameters. This case statement should be used to extract
481 // Function parameters. Add more cases if you want to do more.
487 // Produce string representations of the source and target arguments
488 sprintf(source
,"objv[%d]",j
+1);
489 sprintf(target
,"_arg%d",i
);
490 sprintf(argnum
,"%d",j
+1);
492 // See if this argument is being ignored
495 if (j
>= (pcount
-numopt
))
496 f
.code
<< tab4
<< "if (objc >" << j
+1 << ") { \n";
498 if ((tm
= typemap_lookup("in","tcl8",p
->t
,p
->name
,source
,target
,&f
))) {
499 // Yep. Use it instead of the default
500 f
.code
<< tm
<< "\n";
501 f
.code
.replace("$argnum",argnum
);
502 f
.code
.replace("$arg",source
);
504 if (!p
->t
->is_pointer
) {
506 // Extract a parameter by value.
527 f
.add_local("int","tempint");
528 f
.code
<< tab4
<< "if (Tcl_GetIntFromObj(interp,objv[" << j
+1 << "],&tempint) == TCL_ERROR) return TCL_ERROR;\n";
529 f
.code
<< tab4
<< "_arg" << i
<< " = " << p
->t
->print_cast() << " tempint;\n";
536 f
.add_local("double","tempdouble");
537 f
.add_local("Tcl_Obj *", "dupobj");
538 f
.code
<< tab4
<< "dupobj = Tcl_DuplicateObj(objv[" << j
+1 << "]);\n"
539 << tab4
<< "if (Tcl_GetDoubleFromObj(interp,dupobj,&tempdouble) == TCL_ERROR) {\n"
540 << tab8
<< "Tcl_DecrRefCount(dupobj);\n"
541 << tab8
<< "return TCL_ERROR;\n"
543 << tab4
<< "Tcl_DecrRefCount(dupobj);\n"
544 << tab4
<< "_arg" << i
<< " = " << p
->t
->print_cast() << " tempdouble;\n";
547 // A single character
550 f
.add_local("char *","tempstr");
551 f
.add_local("int","templength");
552 f
.code
<< tab4
<< "if ((tempstr = Tcl_GetStringFromObj(objv[" << j
+1 << "],&templength)) == NULL) return TCL_ERROR;\n"
553 << tab4
<< "_arg" << i
<< " = *tempstr;\n";
556 // Void.. Do nothing.
561 // User defined. This is an error.
565 // Unsupported data type
568 fprintf(stderr
,"%s : Line %d: Unable to use type %s as a function argument.\n",
569 input_file
, line_number
, p
->t
->print_type());
574 // Function argument is some sort of pointer
575 // Look for a string. Otherwise, just pull off a pointer.
577 if ((p
->t
->type
== T_CHAR
) && (p
->t
->is_pointer
== 1)) {
578 f
.add_local("int","templength");
579 f
.code
<< tab4
<< "if ((_arg" << i
<< " = Tcl_GetStringFromObj(objv[" << j
+1 << "], &templength)) == NULL) return TCL_ERROR;\n";
582 // Have a generic pointer type here. Read it in as
586 // Try to parse pointer value directly
589 f
.add_local("char *", "tempstr");
590 f
.add_local("int","templength");
591 f
.code
<< tab4
<< "if ((tempstr = Tcl_GetStringFromObj(objv[" << j
+1 << "],&templength)) == NULL) return TCL_ERROR;\n";
592 get_pointer(iname
,arg_temp
,"tempstr",target
,p
->t
,f
.code
,"return TCL_ERROR");
594 sprintf(arg_temp
,"argument %d",j
+1);
595 f
.add_local("char *", "rettype");
596 get_pointer(iname
,arg_temp
,source
,target
,p
->t
,f
.code
,"return TCL_ERROR");
600 if (j
>= (pcount
-numopt
))
601 f
.code
<< tab4
<< "}\n";
606 // Check to see if there is any sort of "build" typemap (highly complicated)
608 if ((tm
= typemap_lookup("build","tcl8",p
->t
,p
->name
,source
,target
))) {
613 // Check to see if there was any sort of a constaint typemap
614 if ((tm
= typemap_lookup("check","tcl8",p
->t
,p
->name
,source
,target
))) {
615 // Yep. Use it instead of the default
616 f
.code
<< tm
<< "\n";
617 f
.code
.replace("$argnum",argnum
);
618 f
.code
.replace("$arg",source
);
621 // Check if there was any cleanup code (save it for later)
622 if ((tm
= typemap_lookup("freearg","tcl8",p
->t
,p
->name
,target
,"tcl_result"))) {
623 // Yep. Use it instead of the default
624 cleanup
<< tm
<< "\n";
625 cleanup
.replace("$argnum",argnum
);
626 cleanup
.replace("$arg",source
);
628 // Look for output arguments
629 if ((tm
= typemap_lookup("argout","tcl8",p
->t
,p
->name
,target
,"tcl_result"))) {
630 outarg
<< tm
<< "\n";
631 outarg
.replace("$argnum",argnum
);
632 outarg
.replace("$arg",source
);
635 p
= l
->get_next(); // Get next parameter and continue
639 // If there was a "build" typemap, we need to go in and perform a serious hack
644 l
->sub_parmnames(build
); // Replace all parameter names
646 for (i
= 0; i
< l
->nparms
; i
++) {
648 if (strlen(p
->name
) > 0) {
649 sprintf(temp1
,"_in_%s", p
->name
);
651 sprintf(temp1
,"_in_arg%d", i
);
653 sprintf(temp2
,"argv[%d]",j
);
654 build
.replaceid(temp1
,temp2
);
661 // Now write code to make the function call
663 emit_func_call(name
,d
,l
,f
);
665 // Extract the tcl result object
667 f
.code
<< tab4
<< "tcl_result = Tcl_GetObjResult(interp);\n";
670 // Return value if necessary
672 if ((tm
= typemap_lookup("out","tcl8",d
,name
,"_result","tcl_result"))) {
673 // Yep. Use it instead of the default
674 f
.code
<< tm
<< "\n";
675 } else if ((d
->type
!= T_VOID
) || (d
->is_pointer
)) {
676 if (!d
->is_pointer
) {
678 // Function returns a "value"
694 f
.code
<< tab4
<< "Tcl_SetIntObj(tcl_result,(long) _result);\n";
697 // Is a single character. Assume we return it as a string
699 f
.code
<< tab4
<< "Tcl_SetStringObj(tcl_result,&_result,1);\n";
702 // Floating point number
705 f
.code
<< tab4
<< "Tcl_SetDoubleObj(tcl_result,(double) _result);\n";
711 // Okay. We're returning malloced memory at this point.
712 // Probably dangerous, but who said safety was a good thing?
714 // f.add_local("char","resultchar[256]");
717 f
.code
<< tab4
<< "SWIG_MakePtr(resultchar, (void *) _result,\"" << d
->print_mangle() << "\");\n"
718 << tab4
<< "Tcl_SetStringObj(tcl_result,resultchar,-1);\n";
720 f
.code
<< tab4
<< "SWIG_SetPointerObj(tcl_result,(void *) _result,\"" << d
->print_mangle() << "\");\n";
727 fprintf(stderr
,"%s : Line %d: Unable to use return type %s in function %s.\n",
728 input_file
, line_number
, d
->print_type(), name
);
733 // Is a pointer return type
735 if ((d
->type
== T_CHAR
) && (d
->is_pointer
== 1)) {
736 // Return a character string
737 f
.code
<< tab4
<< "Tcl_SetStringObj(tcl_result,_result,-1);\n";
740 f
.add_local("char","resultchar[256]");
741 f
.code
<< tab4
<< "SWIG_MakePtr(resultchar, (void *) _result,\"" << d
->print_mangle() << "\");\n"
742 << tab4
<< "Tcl_SetStringObj(tcl_result,resultchar,-1);\n";
745 f
.code
<< tab4
<< "SWIG_SetPointerObj(tcl_result,(void *) _result,\"" << d
->print_mangle() << "\");\n";
751 // Dump output argument code
754 // Dump the argument cleanup code
757 // Look for any remaining cleanup
760 if ((tm
= typemap_lookup("newfree","tcl8",d
,iname
,"_result",""))) {
761 f
.code
<< tm
<< "\n";
765 if ((tm
= typemap_lookup("ret","tcl8",d
,name
,"_result",""))) {
766 // Yep. Use it instead of the default
767 f
.code
<< tm
<< "\n";
770 // Wrap things up (in a manner of speaking)
772 f
.code
<< tab4
<< "return TCL_OK;\n}";
774 // Substitute the cleanup code
775 f
.code
.replace("$cleanup",cleanup
);
776 f
.code
.replace("$name",iname
);
778 // Dump out the function
782 // Now register the function with Tcl
784 fprintf(f_init
,"\t Tcl_CreateObjCommand(%s, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",interp_name
, iname
, wname
);
786 // If there's a documentation entry, produce a usage string
790 static DocEntry
*last_doc_entry
= 0;
792 // Use usage as description
793 doc_entry
->usage
<< usage
;
795 // Set the cinfo field to specific a return type
797 if (last_doc_entry
!= doc_entry
) {
798 doc_entry
->cinfo
<< "returns " << d
->print_type();
799 last_doc_entry
= doc_entry
;
804 // -----------------------------------------------------------------------
805 // TCL8::link_variable(char *name, char *iname, DataType *t,
808 // Create a TCL link to a variable.
809 // -----------------------------------------------------------------------
811 void TCL8::link_variable(char *name
, char *iname
, DataType
*t
)
817 // See if there were any typemaps
819 tm
= typemap_lookup("varin","tcl8",t
,name
,"","");
820 tm1
= typemap_lookup("varout","tcl8",t
,name
,"","");
822 fprintf(stderr
,"%s : Line %d. Warning. varin/varout typemap methods not supported.",
823 input_file
, line_number
);
826 // Check the datatype. Must be a valid Tcl type (there aren't many)
828 if (((t
->type
== T_INT
) && (!t
->is_pointer
)) ||
829 ((t
->type
== T_UINT
) && (!t
->is_pointer
)) ||
830 ((t
->type
== T_SINT
) && (!t
->is_pointer
)) ||
831 ((t
->type
== T_DOUBLE
) && (!t
->is_pointer
)) ||
832 ((t
->type
== T_BOOL
) && (!t
->is_pointer
)) ||
833 ((t
->type
== T_CHAR
) && (t
->is_pointer
== 1))) {
835 // This is a valid TCL type.
837 if (t
->type
== T_UINT
)
838 fprintf(stderr
,"%s : Line %d : ** Warning. Linkage of unsigned type may be unsafe.\n",
839 input_file
, line_number
);
841 // Now add symbol to the TCL interpreter
846 // Is an array. We have to do something different
847 fprintf(f_wrappers
,"static char *tclvar%s = %s;\n",name
,name
);
848 s
<< "(char *) &tclvar" << name
<< ", TCL_LINK_STRING";
850 s
<< "(char *) &" << name
<< ", TCL_LINK_STRING";
857 s
<< "(char *) &" << name
<< ", TCL_LINK_INT";
860 s
<< "(char *) &" << name
<< ", TCL_LINK_DOUBLE";
863 fprintf(f_init
,"Fatal error. Internal error (Tcl:link_variable)\n");
867 if (Status
& STAT_READONLY
)
868 s
<< " | TCL_LINK_READ_ONLY);\n";
872 fprintf(f_init
,"\t Tcl_LinkVar(%s, SWIG_prefix \"%s\", %s",interp_name
, iname
, s
.get());
874 // Make a usage string for it
877 doc_entry
->usage
<< usage_var(iname
,t
);
878 doc_entry
->cinfo
= "";
879 doc_entry
->cinfo
<< "Global : " << t
->print_type() << " " << name
;
883 // Have some sort of "other" type.
884 // We're going to emit some functions to set/get it's value instead
886 emit_set_get(name
,iname
, t
);
888 doc_entry
->cinfo
= "";
889 doc_entry
->cinfo
<< "Global : " << t
->print_type() << " " << iname
;
892 // If shadow classes are enabled and we have a user-defined type
893 // that we know about, create a command for it.
896 if ((t
->type
== T_USER
) && (t
->is_pointer
< 1)) {
897 // See if the datatype is in our hash table
898 if (hash
.lookup(t
->name
)) {
899 // Yep. Try to create a command for it
901 postinit
<< tab4
<< "{\n"
902 << tab8
<< "char cmd[] = \""
903 << (char *) hash
.lookup(t
->name
) << " " << iname
<< " -this ["
904 << iname
<< "_get ]\";\n"
905 << tab8
<< "Tcl_GlobalEval(interp,cmd);\n"
913 // -----------------------------------------------------------------------
914 // TCL8::declare_const(char *name, char *iname, DataType *type, char *value)
916 // Makes a constant. Really just creates a variable and links to it.
917 // Tcl variable linkage allows read-only variables so we'll use that
918 // instead of just creating a Tcl variable.
919 // ------------------------------------------------------------------------
921 void TCL8::declare_const(char *name
, char *, DataType
*type
, char *value
) {
923 int OldStatus
= Status
; // Save old status flags
928 Status
= STAT_READONLY
; // Enable readonly mode.
930 // Make a static variable;
932 sprintf(var_name
,"_wrap_const_%s",name
);
934 // See if there's a typemap
936 if ((type
->type
== T_CHAR
) && (type
->is_pointer
== 1)) {
940 if ((type
->type
== T_CHAR
) && (type
->is_pointer
== 0)) {
944 if ((tm
= typemap_lookup("const","tcl8",type
,name
,rvalue
.get(),name
))) {
945 // Yep. Use it instead of the default
946 fprintf(f_init
,"%s\n",tm
);
949 // Create variable and assign it a value
951 if (type
->is_pointer
== 0) {
953 case T_BOOL
: case T_INT
: case T_SINT
: case T_DOUBLE
:
954 fprintf(f_header
,"static %s %s = %s;\n", type
->print_type(), var_name
, value
);
955 link_variable(var_name
,name
,type
);
962 fprintf(f_header
,"static %s %s = %s;\n", type
->print_type(), var_name
, value
);
963 fprintf(f_header
,"static char *%s_char;\n", var_name
);
965 fprintf(f_init
,"\t %s_char = new char[32];\n",var_name
);
967 fprintf(f_init
,"\t %s_char = (char *) malloc(32);\n",var_name
);
969 fprintf(f_init
,"\t sprintf(%s_char,\"%%ld\", (long) %s);\n", var_name
, var_name
);
970 sprintf(var_name
,"%s_char",var_name
);
971 t
= new DataType(T_CHAR
);
973 link_variable(var_name
,name
,t
);
980 fprintf(f_header
,"static %s %s = %s;\n", type
->print_type(), var_name
, value
);
981 fprintf(f_header
,"static char *%s_char;\n", var_name
);
983 fprintf(f_init
,"\t %s_char = new char[32];\n",var_name
);
985 fprintf(f_init
,"\t %s_char = (char *) malloc(32);\n",var_name
);
987 fprintf(f_init
,"\t sprintf(%s_char,\"%%lu\", (unsigned long) %s);\n", var_name
, var_name
);
988 sprintf(var_name
,"%s_char",var_name
);
989 t
= new DataType(T_CHAR
);
991 link_variable(var_name
,name
,t
);
995 type
->type
= T_DOUBLE
;
996 strcpy(type
->name
,"double");
997 fprintf(f_header
,"static %s %s = %s (%s);\n", type
->print_type(), var_name
, type
->print_cast(), value
);
998 link_variable(var_name
,name
,type
);
1003 fprintf(f_header
,"static %s %s = \"%s\";\n", type
->print_type(), var_name
, value
);
1004 link_variable(var_name
,name
,type
);
1008 fprintf(stderr
,"%s : Line %d. Unsupported constant value.\n", input_file
, line_number
);
1012 // Have some sort of pointer value here
1013 if ((type
->type
== T_CHAR
) && (type
->is_pointer
== 1)) {
1015 fprintf(f_header
,"static %s %s = \"%s\";\n", type
->print_type(), var_name
, value
);
1016 link_variable(var_name
,name
,type
);
1018 // Something else. Some sort of pointer value
1019 fprintf(f_header
,"static %s %s = %s;\n", type
->print_type(), var_name
, value
);
1020 fprintf(f_header
,"static char *%s_char;\n", var_name
);
1022 fprintf(f_init
,"\t %s_char = new char[%d];\n",var_name
,(int) strlen(type
->print_mangle())+ 20);
1024 fprintf(f_init
,"\t %s_char = (char *) malloc(%d);\n",var_name
, (int) strlen(type
->print_mangle())+ 20);
1026 t
= new DataType(T_CHAR
);
1028 fprintf(f_init
,"\t SWIG_MakePtr(%s_char, (void *) %s,\"%s\");\n",
1029 var_name
, var_name
, type
->print_mangle());
1030 sprintf(var_name
,"%s_char",var_name
);
1031 link_variable(var_name
,name
,t
);
1037 // Create a documentation entry for this
1040 doc_entry
->usage
= ""; // Destroy any previous information from linking
1041 doc_entry
->usage
<< usage_const(name
, type
, value
);
1042 doc_entry
->cinfo
= "";
1043 doc_entry
->cinfo
<< "Constant : " << type
->print_type();
1049 // ----------------------------------------------------------------------
1050 // TCL8::usage_var(char *iname, DataType *t, char **s)
1052 // Produces a usage string for a tcl variable. Stores it in s
1053 // ----------------------------------------------------------------------
1055 char *TCL8::usage_var(char *iname
, DataType
*t
) {
1057 static char temp
[1024];
1060 sprintf(temp
,"$%s%s", prefix
, iname
);
1062 sprintf(temp
,"%s::%s", ns_name
, iname
);
1064 if (!(((t
->type
== T_INT
) && (!t
->is_pointer
)) ||
1065 ((t
->type
== T_UINT
) && (!t
->is_pointer
)) ||
1066 ((t
->type
== T_DOUBLE
) && (!t
->is_pointer
)) ||
1067 ((t
->type
== T_BOOL
) && (!t
->is_pointer
)) ||
1068 ((t
->type
== T_CHAR
) && (t
->is_pointer
)))) {
1069 /* We emitted a pair of set/get functions instead. Doc will be generated for that */
1077 // ---------------------------------------------------------------------------
1078 // char *TCL8::usage_string(char *iname, DataType *t, ParmList *l),
1080 // Generates a generic usage string for a Tcl function.
1081 // ---------------------------------------------------------------------------
1083 char * TCL8::usage_string(char *iname
, DataType
*, ParmList
*l
) {
1087 int i
, numopt
,pcount
;
1090 temp
<< iname
<< " ";
1092 /* Now go through and print parameters */
1095 numopt
= l
->numopt();
1099 // Only print an argument if not ignored
1101 if (!typemap_check("ignore","tcl8",p
->t
,p
->name
)) {
1102 if (i
>= (pcount
-numopt
))
1105 /* If parameter has been named, use that. Otherwise, just print a type */
1107 if ((p
->t
->type
!= T_VOID
) || (p
->t
->is_pointer
)) {
1108 if (strlen(p
->name
) > 0) {
1112 temp
<< "{ " << p
->t
->print_type() << " }";
1115 if (i
>= (pcount
-numopt
))
1125 // ---------------------------------------------------------------------------
1126 // char *TCL8::usage_func(char *iname, DataType *t, ParmList *l),
1128 // Produces a usage string for a function in Tcl
1129 // ---------------------------------------------------------------------------
1131 char * TCL8::usage_func(char *iname
, DataType
*t
, ParmList
*l
) {
1136 temp
<< ns_name
<< "::" << iname
;
1138 temp
<< prefix
<< iname
;
1140 return usage_string(temp
,t
,l
);
1143 // -----------------------------------------------------------------
1144 // TCL8::usage_const(char *name, DataType *type, char *value)
1147 // Makes a usage string and returns it
1148 // -----------------------------------------------------------------
1150 char *TCL8::usage_const(char *name
, DataType
*, char *value
) {
1154 temp
<< ns_name
<< "::" << name
<< " = " << value
;
1156 temp
<< "$" << prefix
<< name
<< " = " << value
;
1161 // -------------------------------------------------------------------
1162 // TCL8::add_native(char *name, char *funcname)
1164 // This adds an already written Tcl wrapper function to our
1165 // initialization function.
1166 // -------------------------------------------------------------------
1169 void TCL8::add_native(char *name
, char *funcname
) {
1171 fprintf(f_init
,"\t Tcl_CreateCommand(%s, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",interp_name
, name
, funcname
);
1175 doc_entry
->usage
<< ns_name
<< "::" << name
<< " args";
1177 doc_entry
->usage
<< prefix
<< name
<< " args";
1179 doc_entry
->cinfo
<< "Native method : " << funcname
;
1184 // -------------------------------------------------------------------
1185 // TCL8::pragma(char *lname, char *name, char *value)
1188 // --------------------------------------------------------------------
1190 void TCL8::pragma(char *, char *, char *) {
1194 // ---------------------------------------------------------------------
1197 // The following functions provide some support for C++ classes and
1199 // ---------------------------------------------------------------------
1201 void TCL8::cpp_open_class(char *classname
, char *rename
, char *ctype
, int strip
) {
1203 this->Language::cpp_open_class(classname
,rename
,ctype
,strip
);
1211 config_options
= "";
1214 have_constructor
= 0;
1215 have_destructor
= 0;
1221 class_name
= copy_string(rename
);
1223 class_name
= copy_string(classname
);
1225 base_class
= (char *) 0;
1227 class_type
= new char[strlen(ctype
)+2];
1228 sprintf(class_type
,"%s ", ctype
);
1232 real_classname
= copy_string(classname
);
1236 void TCL8::cpp_close_class() {
1240 this->Language::cpp_close_class();
1244 sprintf(t
->name
,"%s%s", class_type
, real_classname
);
1248 // Note : The object oriented interface is defined by three files
1249 // delcmd8.swg - Object deletion wrapper
1250 // methodcmd8.swg - Method invocation command
1251 // objcmd8.swg - Command to create a new object
1253 // These files are located in the SWIG library. This module
1254 // grabs the files and performs marker replacements to
1255 // build the wrapper function.
1257 // Generate a Tcl function for object destruction
1259 if (have_destructor
) {
1263 // Dump out method code
1266 // Dump out object creation command
1269 // Now perform marker replacements
1270 code
.replace("@CLASS@",class_name
);
1272 temp
<< name_destroy(class_name
);
1273 code
.replace("@DESTRUCTOR@",temp
);
1274 code
.replace("@CLASSTYPE@",t
->print_type());
1275 "configure " >> methodnames
;
1276 "cget " >> methodnames
;
1277 code
.replace("@METHODLIST@", methodnames
);
1278 code
.replace("@CLASSMANGLE@",t
->print_mangle());
1279 code
.replace("@METHODS@",methods
);
1280 code
.replace("@CONFIGMETHODS@",config
);
1281 code
.replace("@CGETMETHODS@",cget
);
1282 if (have_constructor
) {
1284 temp
<< name_wrapper(name_construct(class_name
),prefix
);
1288 code
.replace("@TCLCONSTRUCTOR@",temp
);
1289 code
.replace("@CONFIGLIST@",config_options
);
1290 code
.replace("@CGETLIST@",options
);
1291 if (have_destructor
) {
1297 code
.replace("@TCLDESTRUCTOR@",temp
);
1298 fprintf(f_wrappers
,"%s\n", code
.get());
1300 fprintf(f_init
,"\t Tcl_CreateObjCommand(interp,SWIG_prefix \"%s\",Tcl%sCmd, (ClientData) NULL, NULL);\n", class_name
, class_name
);
1304 void TCL8::cpp_member_func(char *name
, char *iname
, DataType
*t
, ParmList
*l
) {
1310 this->Language::cpp_member_func(name
,iname
,t
,l
);
1318 // Add stubs for this member to our class handler function
1321 methods
<< tab4
<< "else ";
1326 temp
<< name_member(realname
,class_name
);
1327 rname
= (char *) repeatcmd
.lookup(temp
);
1329 rname
= name_wrapper(temp
.get(),prefix
);
1331 methods
<< "if (strcmp(_str,\"" << realname
<< "\") == 0) {\n"
1332 << tab4
<< tab4
<< "cmd = " << rname
<< ";\n"
1336 methodnames
<< realname
<< " ";
1339 doc_entry
->usage
= "";
1340 doc_entry
->usage
<< usage_string(realname
,t
,l
);
1345 void TCL8::cpp_variable(char *name
, char *iname
, DataType
*t
) {
1350 this->Language::cpp_variable(name
, iname
, t
);
1358 char *bc
= class_name
;
1360 // Write config code
1362 if (!(Status
& STAT_READONLY
)) {
1364 config
<< tab8
<< tab8
;
1369 // Try to figure out if there is already a wrapper for this
1372 temp
<< name_set(name_member(realname
,bc
));
1373 rname
= (char *) repeatcmd
.lookup(temp
);
1375 rname
= name_wrapper(temp
.get(),prefix
);
1377 config
<< "if (strcmp(_str,\"-" << realname
<< "\") == 0) {\n"
1378 << tab8
<< tab8
<< tab4
<< "cmd = " << rname
<< ";\n"
1379 << tab8
<< tab8
<< "} ";
1387 cget
<< tab8
<< tab8
;
1393 // Try to figure out if there is a wrapper for this function
1395 temp
<< name_get(name_member(realname
,bc
));
1396 rname
= (char *) repeatcmd
.lookup(temp
);
1398 rname
= name_wrapper(temp
.get(),prefix
);
1400 cget
<< "if (strcmp(_str,\"-" << realname
<< "\") == 0) {\n"
1401 << tab8
<< tab8
<< tab4
<< "cmd = " << rname
<< ";\n"
1402 << tab8
<< tab8
<< "} ";
1405 options
<< "-" << realname
<< " ";
1406 if (!(Status
& STAT_READONLY
)) {
1407 config_options
<< "-" << realname
<< " ";
1410 doc_entry
->usage
= "";
1411 doc_entry
->usage
<< "-" << realname
<< "\n";
1416 void TCL8::cpp_constructor(char *name
, char *iname
, ParmList
*l
) {
1417 this->Language::cpp_constructor(name
,iname
,l
);
1420 if ((!have_constructor
) && (doc_entry
)) {
1421 doc_entry
->usage
= "";
1422 doc_entry
->usage
<< class_name
<< usage_string(" name",0,l
);
1424 have_constructor
= 1;
1427 void TCL8::cpp_destructor(char *name
, char *newname
) {
1428 this->Language::cpp_destructor(name
,newname
);
1430 if (!have_destructor
) {
1432 doc_entry
->usage
= "rename obj {}";
1435 have_destructor
= 1;
1439 void TCL8::cpp_inherit(char **baseclass
, int) {
1440 this->Language::cpp_inherit(baseclass
);
1443 void TCL8::cpp_declare_const(char *name
, char *iname
, DataType
*type
, char *value
) {
1444 this->Language::cpp_declare_const(name
,iname
,type
,value
);
1447 // --------------------------------------------------------------------------------
1448 // TCL8::add_typedef(DataType *t, char *name)
1450 // This is called whenever a typedef is encountered. When shadow classes are
1451 // used, this function lets us discovered hidden uses of a class. For example :
1457 // typedef FooBar *FooBarPtr;
1459 // --------------------------------------------------------------------------------
1461 void TCL8::add_typedef(DataType
*t
, char *name
) {
1463 if (!shadow
) return;
1465 // First check to see if there aren't too many pointers
1467 if (t
->is_pointer
> 1) return;
1468 if (hash
.lookup(name
)) return; // Already added
1470 // Now look up the datatype in our shadow class hash table
1472 if (hash
.lookup(t
->name
)) {
1474 // Yep. This datatype is in the hash
1475 // Put this types 'new' name into the hash
1476 hash
.add(name
,copy_string((char *) hash
.lookup(t
->name
)));
1480 // -----------------------------------------------------------------------
1481 // TCL8::cpp_class_decl(char *name, char *rename, char *type)
1483 // Treatment of an empty class definition. Used to handle
1484 // shadow classes across modules.
1485 // -----------------------------------------------------------------------
1487 void TCL8::cpp_class_decl(char *name
, char *rename
, char *type
) {
1489 this->Language::cpp_class_decl(name
,rename
, type
);
1492 hash
.add(name
,copy_string(rename
));
1493 // Add full name of datatype to the hash table
1494 if (strlen(type
) > 0) {
1495 sprintf(temp
,"%s %s", type
, name
);
1496 hash
.add(temp
,copy_string(rename
));