tclTestProcBodyObj.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:9k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclTestProcBodyObj.c --
  3.  *
  4.  * Implements the "procbodytest" package, which contains commands
  5.  * to test creation of Tcl procedures whose body argument is a
  6.  * Tcl_Obj of type "procbody" rather than a string.
  7.  *
  8.  * Copyright (c) 1998 by Scriptics Corporation.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * RCS: @(#) $Id: tclTestProcBodyObj.c,v 1.2 1998/11/10 06:54:44 jingham Exp $
  14.  */
  15. #include "tclInt.h"
  16. /*
  17.  * name and version of this package
  18.  */
  19. static char packageName[] = "procbodytest";
  20. static char packageVersion[] = "1.0";
  21. /*
  22.  * Name of the commands exported by this package
  23.  */
  24. static char procCommand[] = "proc";
  25. /*
  26.  * this struct describes an entry in the table of command names and command
  27.  * procs
  28.  */
  29. typedef struct CmdTable
  30. {
  31.     char *cmdName; /* command name */
  32.     Tcl_ObjCmdProc *proc; /* command proc */
  33.     int exportIt; /* if 1, export the command */
  34. } CmdTable;
  35. /*
  36.  * Declarations for functions defined in this file.
  37.  */
  38. static int ProcBodyTestProcObjCmd _ANSI_ARGS_((ClientData dummy,
  39. Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
  40. static int ProcBodyTestInitInternal _ANSI_ARGS_((Tcl_Interp *interp,
  41. int isSafe));
  42. static int RegisterCommand _ANSI_ARGS_((Tcl_Interp* interp,
  43. char *namespace, CONST CmdTable *cmdTablePtr));
  44. int             Procbodytest_Init _ANSI_ARGS_((Tcl_Interp * interp));
  45. int             Procbodytest_SafeInit _ANSI_ARGS_((Tcl_Interp * interp));
  46. /*
  47.  * List of commands to create when the package is loaded; must go after the
  48.  * declarations of the enable command procedure.
  49.  */
  50. static CONST CmdTable commands[] =
  51. {
  52.     { procCommand, ProcBodyTestProcObjCmd, 1 },
  53.     { 0, 0, 0 }
  54. };
  55. static CONST CmdTable safeCommands[] =
  56. {
  57.     { procCommand, ProcBodyTestProcObjCmd, 1 },
  58.     { 0, 0, 0 }
  59. };
  60. /*
  61.  *----------------------------------------------------------------------
  62.  *
  63.  * Procbodytest_Init --
  64.  *
  65.  *  This procedure initializes the "procbodytest" package.
  66.  *
  67.  * Results:
  68.  *  A standard Tcl result.
  69.  *
  70.  * Side effects:
  71.  *  None.
  72.  *
  73.  *----------------------------------------------------------------------
  74.  */
  75. int
  76. Procbodytest_Init(interp)
  77.     Tcl_Interp *interp; /* the Tcl interpreter for which the package
  78.                                  * is initialized */
  79. {
  80.     return ProcBodyTestInitInternal(interp, 0);
  81. }
  82. /*
  83.  *----------------------------------------------------------------------
  84.  *
  85.  * Procbodytest_SafeInit --
  86.  *
  87.  *  This procedure initializes the "procbodytest" package.
  88.  *
  89.  * Results:
  90.  *  A standard Tcl result.
  91.  *
  92.  * Side effects:
  93.  *  None.
  94.  *
  95.  *----------------------------------------------------------------------
  96.  */
  97. int
  98. Procbodytest_SafeInit(interp)
  99.     Tcl_Interp *interp; /* the Tcl interpreter for which the package
  100.                                  * is initialized */
  101. {
  102.     return ProcBodyTestInitInternal(interp, 1);
  103. }
  104. /*
  105.  *----------------------------------------------------------------------
  106.  *
  107.  * RegisterCommand --
  108.  *
  109.  *  This procedure registers a command in the context of the given namespace.
  110.  *
  111.  * Results:
  112.  *  A standard Tcl result.
  113.  *
  114.  * Side effects:
  115.  *  None.
  116.  *
  117.  *----------------------------------------------------------------------
  118.  */
  119. static int RegisterCommand(interp, namespace, cmdTablePtr)
  120.     Tcl_Interp* interp; /* the Tcl interpreter for which the
  121.                                          * operation is performed */
  122.     char *namespace; /* the namespace in which the command
  123.                                          * is registered */
  124.     CONST CmdTable *cmdTablePtr; /* the command to register */
  125. {
  126.     char buf[128];
  127.     if (cmdTablePtr->exportIt) {
  128.         sprintf(buf, "namespace eval %s { namespace export %s }",
  129.                 namespace, cmdTablePtr->cmdName);
  130.         if (Tcl_Eval(interp, buf) != TCL_OK)
  131.             return TCL_ERROR;
  132.     }
  133.     
  134.     sprintf(buf, "%s::%s", namespace, cmdTablePtr->cmdName);
  135.     Tcl_CreateObjCommand(interp, buf, cmdTablePtr->proc, 0, 0);
  136.     return TCL_OK;
  137. }
  138. /*
  139.  *----------------------------------------------------------------------
  140.  *
  141.  * ProcBodyTestInitInternal --
  142.  *
  143.  *  This procedure initializes the Loader package.
  144.  *  The isSafe flag is 1 if the interpreter is safe, 0 otherwise.
  145.  *
  146.  * Results:
  147.  *  A standard Tcl result.
  148.  *
  149.  * Side effects:
  150.  *  None.
  151.  *
  152.  *----------------------------------------------------------------------
  153.  */
  154. static int
  155. ProcBodyTestInitInternal(interp, isSafe)
  156.     Tcl_Interp *interp; /* the Tcl interpreter for which the package
  157.                                  * is initialized */
  158.     int isSafe; /* 1 if this is a safe interpreter */
  159. {
  160.     CONST CmdTable *cmdTablePtr;
  161.     cmdTablePtr = (isSafe) ? &safeCommands[0] : &commands[0];
  162.     for ( ; cmdTablePtr->cmdName ; cmdTablePtr++) {
  163.         if (RegisterCommand(interp, packageName, cmdTablePtr) != TCL_OK) {
  164.             return TCL_ERROR;
  165.         }
  166.     }
  167.     
  168.     return Tcl_PkgProvide(interp, packageName, packageVersion);
  169. }
  170. /*
  171.  *----------------------------------------------------------------------
  172.  *
  173.  * ProcBodyTestProcObjCmd --
  174.  *
  175.  *  Implements the "procbodytest::proc" command. Here is the command
  176.  *  description:
  177.  * procbodytest::proc newName argList bodyName
  178.  *  Looks up a procedure called $bodyName and, if the procedure exists,
  179.  *  constructs a Tcl_Obj of type "procbody" and calls Tcl_ProcObjCmd.
  180.  *  Arguments:
  181.  *    newName the name of the procedure to be created
  182.  *    argList the argument list for the procedure
  183.  *    bodyName the name of an existing procedure from which the
  184.  * body is to be copied.
  185.  *  This command can be used to trigger the branches in Tcl_ProcObjCmd that
  186.  *  construct a proc from a "procbody", for example:
  187.  * proc a {x} {return $x}
  188.  * a 123
  189.  * procbodytest::proc b {x} a
  190.  *  Note the call to "a 123", which is necessary so that the Proc pointer
  191.  *  for "a" is filled in by the internal compiler; this is a hack.
  192.  *
  193.  * Results:
  194.  *  Returns a standard Tcl code.
  195.  *
  196.  * Side effects:
  197.  *  A new procedure is created.
  198.  *  Leaves an error message in the interp's result on error.
  199.  *
  200.  *----------------------------------------------------------------------
  201.  */
  202. static int
  203. ProcBodyTestProcObjCmd (dummy, interp, objc, objv)
  204.     ClientData dummy; /* context; not used */
  205.     Tcl_Interp *interp; /* the current interpreter */
  206.     int objc; /* argument count */
  207.     Tcl_Obj *CONST objv[]; /* arguments */
  208. {
  209.     char *fullName;
  210.     Tcl_Command procCmd;
  211.     Command *cmdPtr;
  212.     Proc *procPtr = (Proc *) NULL;
  213.     Tcl_Obj *bodyObjPtr;
  214.     Tcl_Obj *myobjv[5];
  215.     int result;
  216.     
  217.     if (objc != 4) {
  218. Tcl_WrongNumArgs(interp, 1, objv, "newName argsList bodyName");
  219. return TCL_ERROR;
  220.     }
  221.     /*
  222.      * Find the Command pointer to this procedure
  223.      */
  224.     
  225.     fullName = Tcl_GetStringFromObj(objv[3], (int *) NULL);
  226.     procCmd = Tcl_FindCommand(interp, fullName, (Tcl_Namespace *) NULL,
  227.             TCL_LEAVE_ERR_MSG);
  228.     if (procCmd == NULL) {
  229.         return TCL_ERROR;
  230.     }
  231.     cmdPtr = (Command *) procCmd;
  232.     /*
  233.      * check that this is a procedure and not a builtin command:
  234.      * If a procedure, cmdPtr->objProc is either 0 or TclObjInterpProc,
  235.      * and cmdPtr->proc is either 0 or TclProcInterpProc.
  236.      * Also, the compile proc should be 0, but we don't check for that.
  237.      */
  238.     if (((cmdPtr->objProc != NULL)
  239.             && (cmdPtr->objProc != TclGetObjInterpProc()))
  240.             || ((cmdPtr->proc != NULL)
  241.                     && (cmdPtr->proc != TclGetInterpProc()))) {
  242.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  243. "command "", fullName,
  244. "" is not a Tcl procedure", (char *) NULL);
  245.         return TCL_ERROR;
  246.     }
  247.     /*
  248.      * it is a Tcl procedure: the client data is the Proc structure
  249.      */
  250.     
  251.     if (cmdPtr->objProc != NULL) {
  252.         procPtr = (Proc *) cmdPtr->objClientData;
  253.     } else if (cmdPtr->proc != NULL) {
  254.         procPtr = (Proc *) cmdPtr->clientData;
  255.     }
  256.     if (procPtr == NULL) {
  257.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  258. "procedure "", fullName,
  259. "" does not have a Proc struct!", (char *) NULL);
  260.         return TCL_ERROR;
  261.     }
  262.         
  263.     /*
  264.      * create a new object, initialize our argument vector, call into Tcl
  265.      */
  266.     bodyObjPtr = TclNewProcBodyObj(procPtr);
  267.     if (bodyObjPtr == NULL) {
  268.         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
  269. "failed to create a procbody object for procedure "",
  270.                 fullName, """, (char *) NULL);
  271.         return TCL_ERROR;
  272.     }
  273.     Tcl_IncrRefCount(bodyObjPtr);
  274.     myobjv[0] = objv[0];
  275.     myobjv[1] = objv[1];
  276.     myobjv[2] = objv[2];
  277.     myobjv[3] = bodyObjPtr;
  278.     myobjv[4] = (Tcl_Obj *) NULL;
  279.     result = Tcl_ProcObjCmd((ClientData) NULL, interp, objc, myobjv);
  280.     Tcl_DecrRefCount(bodyObjPtr);
  281.     return result;
  282. }