Provided by: tclx8.4-doc_8.4.1-1_all bug

NAME

       TclCommandWriting - Writing C language extensions to Tcl.

OVERVIEW

       This  document is intended to help the programmer who wishes to extend Tcl with C language
       routines.  It should also be useful to someone wishing to add Tcl to an  existing  editor,
       communications  program, window manager, etc.  Experienced extension writers may find this
       manual helpful in rewriting their applications to use  the  new  Tcl  object  system.   We
       assume  you  are  already fluent in the C programming language and that you have built and
       installed Tcl on your machine.

       Information on the available C interface routines to Tcl can be found in  the  *.3  manual
       pages  in  the  doc directory of the baseline Tcl distribution, and in the *.3 manpages in
       the doc directory of Extended Tcl.

TCL OBJECT SYSTEM

       With the release of Tcl  version  8,  Tcl  has  a  new  system  for  managing  Tcl  values
       internally.   To the Tcl programmer, the new objects look and act like strings, as before.
       But at the C level, these objects can now also hold cached internal representations of the
       strings  in  various  native  datatypes.   For  example,  an  object  containing  a string
       consisting of an integer, will now maintain a machine-code integer representation,  if  an
       integer  representation  has been needed.  Using these objects is much more efficient than
       using the  older-style  Tcl  strings,  although  the  older  style  is  still  (currently)
       supported.

       Although the object system has almost no effect at all on how the Tcl programmer uses Tcl,
       the object  system's  C  interfaces  to  strings,  integers,  lists,  etc.,  have  changed
       considerably.   While converting a package to use the new system can be a lot of work, the
       combination of the object system, which  saves  Tcl  from  having  to  constantly  convert
       strings  to integers and back, etc., and the on-the-fly bytecode compiler (which keeps Tcl
       from having to continually reparse  code  it  is  to  execute)  yield  Tcl  programs  that
       routinely  execute  several  times  more  quickly  than  with previous versions (Tcl 7 and
       before), and in some cases run as much as 2500 (!) times faster than before.

       We have chosen, then, to rewrite the Command Writer's manpage,  which  has  been  shipping
       with  Extended  Tcl  for  a  number of years, to produce this new version based on the new
       object system.  The old manpage, based on the older string-oriented routines,  will  still
       be  included  in  TclX  releases  for now, as it is still relevant to Tcl releases through
       version 7, and may be of use to those modifying/upgrading packages  written  for  the  old
       model.   The old manual will be dropped from the release once we deem it unneeded; the old
       interfaces should now be considered legacy interfaces, and all new development  should  be
       done using the new object interfaces, unless backwards compatibility to pre-Tcl-8 releases
       is needed.

A SIMPLE C EXTENSION

       All C-based Tcl commands are called  with  four  arguments:  a  client  data  pointer,  an
       interpreter pointer, an argument count and a pointer to an array of Tcl objects containing
       the arguments to the command.

       A simple C extension to Tcl is now presented, and described below:

           #include "tcl.h"

           int App_DumpArgsObjCmd(clientData, interp, objc, objv)
               void          *clientData;
               Tcl_Interp    *interp;
               int            objc;
               Tcl_Obj      **objv;
           {
                   int   i;
                int   stringLen;
                char *stringPtr;

                   for (i = 1; i < objc; i++) {
                     stringPtr = Tcl_GetStringFromObj (objv [i], &stringLen);
                           printf("%s", stringPtr);
                     if (i < objc - 1) printf(" ");
                   }
                   printf("\n");
                   return TCL_OK;
           }

       The client data pointer will be described later.

INTERPRETERS

       The  interpreter  pointer  is  the  ``key''  to  an  interpreter.   It  is   returned   by
       Tcl_CreateInterp  and  is  used  extensively  within  Tcl,  and  will  be  used  by your C
       extensions.  The data structure pointed to by the interpreter  pointer,  and  all  of  the
       subordinate  structures  that  branch off of it, make up a Tcl interpreter, which includes
       all of the currently defined procedures, commands, variables,  arrays  and  the  execution
       state  of  that interpreter.  (For more information on creating and deleting interpreters,
       please examine the CrtInterp(3) manpage in the core Tcl distribution.  For information  on
       creating  interpreters  that  include the commands provided by Extended Tcl, check out the
       TclX_Init(3) manpage of Extended Tcl.  For  a  manual  page  describing  the  user-visible
       fields of a Tcl interpreter, please look at Interp(3) in core Tcl.)

OBJECT COUNT AND ARGUMENTS

       The  argument  count,  or  object count (objc), and pointer to an array of pointers to Tcl
       objects of the command's arguments (objv) is handled by your C code, in a  manner  similar
       to  the  one  you would use in writing a C main function -- an argument count and array of
       pointers works the same as in a C main call; pointers to the arguments to the function are
       contained  in  the  objv  array.   Similar to a C main, the first argument (objv[0]) is an
       object containing the name the routine was called as (in a C main, the  name  the  program
       was invoked as).

       In  Tcl,  however,  the  array of pointers are not pointers to character strings (although
       they were in all version of Tcl before 8.0).

       In the above example, all of the arguments are output with a space  between  each  one  by
       looping  through  elements  of  the objv array from one to the argument count, objc, and a
       newline is output to terminate the line -- a simple ``echo'' command.  This  example  uses
       printf  for  simplicity.   Of  course  in  production  code  you would want to use the Tcl
       filesystem interfaces.  See GetFile(3) and friends for more information.

       All arguments from a Tcl call to a Tcl C extension are passed as Tcl Objects.  If  your  C
       routine  wants to look at one of those arguments as an integer, you need to make a call to
       a routine to fetch the representation of  the  object  that  you  need.   In  the  earlier
       example,  for  instance, Tcl_GetStringFromObj is called to obtain a textual representation
       of an object.  Additional routines are available to fetch the  representation  of  a  data
       element    as    other    data    types.    Tcl_GetBooleanFromObj,   Tcl_GetDoubleFromObj,
       Tcl_GetIntFromObj,   Tcl_GetLongFromObj,    and    Tcl_GetIndexFromObj,    fetch    object
       representations of Tcl strings as booleans, double-precision floating point, integer, long
       integer, and lists, among others.

       These routines automatically leave an appropriate error message in the  Tcl  interpreter's
       result  object  and return TCL_ERROR if a conversion error occurs.   (For more information
       on these routines, please look at the Object(3) manpage in the core Tcl distribution.)

RETURNING RESULTS

       As you  might  expect,  the  API  for  setting  results  from  C  extensions  has  changed
       significantly  under  the  object  system.   The  old  technique  of writing small results
       directory into the interpreter's result buffer is no longer used, for example.  The notion
       of  having  to tell Tcl whether a result is static or dynamic is also a thing of the past.
       Under the object system, results are objects that are set up by your code, and objects are
       freed when their reference counts say they should be.  More on this later.

       If  you program produces a numeric result, it should set the result object to contain that
       numeric value.  A common way of doing this is something like...

               Tcl_Obj *obj;

               obj = Tcl_GetObjResult (interp);
            Tcl_SetIntObj (obj, value);

       The above code obtains a pointer to the result object (an object made  available  to  your
       routine  that you're supposed to store your results into) and sets the integer value value
       into it.

       Another way to do it would be to set up a  new  object  and  tell  Tcl  that  this  object
       contains the result...

               Tcl_Obj *resultObj;

               /* create a new object for use as a result */
            resultObj = Tcl_NewObj ();

            Tcl_SetIntObj (obj, value);
            Tcl_SetObjResult (interp, resultObj);

       Understanding  how  results are passed back to Tcl is essential to the C extension writer.
       Please study the SetObjResult(3) manual page in the Tcl distribution for more information.

VALIDATING ARGUMENTS

       It is a design goal of Tcl that no Tcl program be able to cause Tcl to dump core.   It  is
       important that the extension writers, likewise, use the avaiable methods and tools to make
       sure that their extensions do not allow unchecked input, for example, to cause the code to
       get some kind of runtime exception.

       The  object  system  has  simplified, to some degree, the task of validating arguments, in
       that the object system automatically attempts type conversions as needed, and will  return
       an error when a type conversion fails.

       A  simple, but important, check that every C extension should do is verify that it has the
       right number of arguments.

       The act of trying to use, say, a string  as  an  integer,  implicitly  performs  the  type
       conversion  of  the  string and, if it doesn't work as an integer, returns TCL_ERROR.  The
       developer should check for the TCL_ERROR return from all of  the  GetXxxFromObj  commands,
       and  handle  them as appropriate.  Usually this will mean propagating the error on back to
       the user, or to an intevening catch, as the case may be.

       You should also check that values are in range (when  their  ranges  are  known),  and  so
       forth.   When C data structures need to be handled in Tcl in some form or another, yet the
       contents of the data must remain opaque to Tcl, as is usually the case  with  binary  data
       (although futures releases of Tcl are expected to have native abilities to read, write and
       manipulate binary data  instrinsically),  handles  need  to  be  used.   Handles  will  be
       described and examples presented, later in this doc.

ANOTHER C EXTENSION - THE MAX COMMAND

       In  the  command  below,  two or more arguments are compared, and the one with the maximum
       value is returned, if all goes well.  It is an error if there are fewer than two arguments
       (the  pointer  to  the ``max'' command text itself, objv[0], and a pointer to at least one
       object to compare the values of).

           int
           Tcl_MaxCmd (clientData, interp, objc, objv)
               char         *clientData;
               Tcl_Interp   *interp;
               int           objc;
               Tcl_Obj     **objv;
           {
               int maxVal = MININT;
               int value, idx;

               if (objc < 3)
                return TclX_WrongArgs (interp, objv[0],
                                          " num1 num2 [..numN]");

               for (idx = 1; idx < objc; idx++) {
                   if (Tcl_GetIntFromObj (interp, objv[idx], &value) != TCL_OK)
                       return TCL_ERROR;

                   if (value > maxVal) {
                       maxVal = value;
                   }
               }
            Tcl_SetIntObj (Tcl_GetObjResult (interp), value);
               return TCL_OK;
           }

       Here we introduce the Extended Tcl helper function TclX_WrongArgs.  This routine makes  it
       easy  to  create  an  error  message and error return in response to the common mistake of
       being called with a wrong number.

       Tcl_GetIntFromObj is used to fetch the integer values of the remaining arguments.  If  any
       fail  to  be converted, we return a Tcl error.  If an interpreter is specified in the call
       to Tcl_GetIntFromObj, an appropriate error message about the conversion  failure  will  be
       left in the result, so we do that here.

       After  examining  all of the arguments to find the largest value, we set the result object
       to contain that value, and return TCL_OK.

RETURNING RESULTS

       When Tcl-callable functions complete, they should normally  return  TCL_OK  or  TCL_ERROR.
       TCL_OK  is returned when the command succeeded, and TCL_ERROR is returned when the command
       has failed in some abnormal way.  TCL_ERROR should be returned for all syntax errors, non-
       numeric values when numeric ones were expected, and so forth.  Less clear in some cases is
       whether Tcl errors should be returned or whether a function should just  return  a  status
       value.  For example, end-of-file during a gets returns a status, but open returns an error
       if it fails.  Errors can be caught from Tcl programs using the catch command.  (See  Tcl's
       catch(n) and error(n) manual pages.)

       Less  common  return values are TCL_RETURN, TCL_BREAK and TCL_CONTINUE.  These are used if
       you are adding new control and/or looping structures to  Tcl.   To  see  these  values  in
       action,  examine the source code to Extended Tcl's loop commands.  Tcl's while, for and if
       commands used to work in the just same manner, but are now compiled into bytecode  by  the
       bytecode for performance.

ANOTHER C EXTENSION - THE LREVERSE COMMAND

       In  the  command  below, a list is passed as an argument, and a list containing all of the
       elements of the list in reverse order is returned.  It is an error if anything other  than
       two  arguments  are  passed (the pointer to the ``lreverse'' command text itself, objv[0],
       and a pointer to the list to reverse.

       Once lreverse has determined that  it  has  received  the  correct  number  of  arguments,
       Tcl_ListObjGetElements is called to split the list into its own objc count of elements and
       objv array of pointers to the list's elements.

       lreverse then operates on the array of pointers, swapping them  from  lowest  to  highest,
       second-lowest to second-highest, and so forth.

       Tcl_ListObjAppendElement  is  called on successive list elements to build up the new list,
       which is finally returned as result of the command.

       int
       Tcl_LreverseObjCmd(notUsed, interp, objc, objv)
           ClientData    notUsed;         /* Not used. */
           Tcl_Interp   *interp;          /* Current interpreter. */
           int           objc;            /* Number of arguments. */
           Tcl_Obj     **obj;             /* Argument strings. */
       {
           int listObjc, lowListIndex, hiListIndex;
           Tcl_Obj **listObjv;
           char *temp, *resultList;
           Tcl_Obj **newListObjv;

           /* Verify argument count.  Since we take only one argument, argument
            * count must be 2 (command plus one argument).
            */
           if (objc != 2)
            return TclX_WrongArgs (interp, objv [0], "list");

           /* Create an object to handle the new list we're creating */
           newListObjv = Tcl_NewObj();

           /* Crack the list at objv[1] into its own count and array of object
            * pointers.
            */
           if (Tcl_ListObjGetElements (interp, objv[1], &listObjc, &listObjv) != TCL_OK) {
            return TCL_ERROR;
           }

           /* For each element in the source list from last to first, append an
            * element to the new list.
            */
           for (listIndex = listObjc - 1; listIndex >= 0; listIndex--) {
            Tcl_ListObjAppendElement (interp, newListObjv, listObjv[listIndex]);
           }
       FIX: NEED TO RETURN THE LIST.
           return TCL_OK;
       }

INSTALLING YOUR COMMAND

       To install your command into Tcl  you  must  call  Tcl_CreateObjCommand,  passing  it  the
       pointer  to the interpreter you want to install the command into, the name of the command,
       a pointer to the C function that implements the command, a  client  data  pointer,  and  a
       pointer to an optional callback routine.

       The client data pointer and the callback routine will be described later.

       For example, for the max function above (which, incidentally, comes from TclX's tclXmath.c
       in the TclX7.4/src directory):

           Tcl_CreateCommand (interp, "max", Tcl_MaxCmd, (ClientData)NULL,
                             (void (*)())NULL);

       In the above example, the max function is added to the specified interpreter.  The  client
       data  pointer  and  callback  function  pointer  are  NULL.   (For complete information on
       Tcl_CreateCommand  and  its  companion  routine,  Tcl_CommandInfo,  please   examine   the
       CrtCommand(3) command page in the core Tcl distribution.)

DYNAMIC STRINGS

       Dynamic  strings  are  an  important abstraction that first became available with Tcl 7.0.
       Dynamic strings, or DStrings, provide a way to build up arbitrarily long strings through a
       repeated  process  of  appending  information  to  them.   DStrings  reduce  the amount of
       allocating and copying required to add information to a string.   Further,  they  simplify
       the process of doing so.

       At  first glance, it may seem that the object system supersedes DStrings.  It does not, in
       that the performance improvements made possible by the  lazy  conversion  of  an  object's
       representation  from  one  datatype  to  another  does  not  come  into  play  much  while
       constructing strings as the string representation is always available either  without  any
       type  conversion  or  where  type  conversion  would  be necessary in any case as a string
       representation  of  the  object  is  required  when  strings  are  being  constructed   by
       concatenation, etc.

       It  should be noted, however, that the C level string manipulation capabilites of objects,
       such as Tcl_AppendToObj and Tcl_AppendStringsToObj, are often plenty enough for  what  you
       need  to  do.   For complete information on dynamic strings, please examine the DString(3)
       manual page in the core Tcl distribution.  For more on Tcl object's string-oriented calls,
       seek Tcl_StringObj(3) in the same location.

CLIENT DATA

       The  client  data  pointer  provides a means for Tcl commands to have data associated with
       them that is not global to the C program nor included in the Tcl  core.   Client  data  is
       essential  in  a  multi-interpreter environment (where a single program has created and is
       making use of multiple Tcl interpreters) for the C routines to maintain any permanent data
       they need on a per-interpreter basis.  If needed static data was simply declared static in
       C, you will probably have reentrancy problems when you work with multiple interpreters.

       Tcl solves  this  through  the  client  data  mechanism.   When  you  are  about  to  call
       Tcl_CreateObjCommand to add a new command to an interpreter, if your command needs to keep
       some read/write data across invocations, you should allocate the space,  preferably  using
       Tcl_Alloc instead of malloc, then pass the address of that space as the ClientData pointer
       to Tcl_CreateObjCommand.

       When  your  command  is  called  from  Tcl,  the  ClientData   pointer   you   passed   to
       Tcl_CreateObjCommand  will  be  passed  to  your  C routine through the ClientData pointer
       calling argument.

       Commands that need to share this data with one  another  can  do  so  by  using  the  same
       ClientData pointer when the commands are added.

       It is important to note that the Tcl extensions in the tclX8.0.0 directory have had all of
       their data set up in this way.  Since release 6.2, Extended  Tcl  has  supported  multiple
       interpreters within one invocation of Tcl.

THEORY OF HANDLES

       Sometimes  you  need  to  have a data element that isn't readily representable as a string
       within Tcl, for example a pointer to a complex C data structure.  It is not a good idea to
       try  to  pass  pointers around within Tcl as strings by converting them to and from hex or
       integer representations, for example.  It is too easy to  mess  one  up,  and  the  likely
       outcome of doing that is a core dump.

       Instead we have developed and made use of the concept of handles.  Handles are identifiers
       a C extension can pass to, and accept from, Tcl to make the transition between what your C
       code  knows  something  as  and  what  name  Tcl knows it by to be as safe and painless as
       possible.  For example, the I/O system included in Tcl uses file handles.  When you open a
       file  from Tcl, a handle is returned of the form filen where n is a file number.  When you
       pass the file handle back to puts, gets, seek, flush and so forth, they validate the  file
       handle  by  checking  the  the file text is present, then converting the file number to an
       integer that they use to look  into  a  data  structure  of  pointers  to  Tcl  open  file
       structures, which contain a Unix file descriptor, flags indicating whether or not the file
       is currently open, whether the file is a file or a pipe and so forth.

       Handles have proven so useful that, since TclX release  6.1a,  general  support  has  been
       available  to  help  create and manipulate them.  Many of these capabilities have migrated
       into baseline Tcl.  If you have a similar need, you might like to use the handle  routines
       documented  in  Handles(3)  in  Extended Tcl.  We recommend that you use a unique-to-your-
       package textual handle coupled with a specific identifier and let  the  handle  management
       routines validate it when it's passed back.  It is much easier to track down a bug with an
       implicated handle named something like file4 or bitmap6 than just 6.

       Note that Tcl's object offers another way for complex data structures to exist in parallel
       with  and  underneath  Tcl  strings.  As of this writing (May 30, 1997) this is fairly new
       territory, but things are looking good for the prospects of using the Tcl object system in
       this manner, and for enhancements to the object system that allow even Tcl objects to have
       methods in a very straightforward and simple way.

USING COMMANDS TO DO THE SAME THING, AND MORE

       Another handle-like technique, first popularized in the  Tk  toolkit,  offers  handle-like
       capabilities  as  well  as some neat additional capabilities.  That is to create a new Tcl
       command, from C, that uses ClientData to keep a "handle" on its  complex  underlying  data
       structure.   Then  by having that command look at its second argument for what it is to do
       (its sub-functions), you get these nice methods, where you have  several  additional  sub-
       commands that don't pollute the global namespace and only work on (and are available with)
       the objects (new commands)  they  are  relevant  to.   For  example,  in  Tk,  creating  a
       checkbutton (checkbutton .b) creates a new Tcl command (.b), that has methods to configure
       the button, select, deselect, toggle and flash it.

       A lot of people think this is really the way to go, and I am pretty much leaning that  way
       myself.   If  you  use  the  incr tcl script-level object system for Tcl, objects that you
       define in Tcl will  be  highly  compatible  in  terms  of  their  command  interfaces  and
       configuration management with objects you create in C using the the command-and-ClientData
       technique described here.  I believe Tk has some nice facilities for making this easy  for
       the Tcl programmer.  Itcl certainly does.

TRACKING MEMORY CORRUPTION PROBLEMS

       Occasionally  you  may  write  code  that  scribbles past the end of an allocated piece of
       memory.  This will usually result in a core dump or  memory  allocation  failure  sometime
       later  in  the  program,  often  implicating code that is not actually responsible for the
       problem (as you start looking from the point where the error is detected, which is usually
       where the later routine has failed).

       The  memory debugging routines included in Tcl can help find these problems.  Developed by
       Mark and Karl, the memory debugging routines are now part of baseline Tcl, and is  to  our
       knowledge  the  largest  piece  of  TclX  to drop into the core without being reengineered
       first.  (You see, summer back in '91, John was sitting in his office in the CS building at
       UC Berkeley trying to find a memory leak somewhere in Tcl, when he was paid a visit by two
       long-haired-yet-polite programmers bearing gifts in the form of  the  technology  grab-bag
       known  as  Extended Tcl.  He saw that, using TclX's malloc routines, Tcl could be prompted
       to print the filename and line number of every single memory allocation that did not  have
       a  corresponding  free.   It  was  just  what  the  doctor ordered ;-) See Memory(TCL) for
       details.

INSTALLING YOUR EXTENSIONS INTO TCL

       To add your extensions to Tcl, you used to have to statically link them, together with any
       other  extensions,  into a single binary executable image.  Today, although the statically
       linked executable is still an option, most  operating  systems,  even  Microsoft  Windows,
       support  shared  libraries,  and  in  most  cases,  Tcl  can  now make use of those shared
       libraries such that you extensions, and most others, can now be built a  shared  libraries
       that can be loaded in (using package require) by scripts that need them.  Shared libraries
       can simplify a Tcl installation, because only one copy of Tcl is required, rather  than  a
       hodepodge  of  combinations of applications that you might have found at a big Tcl site in
       the previous era.

GNU AUTOCONF

       While the build procedure for shared libraries varies from system to system, most Unix and
       Unix  workalike  systems  will figure out the nuances of the compiler and linker arguments
       automatically when the configure script is run.  If you are building a  package  that  you
       plan  to  make  generally  available,  we  strongly  recommend  that  you use GNU autoconf
       (ftp://prep.ai.mit.edu/pub/gnu) to set up  an  automatic  configure  script  for  it.   Be
       forewarned that autoconf uses some pretty heavy duty shell and sed script magic to get the
       job done, and the learning curve can be pretty steep.  Once done and shaken  out,  though,
       it's  rewarding  to know that your package can build and run on everything from a notebook
       to a Cray to a RISC SMP server.

       Application-specific startup is  accomplished  by  creating  or  editing  the  Tcl_AppInit
       function.   In  Tcl_AppInit you should add a call to an application-specific init function
       which you create.  This function should take the address  of  the  interpreter  it  should
       install its commands into, and it should install those commands with Tcl_CreateCommand and
       do any other application-specific startup that is necessary.

       The naming convention for application startup routines is App_Init, where App is the  name
       of  your  application.   For  example, to add an application named cute one would create a
       Cute_Init routine that expected a Tcl_Interp pointer as an argument, and add the following
       code to Tcl_AppInit:

           if (Cute_Init (interp) == TCL_ERROR) {
            return TCL_ERROR;
           }

       As  you can guess from the above example, if your init routine is unable to initialize, it
       should use Tcl_AppendResult to provide some kind of useful error  message  back  to  TclX,
       then  return  TCL_ERROR  to  indicate  that  an  error  occurred.  If the routine executed
       successfully, it should return TCL_OK.

       When you examine Tcl_AppInit, note that there is one call  already  there  to  install  an
       application -- the call to TclX_Init installs Extended Tcl into the Tcl core.

MAKING APPLICATION INFORMATION VISIBLE FROM EXTENDED TCL

       TclX's  infox  command  can return several pieces of information relevant to Extended Tcl,
       including the application's  name,  descriptive  name,  patch  level  and  version.   Your
       application's  startup  can  set  these  variables  to application-specific values.  If it
       doesn't, they are given default values for Extended Tcl.

       To set these values, first be sure that you include  either  tclExtend.h  or  tclExtdInt.h
       from  the  source  file  that  defines  your  init  routine.   This  will  create external
       declarations for the variables.  Then, set the variables in your init route, for example:

           tclAppName = "cute";
           tclAppLongName = "Call Unix/Tcl Environment";
           tclAppVersion = "2.1";

       Note that the default values are set by TclX_Init, so if you wish to  override  them,  you
       must call your init routine in Tcl_AppInit after its call to TclX_Init.

EXTENDED TCL EXIT

       When  Extended  Tcl  exits,  Tcl_DeleteInterp  may be called to free memory used by Tcl --
       normally, this is only called if TCL_MEM_DEBUG was defined, since Unix will return all  of
       the  allocated  memory  back  to  the system, anyway.  If TCL_MEM_DEBUG was defined, it is
       called so that any memory that was allocated without ever being  freed  can  be  detected.
       This greatly reduces the amount of work to detect and track down memory leaks, a situation
       where some piece of your code allocates memory repeatedly without ever freeing it,  or  at
       least without always freeing it.

       It  is  often  necessary  for an application to perform special cleanup functions upon the
       deletion of an interpreter as well.  To facilitate this activity, Tcl provides the ability
       to  perform  a  function  callback  when  an  interpreter  is deleted.  To arrange for a C
       function to be called when the interpreter is deleted, call Tcl_CallWhenDeleted from  your
       application  initialization  routine.   For  details on how to use this function, read the
       CallDel(3) manual page that ships with core Tcl.

EXECUTING TCL CODE FROM YOUR C EXTENSION

       Suppose you are in the middle of coding a C extension and you realize that you  need  some
       operation  performed,  one  that would be simple from Tcl, but possibly excruciating to do
       directly in C.  Tcl provides a number of C-level interfaces whereby you can cause Tcl code
       to  be  executeed.   The  old-style  calls  are  Tcl_Eval,  Tcl_VarEval,  Tcl_EvalFile and
       Tcl_GlobalEval.  The results of these calls can  be  dug  out  of  the  interpreter  using
       Tcl_GetStringResult,   if   you   want   a   string   representation  of  the  result,  or
       Tcl_GetObjResult if you want the object.  (The use of interp->result to access the  result
       string has been deprecated.)

       The Tcl object system adds Tcl_EvalObj and Tcl_GlobalEvalObj.  The difference here is that
       we are evaluating an object, not just a string, and using these routines in preference  to
       the  aforementioned  ones can result in a major performance improvement in your code, when
       the code is executed repeatedly (even if it only executes once  but  loops  several  times
       within  itself),  as  these routines make it possible for the bytecode compiler to compile
       the code being evaluated and save the  compiled  code  with  the  data  structure,  in  an
       implementation-dependent manner.

       For more information please consult the EvalObj(3) and Eval(3) manual pages within the Tcl
       distribution.

ACCESSING TCL VARIABLES AND ARRAYS FROM YOUR C EXTENSIONS

       In addition to the non-object-system ways of reading from and storing  to  Tcl  variables,
       using  routines  such as Tcl_SetVar2 and Tcl_GetVar2, Tcl variables and arrays can be read
       from a C extension as Tcl objects by using the Tcl_ObjGetVar2 function,  and  set  from  C
       extensions through the Tcl_ObjSetVar2 function.

       Please  note  that the object versions do not carry forward analogues to the one-variable-
       name-argument Tcl_GetVar, Tcl_SetVar, and Tcl_UnsetVar.  If you know you  have  a  scalar,
       call  the  object  variable  get  and  set functions with a NULL second argument.  If your
       variable name might contain an array reference via a self-contained embedded  array  index
       (i.e.,   I'm   asking   Tcl_ObjGetVar2  for  "foo(5)"  instead  of  "foo"  "5"),  add  the
       TCL_PARSE_PART1 to the flags in your call.

       While the fact that Tcl_ObjGetVar2 retrieves Tcl objects, rather than strings, is critical
       for  the  object  system  to  be  able  to provide the performance boosts from "lazy" type
       conversion and the binary data capabilities, the arguments containing the  variable  name,
       or  the  array  name and element name if they've been split out, also must be specified as
       Tcl objects rather than strings.  While this  is  useful  on  occasion,  those  writing  C
       extensions for Tcl in the post-object-system era usually have the names available as plain
       old char * variables, requiring conversion of  the  strings  to  objects  before  use  and
       account for their possible destruction afterwards.

       To  simplify the task in those cases, TclX adds the TclX_ObjGetVar2S subroutine.  It works
       just like Tcl_ObjGetVar2, except the one or two variable name arguments are  specified  as
       strings, and the routine takes care of making and disposing of object equivalents.

       Tcl variables can be unset from C via the Tcl_UnsetVar and Tcl_UnsetVar2 functions.  There
       are currently (as of 8.0) no object-system equivalents, so in the rare case where you have
       the  name  of  the  variable you want unset as an object instead of a string, you can call
       Tcl_GetStringFromObj to obtain the string representation first.

       For complete information  on  these  functions,  please  refer  to  the  ObjSetVar(3)  and
       SetVar(3) manual pages in the doc directory of the core Tcl distribution.

LINKING TCL VARIABLES TO C VARIABLES

       Tcl_LinkVar and Tcl_UnlinkVar can be used to automatically keep Tcl variables synchronized
       with corresponding C variables.  Once a Tcl variable has been linked to a C variable  with
       Tcl_LinkVar,  anytime  the  Tcl variable is read, the value of the C variable is converted
       (if necessary) and returned, and when the Tcl variable is written, the C variable will  be
       updated with the new value.

       Tcl_LinkVar  uses  variable  traces to keep the Tcl variable named by varName in sync with
       the C variable at the address given by addr.

       Int, double, boolean and char *  variables  are  supported.   You  can  make  your  linked
       variables  read  only  from  the Tcl side, as well.  Please note that the C variables must
       continually exist while they are linked, in other words, linking "automatic" C  variables,
       those  created  on  the  stack while a routine is being executed and destroyed afterwards,
       will result in a malfunctioning program at best and a coredump or more at worst.

       For more  information,  please  examine  the  LinkVar(3)  manual  page  in  the  core  Tcl
       distribution.

ADDING NEW MATH FUNCTIONS TO TCL

       As of Tcl version 7.0, math functions such as sin, cos, etc, are directly supported within
       Tcl expressions.  These obsolete the Extended Tcl commands that provided explicit commands
       for  these  functions  for  many, many releases, although procs equivalencing the old TclX
       commands to the new math functions are still provided for backwards compatibility.

       New math functions can be added to Tcl, or existing math functions  can  be  replaced,  by
       calling Tcl_CreateMathFunc.

ACCESSING AND MANIPULATING THE RANDOM NUMBER GENERATOR

       Prior  to  Tcl  version  8.0,  the  Tcl  core  did  not  provide access to a random number
       generator, but TclX did, through its random command.  As of Tcl version 8.0, access  to  a
       random  number  generator is provided by baseline Tcl through the new math functions, rand
       and srand.

       The TclX random command is still available -- it has some useful capabilities not directly
       provided by the new baseline functions.

       For  more  information  on  adding  your  own  math  functions  to  Tcl,  please study the
       CrtMathFnc(3) manual page in the core Tcl distribution.

CONVERTING FILENAMES TO NATIVE FORM AND PERFORMING TILDE SUBSTITUTIONS

       The Tcl_TranslateFileName function is  available  to  C  extension  writers  to  translate
       filenames  to  a form suitable for use by the local operating system.  It converts network
       names to their native form, and if the name starts with a ``~''  character,  the  function
       returns a new string where the name is replaced with the home directory of the given user.

       For  more  information  please  consult  the  Translate(3)  manual  page  in  the core Tcl
       distribution.

SETTING THE RECURSION LIMIT

       Tcl has a preset recursion limit that limits the maximum allowable nesting depth of  calls
       within  an  interpreter.   This  is  useful for detecting infinite recursions before other
       limits such as the process memory limit or, worse, available swap space on the system, run
       out.

       The  default  limit  is  just  a  guess,  however, and applications that make heavy use of
       recursion  may  need  to  call  Tcl_SetRecursionLimit  to  raise  this  limit.   For  more
       information, please consult the SetRecLmt(3) manual page in the core Tcl distribution.

HANDLING SIGNALS FROM TCL EXTENSIONS

       If an event such as a signal occurs while a Tcl script is being executed, it isn't safe to
       do much in the signal handling routine -- the Tcl environment cannot be safely manipulated
       at  this  point  because  it  could  be  in the middle of some operation, such as updating
       pointers, leaving the interpreter in an unreliable state.

       The only safe approach is to set a flag indicating that the event  occurred,  then  handle
       the  event  later  when  the  interpreter  has returned to a safe state, such as after the
       current Tcl command completes.

       The Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, and Tcl_AsyncDelete functions provide
       a  safe  mechanism  for  dealing  with  signals  and  other asynchronous events.  For more
       information on how to use this capability, please refer to the Async(3) manual page in the
       core Tcl distribution.

       Note  that  Extended  Tcl provides built-in support for managing signals in numerous ways,
       including generating them  with  alarm(2)  and  kill(2),  ignoring  them,  trapping  them,
       getting, setting, blocking and unblocking them.  You can cause specific code to execute at
       a safe point after a signal occurs, or cause a Tcl error backtrace  on  one's  occurrence.
       For more information, please examine the TclX documentation.

PARSING BACKSLASH SEQUENCES

       The  Tcl_Backslash  function  is called to parse Tcl backslash sequences.  These backslash
       sequences are the usual sort that you see in the C programming language, such  as  \n  for
       newline,  \r  for  return, and so forth.  Tcl_Backslash parses a single backslash sequence
       and returns a single character corresponding to the backslash sequence.

       For more info on this call,  look  at  the  Backslash(3)  manual  page  in  the  core  Tcl
       distribution.   For  information  on the valid backslash sequences, consult the summary of
       Tcl language syntax, Tcl(n) in the same distribution.

HASH TABLES

       Hash tables provide Tcl with a high-performance facility for looking up and managing  key-
       value  pairs  located and maintained in memory.  Tcl uses hash tables internally to locate
       procedure definitions, Tcl variables, array elements, file  handles  and  so  forth.   Tcl
       makes the hash table functions accessible to C extension writers as well.

       Hash tables grow automatically to maintain efficiency, rather than exposing the table size
       to the programmer at allocation time, which would needlessly add  complexity  to  Tcl  and
       would  be  prone to inefficiency due to the need to guess the number of items that will go
       into the table, and the seemingly inevitable growth in amount of data  processed  per  run
       over the useful life of the program.

       For  more  information  on hash tables, please consult the Hash(3) manual page in the core
       Tcl distribution.

TRACING VARIABLE ACCESSES

       The C extension writer can arrange to have a C routine called whenever a Tcl  variable  is
       read,  written,  or  unset.  Variable traces are the mechanism by which Tk toolkit widgets
       such as radio and checkbuttons, messages  and  so  forth  update  without  Tcl  programmer
       intervention  when  their  data  variables are changed.  They are also used by the routine
       that links Tcl and C variables, Tcl_LinkVar, described above.

       Tcl_TraceVar is called to establish a variable trace.  Entire arrays and individual  array
       elements can be traced as well.  If the programmer already has an array name in one string
       and a variable name in another, Tcl_TraceVar2 can be called.  Calls are also available  to
       request information about traces and to delete them.

       For  more  information on variable traces, consult the TraceVar(3) manual page in the core
       Tcl distribution.

TRACING TCL EXECUTION

       Tcl has the ability to call C routines each time it  executes  a  Tcl  command,  up  to  a
       specified  depth  of  nesting  levels.   The  command Tcl_CreateTrace creates an execution
       trace; Tcl_DeleteTrace deletes it.

       Command tracing is used in Extended Tcl to implement the cmdtrace Tcl  command,  a  useful
       command for debugging Tcl applications.

       For complete information on execution tracing, please look at the CrtTrace(3) manual pages
       in the core Tcl distribution.

EVALUATING TCL EXPRESSIONS FROM C

       Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBool, and Tcl_ExprString all take  string  arguments
       and,  when  called,  evaluate  those strings as Tcl expressions.  Depending on the routine
       called, the result is either a C long, a double, a boolean (int with a value of 0  or  1),
       or a char * (obtainable through Tcl_GetResult).

       To  take  advantage  of  the  performance  gains  available through the bytecode compiler,
       Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBoolObj, and Tcl_ExprObj all  take  an  object
       containing  an  expression  to  be  evaluated  (rather than a string.)  The result is that
       bytecode-compiled version of the expression will be kept  in  the  object,  alongside  the
       string  representation.   If  the expression is evaluated again, without being changed, it
       does not have to be recompiled... a major performance win.

       For complete information on evaluating Tcl expressions from C, you are invited to  examine
       the ExprLong(3) and ExprLongObj(3) manpages in the core Tcl distribution.

PATTERN MATCHING

       The Tcl_StringMatch function can be called to see if a string matches a specified pattern.
       Tcl_StringMatch is called by the Tcl string match command, so the format for  patterns  is
       identical.   The  pattern  format  is  similar  to  the one used by the C-shell; string(n)
       describes this format.

       More information about Tcl_StringMatch is available in the StrMatch(3) manpage in the core
       Tcl distribution.

REGULAR EXPRESSION PATTERN MATCHING

       Tcl_RegExpMatch  can be called to determine whether a string matches a regular expression.
       Tcl_RegExpMatch is used internally by the regexp Tcl command.

       As regular expressions are typically "compiled" before use, a fairly involved process, Tcl
       also  supports  routines  that  separate  the  compilation  of an expression from its use:
       Tcl_RegExpCompile, Tcl_RegExpExec, and Tcl_RegExpRange.  If an expression is going  to  be
       matched  many  times,  doing  the compile once and caching the compiled regular expression
       result, then reusing the cached version by using  Tcl_RegExpExec,  can  be  a  significant
       performance win.

       For  more  information  on this function, please consult the RegExp(3) manpage in the core
       Tcl distribution.

MANIPULATING TCL LISTS FROM C EXTENSIONS

       The C extension writer  often  needs  to  create,  manipulate  and  decompose  Tcl  lists.
       Tcl_SplitList  and  Tcl_Merge used to be the only way to parse strings into lists and vice
       versa.   As  of  Tcl  8,  lists  can  be  parsed  and   assembled,   object-style,   using
       Tcl_ListObjGetElements  and  Tcl_SetListObj,  and  friends.  Once again the "win" of using
       object-system-based list manipulation, instead of the previous string based  routines,  is
       that the parsing of a string in an object to a list is cached in the object structure, the
       same as with integers and floating point numbers, compiled procedures, etc.  The next time
       this  string  needs  to  be  looked  at  as a list, if the contents of the string have not
       changed, the string does not have to be parsed.

       In the author's experience, working with an admittedly degenerate test whereby we iterated
       rather  inefficiently  across a 6,000-element list, a speedup factor of more than 2500 was
       obtained over the previous non-object-based version of Tcl.

       For more information on these commands, please consult the ListObj(3) manual page  in  the
       core Tcl distribution.

CONCATENATING STRINGS

       Tcl_ConcatObj concatenates the string representation of zero or more objects into a single
       new object.  The elements of the new string are space-separated.  Tcl_Concat does the same
       thing for strings, as Tcl_ConcatObj does for objects.

       Concatenating   strings   is   similar  to  constructing  lists  from  them,  except  that
       Tcl_ConcatObj and Tcl_Concat do not attempt to make the resulting string into a valid  Tcl
       list.

       Tcl_Concat  is  documented  in  the  Concat(3)  manpage, and Tcl_ConcatObj in the tringObj
       manpage, both in the core Tcl distribution.

DETECTING WHETHER OR NOT YOU HAVE A COMPLETE COMMAND

       C routines that collect data to form a command to be passed to Tcl_Eval often need  a  way
       to  tell  whether  they  have  a  complete command already or whether they need more data.
       (Programs that read typed-in Tcl input such  as  Tcl  shells  need  this  capability,  for
       instance.)   Tcl_CommandComplete  can  be  used to tell whether or not you have a complete
       command.

       For more information examine CmdCmplt(3) in the core Tcl distribution.

RECORDING COMMANDS FOR COMMAND HISTORY

       Tcl has a history mechanism that is accessed from Tcl through the history command.  If you
       want  your  extension  to  propagate  commands  into  the command history, you should call
       Tcl_RecordAndEvalObj (object system) or Tcl_RecordAndEval (old system),

       These commands work  like  Tcl_EvalObj  and  Tcl_Eval,  respectively,  except  that  these
       versions record the command as well as executing it.

       Tcl_RecordAndEval  and  Tcl_RecordAndEvlObj  should  only be called with user-entered top-
       level commands, since the history mechanism exists to allow the  user  to  easily  access,
       edit and reissue previously issued commands.

       For  complete  information  on  these  functions,  please  examine  the  RecordEval.3  and
       RecEvalObj.3 manual pages in the core Tcl distribution.

CONVERTING FLOATING POINT VALUES TO STRINGS

       The Tcl object system's Tcl_GetDoubleFromObj and Tcl_SetDoubleObj use Tcl objects,  rather
       than  the strings used by Tcl_PrintDouble, and convert, when necessary, an ASCII string to
       a double and back again.

       These routines ensure that the string output  will  continue  to  be  interpretable  as  a
       floating point number, rather than an integer, by always putting a ``.'' or ``e'' into the
       string representing the number.

       The precision of the output string is controlled by the Tcl tcl_precision variable.

       For complete information on these routines, please examine DoubleObj(3) and PrintDbl(3) in
       the core Tcl distribution.

CREATING CHILD PROCESSES AND PIPELINES FROM C

       Tcl_OpenCommandChannel  provides  a  C-level interface to the exec and open commands.  The
       child (or pipeline of children) can have its standard input, output and  error  redirected
       from  files,  variables  or  pipes.   To understand the meaning of the redirection symbols
       understood by this function, look at the exec(n) Tcl command.  For complete information on
       Tcl_OpenCommandChannel, please examine OpenFileChnl(3).

ACCESSING TCL FILEHANDLES FROM C

       On  Posix/Unix  systems, Tcl filehandles passed to your C extension can be translated to a
       Posix FILE * structure using the Tcl_GetOpenFile function, documented in GetOpnFl.3.

MANAGING BACKGROUND PROCESS TERMINATION AND CLEANUP

       When a Posix system does a fork to create a new process, the process ID of  the  child  is
       returned  to the caller.  After the child process exits, its process table entry (and some
       other data associated with the process) cannot be reclaimed by the operating system  until
       a call to waitpid, or one of a couple of other, similar system calls, has been made by the
       parent process.

       The C extension writer who has created a subprocess, by whatever mechanism, can turn  over
       responsibility  for detecting the processes' termination and calling waitpid to obtain its
       exit status, by calling Tcl_DetachPids on it.

       Tcl_ReapDetachedProcs is the C routine that will detect the termination of  any  processes
       turned  over  to  Tcl,  permitting  the  processes  to be fully reclaimed by the operating
       system.  It is usually not necessary  to  call  Tcl_ReapDetachedProcs,  as  it  is  called
       automatically every time exec is performed.

       For  complete  information on these routines, please look at DetachPids(3) in the core Tcl
       distribution.

FOR MORE INFORMATION

       In addition to the documentation referenced above, you can learn a  lot  by  studying  the
       source  code  of  the  commands added by Tcl, Tk and Extended Tcl, etc.  The comp.lang.tcl
       Usenet newsgroup is read by hundreds of thousands of Tcl people.  A number  of  Frequently
       Asked  Questions  (FAQs) about Tcl are posted there periodically.  The newsgroup is a good
       place to ask questions (after you've made sure they're not already answered in the FAQ ;-)

       Finally,   if   you   have   interactive    Internet    access,    you    can    ftp    to
       ftp://ftp.neosoft.com/pub/tcl,  the  site for contributed Tcl sources.  This site contains
       quite a few extensions, applications, and  so  forth,  including  several  object-oriented
       extension packages.

       If  you  have  access  via  the  world-wide  web,  check  out  the  Sun  Microsystems site
       (http://sunscript.sun.com),     the     contributed      sources      archive      website
       (http://www.neosoft.com/tcl),      and      the      homepage     for     Extended     Tcl
       (http://www.neosoft.com/tclx).

AUTHORS

       Extended  Tcl  was  created  by  Karl  Lehenbauer  (karl@neosoft.com)  and  Mark  Diekhans
       (markd@grizzly.com).