os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclIndexObj.c
Update contrib.
4 * This file implements objects of type "index". This object type
5 * is used to lookup a keyword in a table of valid values and cache
6 * the index of the matching entry.
8 * Copyright (c) 1997 Sun Microsystems, Inc.
9 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * RCS: @(#) $Id: tclIndexObj.c,v 1.16.2.5 2006/04/06 18:57:24 dgp Exp $
21 * Prototypes for procedures defined later in this file:
24 static int SetIndexFromAny _ANSI_ARGS_((Tcl_Interp *interp,
26 static void UpdateStringOfIndex _ANSI_ARGS_((Tcl_Obj *objPtr));
27 static void DupIndex _ANSI_ARGS_((Tcl_Obj *srcPtr,
29 static void FreeIndex _ANSI_ARGS_((Tcl_Obj *objPtr));
32 * The structure below defines the index Tcl object type by means of
33 * procedures that can be invoked by generic object code.
36 Tcl_ObjType tclIndexType = {
38 FreeIndex, /* freeIntRepProc */
39 DupIndex, /* dupIntRepProc */
40 UpdateStringOfIndex, /* updateStringProc */
41 SetIndexFromAny /* setFromAnyProc */
45 * The definition of the internal representation of the "index"
46 * object; The internalRep.otherValuePtr field of an object of "index"
47 * type will be a pointer to one of these structures.
49 * Keep this structure declaration in sync with tclTestObj.c
53 VOID *tablePtr; /* Pointer to the table of strings */
54 int offset; /* Offset between table entries */
55 int index; /* Selected index into table. */
59 * The following macros greatly simplify moving through a table...
61 #define STRING_AT(table, offset, index) \
62 (*((CONST char * CONST *)(((char *)(table)) + ((offset) * (index)))))
63 #define NEXT_ENTRY(table, offset) \
64 (&(STRING_AT(table, offset, 1)))
65 #define EXPAND_OF(indexRep) \
66 STRING_AT((indexRep)->tablePtr, (indexRep)->offset, (indexRep)->index)
70 *----------------------------------------------------------------------
72 * Tcl_GetIndexFromObj --
74 * This procedure looks up an object's value in a table of strings
75 * and returns the index of the matching string, if any.
79 * If the value of objPtr is identical to or a unique abbreviation
80 * for one of the entries in objPtr, then the return value is
81 * TCL_OK and the index of the matching entry is stored at
82 * *indexPtr. If there isn't a proper match, then TCL_ERROR is
83 * returned and an error message is left in interp's result (unless
84 * interp is NULL). The msg argument is used in the error
85 * message; for example, if msg has the value "option" then the
86 * error message will say something flag 'bad option "foo": must be
90 * The result of the lookup is cached as the internal rep of
91 * objPtr, so that repeated lookups can be done quickly.
93 *----------------------------------------------------------------------
97 Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr)
98 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
99 Tcl_Obj *objPtr; /* Object containing the string to lookup. */
100 CONST char **tablePtr; /* Array of strings to compare against the
101 * value of objPtr; last entry must be NULL
102 * and there must not be duplicate entries. */
103 CONST char *msg; /* Identifying word to use in error messages. */
104 int flags; /* 0 or TCL_EXACT */
105 int *indexPtr; /* Place to store resulting integer index. */
109 * See if there is a valid cached result from a previous lookup
110 * (doing the check here saves the overhead of calling
111 * Tcl_GetIndexFromObjStruct in the common case where the result
115 if (objPtr->typePtr == &tclIndexType) {
116 IndexRep *indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
118 * Here's hoping we don't get hit by unfortunate packing
119 * constraints on odd platforms like a Cray PVP...
121 if (indexRep->tablePtr == (VOID *)tablePtr &&
122 indexRep->offset == sizeof(char *)) {
123 *indexPtr = indexRep->index;
127 return Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, sizeof(char *),
128 msg, flags, indexPtr);
132 *----------------------------------------------------------------------
134 * Tcl_GetIndexFromObjStruct --
136 * This procedure looks up an object's value given a starting
137 * string and an offset for the amount of space between strings.
138 * This is useful when the strings are embedded in some other
143 * If the value of objPtr is identical to or a unique abbreviation
144 * for one of the entries in objPtr, then the return value is
145 * TCL_OK and the index of the matching entry is stored at
146 * *indexPtr. If there isn't a proper match, then TCL_ERROR is
147 * returned and an error message is left in interp's result (unless
148 * interp is NULL). The msg argument is used in the error
149 * message; for example, if msg has the value "option" then the
150 * error message will say something flag 'bad option "foo": must be
154 * The result of the lookup is cached as the internal rep of
155 * objPtr, so that repeated lookups can be done quickly.
157 *----------------------------------------------------------------------
161 Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags,
163 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
164 Tcl_Obj *objPtr; /* Object containing the string to lookup. */
165 CONST VOID *tablePtr; /* The first string in the table. The second
166 * string will be at this address plus the
167 * offset, the third plus the offset again,
168 * etc. The last entry must be NULL
169 * and there must not be duplicate entries. */
170 int offset; /* The number of bytes between entries */
171 CONST char *msg; /* Identifying word to use in error messages. */
172 int flags; /* 0 or TCL_EXACT */
173 int *indexPtr; /* Place to store resulting integer index. */
175 int index, i, numAbbrev;
178 CONST char * CONST *entryPtr;
183 * See if there is a valid cached result from a previous lookup.
186 if (objPtr->typePtr == &tclIndexType) {
187 indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
188 if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) {
189 *indexPtr = indexRep->index;
195 * Lookup the value of the object in the table. Accept unique
196 * abbreviations unless TCL_EXACT is set in flags.
199 key = TclGetString(objPtr);
204 * Scan the table looking for one of:
205 * - An exact match (always preferred)
206 * - A single abbreviation (allowed depending on flags)
207 * - Several abbreviations (never allowed, but overridden by exact match)
209 for (entryPtr = tablePtr, i = 0; *entryPtr != NULL;
210 entryPtr = NEXT_ENTRY(entryPtr, offset), i++) {
211 for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) {
219 * The value is an abbreviation for this entry. Continue
220 * checking other entries to make sure it's unique. If we
221 * get more than one unique abbreviation, keep searching to
222 * see if there is an exact match, but remember the number
223 * of unique abbreviations and don't allow either.
231 * Check if we were instructed to disallow abbreviations.
233 if ((flags & TCL_EXACT) || (key[0] == '\0') || (numAbbrev != 1)) {
239 * Cache the found representation. Note that we want to avoid
240 * allocating a new internal-rep if at all possible since that is
241 * potentially a slow operation.
243 if (objPtr->typePtr == &tclIndexType) {
244 indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
246 if ((objPtr->typePtr != NULL)
247 && (objPtr->typePtr->freeIntRepProc != NULL)) {
248 objPtr->typePtr->freeIntRepProc(objPtr);
250 indexRep = (IndexRep *) ckalloc(sizeof(IndexRep));
251 objPtr->internalRep.otherValuePtr = (VOID *) indexRep;
252 objPtr->typePtr = &tclIndexType;
254 indexRep->tablePtr = (VOID*) tablePtr;
255 indexRep->offset = offset;
256 indexRep->index = index;
262 if (interp != NULL) {
264 * Produce a fancy error message.
268 TclNewObj(resultPtr);
269 Tcl_SetObjResult(interp, resultPtr);
270 Tcl_AppendStringsToObj(resultPtr, (numAbbrev > 1) &&
271 !(flags & TCL_EXACT) ? "ambiguous " : "bad ", msg, " \"",
272 key, "\": must be ", STRING_AT(tablePtr,offset,0), (char*)NULL);
273 for (entryPtr = NEXT_ENTRY(tablePtr, offset), count = 0;
275 entryPtr = NEXT_ENTRY(entryPtr, offset), count++) {
276 if (*NEXT_ENTRY(entryPtr, offset) == NULL) {
277 Tcl_AppendStringsToObj(resultPtr,
278 (count > 0) ? ", or " : " or ", *entryPtr,
281 Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr,
290 *----------------------------------------------------------------------
294 * This procedure is called to convert a Tcl object to index
295 * internal form. However, this doesn't make sense (need to have a
296 * table of keywords in order to do the conversion) so the
297 * procedure always generates an error.
300 * The return value is always TCL_ERROR, and an error message is
301 * left in interp's result if interp isn't NULL.
306 *----------------------------------------------------------------------
310 SetIndexFromAny(interp, objPtr)
311 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
312 register Tcl_Obj *objPtr; /* The object to convert. */
314 Tcl_AppendToObj(Tcl_GetObjResult(interp),
315 "can't convert value to index except via Tcl_GetIndexFromObj API",
321 *----------------------------------------------------------------------
323 * UpdateStringOfIndex --
325 * This procedure is called to convert a Tcl object from index
326 * internal form to its string form. No abbreviation is ever
333 * The string representation of the object is updated.
335 *----------------------------------------------------------------------
339 UpdateStringOfIndex(objPtr)
342 IndexRep *indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
344 register unsigned len;
345 register CONST char *indexStr = EXPAND_OF(indexRep);
347 len = strlen(indexStr);
348 buf = (char *) ckalloc(len + 1);
349 memcpy(buf, indexStr, len+1);
351 objPtr->length = len;
355 *----------------------------------------------------------------------
359 * This procedure is called to copy the internal rep of an index
360 * Tcl object from to another object.
366 * The internal representation of the target object is updated
367 * and the type is set.
369 *----------------------------------------------------------------------
373 DupIndex(srcPtr, dupPtr)
374 Tcl_Obj *srcPtr, *dupPtr;
376 IndexRep *srcIndexRep = (IndexRep *) srcPtr->internalRep.otherValuePtr;
377 IndexRep *dupIndexRep = (IndexRep *) ckalloc(sizeof(IndexRep));
379 memcpy(dupIndexRep, srcIndexRep, sizeof(IndexRep));
380 dupPtr->internalRep.otherValuePtr = (VOID *) dupIndexRep;
381 dupPtr->typePtr = &tclIndexType;
385 *----------------------------------------------------------------------
389 * This procedure is called to delete the internal rep of an index
396 * The internal representation of the target object is deleted.
398 *----------------------------------------------------------------------
405 ckfree((char *) objPtr->internalRep.otherValuePtr);
409 *----------------------------------------------------------------------
411 * Tcl_WrongNumArgs --
413 * This procedure generates a "wrong # args" error message in an
414 * interpreter. It is used as a utility function by many command
421 * An error message is generated in interp's result object to
422 * indicate that a command was invoked with the wrong number of
423 * arguments. The message has the form
424 * wrong # args: should be "foo bar additional stuff"
425 * where "foo" and "bar" are the initial objects in objv (objc
426 * determines how many of these are printed) and "additional stuff"
427 * is the contents of the message argument.
429 *----------------------------------------------------------------------
433 Tcl_WrongNumArgs(interp, objc, objv, message)
434 Tcl_Interp *interp; /* Current interpreter. */
435 int objc; /* Number of arguments to print
437 Tcl_Obj *CONST objv[]; /* Initial argument objects, which
438 * should be included in the error
440 CONST char *message; /* Error message to print after the
441 * leading objects in objv. The
442 * message may be NULL. */
446 register IndexRep *indexRep;
449 Tcl_SetObjResult(interp, objPtr);
450 Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
451 for (i = 0; i < objc; i++) {
453 * If the object is an index type use the index table which allows
454 * for the correct error message even if the subcommand was
455 * abbreviated. Otherwise, just use the string rep.
458 if (objv[i]->typePtr == &tclIndexType) {
459 indexRep = (IndexRep *) objv[i]->internalRep.otherValuePtr;
460 Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), (char *) NULL);
462 Tcl_AppendStringsToObj(objPtr, Tcl_GetString(objv[i]),
467 * Append a space character (" ") if there is more text to follow
468 * (either another element from objv, or the message string).
470 if ((i < (objc - 1)) || message) {
471 Tcl_AppendStringsToObj(objPtr, " ", (char *) NULL);
476 Tcl_AppendStringsToObj(objPtr, message, (char *) NULL);
478 Tcl_AppendStringsToObj(objPtr, "\"", (char *) NULL);