Ticket UUID: | 520304 | |||
Title: | Tcl_GetIndexFromObjStruct signature | |||
Type: | Bug | Version: | obsolete: 8.4a4 | |
Submitter: | jenglish | Created on: | 2002-02-20 02:56:44 | |
Subsystem: | 13. Index Object | Assigned To: | dgp | |
Priority: | 5 Medium | Severity: | ||
Status: | Closed | Last Modified: | 2002-02-28 12:09:55 | |
Resolution: | Fixed | Closed By: | dgp | |
Closed on: | 2002-02-28 05:09:55 | |||
Description: |
In the TIP27-ification of tclIndexObj.c, the third parameter of Tcl_GetIndexFromObjStruct() changed from a 'char **' to a 'CONST char **' (actually a CONST84 char **). In the actual use of the function though, the 'tablePtr' argument typically does not point (directly) to a 'char *' or a 'const char *', but rather to an array of some user-defined structure type (whose first member is a 'char *' or 'const char *'). So the most appropriate type is probably 'void *structTablePtr' (which should be cast to a 'char *' internally to do address arithmetic and to a 'CONST char **' to extract the string value, just like it does now.) This change would also make it easier to write extensions that compile against pre- and post-TIP27 versions of the core without resorting to #ifdefs or -DUSE_NON_CONST; inserting a cast to (void *) would suffice for pre-TIP27 versions. | |||
User Comments: |
dgp added on 2002-02-28 12:09:55:
Logged In: YES user_id=80530 committing on the blessing of the maintainer. I've fixed the documentation. I kept the macro, though; it's defined in the very same file, so availability should not be a problem. nijtmans added on 2002-02-26 21:53:57: Logged In: YES user_id=61031 The attached patch only rises one question,regarding generic/tclIndexObj.c line 77: STRING_AT(tablePtr,offset,0) I think it is better simply to write: *(CONST char **) tablePtr Probably those two are identical, but I am always reductant to depend on the availability of such macros. Apart from that there is a "*" too much in doc/GetIndex.3 line 39: .AP "CONST VOID" **structTablePtr in this should be .AP "CONST VOID" *structTablePtr in With those 2 little changes the patch is OK with me. Thanks for the very fruitful discussion! Regards, Jan Nijtmans dgp added on 2002-02-22 06:26:22: Logged In: YES user_id=80530 seems to work. If it's good enough for the maintainer, it's good enough for me. jenglish added on 2002-02-22 04:44:31: File Added - 18224: patch jenglish added on 2002-02-22 04:44:30: Logged In: YES user_id=68433 > Got a patch, anyone? OK, see attached. My changes to doc/GetIndex.3 should probably be rewritten, but it compiles cleanly and passes indexObj.test. dgp added on 2002-02-22 02:38:45: Logged In: YES user_id=80530 Got a patch, anyone? dkf added on 2002-02-21 22:56:28: Logged In: YES user_id=79902 Seems like a good plan to me, describing (as it does) that it's a pointer to some unknown structure that won't get modified... nijtmans added on 2002-02-21 22:31:47: Logged In: YES user_id=61031 One of the reasons for TIP 27 was to be able to use the Tcl library in C++ code, even if input parameters were declared const. So, what if we use "static const struct substOption" in stead of "static struct substOption". The example code by Jou still then works without any type-cast. In that light, I would prefer to use (const void *) as the second parameter of Tcl_GetIndexFromObjStruct, and that's what it really is: a const pointer to an unknown structure. Then the (SOME_CAST) in Jou's example code can simply be left out, both in C and C++ code. Is everybody happy with that alternative? jenglish added on 2002-02-21 03:02:46: Logged In: YES user_id=68433 Hm, I'm having a hard time locating instances of Tcl_GetIndexFromObjStruct in the wild. As an example, here's a modified version of the option-parsing part of Tcl_SubstObjCommand; switching to Tcl_GetIndexFromObjStruct() simplifies the code since we can get rid of an enum declaration and a switch statement: static struct substOption { const char *option; unsigned int mask; } substOptions[] = { { "-nobackslashes", TCL_SUBST_BACKSLASHES }, { "-nocommands", TCL_SUBST_COMMANDS }, { "-novariables", TCL_SUBST_VARIABLES }, { NULL, 0 } }; flags = TCL_SUBST_ALL; for (i = 1; i < (objc-1); i++) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], (SOME_CAST)substOptions, sizeof(substOptions[0]), "switch", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } flags &= ~substOptions[optionIndex].mask; } /* ... */ With the old signature, "SOME_CAST" is 'char **'; with the current signature 'SOME_CAST' is 'CONST84 char **'. With the proposed signature, a cast isn't necessary. For cross-version compatibility, SOME_CAST can be 'void *', which will work with all three signatures (except in C++ code, in which case it will only work if Tcl_GetIndexFromObjStruct takes a 'void *'). But the main issue is that the "tablePtr" argument normally points to a an array of structures of unknown type, so 'void *' is the most appropriate type. [later] > Payoff is really in calls to Tcl_GetIndexFromObj(), where you can let the compiler auto-cast to (void *) I don't think Tcl_GetIndexFromObj() should be changed, only Tcl_GetIndexFromObjStruct(). The 'tablePtr' argument to the former really _is_ a 'const char **'; declaring it as a 'void *' would only weaken the type-safety that TIP27 was intended to enhance. dgp added on 2002-02-21 01:03:47: Logged In: YES user_id=80530 Maybe I'm getting it. Payoff is really in calls to Tcl_GetIndexFromObj(), where you can let the compiler auto-cast to (void *) ? Got a patch we can try? dgp added on 2002-02-21 00:54:35: Logged In: YES user_id=80530 An example would help me understand. Where is there extension code that calls Tcl_GetIndexFromObjStruct(), and how would a different signature help that code compile against 8.3 and 8.4 headers? |
Attachments:
- patch [download] added by jenglish on 2002-02-22 04:44:30. [details]