OpenFPGA/libs/EXTERNAL/tcl8.6.12/pkgs/thread2.8.7/generic/threadSvKeylistCmd.c

350 lines
9.4 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* threadSvKeylist.c --
*
* This file implements keyed-list commands as part of the thread
* shared variable implementation.
*
* Keyed list implementation is borrowed from Mark Diekhans and
* Karl Lehenbauer "TclX" (extended Tcl) extension. Please look
* into the keylist.c file for more information.
*
* See the file "license.txt" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
* ---------------------------------------------------------------------------
*/
#include "threadSvCmd.h"
#include "threadSvKeylistCmd.h"
#include "tclXkeylist.h"
/*
* Wrapped keyed-list commands
*/
static Tcl_ObjCmdProc SvKeylsetObjCmd;
static Tcl_ObjCmdProc SvKeylgetObjCmd;
static Tcl_ObjCmdProc SvKeyldelObjCmd;
static Tcl_ObjCmdProc SvKeylkeysObjCmd;
/*
* This mutex protects a static variable which tracks
* registration of commands and object types.
*/
static Tcl_Mutex initMutex;
/*
*-----------------------------------------------------------------------------
*
* Sv_RegisterKeylistCommands --
*
* Register shared variable commands for TclX keyed lists.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Memory gets allocated
*
*-----------------------------------------------------------------------------
*/
void
Sv_RegisterKeylistCommands(void)
{
static int initialized;
if (initialized == 0) {
Tcl_MutexLock(&initMutex);
if (initialized == 0) {
Sv_RegisterCommand("keylset", SvKeylsetObjCmd, NULL, 0);
Sv_RegisterCommand("keylget", SvKeylgetObjCmd, NULL, 0);
Sv_RegisterCommand("keyldel", SvKeyldelObjCmd, NULL, 0);
Sv_RegisterCommand("keylkeys", SvKeylkeysObjCmd, NULL, 0);
Sv_RegisterObjType(&keyedListType, DupKeyedListInternalRepShared);
initialized = 1;
}
Tcl_MutexUnlock(&initMutex);
}
}
/*
*-----------------------------------------------------------------------------
*
* SvKeylsetObjCmd --
*
* This procedure is invoked to process the "tsv::keylset" command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*-----------------------------------------------------------------------------
*/
static int
SvKeylsetObjCmd(
void *arg, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[] /* Argument objects. */
) {
int i, off, ret, flg;
char *key;
Tcl_Obj *val;
Container *svObj = (Container*)arg;
/*
* Syntax:
* sv::keylset array lkey key value ?key value ...?
* $keylist keylset key value ?key value ...?
*/
flg = FLAGS_CREATEARRAY | FLAGS_CREATEVAR;
ret = Sv_GetContainer(interp, objc, objv, &svObj, &off, flg);
if (ret != TCL_OK) {
return TCL_ERROR;
}
if ((objc - off) < 2 || ((objc - off) % 2)) {
Tcl_WrongNumArgs(interp, off, objv, "key value ?key value ...?");
goto cmd_err;
}
for (i = off; i < objc; i += 2) {
key = Tcl_GetString(objv[i]);
val = Sv_DuplicateObj(objv[i+1]);
ret = TclX_KeyedListSet(interp, svObj->tclObj, key, val);
if (ret != TCL_OK) {
goto cmd_err;
}
}
return Sv_PutContainer(interp, svObj, SV_CHANGED);
cmd_err:
return Sv_PutContainer(interp, svObj, SV_ERROR);
}
/*
*-----------------------------------------------------------------------------
*
* SvKeylgetObjCmd --
*
* This procedure is invoked to process the "tsv::keylget" command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*-----------------------------------------------------------------------------
*/
static int
SvKeylgetObjCmd(
void *arg, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[] /* Argument objects. */
) {
int ret, flg, off;
char *key;
Tcl_Obj *varObjPtr = NULL, *valObjPtr = NULL;
Container *svObj = (Container*)arg;
/*
* Syntax:
* sv::keylget array lkey ?key? ?var?
* $keylist keylget ?key? ?var?
*/
flg = FLAGS_CREATEARRAY | FLAGS_CREATEVAR;
ret = Sv_GetContainer(interp, objc, objv, &svObj, &off, flg);
if (ret != TCL_OK) {
return TCL_ERROR;
}
if ((objc - off) > 2) {
Tcl_WrongNumArgs(interp, off, objv, "?key? ?var?");
goto cmd_err;
}
if ((objc - off) == 0) {
if (Sv_PutContainer(interp, svObj, SV_UNCHANGED) != TCL_OK) {
return TCL_ERROR;
}
return SvKeylkeysObjCmd(arg, interp, objc, objv);
}
if ((objc - off) == 2) {
varObjPtr = objv[off+1];
} else {
varObjPtr = NULL;
}
key = Tcl_GetString(objv[off]);
ret = TclX_KeyedListGet(interp, svObj->tclObj, key, &valObjPtr);
if (ret == TCL_ERROR) {
goto cmd_err;
}
if (ret == TCL_BREAK) {
if (varObjPtr) {
Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
} else {
Tcl_AppendResult (interp, "key \"", key, "\" not found", NULL);
goto cmd_err;
}
} else {
Tcl_Obj *resObjPtr = Sv_DuplicateObj(valObjPtr);
if (varObjPtr) {
Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
Tcl_GetString(varObjPtr);
if (varObjPtr->length) {
Tcl_ObjSetVar2(interp, varObjPtr, NULL, resObjPtr, 0);
}
} else {
Tcl_SetObjResult(interp, resObjPtr);
}
}
return Sv_PutContainer(interp, svObj, SV_UNCHANGED);
cmd_err:
return Sv_PutContainer(interp, svObj, SV_ERROR);
}
/*
*-----------------------------------------------------------------------------
*
* SvKeyldelObjCmd --
*
* This procedure is invoked to process the "tsv::keyldel" command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*-----------------------------------------------------------------------------
*/
static int
SvKeyldelObjCmd(
void *arg, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[] /* Argument objects. */
) {
int i, off, ret;
char *key;
Container *svObj = (Container*)arg;
/*
* Syntax:
* sv::keyldel array lkey key ?key ...?
* $keylist keyldel ?key ...?
*/
ret = Sv_GetContainer(interp, objc, objv, &svObj, &off, 0);
if (ret != TCL_OK) {
return TCL_ERROR;
}
if ((objc - off) < 1) {
Tcl_WrongNumArgs(interp, off, objv, "key ?key ...?");
goto cmd_err;
}
for (i = off; i < objc; i++) {
key = Tcl_GetString(objv[i]);
ret = TclX_KeyedListDelete(interp, svObj->tclObj, key);
if (ret == TCL_BREAK) {
Tcl_AppendResult(interp, "key \"", key, "\" not found", NULL);
}
if (ret == TCL_BREAK || ret == TCL_ERROR) {
goto cmd_err;
}
}
return Sv_PutContainer(interp, svObj, SV_CHANGED);
cmd_err:
return Sv_PutContainer(interp, svObj, SV_ERROR);
}
/*
*-----------------------------------------------------------------------------
*
* SvKeylkeysObjCmd --
*
* This procedure is invoked to process the "tsv::keylkeys" command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*-----------------------------------------------------------------------------
*/
static int
SvKeylkeysObjCmd(
void *arg, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[] /* Argument objects. */
) {
int ret, off;
char *key = NULL;
Tcl_Obj *listObj = NULL;
Container *svObj = (Container*)arg;
/*
* Syntax:
* sv::keylkeys array lkey ?key?
* $keylist keylkeys ?key?
*/
ret = Sv_GetContainer(interp, objc, objv, &svObj, &off, 0);
if (ret != TCL_OK) {
return TCL_ERROR;
}
if ((objc - off) > 1) {
Tcl_WrongNumArgs(interp, 1, objv, "?lkey?");
goto cmd_err;
}
if ((objc - off) == 1) {
key = Tcl_GetString(objv[off]);
}
ret = TclX_KeyedListGetKeys(interp, svObj->tclObj, key, &listObj);
if (key && ret == TCL_BREAK) {
Tcl_AppendResult(interp, "key \"", key, "\" not found", NULL);
}
if (ret == TCL_BREAK || ret == TCL_ERROR) {
goto cmd_err;
}
Tcl_SetObjResult (interp, listObj); /* listObj allocated by API !*/
return Sv_PutContainer(interp, svObj, SV_UNCHANGED);
cmd_err:
return Sv_PutContainer(interp, svObj, SV_ERROR);
}
/* EOF $RCSfile: threadSvKeylistCmd.c,v $ */
/* Emacs Setup Variables */
/* Local Variables: */
/* mode: C */
/* indent-tabs-mode: nil */
/* c-basic-offset: 4 */
/* End: */