diff options
author | Steve Bennett <steveb@workware.net.au> | 2011-04-13 10:37:31 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2011-06-01 12:05:19 +1000 |
commit | a2694699f8d3d14465cbd9310678ab723f4bc79f (patch) | |
tree | ca178158c7026183715cf6643c5d2de02ab73553 /jim.c | |
parent | 229239b9443c366f90ca251ede04bfa04ae16cc2 (diff) | |
download | jimtcl-a2694699f8d3d14465cbd9310678ab723f4bc79f.zip jimtcl-a2694699f8d3d14465cbd9310678ab723f4bc79f.tar.gz jimtcl-a2694699f8d3d14465cbd9310678ab723f4bc79f.tar.bz2 |
Add [upcall] command
Allows previous command definitions to be invoked when
otherwise hidden via [local]
Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'jim.c')
-rw-r--r-- | jim.c | 47 |
1 files changed, 44 insertions, 3 deletions
@@ -3297,8 +3297,8 @@ int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName, cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); /* Store the new details for this proc */ + memset(cmdPtr, 0, sizeof(*cmdPtr)); cmdPtr->inUse = 1; - cmdPtr->isproc = 0; cmdPtr->u.native.delProc = delProc; cmdPtr->u.native.cmdProc = cmdProc; cmdPtr->u.native.privData = privData; @@ -3319,6 +3319,7 @@ static int JimCreateProcedure(Jim_Interp *interp, const char *cmdName, Jim_HashEntry *he; cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); + memset(cmdPtr, 0, sizeof(*cmdPtr)); cmdPtr->inUse = 1; cmdPtr->isproc = 1; cmdPtr->u.proc.argListObjPtr = argListObjPtr; @@ -3331,6 +3332,7 @@ static int JimCreateProcedure(Jim_Interp *interp, const char *cmdName, cmdPtr->u.proc.rightArity = rightArity; cmdPtr->u.proc.staticVars = NULL; cmdPtr->u.proc.prevCmd = NULL; + cmdPtr->inUse = 1; /* Create the statics hash table. */ if (staticsListObjPtr) { @@ -3517,9 +3519,14 @@ int SetCommandFromAny(Jim_Interp *interp, Jim_Obj *objPtr) * stored in objPtr. It tries to specialize the objPtr to contain * a cached info instead to perform the lookup into the hash table * every time. The information cached may not be uptodate, in such - * a case the lookup is performed and the cache updated. */ + * a case the lookup is performed and the cache updated. + * + * Respects the 'upcall' setting + */ Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags) { + Jim_Cmd *cmd; + if ((objPtr->typePtr != &commandObjType || objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch) && SetCommandFromAny(interp, objPtr) == JIM_ERR) { @@ -3528,7 +3535,11 @@ Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags) } return NULL; } - return objPtr->internalRep.cmdValue.cmdPtr; + cmd = objPtr->internalRep.cmdValue.cmdPtr; + while (cmd->isproc && cmd->u.proc.upcall) { + cmd = cmd->u.proc.prevCmd; + } + return cmd; } /* ----------------------------------------------------------------------------- @@ -12254,6 +12265,35 @@ static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar return retcode; } +/* [upcall] */ +static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); + return JIM_ERR; + } + else { + int retcode; + + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); + if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->u.proc.prevCmd) { + Jim_SetResultFormatted(interp, "no previous proc: \"%#s\"", argv[1]); + return JIM_ERR; + } + /* OK. Mark this command as being in an upcall */ + cmdPtr->u.proc.upcall++; + JimIncrCmdRefCount(cmdPtr); + + /* Invoke the command as normal */ + retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); + + /* No longer in an upcall */ + cmdPtr->u.proc.upcall--; + JimDecrCmdRefCount(interp, cmdPtr); + + return retcode; + } +} /* [concat] */ static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) @@ -13957,6 +13997,7 @@ static const struct { {"rand", Jim_RandCoreCommand}, {"tailcall", Jim_TailcallCoreCommand}, {"local", Jim_LocalCoreCommand}, + {"upcall", Jim_UpcallCoreCommand}, {NULL, NULL}, }; |