]>
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
));