[AMG]: Tcl arrays are enumerated via the [[[array names]]] or [[[array get]]] commands or by the (virtually obsolete) combination of [[[array startsearch]]], [[[array nextelement]]], [[[array anymore]]], and [[[array donesearch]]]. At present, they cannot be enumerated via the Tcl C API. The [FlightAware] Tcl bounty program [https://github.com/flightaware/Tcl-bounties] seeks to address this and other Tcl shortcomings. I intend to implement a Tcl C API for enumerating array elements. I am patterning my API on Tcl API listed above and on the C API for accessing variables. The implementation will be obtained by rearranging existing code as much as possible to minimize the inadvertent introduction of new bugs. The above-listed [[[array]]] commands will be reimplemented as calls into the new C API so that it can be tested by the existing Tcl test suite. This will be my first [TIP] and my first case of Tcl core programming. Outside of random bug and documentation fixes, my Tcl C experience is writing proprietary Tcl extensions over the last 10-15 years, and my Tcl scripting experience goes back to 1999. I have commit access to the Tcl Fossil repository. Would there be any problem with me committing my work there onto a branch? Is there anything I should be aware of before I take this step? ---- **API** Here is my working API design. Please share any comments or questions you may have. I welcome opinions about the alternatives and wishes I outline below, and please feel free to add your own ideas. ======c /* Tcl_ArraySearch is an opaque pointer to struct ArraySearch which has * the search internals. The term "search" is reused for the C API even * though it's actually a full enumeration. */ typedef struct ArraySearch *Tcl_ArraySearch; /* Common argument definitions. See Tcl_SetVar(3) for details. */ Tcl_Interp *interp (in) Tcl_Obj *part1Ptr (in) int *objcPtr (out) Tcl_Obj ***objvPtr (out) Tcl_ArraySearch search (in): obtained from Tcl_ArraySearchStart() int flags (in): TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG /* Returns array size or -1 on error. For compatibility with [array * size], 0 is returned if the variable is a scalar or does not exist. * * Alternative: Take an intPtr argument and return TCL_OK or TCL_ERROR. * This approach matches Tcl_ListObjLength(). */ int Tcl_ArraySize(interp, part1Ptr, flags) /* Returns a Tcl_ArraySearch on success or NULL on error. * * Wish: Optional glob filter to match [array names]. */ Tcl_ArraySearch Tcl_ArraySearchStart(interp, part1Ptr, flags) /* Returns name of next element or NULL if finished. */ Tcl_Obj * Tcl_ArraySearchNext(search) /* Cleans up array search internals. * * Alternative name: Tcl_ArraySearchStop(). */ void Tcl_ArraySearchDone(search) /* Gets a list of all array element names. Call ckfree() on objvPtr * when done. * * Alternative: Give caller the option to manage objvPtr memory * directly. Only automatically allocate if *objvPtr is NULL, otherwise * assume it points to a block of memory big enough for Tcl_ArraySize() * Tcl_Obj pointers. * * Alternative: Hybrid approach. If *objvPtr is not NULL and *objcPtr * is at least Tcl_ArraySize(), use it directly as described above. If * *objvPtr is not NULL but *objcPtr is insufficient, attemptckrealloc() * *objvPtr to the minimum required size. This way, Tcl_ArrayGetNames() * can be used many times in a row without allocating and freeing memory * more than needed. Changes objcPtr and objvPtr to be (in/out). Even * if glob filter wish is implemented, would still allocate to match the * array size just in case the filter ends up matching everything. * * Alternative name: Tcl_ArrayNames(). * * Wish: Optional glob filter to match [array names]. */ int Tcl_ArrayGetNames(interp, part1Ptr, objcPtr, objvPtr, flags) ====== ---- **Progress** 20 November 2016 : Began work, implemented Tcl_ArraySize(). <>