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