[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 programme] [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. ---- **Code** http://core.tcl.tk/tcl/timeline?r=amg-array-enum-c-api ---- **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. ***Types*** ****typedef struct ArraySearch *Tcl_ArraySearch**** 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. ***Arguments*** ****Tcl_Interp *interp (in)**** Interpreter containing array variable. ****Tcl_Obj *part1Ptr (in)**** Points to a Tcl object containing the variable's name. The name may include a series of :: namespace qualifiers to specify an array varaible in a particular namespace. ****Tcl_Obj *part2Ptr (in)**** Points to a Tcl object containing the element name filter. If NULL, no filtering is applied. ****Tcl_Obj *listPtr (out)**** Tcl list object to which array names are appended. ****Tcl_ArraySearch search (in)**** Search token obtained from Tcl_ArraySearchStart(). ****int flags (in)**** OR-ed combination of bits providing additional information. Can be TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG | TCL_MATCH_EXACT | TCL_MATCH_GLOB | TCL_MATCH_REGEXP. ***Functions*** ****int Tcl_ArraySize(interp, part1Ptr, flags)**** Returns array size or -1 on error. part2Ptr can be used to specify an element filter, in which case the return value is the number of array elements matching the filter. ****Tcl_ArraySearch Tcl_ArraySearchStart(interp, part1Ptr, part2Ptr, flags)**** Returns a Tcl_ArraySearch on success or NULL on error. part2Ptr can be used to specify an element filter. ****Tcl_Obj *Tcl_ArraySearchNext(search)**** Returns name of next element or NULL if finished. ****void Tcl_ArraySearchDone(search)**** Cleans up array search internals. ****int Tcl_ArrayNames(interp, part1Ptr, part2Ptr, listPtr, flags)**** Appends array element names to the listPtr list object. part2Ptr can be used to specify an element filter. The reason listPtr is not created or reinitialized but rather appended to is so Tcl_ArrayNames() can be called multiple times on a single list object, with a different filter each time, to build a list of all elements matching any one of the filters. In this usage, elements matching multiple filters will be listed multiple times. To reset listPtr before calling Tcl_ArrayNames(), truncate it by calling Tcl_SetListObj(listPtr, 0, NULL). ---- **Progress** 20 November 2016 : Began work, implemented Tcl_ArraySize(). 24 November 2016 : Published commits, fixed [[[array size]]] reporting of trace errors, improved Wiki page, added filtering, implemented Tcl_ArraySearchStart(). <>