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