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