]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wxSWIG/Modules/tcl8.cxx
Since I have made several changes to SWIG over the years to accomodate
[wxWidgets.git] / wxPython / wxSWIG / Modules / tcl8.cxx
diff --git a/wxPython/wxSWIG/Modules/tcl8.cxx b/wxPython/wxSWIG/Modules/tcl8.cxx
new file mode 100644 (file)
index 0000000..f0911d9
--- /dev/null
@@ -0,0 +1,1499 @@
+/*******************************************************************************
+ * Simplified Wrapper and Interface Generator  (SWIG)
+ * 
+ * Author : David Beazley
+ *
+ * Department of Computer Science        
+ * University of Chicago
+ * 1100 E 58th Street
+ * Chicago, IL  60637
+ * beazley@cs.uchicago.edu
+ *
+ * Please read the file LICENSE for the copyright and terms by which SWIG
+ * can be used and distributed.
+ *******************************************************************************/
+
+/***********************************************************************
+ * $Header$
+ *
+ * tcl8.cxx
+ *
+ * Module for creating Tcl 8.0 native wrapper functions.  Older SWIG
+ * modules will work with Tcl 8.0, but this one provides a significant
+ * boost in performance.
+ ***********************************************************************/
+
+#include "swig.h"
+#include "tcl8.h"
+#include <ctype.h>
+
+static char *Tcl_config="swigtcl.swg";
+static char *usage = "\
+Tcl 8.0 Options (available with -tcl)\n\
+     -module name    - Set name of module\n\
+     -prefix name    - Set a prefix to be appended to all names\n\
+     -namespace      - Build module into a Tcl 8 namespace. \n\
+     -noobject       - Omit code for object oriented interface.\n\
+     -old            - Use old SWIG interface (same as -noobject).\n\n";
+
+static char *ns_name = 0;
+
+static String mod_init;
+static String mod_extern;
+
+// ---------------------------------------------------------------------
+// TCL8::parse_args(int argc, char *argv[])
+//
+// Parse tcl specific command line options
+// ---------------------------------------------------------------------
+
+void TCL8::parse_args(int argc, char *argv[]) {
+  
+  int i = 1;
+  sprintf(LibDir,"%s",tcl_path);
+
+  // Look for certain command line options
+
+  for (i = 1; i < argc; i++) {
+      if (argv[i]) {
+         if (strcmp(argv[i],"-prefix") == 0) {
+           if (argv[i+1]) {
+             prefix = new char[strlen(argv[i+1])+2];
+             strcpy(prefix, argv[i+1]);
+             mark_arg(i);
+             mark_arg(i+1);
+             i++;
+           } else {
+             arg_error();
+           }
+         } else if (strcmp(argv[i],"-module") == 0) {
+           if (argv[i+1]) {
+             set_module(argv[i+1],0);
+             mark_arg(i);
+             mark_arg(i+1);
+             i++;
+           } else {
+             arg_error();
+           }
+         } else if (strcmp(argv[i],"-namespace") == 0) {
+           nspace = 1;
+           mark_arg(i);
+         } else if (strcmp(argv[i],"-old") == 0) {
+           shadow = 0;
+           mark_arg(i);
+          } else if (strcmp(argv[i],"-noobject") == 0) {
+           shadow = 0;
+           mark_arg(i);
+         } else if (strcmp(argv[i],"-help") == 0) {
+           fputs(usage,stderr);
+         }
+      }
+  }
+
+  // If a package has been specified, make sure it ends with a '_'
+
+  if (prefix) {
+    ns_name = copy_string(prefix);
+    if (prefix[strlen(prefix)] != '_') {
+      prefix[strlen(prefix)+1] = 0;
+      prefix[strlen(prefix)] = '_';
+    }
+  } else 
+    prefix = "";
+
+  // Create a symbol SWIGTCL
+
+  add_symbol("SWIGTCL",0,0);
+  add_symbol("SWIGTCL8",0,0);
+
+  // Set name of typemaps
+
+  typemap_lang = "tcl8";
+
+  // Attempt to load up the C++ configuration files
+
+  get_file("delcmd8.swg",delcmd);
+  get_file("methodcmd8.swg",methodcmd);
+  get_file("objcmd8.swg",objcmd);
+
+}
+
+// ---------------------------------------------------------------------
+// void TCL8::parse()
+//
+// Start parsing an interface file for Tcl.
+// ---------------------------------------------------------------------
+
+void TCL8::parse() {
+
+  fprintf(stderr,"Making wrappers for Tcl 8.x\n");
+
+  // Print out TCL specific headers
+  
+  headers();
+  
+  // Run the parser
+  
+  yyparse();
+
+}
+
+// ---------------------------------------------------------------------
+// TCL8::set_module(char *mod_name,char **mod_list)
+//
+// Sets the module name.
+// Does nothing if it's already set (so it can be overridden as a command
+// line option).
+//
+// mod_list is a NULL-terminated list of additional modules.  This
+// is really only useful when building static executables and other
+// things.
+//----------------------------------------------------------------------
+
+void TCL8::set_module(char *mod_name, char **mod_list) {
+
+  char temp[256], *c;
+  int  i;
+
+  if (module) return;
+  
+  module = new char[strlen(mod_name)+1];
+  strcpy(module,mod_name);
+
+  // Fix capitalization for Tcl 
+
+  c = module;
+  while (*c) {
+    *c = (char) tolower(*c);
+    c++;
+  }
+
+  // Now create an initialization function
+
+  sprintf(temp,"%s_Init", module);
+  init_name = new char[strlen(temp) + 1];
+  strcpy(init_name, temp);
+  *init_name = toupper(*init_name);
+
+  if (!ns_name) ns_name = copy_string(module);
+
+  // If namespaces have been specified, set the prefix to the module name
+
+  if ((nspace) && (strlen(prefix) < 1)) {
+    prefix = new char[strlen(module)+2];
+    strcpy(prefix,module);
+    prefix[strlen(module)] = '_';
+    prefix[strlen(module)+1] = 0;
+  }
+
+  // If additional modules have been specified, create some code for
+  // initializing them.
+
+  if (mod_list) {
+    i = 0;
+    while (mod_list[i]) {
+      c = mod_list[i];
+      while (*c) {
+       *c = (char) tolower(*c);
+       c++;
+      }
+      sprintf(temp,"%s_Init",mod_list[i]);
+      temp[0] = toupper(temp[0]);
+      
+      // Dump out some initialization code
+      
+      mod_init << tab4 << "if (" << temp << "(" << interp_name << ") == TCL_ERROR) {\n"
+              << tab8 << "return TCL_ERROR;\n"
+              << tab4 << "}\n\n";
+      mod_extern << "extern int " << temp << "(Tcl_Interp *);\n";
+      i++;
+    }
+  }
+}
+
+
+// ---------------------------------------------------------------------
+// TCL8::set_init(char *iname)
+//
+// Sets the initialization function name.
+// Does nothing if it's already set
+//
+//----------------------------------------------------------------------
+
+void TCL8::set_init(char *iname) {
+
+  if (init_name) return;
+  init_name = new char[strlen(iname)+1];
+  strcpy(init_name, iname);
+
+}
+
+// ---------------------------------------------------------------------
+// TCL8::headers(void)
+//
+// Generate the appropriate header files for TCL interface.
+// ----------------------------------------------------------------------
+
+void TCL8::headers(void)
+{
+
+  emit_banner(f_header);
+  fprintf(f_header,"/* Implementation : TCL 8.0 */\n\n");
+  fprintf(f_header,"#include <tcl.h>\n");
+  fprintf(f_header,"#include <string.h>\n");
+  fprintf(f_header,"#include <stdlib.h>\n");
+  fprintf(f_header,"#define SWIGTCL\n");
+  fprintf(f_header,"#define SWIGTCL8\n");
+  
+  // Include a Tcl configuration file for Unix,Mac,Wintel.
+
+  if (NoInclude) {
+    fprintf(f_header,"#define SWIG_NOINCLUDE\n");
+  }
+
+  if (insert_file("swigtcl8.swg",f_header) == -1) {
+    fprintf(stderr,"SWIG : Fatal error. Unable to locate 'swigtcl8.swg' in SWIG library.\n");
+    SWIG_exit(1);
+  }
+}
+
+// --------------------------------------------------------------------
+// TCL8::initialize(void)
+//
+// Produces an initialization function.   Assumes that the init function
+// name has already been specified.
+// ---------------------------------------------------------------------
+
+void TCL8::initialize() 
+{
+
+  if ((!ns_name) && (nspace)) {
+    fprintf(stderr,"Tcl error.   Must specify a namespace.\n");
+    SWIG_exit(1);
+  }
+
+  if (!init_name) {
+    init_name = "Swig_Init";
+    fprintf(stderr,"SWIG : *** Warning. No module name specified.\n");
+  }
+
+  fprintf(f_header,"#define SWIG_init    %s\n", init_name);
+  if (!module) module = "swig";
+  fprintf(f_header,"#define SWIG_name    \"%s\"\n", module);
+  if (nspace) {
+    fprintf(f_header,"#define SWIG_prefix  \"%s::\"\n", ns_name);
+    fprintf(f_header,"#define SWIG_namespace \"%s\"\n\n", ns_name);
+  } else {
+    fprintf(f_header,"#define SWIG_prefix  \"%s\"\n", prefix);
+    fprintf(f_header,"#define SWIG_namespace \"\"\n\n");
+  }
+  fprintf(f_header,"#ifdef __cplusplus\n");
+  fprintf(f_header,"extern \"C\" {\n");
+  fprintf(f_header,"#endif\n");
+  fprintf(f_header,"#ifdef MAC_TCL\n");
+  fprintf(f_header,"#pragma export on\n");
+  fprintf(f_header,"#endif\n");
+  fprintf(f_header,"SWIGEXPORT(int) %s(Tcl_Interp *);\n", init_name);
+  fprintf(f_header,"#ifdef MAC_TCL\n");
+  fprintf(f_header,"#pragma export off\n");
+  fprintf(f_header,"#endif\n");
+  fprintf(f_header,"#ifdef __cplusplus\n");
+  fprintf(f_header,"}\n");
+  fprintf(f_header,"#endif\n");
+  
+
+  fprintf(f_init,"SWIGEXPORT(int) %s(Tcl_Interp *%s) {\n", init_name, interp_name);
+  if (nspace) {
+    fprintf(f_init,"#ifdef ITCL_NAMESPACES\n");
+    fprintf(f_init,"\t Itcl_Namespace spaceId;\n");
+    fprintf(f_init,"#endif\n");
+  }
+  
+  fprintf(f_init,"\t if (%s == 0) \n", interp_name);
+  fprintf(f_init,"\t\t return TCL_ERROR;\n");
+
+  /* Set up SwigPtrType table */
+
+  fprintf(f_init,"\t SWIG_RegisterType();\n");
+
+  /* Check to see if other initializations need to be performed */
+
+  if (strlen(mod_extern.get())) {
+    fprintf(f_init,"%s\n",mod_init.get());
+    fprintf(f_header,"#ifdef __cplusplus\n");
+    fprintf(f_header,"extern \"C\" {\n");
+    fprintf(f_header,"#endif\n");
+    fprintf(f_header,"%s\n",mod_extern.get());
+    fprintf(f_header,"#ifdef __cplusplus\n");
+    fprintf(f_header,"}\n");
+    fprintf(f_header,"#endif\n");
+  }
+
+
+  /* Check to see if we're adding support for Tcl8 nspaces */
+  if (nspace) {
+    fprintf(f_init,"#if (TCL_MAJOR_VERSION >= 8)\n");
+    fprintf(f_init,"\t Tcl_Eval(%s,\"namespace eval %s { }\");\n", interp_name, ns_name);
+    fprintf(f_init,"#endif\n");
+  }
+}
+
+// ---------------------------------------------------------------------
+// TCL8::close(void)
+//
+// Wrap things up.  Close initialization function.
+// ---------------------------------------------------------------------
+
+void TCL8::close(void)
+{
+
+  // Dump the pointer equivalency table
+
+  emit_ptr_equivalence(f_init);
+
+  // Close the init file and quit
+
+  fprintf(f_init,"%s",postinit.get());
+  fprintf(f_init,"\t return TCL_OK;\n");
+  fprintf(f_init,"}\n");
+
+}
+
+// ----------------------------------------------------------------------
+// TCL8::get_pointer(char *iname, char *srcname, char *src, char *dest,
+//                  DataType *t, String &f, char *ret)
+//
+// iname     = name of function or variable
+// srcname   = name of source
+// src       = source variable in wrapper code
+// dest      = destination variable in wrapper code
+// t         = Datatype 
+// f         = String where output is going to go
+// ret       = Return action
+// ----------------------------------------------------------------------
+
+void TCL8::get_pointer(char *iname, char *srcname, char *src, char *dest,
+                     DataType *t, String &f, char *ret) {
+
+  // Pointers are read as hex-strings with encoded type information
+  
+  f << tab4 << "if ((rettype = SWIG_GetPointerObj(interp," << src << ",(void **) &" << dest << ",";
+
+  if (t->type == T_VOID) f << "(char *) 0))) {\n";
+  else 
+    f << "\"" << t->print_mangle() << "\"))) {\n";
+
+  // Now emit code according to the level of strictness desired
+
+  switch(TypeStrict) {
+  case 0: // No type checking
+    f << tab4 << "}\n";
+    break;
+  case 1: // Warning message only
+    f << tab8 << "fprintf(stderr,\"Warning : type mismatch in " << srcname 
+      << " of " << iname << ". Expected " << t->print_mangle() 
+      << ", received %s\\n\", rettype);\n"
+      << tab4 << "}\n";
+  case 2: // Super strict mode.
+    f << tab8 << "Tcl_SetStringObj(tcl_result, \"Type error in " << srcname << " of " << iname
+      << ". Expected " << t->print_mangle() << ", received \", -1);\n"
+      << tab8 << "Tcl_AppendToObj(tcl_result, rettype, -1);\n"
+      << tab8 << ret << ";\n"
+      << tab4 << "}\n";
+    break;
+  default :
+    fprintf(stderr,"Unknown strictness level\n");
+    break;
+  }
+}
+
+
+// ----------------------------------------------------------------------
+// TCL8::create_command(char *cname, char *iname)
+//
+// Creates a Tcl command from a C function.
+// ----------------------------------------------------------------------
+
+void TCL8::create_command(char *cname, char *iname) {
+
+  char *wname = name_wrapper(cname,prefix);
+
+  fprintf(f_init,"\t Tcl_CreateObjCommand(%s, SWIG_prefix \"%s\",%s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n", interp_name, iname, wname);
+
+  // Add interpreter name to repeatcmd hash table.  This hash is used in C++ code
+  // generation to try and find repeated wrapper functions.
+
+  repeatcmd.add(iname,copy_string(wname));
+}
+
+// ----------------------------------------------------------------------
+// TCL8::create_function(char *name, char *iname, DataType *d, ParmList *l)
+//
+// Create a function declaration and register it with the interpreter.
+// ----------------------------------------------------------------------
+
+void TCL8::create_function(char *name, char *iname, DataType *d, ParmList *l)
+{
+  Parm            *p;
+  int              pcount,i,j;
+  char            *wname;
+  char            *usage = 0, *tm;
+  char             source[64];
+  char             target[64];
+  char             argnum[32];
+  WrapperFunction  f;
+  String           cleanup, outarg, build;
+  int              numopt= 0;
+  int              have_build = 0;
+
+  // Make a wrapper name for this function
+
+  wname = name_wrapper(iname,prefix);
+
+  // Now write the wrapper function itself....this is pretty ugly
+
+  f.def << "static int " << wname << "(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {\n";
+
+  f.code << tab4 << "clientData = clientData; objv = objv;\n";
+
+  // Print out variables for storing arguments.
+
+  pcount = emit_args(d, l, f);
+  numopt = l->numopt();
+
+  // Create a local variable for holding the interpreter result value
+
+  f.add_local("Tcl_Obj *", "tcl_result");
+
+  // Extract the tcl result object
+
+  f.code << tab4 << "tcl_result = Tcl_GetObjResult(interp);\n";
+
+  // Check the number of arguments
+
+  usage = usage_func(iname,d,l);       // Create a usage string
+  f.code << tab4 << "if ((objc < " << (pcount-numopt) +1 << ") || (objc > " << l->numarg()+1 << ")) {\n"
+        << tab8 << "Tcl_SetStringObj(tcl_result,\"Wrong # args. " << usage << "\",-1);\n"
+        << tab8 << "return TCL_ERROR;\n"
+        << tab4 << "}\n";
+
+  // Extract parameters.    This case statement should be used to extract
+  // Function parameters.   Add more cases if you want to do more.
+
+  i = 0;
+  j = 0;
+  p = l->get_first();
+  while (p != 0) {
+    // Produce string representations of the source and target arguments
+    sprintf(source,"objv[%d]",j+1);
+    sprintf(target,"_arg%d",i);
+    sprintf(argnum,"%d",j+1);
+
+    // See if this argument is being ignored
+    
+    if (!p->ignore) {
+      if (j >= (pcount-numopt)) 
+       f.code << tab4 << "if (objc >" << j+1 << ") { \n";
+
+      if ((tm = typemap_lookup("in","tcl8",p->t,p->name,source,target,&f))) {
+       // Yep.  Use it instead of the default
+       f.code << tm << "\n";
+       f.code.replace("$argnum",argnum);
+       f.code.replace("$arg",source);
+      } else {
+       if (!p->t->is_pointer) {
+       
+         // Extract a parameter by value.
+       
+         switch(p->t->type) {
+           
+           // Signed Integers
+         
+         case T_BOOL:
+         case T_INT:
+         case T_SINT:
+         case T_SHORT:
+         case T_SSHORT:
+         case T_LONG:
+         case T_SLONG:
+         case T_SCHAR:
+           
+           // Unsigned integers
+         
+         case T_UINT:
+         case T_USHORT:
+         case T_ULONG:
+         case T_UCHAR:
+           f.add_local("int","tempint");
+           f.code << tab4 << "if (Tcl_GetIntFromObj(interp,objv[" << j+1 << "],&tempint) == TCL_ERROR) return TCL_ERROR;\n";
+           f.code << tab4 << "_arg" << i << " = " << p->t->print_cast() << " tempint;\n";
+         break;
+         
+         // Floating point
+
+         case T_FLOAT:
+         case T_DOUBLE:
+           f.add_local("double","tempdouble");
+           f.add_local("Tcl_Obj *", "dupobj");
+           f.code << tab4 << "dupobj = Tcl_DuplicateObj(objv[" << j+1 << "]);\n"
+                  << tab4 << "if (Tcl_GetDoubleFromObj(interp,dupobj,&tempdouble) == TCL_ERROR) {\n"
+                  << tab8 << "Tcl_DecrRefCount(dupobj);\n"
+                  << tab8 << "return TCL_ERROR;\n"
+                  << tab4 << "}\n"
+                  << tab4 << "Tcl_DecrRefCount(dupobj);\n"
+                  << tab4 << "_arg" << i << " = " << p->t->print_cast() << " tempdouble;\n";
+           break;
+         
+           // A single character
+           
+         case T_CHAR :
+           f.add_local("char *","tempstr");
+           f.add_local("int","templength");
+           f.code << tab4 << "if ((tempstr = Tcl_GetStringFromObj(objv[" << j+1 << "],&templength)) == NULL) return TCL_ERROR;\n"
+                  << tab4 << "_arg" << i << " = *tempstr;\n";
+           break;
+         
+           // Void.. Do nothing.
+         
+         case T_VOID :
+           break;
+           
+           // User defined.   This is an error.
+           
+         case T_USER:
+           
+           // Unsupported data type
+           
+         default :
+           fprintf(stderr,"%s : Line %d: Unable to use type %s as a function argument.\n",
+                   input_file, line_number, p->t->print_type());
+           break;
+         }
+       } else {
+         
+         // Function argument is some sort of pointer
+         // Look for a string.   Otherwise, just pull off a pointer.
+         
+         if ((p->t->type == T_CHAR) && (p->t->is_pointer == 1)) {
+           f.add_local("int","templength");
+           f.code << tab4 << "if ((_arg" << i << " = Tcl_GetStringFromObj(objv[" << j+1 << "], &templength)) == NULL) return TCL_ERROR;\n";
+         } else {
+         
+           // Have a generic pointer type here.    Read it in as
+           // a hex-string
+           char arg_temp[256];
+           
+           // Try to parse pointer value directly
+           
+#ifdef OLD
+           f.add_local("char *", "tempstr");
+           f.add_local("int","templength");
+           f.code << tab4 << "if ((tempstr = Tcl_GetStringFromObj(objv[" << j+1 << "],&templength)) == NULL) return TCL_ERROR;\n";
+           get_pointer(iname,arg_temp,"tempstr",target,p->t,f.code,"return TCL_ERROR");
+#endif
+           sprintf(arg_temp,"argument %d",j+1);
+           f.add_local("char *", "rettype");
+           get_pointer(iname,arg_temp,source,target,p->t,f.code,"return TCL_ERROR");
+         }
+       }
+      }
+      if (j >= (pcount-numopt))
+       f.code << tab4 << "}\n";
+      j++;
+    }
+
+
+    // Check to see if there is any sort of "build" typemap (highly complicated)
+
+    if ((tm = typemap_lookup("build","tcl8",p->t,p->name,source,target))) {
+      build << tm << "\n";
+      have_build = 1;
+    }
+
+    // Check to see if there was any sort of a constaint typemap
+    if ((tm = typemap_lookup("check","tcl8",p->t,p->name,source,target))) {
+      // Yep.  Use it instead of the default
+      f.code << tm << "\n";
+      f.code.replace("$argnum",argnum);
+      f.code.replace("$arg",source);
+    }
+
+    // Check if there was any cleanup code (save it for later)
+    if ((tm = typemap_lookup("freearg","tcl8",p->t,p->name,target,"tcl_result"))) {
+      // Yep.  Use it instead of the default
+      cleanup << tm << "\n";
+      cleanup.replace("$argnum",argnum);
+      cleanup.replace("$arg",source);
+    }
+    // Look for output arguments
+    if ((tm = typemap_lookup("argout","tcl8",p->t,p->name,target,"tcl_result"))) {
+      outarg << tm << "\n";
+      outarg.replace("$argnum",argnum);
+      outarg.replace("$arg",source);
+    }
+    i++;
+    p = l->get_next();   // Get next parameter and continue
+  }
+
+
+  // If there was a "build" typemap, we need to go in and perform a serious hack
+  
+  if (have_build) {
+    char temp1[32];
+    char temp2[256];
+    l->sub_parmnames(build);            // Replace all parameter names
+    j = 1;
+    for (i = 0; i < l->nparms; i++) {
+      p = l->get(i);
+      if (strlen(p->name) > 0) {
+       sprintf(temp1,"_in_%s", p->name);
+      } else {
+       sprintf(temp1,"_in_arg%d", i);
+      }
+      sprintf(temp2,"argv[%d]",j);
+      build.replaceid(temp1,temp2);
+      if (!p->ignore) 
+       j++;
+    }
+    f.code << build;
+  }
+
+  // Now write code to make the function call
+
+  emit_func_call(name,d,l,f);
+
+  // Extract the tcl result object
+
+  f.code << tab4 << "tcl_result = Tcl_GetObjResult(interp);\n";
+
+
+  // Return value if necessary 
+
+  if ((tm = typemap_lookup("out","tcl8",d,name,"_result","tcl_result"))) {
+    // Yep.  Use it instead of the default
+    f.code << tm << "\n";
+  } else if ((d->type != T_VOID) || (d->is_pointer)) {
+    if (!d->is_pointer) {
+       
+      // Function returns a "value"
+       
+      switch(d->type) {
+       // Is an integer
+      case T_BOOL:
+      case T_INT:
+      case T_SINT:
+      case T_SHORT:
+      case T_SSHORT:
+      case T_LONG :
+      case T_SLONG:
+      case T_SCHAR:
+      case T_UINT:
+      case T_USHORT:
+      case T_ULONG:
+      case T_UCHAR:
+       f.code << tab4 << "Tcl_SetIntObj(tcl_result,(long) _result);\n";
+       break;
+       
+       // Is a single character.  Assume we return it as a string
+      case T_CHAR :
+       f.code << tab4 << "Tcl_SetStringObj(tcl_result,&_result,1);\n";
+       break;
+       
+       // Floating point number
+      case T_DOUBLE :
+      case T_FLOAT :
+       f.code << tab4 << "Tcl_SetDoubleObj(tcl_result,(double) _result);\n";
+       break;
+       
+       // User defined type
+      case T_USER :
+       
+       // Okay. We're returning malloced memory at this point.
+       // Probably dangerous, but who said safety was a good thing?
+       
+       //      f.add_local("char","resultchar[256]");
+       d->is_pointer++;
+#ifdef OLD
+       f.code << tab4 << "SWIG_MakePtr(resultchar, (void *) _result,\"" << d->print_mangle() << "\");\n"
+              << tab4 << "Tcl_SetStringObj(tcl_result,resultchar,-1);\n";
+#endif
+       f.code << tab4 << "SWIG_SetPointerObj(tcl_result,(void *) _result,\"" << d->print_mangle() << "\");\n";
+       
+       d->is_pointer--;
+       break;
+       
+       // Unknown type
+      default :
+       fprintf(stderr,"%s : Line %d: Unable to use return type %s in function %s.\n",
+               input_file, line_number, d->print_type(), name);
+       break;
+      }
+    } else {
+       
+      // Is a pointer return type
+      
+      if ((d->type == T_CHAR) && (d->is_pointer == 1)) {
+       // Return a character string
+       f.code << tab4 << "Tcl_SetStringObj(tcl_result,_result,-1);\n";
+      } else {
+#ifdef OLD
+       f.add_local("char","resultchar[256]");
+       f.code << tab4 << "SWIG_MakePtr(resultchar, (void *) _result,\"" << d->print_mangle() << "\");\n"
+              << tab4 << "Tcl_SetStringObj(tcl_result,resultchar,-1);\n";
+#endif
+       
+       f.code << tab4 << "SWIG_SetPointerObj(tcl_result,(void *) _result,\"" << d->print_mangle() << "\");\n"; 
+      }
+    }
+  }
+
+
+  // Dump output argument code
+  f.code << outarg;
+
+  // Dump the argument cleanup code
+  f.code << cleanup;
+
+  // Look for any remaining cleanup
+
+  if (NewObject) {
+    if ((tm = typemap_lookup("newfree","tcl8",d,iname,"_result",""))) {
+      f.code << tm << "\n";
+    }
+  }
+
+  if ((tm = typemap_lookup("ret","tcl8",d,name,"_result",""))) {
+    // Yep.  Use it instead of the default
+    f.code << tm << "\n";
+  }
+  
+  // Wrap things up (in a manner of speaking)
+
+  f.code << tab4 << "return TCL_OK;\n}";
+
+  // Substitute the cleanup code
+  f.code.replace("$cleanup",cleanup);
+  f.code.replace("$name",iname);
+
+  // Dump out the function
+
+  f.print(f_wrappers);
+
+  // Now register the function with Tcl
+
+  fprintf(f_init,"\t Tcl_CreateObjCommand(%s, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",interp_name, iname, wname);
+
+  // If there's a documentation entry, produce a usage string
+
+  if (doc_entry) {
+
+    static DocEntry *last_doc_entry = 0;
+
+    // Use usage as description
+    doc_entry->usage << usage;
+
+    // Set the cinfo field to specific a return type 
+
+    if (last_doc_entry != doc_entry) {
+      doc_entry->cinfo << "returns " << d->print_type();
+      last_doc_entry = doc_entry;
+    }
+  }
+}
+
+// -----------------------------------------------------------------------
+// TCL8::link_variable(char *name, char *iname, DataType *t,
+//                           int ex)
+//
+// Create a TCL link to a variable.
+// -----------------------------------------------------------------------
+
+void TCL8::link_variable(char *name, char *iname, DataType *t)
+{
+
+  String    s;
+  char      *tm, *tm1;
+
+  // See if there were any typemaps
+
+  tm = typemap_lookup("varin","tcl8",t,name,"","");
+  tm1 = typemap_lookup("varout","tcl8",t,name,"","");
+  if (tm || tm1) {
+    fprintf(stderr,"%s : Line %d. Warning. varin/varout typemap methods not supported.",
+           input_file, line_number);
+  }
+
+  // Check the datatype.  Must be a valid Tcl type (there aren't many)
+
+  if (((t->type == T_INT) && (!t->is_pointer)) ||
+      ((t->type == T_UINT) && (!t->is_pointer)) ||
+      ((t->type == T_SINT) && (!t->is_pointer)) ||
+      ((t->type == T_DOUBLE) && (!t->is_pointer)) ||
+      ((t->type == T_BOOL) && (!t->is_pointer)) ||
+      ((t->type == T_CHAR) && (t->is_pointer == 1))) {
+
+    // This is a valid TCL type. 
+
+    if (t->type == T_UINT)
+      fprintf(stderr,"%s : Line %d : ** Warning. Linkage of unsigned type may be unsafe.\n",
+              input_file,  line_number);
+
+    // Now add symbol to the TCL interpreter
+
+    switch(t->type) {
+    case T_CHAR :
+      if (t->arraystr) {
+       // Is an array.  We have to do something different
+       fprintf(f_wrappers,"static char *tclvar%s = %s;\n",name,name);
+       s << "(char *) &tclvar" << name << ", TCL_LINK_STRING";
+      } else {
+       s << "(char *) &" << name << ", TCL_LINK_STRING";
+      }
+      break;
+    case T_BOOL:
+    case T_INT :
+    case T_UINT:
+    case T_SINT:
+      s << "(char *) &" << name << ", TCL_LINK_INT";
+      break;
+    case T_DOUBLE :
+      s << "(char *) &" << name << ", TCL_LINK_DOUBLE";
+      break;
+    default :
+      fprintf(f_init,"Fatal error. Internal error (Tcl:link_variable)\n");
+      break;
+    }
+
+    if (Status & STAT_READONLY)
+      s << " | TCL_LINK_READ_ONLY);\n";
+    else
+      s << ");\n";
+
+    fprintf(f_init,"\t Tcl_LinkVar(%s, SWIG_prefix \"%s\", %s",interp_name, iname, s.get());    
+    
+    // Make a usage string for it
+
+    if (doc_entry) {
+      doc_entry->usage << usage_var(iname,t);
+      doc_entry->cinfo = "";
+      doc_entry->cinfo << "Global : " << t->print_type() << " " << name;
+    }
+  } else {
+
+    // Have some sort of "other" type.
+    // We're going to emit some functions to set/get it's value instead
+    
+    emit_set_get(name,iname, t);
+    if (doc_entry) {
+      doc_entry->cinfo = "";
+      doc_entry->cinfo << "Global : " << t->print_type() << " " << iname;
+    }
+
+    // If shadow classes are enabled and we have a user-defined type
+    // that we know about, create a command for it.  
+
+    if (shadow) {
+      if ((t->type == T_USER) && (t->is_pointer < 1)) {
+       // See if the datatype is in our hash table
+       if (hash.lookup(t->name)) {
+         // Yep.  Try to create a command for it
+
+         postinit << tab4 << "{\n"
+                  << tab8 << "char cmd[] = \"" 
+                  << (char *) hash.lookup(t->name) << " " << iname << " -this ["
+                  << iname << "_get ]\";\n"
+                  << tab8 << "Tcl_GlobalEval(interp,cmd);\n"
+                  << tab4 << "}\n";
+       }
+      }
+    }
+  }  
+}
+
+// -----------------------------------------------------------------------
+// TCL8::declare_const(char *name, char *iname, DataType *type, char *value)
+//
+// Makes a constant.  Really just creates a variable and links to it.
+// Tcl variable linkage allows read-only variables so we'll use that
+// instead of just creating a Tcl variable.
+// ------------------------------------------------------------------------
+
+void TCL8::declare_const(char *name, char *, DataType *type, char *value) {
+
+  int OldStatus = Status;      // Save old status flags
+  DataType *t; 
+  char   var_name[256];
+  char     *tm;
+  String  rvalue;
+  Status = STAT_READONLY;      // Enable readonly mode.
+
+  // Make a static variable;
+
+  sprintf(var_name,"_wrap_const_%s",name);
+  
+  // See if there's a typemap
+  rvalue = value;
+  if ((type->type == T_CHAR) && (type->is_pointer == 1)) {
+    rvalue << "\""; 
+    "\"" >> rvalue;
+  } 
+  if ((type->type == T_CHAR) && (type->is_pointer == 0)) {
+    rvalue << "'";
+    "'" >> rvalue;
+  }
+  if ((tm = typemap_lookup("const","tcl8",type,name,rvalue.get(),name))) {
+    // Yep.  Use it instead of the default
+    fprintf(f_init,"%s\n",tm);
+  } else {
+
+    // Create variable and assign it a value
+    
+    if (type->is_pointer == 0) {
+      switch(type->type) {
+      case T_BOOL: case T_INT: case T_SINT: case T_DOUBLE:
+       fprintf(f_header,"static %s %s = %s;\n", type->print_type(), var_name, value);
+       link_variable(var_name,name,type);
+       break;
+      case T_SHORT:
+      case T_LONG:
+      case T_SSHORT:
+      case T_SCHAR:
+      case T_SLONG:
+       fprintf(f_header,"static %s %s = %s;\n", type->print_type(), var_name, value);
+       fprintf(f_header,"static char *%s_char;\n", var_name);
+       if (CPlusPlus)
+         fprintf(f_init,"\t %s_char = new char[32];\n",var_name);
+       else
+         fprintf(f_init,"\t %s_char = (char *) malloc(32);\n",var_name);
+       
+       fprintf(f_init,"\t sprintf(%s_char,\"%%ld\", (long) %s);\n", var_name, var_name);
+       sprintf(var_name,"%s_char",var_name);
+       t = new DataType(T_CHAR);
+       t->is_pointer = 1;
+       link_variable(var_name,name,t);
+       delete t;
+       break;
+      case T_UINT:
+      case T_USHORT:
+      case T_ULONG:
+      case T_UCHAR:
+       fprintf(f_header,"static %s %s = %s;\n", type->print_type(), var_name, value);
+       fprintf(f_header,"static char *%s_char;\n", var_name);
+       if (CPlusPlus)
+         fprintf(f_init,"\t %s_char = new char[32];\n",var_name);
+       else
+         fprintf(f_init,"\t %s_char = (char *) malloc(32);\n",var_name);
+       
+       fprintf(f_init,"\t sprintf(%s_char,\"%%lu\", (unsigned long) %s);\n", var_name, var_name);
+       sprintf(var_name,"%s_char",var_name);
+       t = new DataType(T_CHAR);
+       t->is_pointer = 1;
+       link_variable(var_name,name,t);
+       delete t;
+       break;
+      case T_FLOAT:
+       type->type = T_DOUBLE;
+       strcpy(type->name,"double");
+       fprintf(f_header,"static %s %s = %s (%s);\n", type->print_type(), var_name, type->print_cast(), value);
+       link_variable(var_name,name,type);
+       break;
+       
+      case T_CHAR:
+       type->is_pointer++;
+       fprintf(f_header,"static %s %s = \"%s\";\n", type->print_type(), var_name, value);
+       link_variable(var_name,name,type);
+       type->is_pointer--;
+       break;
+      default:
+       fprintf(stderr,"%s : Line %d. Unsupported constant value.\n", input_file, line_number);
+       break;
+      }
+    } else {
+      // Have some sort of pointer value here
+      if ((type->type == T_CHAR) && (type->is_pointer == 1)) {
+       // Character string
+       fprintf(f_header,"static %s %s = \"%s\";\n", type->print_type(), var_name, value);
+       link_variable(var_name,name,type);
+      } else {
+       // Something else.   Some sort of pointer value
+       fprintf(f_header,"static %s %s = %s;\n", type->print_type(), var_name, value);
+       fprintf(f_header,"static char *%s_char;\n", var_name);
+       if (CPlusPlus)
+         fprintf(f_init,"\t %s_char = new char[%d];\n",var_name,(int) strlen(type->print_mangle())+ 20);
+       else
+         fprintf(f_init,"\t %s_char = (char *) malloc(%d);\n",var_name, (int) strlen(type->print_mangle())+ 20);
+       
+       t = new DataType(T_CHAR);
+       t->is_pointer = 1;
+       fprintf(f_init,"\t SWIG_MakePtr(%s_char, (void *) %s,\"%s\");\n",
+               var_name, var_name, type->print_mangle());
+       sprintf(var_name,"%s_char",var_name);
+       link_variable(var_name,name,t);
+       delete t;
+      }
+    }
+  }
+
+  // Create a documentation entry for this
+
+  if (doc_entry) {
+    doc_entry->usage = "";       // Destroy any previous information from linking
+    doc_entry->usage << usage_const(name, type, value);
+    doc_entry->cinfo = "";
+    doc_entry->cinfo << "Constant : " << type->print_type();
+  }
+
+  Status = OldStatus;
+}
+
+// ----------------------------------------------------------------------
+// TCL8::usage_var(char *iname, DataType *t, char **s)
+//
+// Produces a usage string for a tcl variable.  Stores it in s
+// ----------------------------------------------------------------------
+
+char *TCL8::usage_var(char *iname, DataType *t) {
+
+  static char temp[1024];
+
+  if (!nspace) {
+    sprintf(temp,"$%s%s", prefix, iname);
+  } else { 
+    sprintf(temp,"%s::%s", ns_name, iname);
+  }
+  if (!(((t->type == T_INT) && (!t->is_pointer)) ||
+       ((t->type == T_UINT) && (!t->is_pointer)) ||
+       ((t->type == T_DOUBLE) && (!t->is_pointer)) ||
+       ((t->type == T_BOOL) && (!t->is_pointer)) ||
+       ((t->type == T_CHAR) && (t->is_pointer)))) {
+    /* We emitted a pair of set/get functions instead.  Doc will be generated for that */
+    return temp;
+  }
+  return temp;
+}
+
+
+
+// ---------------------------------------------------------------------------
+// char *TCL8::usage_string(char *iname, DataType *t, ParmList *l),
+// 
+// Generates a generic usage string for a Tcl function.
+// ---------------------------------------------------------------------------
+
+char * TCL8::usage_string(char *iname, DataType *, ParmList *l) {
+
+  static String temp;
+  Parm  *p;
+  int   i, numopt,pcount;
+
+  temp = "";
+  temp << iname << " ";
+  
+  /* Now go through and print parameters */
+  i = 0;
+  pcount = l->nparms;
+  numopt = l->numopt();
+  p = l->get_first();
+  while (p != 0) {
+
+    // Only print an argument if not ignored
+
+    if (!typemap_check("ignore","tcl8",p->t,p->name)) {
+      if (i >= (pcount-numopt))
+       temp << "?";
+
+      /* If parameter has been named, use that.   Otherwise, just print a type  */
+
+      if ((p->t->type != T_VOID) || (p->t->is_pointer)) {
+       if (strlen(p->name) > 0) {
+         temp << p->name;
+       }
+       else {
+         temp << "{ " << p->t->print_type() << " }";
+       }
+      }
+      if (i >= (pcount-numopt))
+       temp << "?";
+      temp << " ";
+      i++;
+    }
+    p = l->get_next();
+  }
+  return temp;
+}
+
+// ---------------------------------------------------------------------------
+// char *TCL8::usage_func(char *iname, DataType *t, ParmList *l),
+// 
+// Produces a usage string for a function in Tcl
+// ---------------------------------------------------------------------------
+
+char * TCL8::usage_func(char *iname, DataType *t, ParmList *l) {
+
+  String temp;
+
+  if (nspace) {
+    temp << ns_name << "::" << iname;
+  } else {
+    temp << prefix << iname;
+  }
+  return usage_string(temp,t,l);
+}
+
+// -----------------------------------------------------------------
+// TCL8::usage_const(char *name, DataType *type, char *value)
+//                         char **s)
+//
+// Makes a usage string and returns it
+// -----------------------------------------------------------------
+
+char *TCL8::usage_const(char *name, DataType *, char *value) {
+  static String temp;
+  temp = "";
+  if (nspace) {
+    temp << ns_name << "::" << name << " = " << value;
+  } else {
+    temp << "$" << prefix << name << " = " << value;
+  }
+  return temp.get();
+}
+    
+// -------------------------------------------------------------------
+// TCL8::add_native(char *name, char *funcname)
+//
+// This adds an already written Tcl wrapper function to our
+// initialization function.
+// -------------------------------------------------------------------
+
+
+void TCL8::add_native(char *name, char *funcname) {
+
+  fprintf(f_init,"\t Tcl_CreateCommand(%s, SWIG_prefix \"%s\", %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n",interp_name, name, funcname);
+  
+  if (doc_entry) {
+    if (nspace) 
+      doc_entry->usage << ns_name << "::" << name << " args";
+    else
+      doc_entry->usage << prefix << name << " args";
+
+    doc_entry->cinfo << "Native method : " << funcname;
+  }
+    
+}
+// -------------------------------------------------------------------
+// TCL8::pragma(char *lname, char *name, char *value)
+//
+// Handle pragmas.
+// --------------------------------------------------------------------
+
+void TCL8::pragma(char *, char *, char *) {
+
+}
+
+// ---------------------------------------------------------------------
+// C++ Handling
+//
+// The following functions provide some support for C++ classes and
+// C structs.   
+// ---------------------------------------------------------------------
+
+void TCL8::cpp_open_class(char *classname, char *rename, char *ctype, int strip) {
+
+  this->Language::cpp_open_class(classname,rename,ctype,strip);
+
+  if (shadow) {
+  
+    config = "";
+    cget = "";
+    methods = "";
+    options = "";
+    config_options = "";
+    methodnames = "";
+    
+    have_constructor = 0;
+    have_destructor = 0;
+    have_methods = 0;
+    have_config = 0;
+    have_cget = 0;
+
+    if (rename)
+      class_name = copy_string(rename);
+    else
+      class_name = copy_string(classname);
+  
+    base_class = (char *) 0;
+    if (!strip) {
+      class_type = new char[strlen(ctype)+2];
+      sprintf(class_type,"%s ", ctype);
+    } else
+      class_type = "";
+
+    real_classname = copy_string(classname);
+  }
+}
+
+void TCL8::cpp_close_class() {
+  String code,temp;
+  DataType *t;
+
+  this->Language::cpp_close_class();
+  if (shadow) {
+
+    t = new DataType;
+    sprintf(t->name,"%s%s", class_type, real_classname);
+    t->type = T_USER;
+    t->is_pointer = 1;
+    
+    // Note : The object oriented interface is defined by three files
+    //     delcmd8.swg          - Object deletion wrapper
+    //     methodcmd8.swg       - Method invocation command
+    //     objcmd8.swg          - Command to create a new object
+    //
+    // These files are located in the SWIG library.  This module
+    // grabs the files and performs marker replacements to
+    // build the wrapper function.
+    
+    // Generate a Tcl function for object destruction
+    
+    if (have_destructor) {
+      code << delcmd;
+    }
+
+    // Dump out method code
+    code << methodcmd;
+
+    // Dump out object creation command
+    code << objcmd;
+
+    // Now perform marker replacements
+    code.replace("@CLASS@",class_name);
+    temp = "";
+    temp << name_destroy(class_name);
+    code.replace("@DESTRUCTOR@",temp);
+    code.replace("@CLASSTYPE@",t->print_type());
+    "configure " >> methodnames;
+    "cget " >> methodnames;
+    code.replace("@METHODLIST@", methodnames);
+    code.replace("@CLASSMANGLE@",t->print_mangle());
+    code.replace("@METHODS@",methods);
+    code.replace("@CONFIGMETHODS@",config);
+    code.replace("@CGETMETHODS@",cget);
+    if (have_constructor) {
+      temp = "";
+      temp << name_wrapper(name_construct(class_name),prefix);
+    } else {
+      temp = "0";
+    }
+    code.replace("@TCLCONSTRUCTOR@",temp);
+    code.replace("@CONFIGLIST@",config_options);
+    code.replace("@CGETLIST@",options);
+    if (have_destructor) {
+      temp = "TclDelete";
+      temp << class_name;
+    } else {
+      temp = "0";
+    }
+    code.replace("@TCLDESTRUCTOR@",temp);
+    fprintf(f_wrappers,"%s\n", code.get());
+
+    fprintf(f_init,"\t Tcl_CreateObjCommand(interp,SWIG_prefix \"%s\",Tcl%sCmd, (ClientData) NULL, NULL);\n", class_name, class_name);
+  }
+}
+
+void TCL8::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) {
+
+  char *realname;
+  String temp;
+  char  *rname;
+
+  this->Language::cpp_member_func(name,iname,t,l);
+
+  if (shadow) {
+    if (iname) 
+      realname = iname;
+    else
+      realname = name;
+    
+    // Add stubs for this member to our class handler function
+
+    if (have_methods) 
+      methods << tab4 << "else ";
+    else 
+      methods << tab4;
+
+    temp = "";
+    temp << name_member(realname,class_name);
+    rname = (char *) repeatcmd.lookup(temp);
+    if (!rname)
+      rname = name_wrapper(temp.get(),prefix);
+    
+    methods << "if (strcmp(_str,\"" << realname << "\") == 0) {\n"
+           << tab4 << tab4 << "cmd = " << rname << ";\n"
+           << tab4 << "}";
+
+    have_methods = 1;
+    methodnames << realname << " ";
+
+    if (doc_entry) {
+      doc_entry->usage = "";
+      doc_entry->usage << usage_string(realname,t,l);
+    }
+  }
+}
+
+void TCL8::cpp_variable(char *name, char *iname, DataType *t) {
+  char *realname;
+  String temp;
+  char *rname;
+
+  this->Language::cpp_variable(name, iname, t);
+
+  if (shadow) {
+    if (iname)
+      realname = iname;
+    else
+      realname = name;
+    
+    char *bc = class_name;
+
+    // Write config code
+    
+    if (!(Status & STAT_READONLY)) {
+      if (!have_config) {
+       config << tab8 << tab8;
+      } else {
+       config << " else ";
+      }
+
+      // Try to figure out if there is already a wrapper for this
+      
+      temp = "";
+      temp << name_set(name_member(realname,bc));
+      rname = (char *) repeatcmd.lookup(temp);
+      if (!rname) 
+       rname = name_wrapper(temp.get(),prefix);
+
+      config << "if (strcmp(_str,\"-" << realname << "\") == 0) {\n"
+            << tab8 << tab8 << tab4 << "cmd = " << rname << ";\n"
+            << tab8 << tab8 << "} ";
+      
+      have_config = 1;
+    }
+    
+    // Write cget code
+    
+    if (!have_cget) {
+      cget << tab8 << tab8;
+    } else {
+      cget << " else ";
+    }
+
+
+    // Try to figure out if there is a wrapper for this function
+    temp = "";
+    temp << name_get(name_member(realname,bc));
+    rname = (char *) repeatcmd.lookup(temp);
+    if (!rname) 
+      rname = name_wrapper(temp.get(),prefix);
+
+    cget << "if (strcmp(_str,\"-" << realname << "\") == 0) {\n"
+        << tab8 << tab8 << tab4 << "cmd = " << rname << ";\n"
+        << tab8 << tab8 << "} ";
+    have_cget = 1;
+    
+    options << "-" << realname << " ";
+    if (!(Status & STAT_READONLY)) {
+      config_options << "-" << realname << " ";
+    }
+    if (doc_entry){
+      doc_entry->usage = "";
+      doc_entry->usage << "-" << realname << "\n";
+    }
+  }
+}
+
+void TCL8::cpp_constructor(char *name, char *iname, ParmList *l) {
+  this->Language::cpp_constructor(name,iname,l);
+
+  if (shadow) {
+    if ((!have_constructor) && (doc_entry)) {
+      doc_entry->usage = "";
+      doc_entry->usage << class_name << usage_string(" name",0,l);
+    }
+    have_constructor = 1;
+  }
+}
+void TCL8::cpp_destructor(char *name, char *newname) {
+  this->Language::cpp_destructor(name,newname);
+  if (shadow) {
+    if (!have_destructor) {
+      if (doc_entry) {
+       doc_entry->usage = "rename obj {}";
+      }
+    }
+    have_destructor = 1;
+  }
+}
+
+void TCL8::cpp_inherit(char **baseclass, int) {
+  this->Language::cpp_inherit(baseclass);
+}
+
+void TCL8::cpp_declare_const(char *name, char *iname, DataType *type, char *value) {
+  this->Language::cpp_declare_const(name,iname,type,value);
+}
+
+// --------------------------------------------------------------------------------
+// TCL8::add_typedef(DataType *t, char *name)
+//
+// This is called whenever a typedef is encountered.   When shadow classes are
+// used, this function lets us discovered hidden uses of a class.  For example :
+//
+//     struct FooBar {
+//            ...
+//     }
+//
+// typedef FooBar *FooBarPtr;
+//
+// --------------------------------------------------------------------------------
+
+void TCL8::add_typedef(DataType *t, char *name) {
+
+  if (!shadow) return;
+
+  // First check to see if there aren't too many pointers
+
+  if (t->is_pointer > 1) return;
+  if (hash.lookup(name)) return;      // Already added
+
+  // Now look up the datatype in our shadow class hash table
+
+  if (hash.lookup(t->name)) {
+
+    // Yep.   This datatype is in the hash
+    // Put this types 'new' name into the hash
+    hash.add(name,copy_string((char *) hash.lookup(t->name)));
+  }
+}
+
+// -----------------------------------------------------------------------
+// TCL8::cpp_class_decl(char *name, char *rename, char *type)
+//
+// Treatment of an empty class definition.    Used to handle
+// shadow classes across modules.
+// -----------------------------------------------------------------------
+
+void TCL8::cpp_class_decl(char *name, char *rename, char *type) {
+  char temp[256];
+  this->Language::cpp_class_decl(name,rename, type);
+
+  if (shadow) {
+    hash.add(name,copy_string(rename));
+    // Add full name of datatype to the hash table
+    if (strlen(type) > 0) {
+      sprintf(temp,"%s %s", type, name);
+      hash.add(temp,copy_string(rename));
+    }
+  }
+}