TIP 618: New Tcl_GetBool* functions with TCL_NULL_OK flag

Login
Author:         Jan Nijtmans <[email protected]>
State:          Final
Type:           Project
Vote:           Done
Post-History:   
Keywords:       Tcl Tcl_GetBoolFromObj() Tcl_GetBool()
Tcl-Version:    8.7
Tcl-Branch:     tip-618
Vote-Summary   Accepted 5/0/0
Votes-For:     FV, JN, KW, MC, SL
Votes-Against: none
Votes-Present: none

Abstract

This TIP proposes new functions Tcl_GetBoolFromObj/Tcl_GetBool which are the same as Tcl_GetBooleanFromObj/Tcl_GetBoolean but have an additional flags parameter, and use char as variable type. Also accepted is the TCL_NULL_OK flag, which is - actually - a renamed TCL_INDEX_NULL_OK: We wouldn't want a separate TCL_BOOL_NULL_OK.

If Tcl_GetBooleanFromObj/Tcl_GetBoolean is provided the TCL_NULL_OK flag, it can output not only 0 or 1 but also '\xFF'. Without the TCL_NULL_OK flag, the only possible outcomes are 0 and 1. In Tcl, there is not much usage for the TCL_NULL_OK, flag but in Tk it is more common to have values which can be empty as well as 0 or 1. E.g. the -elide, -overstrike and underline options of text tags.

Rationale

The functions Tcl_GetBooleanFromObj/Tcl_GetBoolean store a boolean value into a int, which - in many cases - is overkill since 0 and 1 are the only possible value.

With the new functions, we can do:

    #include <tcl.h>
    char bool1;
    Tcl_Obj *obj = Tcl_NewStringObj("true", -1);
    Tcl_GetBoolFromObj(NULL, obj, 0, &bool1);

Also, the functions Tcl_GetBoolFromObj/Tcl_GetBool have an additional flags parameter. At this moment only the values 0 and TCL_NULL_OK are allowed. Thanks to the TCL_NULL_OK flag, we can replace this code in Tk with a single call to Tcl_GetBoolFromObj(): The -elide, -overstrike and -underline options for text tags are already mentioned, that's the intended usage of this flag.

Other flag values can be added in the future.

History

This TIP has been in vote before, with the result of only gaining one YES vote and 3 PRESENT votes. There were 2 main remarks, indicating this TIP did too many things at once, the implications of that couldn't be grasped by the voters. Therefore, the TIP has been rewritten (and the implementation simplified). The remarks were:

  1. "... I don't think I grok the entire implications of the discussion we had on this list about (void *) abuses".

In C, "void *" can be used when the function accepts multiple different types. E.g. malloc() or memcpy() are perfect examples, but also the use of ClientData in Tcl is not an abuse of "void *". The caller is responsible making sure that a pointer of the correct type is used. In the case of Tcl_GetBoolFromObj/Tcl_GetBool, the function accepts any 1-, 2-, 4- or 8-byte enum, bool or integer type. As long as the functions know the sizeof() of the variable, no invalid memory will be addressed.

The suggestion is also done to split this into different functions depending on the sizeof() the variable. That would be possible, but then 8 new functions should be added, and - still - a "void *" should be used as last argument: possible 1-byte types could be bool, char, signed char or unsigned char. 2-byte types could be VARIANT_BOOL, wchar_t, short or unsigned short. We don't want functions for every possible type here, when the sizeof() the variable is the only thing we really care about.

  1. "Even after sleeping over it I find myself unable to agree to the macro shenanigans for the transmission of the size of the referenced variable, even while admiring the hackishness of it."

The implementation rewrite doesn't use macro's any more.

Implementation

Available in the tip-618 branch.

This branch targets 8.7.

Copyright

This document has been placed in the public domain.