• Values being overwritten in Tcl_HashTable

    From Kevin Walzer@21:1/5 to All on Sun Nov 10 22:37:07 2024
    I am trying to write mulitple key-value pairs to a Tcl_HashTable, but
    when I call Tcl_SetObjResult(ip, Tcl_GetHashValue(hPtr2)), it reads the
    last value written to the hash table - even if that value is not
    associated with the key that I am using.

    Is there a best practice I am missing here? I thought that differing
    keys would be tracked in the hash table and the Tcl_FindHashEntry call
    would return different data depending on the key.

    Tcl_ResetResult does not change the result in the interpreter, which
    tells me the issue is with the table - calls to the key for "role" and
    "name" return the value for "name" - seems like the "role" value has
    been overwritten.

    My C code is below. Any help is appreciated.

    int
    Tk_SetAccessibleRole(
    TCL_UNUSED(void *),
    Tcl_Interp *ip, /* Current interpreter. */
    int objc, /* Number of arguments. */
    Tcl_Obj *const objv[]) /* Argument objects. */
    {
    if (objc < 3) {
    Tcl_WrongNumArgs(ip, 1, objv, "window? role?");
    return TCL_ERROR;
    }

    Tk_Window win;
    char *role;
    Tcl_HashEntry *hPtr, *hPtr2;

    Tcl_HashTable *AccessibleAttributes;
    AccessibleAttributes = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
    Tcl_InitHashTable(AccessibleAttributes,TCL_STRING_KEYS);

    int isNew;
    win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));
    if (win == NULL) {
    return TCL_ERROR;
    }

    /* Set accessible role for window. */
    hPtr=Tcl_CreateHashEntry(TkAccessibilityObject, win, &isNew);

    Tcl_SetHashValue(hPtr, AccessibleAttributes);

    hPtr2 = Tcl_CreateHashEntry(AccessibleAttributes, role, &isNew);
    if (!isNew) {
    Tcl_DecrRefCount(Tcl_GetHashValue(hPtr2));
    }
    Tcl_IncrRefCount(objv[2]);
    Tcl_SetHashValue(hPtr2, objv[2]);

    Tcl_SetObjResult(ip, Tcl_GetHashValue(hPtr2));
    return TCL_OK;
    }


    int
    Tk_SetAccessibleName(
    TCL_UNUSED(void *),
    Tcl_Interp *ip, /* Current interpreter. */
    int objc, /* Number of arguments. */
    Tcl_Obj *const objv[]) /* Argument objects. */
    {
    if (objc < 3) {
    Tcl_WrongNumArgs(ip, 1, objv, "window? name?");
    return TCL_ERROR;
    }

    Tk_Window win;
    char *name;
    Tcl_HashEntry *hPtr, *hPtr2;
    int isNew;
    Tcl_HashTable *AccessibleAttributes;

    win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));
    if (win == NULL) {
    return TCL_ERROR;
    }

    /* Set accessible name for window. */

    hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);
    if (!hPtr) {
    Tcl_AppendResult(ip, "No table found", (char *) NULL);
    return TCL_ERROR;
    }

    AccessibleAttributes = Tcl_GetHashValue(hPtr);
    hPtr2 = Tcl_CreateHashEntry(AccessibleAttributes, name, &isNew);
    if (!isNew) {
    Tcl_DecrRefCount(Tcl_GetHashValue(hPtr2));
    }
    Tcl_IncrRefCount(objv[2]);
    Tcl_SetHashValue(hPtr2, objv[2]);

    Tcl_SetObjResult(ip, Tcl_GetHashValue(hPtr2));
    return TCL_OK;
    }

    int
    Tk_GetAccessibleRole(
    TCL_UNUSED(void *),
    Tcl_Interp *ip, /* Current interpreter. */
    int objc, /* Number of arguments. */
    Tcl_Obj *const objv[]) /* Argument objects. */
    {
    if (objc < 2) {
    Tcl_WrongNumArgs(ip, 1, objv, "window?");
    return TCL_ERROR;
    }

    Tk_Window win;
    char *role;
    Tcl_HashEntry *hPtr, *hPtr2;

    Tcl_HashTable *AccessibleAttributes;

    win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));
    if (win == NULL) {
    return TCL_ERROR;
    }

    /* Get accessible role for window. */
    hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);
    if (!hPtr) {
    Tcl_AppendResult(ip, "No table found", (char *) NULL);
    return TCL_ERROR;
    }
    AccessibleAttributes = Tcl_GetHashValue(hPtr);
    hPtr2=Tcl_FindHashEntry(AccessibleAttributes, (char*) role);
    if (!hPtr2) {
    Tcl_AppendResult(ip, "No role found", (char *) NULL);
    return TCL_ERROR;
    }

    Tcl_SetObjResult(ip, Tcl_GetHashValue(hPtr2));
    return TCL_OK;
    }

    int
    Tk_GetAccessibleName(
    TCL_UNUSED(void *),
    Tcl_Interp *ip, /* Current interpreter. */
    int objc, /* Number of arguments. */
    Tcl_Obj *const objv[]) /* Argument objects. */
    {
    if (objc < 2) {
    Tcl_WrongNumArgs(ip, 1, objv, "window?");
    return TCL_ERROR;
    }

    Tk_Window win;
    char *name;
    Tcl_HashEntry *hPtr, *hPtr2;

    Tcl_HashTable *AccessibleAttributes;

    win = Tk_NameToWindow(ip, Tcl_GetString(objv[1]), Tk_MainWindow(ip));
    if (win == NULL) {
    return TCL_ERROR;
    }

    /* Get accessible name for window. */
    hPtr=Tcl_FindHashEntry(TkAccessibilityObject, win);
    if (!hPtr) {
    Tcl_AppendResult(ip, "No table found", (char *) NULL);
    return TCL_ERROR;
    }
    AccessibleAttributes = Tcl_GetHashValue(hPtr);
    hPtr2=Tcl_FindHashEntry(AccessibleAttributes, (char *) name);
    if (!hPtr2) {
    Tcl_AppendResult(ip, "No name found", (char *) NULL);
    return TCL_ERROR;
    }

    Tcl_SetObjResult(ip, Tcl_GetHashValue(hPtr2));
    return TCL_OK;
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)