TIP 731: Use C Enums in Public Tcl API

Login
Bounty program for improvements to Tcl and certain Tcl packages.
 Author:         Donal K. Fellows <dkf@users.sf.net>
 State:          Draft
 Type:           Project
 Tcl-Version:    9.1
 Vote:           Pending
 Created:        08-Sep-2025
 Keywords:       Tcl, C, API, constant
 Tcl-Branch:     public-enum

Abstract

The Tcl C API makes many constants available for callers to use. This TIP proposes making many of them into enum members.

Rationale

Tcl's C API has many constants defined in it, for all sorts of reasons. Mostly, they're defined something like this:

/*
 *----------------------------------------------------------------------------
 * Type values returned by Tcl_GetNumberFromObj
 *	TCL_NUMBER_INT		Representation is a Tcl_WideInt
 *	TCL_NUMBER_BIG		Representation is an mp_int
 *	TCL_NUMBER_DOUBLE	Representation is a double
 *	TCL_NUMBER_NAN		Value is NaN.
 */

#define TCL_NUMBER_INT          2
#define TCL_NUMBER_BIG          3
#define TCL_NUMBER_DOUBLE       4
#define TCL_NUMBER_NAN          5

Constants with patterns like that feel a lot like enumeration members. We should make that more formal, though only where we can and when it feels suitable (i.e., they're a group of pseudo-sequential values or a set of bit flags).

Specification

I propose changing the above to be something more like this:

/*
 *----------------------------------------------------------------------------
 * Type values returned by Tcl_GetNumberFromObj
 */
enum Tcl_GetNumberFromObjTypes {
    TCL_NUMBER_INT = 2,		/* Representation is a Tcl_WideInt */
    TCL_NUMBER_BIG = 3,		/* Representation is an mp_int */
    TCL_NUMBER_DOUBLE = 4,	/* Representation is a double */
    TCL_NUMBER_NAN = 5		/* Value is NaN. */
};

As used, this works identically, but now actually provides a stronger hint that these values are semantically related.

I've given the enum a name based on its usage (the namespace of enum types in C is separate from other namespaces) but haven't done any typedefs. As far as I'm aware (from searching on Github), no code exists that checks whether any of these constants are defined macros.

Be aware that the release levels at the top of tcl.h must not be converted, due to their use by the Windows resource compiler. There are a few other exceptions to the conversion, and I've also left anything that people might want to tune. But nobody's going to want to tune the number type codes unless they're rebuilding Tcl itself!

List of Added Enum Names

In order of their appearance in tcl.h (non-normative; other TIPs may add to this list):

  • Tcl_CreateThreadFlags
  • Tcl_StringCaseMatchFlags
  • Tcl_GetRegExpFromObjFlags
  • Tcl_RegExpExecObjFlags
  • Tcl_ResultCode
  • Tcl_SubstObjFlags
  • Tcl_GetNumberFromObjTypes
  • Tcl_ConvertElementFlags
  • Tcl_GetIndexFromObjFlags
  • Tcl_UniCharToUtfFlags
  • Tcl_EvalFlags
  • Tcl_VarFlags
  • Tcl_EnsembleFlags
  • Tcl_CommandFlags
  • Tcl_LinkTypes
  • Tcl_HashKeyTypeFlags
  • Tcl_HashKeyTypeVersions
  • Tcl_HashKeyTypes
  • Tcl_DoOneEventFlags
  • Tcl_QueuePosition - name added follows existing typedef
  • Tcl_ServiceModes
  • Tcl_ChannelHandlerFlags
  • Tcl_OpenCommandChannelFlags
  • Tcl_CloseDirection
  • Tcl_ChannelThreadActions
  • Tcl_BlockModeFlags
  • Tcl_GlobTypes
  • Tcl_GlobPermissions
  • Tcl_UnloadOperations
  • Tcl_FSLinkActions
  • Tcl_TokenTypes
  • Tcl_ParseResults
  • Tcl_EncodingConversionFlags
  • Tcl_EncodingProfiles
  • Tcl_EncodingConversionResults
  • Tcl_UnicodeNormalizationForm - name added follows existing typedef
  • Tcl_LimitTypes
  • Tcl_ArgvInfoTypes
  • Tcl_ZlibFormats
  • Tcl_ZlibStreamModes
  • Tcl_ZlibCompressionLevels
  • Tcl_ZlibFlushModes
  • Tcl_LoadFileFlags
  • Tcl_OpenTcpFlags

Implementation

See the public-enum branch.

Copyright

This document has been placed in the public domain.

History