Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/generic/tclStringObj.c @ 25

Last change on this file since 25 was 25, checked in by landauf, 16 years ago

added tcl to libs

File size: 72.5 KB
Line 
1/*
2 * tclStringObj.c --
3 *
4 *      This file contains functions that implement string operations on Tcl
5 *      objects. Some string operations work with UTF strings and others
6 *      require Unicode format. Functions that require knowledge of the width
7 *      of each character, such as indexing, operate on Unicode data.
8 *
9 *      A Unicode string is an internationalized string. Conceptually, a
10 *      Unicode string is an array of 16-bit quantities organized as a
11 *      sequence of properly formed UTF-8 characters. There is a one-to-one
12 *      map between Unicode and UTF characters. Because Unicode characters
13 *      have a fixed width, operations such as indexing operate on Unicode
14 *      data. The String object is optimized for the case where each UTF char
15 *      in a string is only one byte. In this case, we store the value of
16 *      numChars, but we don't store the Unicode data (unless Tcl_GetUnicode
17 *      is explicitly called).
18 *
19 *      The String object type stores one or both formats. The default
20 *      behavior is to store UTF. Once Unicode is calculated by a function, it
21 *      is stored in the internal rep for future access (without an additional
22 *      O(n) cost).
23 *
24 *      To allow many appends to be done to an object without constantly
25 *      reallocating the space for the string or Unicode representation, we
26 *      allocate double the space for the string or Unicode and use the
27 *      internal representation to keep track of how much space is used vs.
28 *      allocated.
29 *
30 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
31 * Copyright (c) 1999 by Scriptics Corporation.
32 *
33 * See the file "license.terms" for information on usage and redistribution of
34 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
35 *
36 * RCS: @(#) $Id: tclStringObj.c,v 1.70 2008/02/28 17:36:49 dgp Exp $ */
37
38#include "tclInt.h"
39#include "tommath.h"
40
41/*
42 * Prototypes for functions defined later in this file:
43 */
44
45static void             AppendUnicodeToUnicodeRep(Tcl_Obj *objPtr,
46                            const Tcl_UniChar *unicode, int appendNumChars);
47static void             AppendUnicodeToUtfRep(Tcl_Obj *objPtr,
48                            const Tcl_UniChar *unicode, int numChars);
49static void             AppendUtfToUnicodeRep(Tcl_Obj *objPtr,
50                            const char *bytes, int numBytes);
51static void             AppendUtfToUtfRep(Tcl_Obj *objPtr,
52                            const char *bytes, int numBytes);
53static void             FillUnicodeRep(Tcl_Obj *objPtr);
54static void             AppendPrintfToObjVA(Tcl_Obj *objPtr,
55                            const char *format, va_list argList);
56static void             FreeStringInternalRep(Tcl_Obj *objPtr);
57static void             DupStringInternalRep(Tcl_Obj *objPtr,
58                            Tcl_Obj *copyPtr);
59static int              SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
60static void             UpdateStringOfString(Tcl_Obj *objPtr);
61
62/*
63 * The structure below defines the string Tcl object type by means of
64 * functions that can be invoked by generic object code.
65 */
66
67Tcl_ObjType tclStringType = {
68    "string",                   /* name */
69    FreeStringInternalRep,      /* freeIntRepPro */
70    DupStringInternalRep,       /* dupIntRepProc */
71    UpdateStringOfString,       /* updateStringProc */
72    SetStringFromAny            /* setFromAnyProc */
73};
74
75/*
76 * The following structure is the internal rep for a String object. It keeps
77 * track of how much memory has been used and how much has been allocated for
78 * the Unicode and UTF string to enable growing and shrinking of the UTF and
79 * Unicode reps of the String object with fewer mallocs. To optimize string
80 * length and indexing operations, this structure also stores the number of
81 * characters (same of UTF and Unicode!) once that value has been computed.
82 *
83 * Under normal configurations, what Tcl calls "Unicode" is actually UTF-16
84 * restricted to the Basic Multilingual Plane (i.e. U+00000 to U+0FFFF). This
85 * can be officially modified by altering the definition of Tcl_UniChar in
86 * tcl.h, but do not do that unless you are sure what you're doing!
87 */
88
89typedef struct String {
90    int numChars;               /* The number of chars in the string. -1 means
91                                 * this value has not been calculated. >= 0
92                                 * means that there is a valid Unicode rep, or
93                                 * that the number of UTF bytes == the number
94                                 * of chars. */
95    size_t allocated;           /* The amount of space actually allocated for
96                                 * the UTF string (minus 1 byte for the
97                                 * termination char). */
98    size_t uallocated;          /* The amount of space actually allocated for
99                                 * the Unicode string (minus 2 bytes for the
100                                 * termination char). */
101    int hasUnicode;             /* Boolean determining whether the string has
102                                 * a Unicode representation. */
103    Tcl_UniChar unicode[2];     /* The array of Unicode chars. The actual size
104                                 * of this field depends on the 'uallocated'
105                                 * field above. */
106} String;
107
108#define STRING_UALLOC(numChars) \
109        (numChars * sizeof(Tcl_UniChar))
110#define STRING_SIZE(ualloc) \
111        ((unsigned) ((ualloc) \
112                 ? sizeof(String) - sizeof(Tcl_UniChar) + (ualloc) \
113                 : sizeof(String)))
114#define GET_STRING(objPtr) \
115        ((String *) (objPtr)->internalRep.otherValuePtr)
116#define SET_STRING(objPtr, stringPtr) \
117        ((objPtr)->internalRep.otherValuePtr = (void *) (stringPtr))
118
119/*
120 * TCL STRING GROWTH ALGORITHM
121 *
122 * When growing strings (during an append, for example), the following growth
123 * algorithm is used:
124 *
125 *   Attempt to allocate 2 * (originalLength + appendLength)
126 *   On failure:
127 *      attempt to allocate originalLength + 2*appendLength +
128 *                      TCL_GROWTH_MIN_ALLOC
129 *
130 * This algorithm allows very good performance, as it rapidly increases the
131 * memory allocated for a given string, which minimizes the number of
132 * reallocations that must be performed. However, using only the doubling
133 * algorithm can lead to a significant waste of memory. In particular, it may
134 * fail even when there is sufficient memory available to complete the append
135 * request (but there is not 2*totalLength memory available). So when the
136 * doubling fails (because there is not enough memory available), the
137 * algorithm requests a smaller amount of memory, which is still enough to
138 * cover the request, but which hopefully will be less than the total
139 * available memory.
140 *
141 * The addition of TCL_GROWTH_MIN_ALLOC allows for efficient handling of very
142 * small appends. Without this extra slush factor, a sequence of several small
143 * appends would cause several memory allocations. As long as
144 * TCL_GROWTH_MIN_ALLOC is a reasonable size, we can avoid that behavior.
145 *
146 * The growth algorithm can be tuned by adjusting the following parameters:
147 *
148 * TCL_GROWTH_MIN_ALLOC         Additional space, in bytes, to allocate when
149 *                              the double allocation has failed. Default is
150 *                              1024 (1 kilobyte).
151 */
152
153#ifndef TCL_GROWTH_MIN_ALLOC
154#define TCL_GROWTH_MIN_ALLOC    1024
155#endif
156
157/*
158 *----------------------------------------------------------------------
159 *
160 * Tcl_NewStringObj --
161 *
162 *      This function is normally called when not debugging: i.e., when
163 *      TCL_MEM_DEBUG is not defined. It creates a new string object and
164 *      initializes it from the byte pointer and length arguments.
165 *
166 *      When TCL_MEM_DEBUG is defined, this function just returns the result
167 *      of calling the debugging version Tcl_DbNewStringObj.
168 *
169 * Results:
170 *      A newly created string object is returned that has ref count zero.
171 *
172 * Side effects:
173 *      The new object's internal string representation will be set to a copy
174 *      of the length bytes starting at "bytes". If "length" is negative, use
175 *      bytes up to the first NUL byte; i.e., assume "bytes" points to a
176 *      C-style NUL-terminated string. The object's type is set to NULL. An
177 *      extra NUL is added to the end of the new object's byte array.
178 *
179 *----------------------------------------------------------------------
180 */
181
182#ifdef TCL_MEM_DEBUG
183#undef Tcl_NewStringObj
184Tcl_Obj *
185Tcl_NewStringObj(
186    const char *bytes,          /* Points to the first of the length bytes
187                                 * used to initialize the new object. */
188    int length)                 /* The number of bytes to copy from "bytes"
189                                 * when initializing the new object. If
190                                 * negative, use bytes up to the first NUL
191                                 * byte. */
192{
193    return Tcl_DbNewStringObj(bytes, length, "unknown", 0);
194}
195#else /* if not TCL_MEM_DEBUG */
196Tcl_Obj *
197Tcl_NewStringObj(
198    const char *bytes,          /* Points to the first of the length bytes
199                                 * used to initialize the new object. */
200    int length)                 /* The number of bytes to copy from "bytes"
201                                 * when initializing the new object. If
202                                 * negative, use bytes up to the first NUL
203                                 * byte. */
204{
205    register Tcl_Obj *objPtr;
206
207    if (length < 0) {
208        length = (bytes? strlen(bytes) : 0);
209    }
210    TclNewStringObj(objPtr, bytes, length);
211    return objPtr;
212}
213#endif /* TCL_MEM_DEBUG */
214
215/*
216 *----------------------------------------------------------------------
217 *
218 * Tcl_DbNewStringObj --
219 *
220 *      This function is normally called when debugging: i.e., when
221 *      TCL_MEM_DEBUG is defined. It creates new string objects. It is the
222 *      same as the Tcl_NewStringObj function above except that it calls
223 *      Tcl_DbCkalloc directly with the file name and line number from its
224 *      caller. This simplifies debugging since then the [memory active]
225 *      command will report the correct file name and line number when
226 *      reporting objects that haven't been freed.
227 *
228 *      When TCL_MEM_DEBUG is not defined, this function just returns the
229 *      result of calling Tcl_NewStringObj.
230 *
231 * Results:
232 *      A newly created string object is returned that has ref count zero.
233 *
234 * Side effects:
235 *      The new object's internal string representation will be set to a copy
236 *      of the length bytes starting at "bytes". If "length" is negative, use
237 *      bytes up to the first NUL byte; i.e., assume "bytes" points to a
238 *      C-style NUL-terminated string. The object's type is set to NULL. An
239 *      extra NUL is added to the end of the new object's byte array.
240 *
241 *----------------------------------------------------------------------
242 */
243
244#ifdef TCL_MEM_DEBUG
245Tcl_Obj *
246Tcl_DbNewStringObj(
247    const char *bytes,          /* Points to the first of the length bytes
248                                 * used to initialize the new object. */
249    int length,                 /* The number of bytes to copy from "bytes"
250                                 * when initializing the new object. If
251                                 * negative, use bytes up to the first NUL
252                                 * byte. */
253    const char *file,           /* The name of the source file calling this
254                                 * function; used for debugging. */
255    int line)                   /* Line number in the source file; used for
256                                 * debugging. */
257{
258    register Tcl_Obj *objPtr;
259
260    if (length < 0) {
261        length = (bytes? strlen(bytes) : 0);
262    }
263    TclDbNewObj(objPtr, file, line);
264    TclInitStringRep(objPtr, bytes, length);
265    return objPtr;
266}
267#else /* if not TCL_MEM_DEBUG */
268Tcl_Obj *
269Tcl_DbNewStringObj(
270    const char *bytes,          /* Points to the first of the length bytes
271                                 * used to initialize the new object. */
272    register int length,        /* The number of bytes to copy from "bytes"
273                                 * when initializing the new object. If
274                                 * negative, use bytes up to the first NUL
275                                 * byte. */
276    const char *file,           /* The name of the source file calling this
277                                 * function; used for debugging. */
278    int line)                   /* Line number in the source file; used for
279                                 * debugging. */
280{
281    return Tcl_NewStringObj(bytes, length);
282}
283#endif /* TCL_MEM_DEBUG */
284
285/*
286 *---------------------------------------------------------------------------
287 *
288 * Tcl_NewUnicodeObj --
289 *
290 *      This function is creates a new String object and initializes it from
291 *      the given Unicode String. If the Utf String is the same size as the
292 *      Unicode string, don't duplicate the data.
293 *
294 * Results:
295 *      The newly created object is returned. This object will have no initial
296 *      string representation. The returned object has a ref count of 0.
297 *
298 * Side effects:
299 *      Memory allocated for new object and copy of Unicode argument.
300 *
301 *---------------------------------------------------------------------------
302 */
303
304Tcl_Obj *
305Tcl_NewUnicodeObj(
306    const Tcl_UniChar *unicode, /* The unicode string used to initialize the
307                                 * new object. */
308    int numChars)               /* Number of characters in the unicode
309                                 * string. */
310{
311    Tcl_Obj *objPtr;
312    String *stringPtr;
313    size_t uallocated;
314
315    if (numChars < 0) {
316        numChars = 0;
317        if (unicode) {
318            while (unicode[numChars] != 0) {
319                numChars++;
320            }
321        }
322    }
323    uallocated = STRING_UALLOC(numChars);
324
325    /*
326     * Create a new obj with an invalid string rep.
327     */
328
329    TclNewObj(objPtr);
330    Tcl_InvalidateStringRep(objPtr);
331    objPtr->typePtr = &tclStringType;
332
333    stringPtr = (String *) ckalloc(STRING_SIZE(uallocated));
334    stringPtr->numChars = numChars;
335    stringPtr->uallocated = uallocated;
336    stringPtr->hasUnicode = (numChars > 0);
337    stringPtr->allocated = 0;
338    memcpy(stringPtr->unicode, unicode, uallocated);
339    stringPtr->unicode[numChars] = 0;
340    SET_STRING(objPtr, stringPtr);
341    return objPtr;
342}
343
344/*
345 *----------------------------------------------------------------------
346 *
347 * Tcl_GetCharLength --
348 *
349 *      Get the length of the Unicode string from the Tcl object.
350 *
351 * Results:
352 *      Pointer to unicode string representing the unicode object.
353 *
354 * Side effects:
355 *      Frees old internal rep. Allocates memory for new "String" internal
356 *      rep.
357 *
358 *----------------------------------------------------------------------
359 */
360
361int
362Tcl_GetCharLength(
363    Tcl_Obj *objPtr)            /* The String object to get the num chars
364                                 * of. */
365{
366    String *stringPtr;
367
368    SetStringFromAny(NULL, objPtr);
369    stringPtr = GET_STRING(objPtr);
370
371    /*
372     * If numChars is unknown, then calculate the number of characaters while
373     * populating the Unicode string.
374     */
375
376    if (stringPtr->numChars == -1) {
377        register int i = objPtr->length;
378        register unsigned char *str = (unsigned char *) objPtr->bytes;
379
380        /*
381         * This is a speed sensitive function, so run specially over the
382         * string to count continuous ascii characters before resorting to the
383         * Tcl_NumUtfChars call. This is a long form of:
384         stringPtr->numChars = Tcl_NumUtfChars(objPtr->bytes,objPtr->length);
385         *
386         * TODO: Consider macro-izing this.
387         */
388
389        while (i && (*str < 0xC0)) {
390            i--;
391            str++;
392        }
393        stringPtr->numChars = objPtr->length - i;
394        if (i) {
395            stringPtr->numChars += Tcl_NumUtfChars(objPtr->bytes
396                    + (objPtr->length - i), i);
397        }
398
399        if (stringPtr->numChars == objPtr->length) {
400            /*
401             * Since we've just calculated the number of chars, and all UTF
402             * chars are 1-byte long, we don't need to store the unicode
403             * string.
404             */
405
406            stringPtr->hasUnicode = 0;
407        } else {
408            /*
409             * Since we've just calucalated the number of chars, and not all
410             * UTF chars are 1-byte long, go ahead and populate the unicode
411             * string.
412             */
413
414            FillUnicodeRep(objPtr);
415
416            /*
417             * We need to fetch the pointer again because we have just
418             * reallocated the structure to make room for the Unicode data.
419             */
420
421            stringPtr = GET_STRING(objPtr);
422        }
423    }
424    return stringPtr->numChars;
425}
426
427/*
428 *----------------------------------------------------------------------
429 *
430 * Tcl_GetUniChar --
431 *
432 *      Get the index'th Unicode character from the String object. The index
433 *      is assumed to be in the appropriate range.
434 *
435 * Results:
436 *      Returns the index'th Unicode character in the Object.
437 *
438 * Side effects:
439 *      Fills unichar with the index'th Unicode character.
440 *
441 *----------------------------------------------------------------------
442 */
443
444Tcl_UniChar
445Tcl_GetUniChar(
446    Tcl_Obj *objPtr,            /* The object to get the Unicode charater
447                                 * from. */
448    int index)                  /* Get the index'th Unicode character. */
449{
450    Tcl_UniChar unichar;
451    String *stringPtr;
452
453    SetStringFromAny(NULL, objPtr);
454    stringPtr = GET_STRING(objPtr);
455
456    if (stringPtr->numChars == -1) {
457        /*
458         * We haven't yet calculated the length, so we don't have the Unicode
459         * str. We need to know the number of chars before we can do indexing.
460         */
461
462        Tcl_GetCharLength(objPtr);
463
464        /*
465         * We need to fetch the pointer again because we may have just
466         * reallocated the structure.
467         */
468
469        stringPtr = GET_STRING(objPtr);
470    }
471    if (stringPtr->hasUnicode == 0) {
472        /*
473         * All of the characters in the Utf string are 1 byte chars, so we
474         * don't store the unicode char. We get the Utf string and convert the
475         * index'th byte to a Unicode character.
476         */
477
478        unichar = (Tcl_UniChar) objPtr->bytes[index];
479    } else {
480        unichar = stringPtr->unicode[index];
481    }
482    return unichar;
483}
484
485/*
486 *----------------------------------------------------------------------
487 *
488 * Tcl_GetUnicode --
489 *
490 *      Get the Unicode form of the String object. If the object is not
491 *      already a String object, it will be converted to one. If the String
492 *      object does not have a Unicode rep, then one is create from the UTF
493 *      string format.
494 *
495 * Results:
496 *      Returns a pointer to the object's internal Unicode string.
497 *
498 * Side effects:
499 *      Converts the object to have the String internal rep.
500 *
501 *----------------------------------------------------------------------
502 */
503
504Tcl_UniChar *
505Tcl_GetUnicode(
506    Tcl_Obj *objPtr)            /* The object to find the unicode string
507                                 * for. */
508{
509    String *stringPtr;
510
511    SetStringFromAny(NULL, objPtr);
512    stringPtr = GET_STRING(objPtr);
513
514    if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
515        /*
516         * We haven't yet calculated the length, or all of the characters in
517         * the Utf string are 1 byte chars (so we didn't store the unicode
518         * str). Since this function must return a unicode string, and one has
519         * not yet been stored, force the Unicode to be calculated and stored
520         * now.
521         */
522
523        FillUnicodeRep(objPtr);
524
525        /*
526         * We need to fetch the pointer again because we have just reallocated
527         * the structure to make room for the Unicode data.
528         */
529
530        stringPtr = GET_STRING(objPtr);
531    }
532    return stringPtr->unicode;
533}
534
535/*
536 *----------------------------------------------------------------------
537 *
538 * Tcl_GetUnicodeFromObj --
539 *
540 *      Get the Unicode form of the String object with length. If the object
541 *      is not already a String object, it will be converted to one. If the
542 *      String object does not have a Unicode rep, then one is create from the
543 *      UTF string format.
544 *
545 * Results:
546 *      Returns a pointer to the object's internal Unicode string.
547 *
548 * Side effects:
549 *      Converts the object to have the String internal rep.
550 *
551 *----------------------------------------------------------------------
552 */
553
554Tcl_UniChar *
555Tcl_GetUnicodeFromObj(
556    Tcl_Obj *objPtr,            /* The object to find the unicode string
557                                 * for. */
558    int *lengthPtr)             /* If non-NULL, the location where the string
559                                 * rep's unichar length should be stored. If
560                                 * NULL, no length is stored. */
561{
562    String *stringPtr;
563
564    SetStringFromAny(NULL, objPtr);
565    stringPtr = GET_STRING(objPtr);
566
567    if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
568        /*
569         * We haven't yet calculated the length, or all of the characters in
570         * the Utf string are 1 byte chars (so we didn't store the unicode
571         * str). Since this function must return a unicode string, and one has
572         * not yet been stored, force the Unicode to be calculated and stored
573         * now.
574         */
575
576        FillUnicodeRep(objPtr);
577
578        /*
579         * We need to fetch the pointer again because we have just reallocated
580         * the structure to make room for the Unicode data.
581         */
582
583        stringPtr = GET_STRING(objPtr);
584    }
585
586    if (lengthPtr != NULL) {
587        *lengthPtr = stringPtr->numChars;
588    }
589    return stringPtr->unicode;
590}
591
592/*
593 *----------------------------------------------------------------------
594 *
595 * Tcl_GetRange --
596 *
597 *      Create a Tcl Object that contains the chars between first and last of
598 *      the object indicated by "objPtr". If the object is not already a
599 *      String object, convert it to one. The first and last indices are
600 *      assumed to be in the appropriate range.
601 *
602 * Results:
603 *      Returns a new Tcl Object of the String type.
604 *
605 * Side effects:
606 *      Changes the internal rep of "objPtr" to the String type.
607 *
608 *----------------------------------------------------------------------
609 */
610
611Tcl_Obj *
612Tcl_GetRange(
613    Tcl_Obj *objPtr,            /* The Tcl object to find the range of. */
614    int first,                  /* First index of the range. */
615    int last)                   /* Last index of the range. */
616{
617    Tcl_Obj *newObjPtr;         /* The Tcl object to find the range of. */
618    String *stringPtr;
619
620    SetStringFromAny(NULL, objPtr);
621    stringPtr = GET_STRING(objPtr);
622
623    if (stringPtr->numChars == -1) {
624        /*
625         * We haven't yet calculated the length, so we don't have the Unicode
626         * str. We need to know the number of chars before we can do indexing.
627         */
628
629        Tcl_GetCharLength(objPtr);
630
631        /*
632         * We need to fetch the pointer again because we may have just
633         * reallocated the structure.
634         */
635
636        stringPtr = GET_STRING(objPtr);
637    }
638
639    if (objPtr->bytes && (stringPtr->numChars == objPtr->length)) {
640        char *str = TclGetString(objPtr);
641
642        /*
643         * All of the characters in the Utf string are 1 byte chars, so we
644         * don't store the unicode char. Create a new string object containing
645         * the specified range of chars.
646         */
647
648        newObjPtr = Tcl_NewStringObj(&str[first], last-first+1);
649
650        /*
651         * Since we know the new string only has 1-byte chars, we can set it's
652         * numChars field.
653         */
654
655        SetStringFromAny(NULL, newObjPtr);
656        stringPtr = GET_STRING(newObjPtr);
657        stringPtr->numChars = last-first+1;
658    } else {
659        newObjPtr = Tcl_NewUnicodeObj(stringPtr->unicode + first,
660                last-first+1);
661    }
662    return newObjPtr;
663}
664
665/*
666 *----------------------------------------------------------------------
667 *
668 * Tcl_SetStringObj --
669 *
670 *      Modify an object to hold a string that is a copy of the bytes
671 *      indicated by the byte pointer and length arguments.
672 *
673 * Results:
674 *      None.
675 *
676 * Side effects:
677 *      The object's string representation will be set to a copy of the
678 *      "length" bytes starting at "bytes". If "length" is negative, use bytes
679 *      up to the first NUL byte; i.e., assume "bytes" points to a C-style
680 *      NUL-terminated string. The object's old string and internal
681 *      representations are freed and the object's type is set NULL.
682 *
683 *----------------------------------------------------------------------
684 */
685
686void
687Tcl_SetStringObj(
688    register Tcl_Obj *objPtr,   /* Object whose internal rep to init. */
689    const char *bytes,          /* Points to the first of the length bytes
690                                 * used to initialize the object. */
691    register int length)        /* The number of bytes to copy from "bytes"
692                                 * when initializing the object. If negative,
693                                 * use bytes up to the first NUL byte.*/
694{
695    /*
696     * Free any old string rep, then set the string rep to a copy of the
697     * length bytes starting at "bytes".
698     */
699
700    if (Tcl_IsShared(objPtr)) {
701        Tcl_Panic("%s called with shared object", "Tcl_SetStringObj");
702    }
703
704    /*
705     * Set the type to NULL and free any internal rep for the old type.
706     */
707
708    TclFreeIntRep(objPtr);
709    objPtr->typePtr = NULL;
710
711    Tcl_InvalidateStringRep(objPtr);
712    if (length < 0) {
713        length = (bytes? strlen(bytes) : 0);
714    }
715    TclInitStringRep(objPtr, bytes, length);
716}
717
718/*
719 *----------------------------------------------------------------------
720 *
721 * Tcl_SetObjLength --
722 *
723 *      This function changes the length of the string representation of an
724 *      object.
725 *
726 * Results:
727 *      None.
728 *
729 * Side effects:
730 *      If the size of objPtr's string representation is greater than length,
731 *      then it is reduced to length and a new terminating null byte is stored
732 *      in the strength. If the length of the string representation is greater
733 *      than length, the storage space is reallocated to the given length; a
734 *      null byte is stored at the end, but other bytes past the end of the
735 *      original string representation are undefined. The object's internal
736 *      representation is changed to "expendable string".
737 *
738 *----------------------------------------------------------------------
739 */
740
741void
742Tcl_SetObjLength(
743    register Tcl_Obj *objPtr,   /* Pointer to object. This object must not
744                                 * currently be shared. */
745    register int length)        /* Number of bytes desired for string
746                                 * representation of object, not including
747                                 * terminating null byte. */
748{
749    String *stringPtr;
750
751    if (Tcl_IsShared(objPtr)) {
752        Tcl_Panic("%s called with shared object", "Tcl_SetObjLength");
753    }
754    SetStringFromAny(NULL, objPtr);
755
756    stringPtr = GET_STRING(objPtr);
757
758    /*
759     * Check that we're not extending a pure unicode string.
760     */
761
762    if (length > (int) stringPtr->allocated &&
763            (objPtr->bytes != NULL || stringPtr->hasUnicode == 0)) {
764        /*
765         * Not enough space in current string. Reallocate the string space and
766         * free the old string.
767         */
768
769        if (objPtr->bytes != tclEmptyStringRep) {
770            objPtr->bytes = ckrealloc((char *) objPtr->bytes,
771                    (unsigned) (length + 1));
772        } else {
773            char *newBytes = ckalloc((unsigned) (length+1));
774
775            if (objPtr->bytes != NULL && objPtr->length != 0) {
776                memcpy(newBytes, objPtr->bytes, (size_t) objPtr->length);
777                Tcl_InvalidateStringRep(objPtr);
778            }
779            objPtr->bytes = newBytes;
780        }
781        stringPtr->allocated = length;
782
783        /*
784         * Invalidate the unicode data.
785         */
786
787        stringPtr->hasUnicode = 0;
788    }
789
790    if (objPtr->bytes != NULL) {
791        objPtr->length = length;
792        if (objPtr->bytes != tclEmptyStringRep) {
793            /*
794             * Ensure the string is NUL-terminated.
795             */
796
797            objPtr->bytes[length] = 0;
798        }
799
800        /*
801         * Invalidate the unicode data.
802         */
803
804        stringPtr->numChars = -1;
805        stringPtr->hasUnicode = 0;
806    } else {
807        /*
808         * Changing length of pure unicode string.
809         */
810
811        size_t uallocated = STRING_UALLOC(length);
812
813        if (uallocated > stringPtr->uallocated) {
814            stringPtr = (String *) ckrealloc((char*) stringPtr,
815                    STRING_SIZE(uallocated));
816            SET_STRING(objPtr, stringPtr);
817            stringPtr->uallocated = uallocated;
818        }
819        stringPtr->numChars = length;
820        stringPtr->hasUnicode = (length > 0);
821
822        /*
823         * Ensure the string is NUL-terminated.
824         */
825
826        stringPtr->unicode[length] = 0;
827        stringPtr->allocated = 0;
828        objPtr->length = 0;
829    }
830}
831
832/*
833 *----------------------------------------------------------------------
834 *
835 * Tcl_AttemptSetObjLength --
836 *
837 *      This function changes the length of the string representation of an
838 *      object. It uses the attempt* (non-panic'ing) memory allocators.
839 *
840 * Results:
841 *      1 if the requested memory was allocated, 0 otherwise.
842 *
843 * Side effects:
844 *      If the size of objPtr's string representation is greater than length,
845 *      then it is reduced to length and a new terminating null byte is stored
846 *      in the strength. If the length of the string representation is greater
847 *      than length, the storage space is reallocated to the given length; a
848 *      null byte is stored at the end, but other bytes past the end of the
849 *      original string representation are undefined. The object's internal
850 *      representation is changed to "expendable string".
851 *
852 *----------------------------------------------------------------------
853 */
854
855int
856Tcl_AttemptSetObjLength(
857    register Tcl_Obj *objPtr,   /* Pointer to object. This object must not
858                                 * currently be shared. */
859    register int length)        /* Number of bytes desired for string
860                                 * representation of object, not including
861                                 * terminating null byte. */
862{
863    String *stringPtr;
864
865    if (Tcl_IsShared(objPtr)) {
866        Tcl_Panic("%s called with shared object", "Tcl_AttemptSetObjLength");
867    }
868    SetStringFromAny(NULL, objPtr);
869
870    stringPtr = GET_STRING(objPtr);
871
872    /*
873     * Check that we're not extending a pure unicode string.
874     */
875
876    if (length > (int) stringPtr->allocated &&
877            (objPtr->bytes != NULL || stringPtr->hasUnicode == 0)) {
878        char *newBytes;
879
880        /*
881         * Not enough space in current string. Reallocate the string space and
882         * free the old string.
883         */
884
885        if (objPtr->bytes != tclEmptyStringRep) {
886            newBytes = attemptckrealloc(objPtr->bytes,
887                    (unsigned)(length + 1));
888            if (newBytes == NULL) {
889                return 0;
890            }
891        } else {
892            newBytes = attemptckalloc((unsigned) (length + 1));
893            if (newBytes == NULL) {
894                return 0;
895            }
896            if (objPtr->bytes != NULL && objPtr->length != 0) {
897                memcpy(newBytes, objPtr->bytes, (size_t) objPtr->length);
898                Tcl_InvalidateStringRep(objPtr);
899            }
900        }
901        objPtr->bytes = newBytes;
902        stringPtr->allocated = length;
903
904        /*
905         * Invalidate the unicode data.
906         */
907
908        stringPtr->hasUnicode = 0;
909    }
910
911    if (objPtr->bytes != NULL) {
912        objPtr->length = length;
913        if (objPtr->bytes != tclEmptyStringRep) {
914            /*
915             * Ensure the string is NULL-terminated.
916             */
917
918            objPtr->bytes[length] = 0;
919        }
920
921        /*
922         * Invalidate the unicode data.
923         */
924
925        stringPtr->numChars = -1;
926        stringPtr->hasUnicode = 0;
927    } else {
928        /*
929         * Changing length of pure unicode string.
930         */
931
932        size_t uallocated = STRING_UALLOC(length);
933
934        if (uallocated > stringPtr->uallocated) {
935            stringPtr = (String *) attemptckrealloc((char*) stringPtr,
936                    STRING_SIZE(uallocated));
937            if (stringPtr == NULL) {
938                return 0;
939            }
940            SET_STRING(objPtr, stringPtr);
941            stringPtr->uallocated = uallocated;
942        }
943        stringPtr->numChars = length;
944        stringPtr->hasUnicode = (length > 0);
945
946        /*
947         * Ensure the string is NUL-terminated.
948         */
949
950        stringPtr->unicode[length] = 0;
951        stringPtr->allocated = 0;
952        objPtr->length = 0;
953    }
954    return 1;
955}
956
957/*
958 *---------------------------------------------------------------------------
959 *
960 * TclSetUnicodeObj --
961 *
962 *      Modify an object to hold the Unicode string indicated by "unicode".
963 *
964 * Results:
965 *      None.
966 *
967 * Side effects:
968 *      Memory allocated for new "String" internal rep.
969 *
970 *---------------------------------------------------------------------------
971 */
972
973void
974Tcl_SetUnicodeObj(
975    Tcl_Obj *objPtr,            /* The object to set the string of. */
976    const Tcl_UniChar *unicode, /* The unicode string used to initialize the
977                                 * object. */
978    int numChars)               /* Number of characters in the unicode
979                                 * string. */
980{
981    String *stringPtr;
982    size_t uallocated;
983
984    if (numChars < 0) {
985        numChars = 0;
986        if (unicode) {
987            while (unicode[numChars] != 0) {
988                numChars++;
989            }
990        }
991    }
992    uallocated = STRING_UALLOC(numChars);
993
994    /*
995     * Free the internal rep if one exists, and invalidate the string rep.
996     */
997
998    TclFreeIntRep(objPtr);
999    objPtr->typePtr = &tclStringType;
1000
1001    /*
1002     * Allocate enough space for the String structure + Unicode string.
1003     */
1004
1005    stringPtr = (String *) ckalloc(STRING_SIZE(uallocated));
1006    stringPtr->numChars = numChars;
1007    stringPtr->uallocated = uallocated;
1008    stringPtr->hasUnicode = (numChars > 0);
1009    stringPtr->allocated = 0;
1010    memcpy(stringPtr->unicode, unicode, uallocated);
1011    stringPtr->unicode[numChars] = 0;
1012
1013    SET_STRING(objPtr, stringPtr);
1014    Tcl_InvalidateStringRep(objPtr);
1015    return;
1016}
1017
1018/*
1019 *----------------------------------------------------------------------
1020 *
1021 * Tcl_AppendLimitedToObj --
1022 *
1023 *      This function appends a limited number of bytes from a sequence of
1024 *      bytes to an object, marking any limitation with an ellipsis.
1025 *
1026 * Results:
1027 *      None.
1028 *
1029 * Side effects:
1030 *      The bytes at *bytes are appended to the string representation of
1031 *      objPtr.
1032 *
1033 *----------------------------------------------------------------------
1034 */
1035
1036void
1037Tcl_AppendLimitedToObj(
1038    register Tcl_Obj *objPtr,   /* Points to the object to append to. */
1039    const char *bytes,          /* Points to the bytes to append to the
1040                                 * object. */
1041    register int length,        /* The number of bytes available to be
1042                                 * appended from "bytes". If < 0, then all
1043                                 * bytes up to a NUL byte are available. */
1044    register int limit,         /* The maximum number of bytes to append to
1045                                 * the object. */
1046    const char *ellipsis)       /* Ellipsis marker string, appended to the
1047                                 * object to indicate not all available bytes
1048                                 * at "bytes" were appended. */
1049{
1050    String *stringPtr;
1051    int toCopy = 0;
1052
1053    if (Tcl_IsShared(objPtr)) {
1054        Tcl_Panic("%s called with shared object", "Tcl_AppendLimitedToObj");
1055    }
1056
1057    SetStringFromAny(NULL, objPtr);
1058
1059    if (length < 0) {
1060        length = (bytes ? strlen(bytes) : 0);
1061    }
1062    if (length == 0) {
1063        return;
1064    }
1065
1066    if (length <= limit) {
1067        toCopy = length;
1068    } else {
1069        if (ellipsis == NULL) {
1070            ellipsis = "...";
1071        }
1072        toCopy = Tcl_UtfPrev(bytes+limit+1-strlen(ellipsis), bytes) - bytes;
1073    }
1074
1075    /*
1076     * If objPtr has a valid Unicode rep, then append the Unicode conversion
1077     * of "bytes" to the objPtr's Unicode rep, otherwise append "bytes" to
1078     * objPtr's string rep.
1079     */
1080
1081    stringPtr = GET_STRING(objPtr);
1082    if (stringPtr->hasUnicode != 0) {
1083        AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
1084    } else {
1085        AppendUtfToUtfRep(objPtr, bytes, toCopy);
1086    }
1087
1088    if (length <= limit) {
1089        return;
1090    }
1091
1092    stringPtr = GET_STRING(objPtr);
1093    if (stringPtr->hasUnicode != 0) {
1094        AppendUtfToUnicodeRep(objPtr, ellipsis, -1);
1095    } else {
1096        AppendUtfToUtfRep(objPtr, ellipsis, -1);
1097    }
1098}
1099
1100/*
1101 *----------------------------------------------------------------------
1102 *
1103 * Tcl_AppendToObj --
1104 *
1105 *      This function appends a sequence of bytes to an object.
1106 *
1107 * Results:
1108 *      None.
1109 *
1110 * Side effects:
1111 *      The bytes at *bytes are appended to the string representation of
1112 *      objPtr.
1113 *
1114 *----------------------------------------------------------------------
1115 */
1116
1117void
1118Tcl_AppendToObj(
1119    register Tcl_Obj *objPtr,   /* Points to the object to append to. */
1120    const char *bytes,          /* Points to the bytes to append to the
1121                                 * object. */
1122    register int length)        /* The number of bytes to append from "bytes".
1123                                 * If < 0, then append all bytes up to NUL
1124                                 * byte. */
1125{
1126    Tcl_AppendLimitedToObj(objPtr, bytes, length, INT_MAX, NULL);
1127}
1128
1129/*
1130 *----------------------------------------------------------------------
1131 *
1132 * Tcl_AppendUnicodeToObj --
1133 *
1134 *      This function appends a Unicode string to an object in the most
1135 *      efficient manner possible. Length must be >= 0.
1136 *
1137 * Results:
1138 *      None.
1139 *
1140 * Side effects:
1141 *      Invalidates the string rep and creates a new Unicode string.
1142 *
1143 *----------------------------------------------------------------------
1144 */
1145
1146void
1147Tcl_AppendUnicodeToObj(
1148    register Tcl_Obj *objPtr,   /* Points to the object to append to. */
1149    const Tcl_UniChar *unicode, /* The unicode string to append to the
1150                                 * object. */
1151    int length)                 /* Number of chars in "unicode". */
1152{
1153    String *stringPtr;
1154
1155    if (Tcl_IsShared(objPtr)) {
1156        Tcl_Panic("%s called with shared object", "Tcl_AppendUnicodeToObj");
1157    }
1158
1159    if (length == 0) {
1160        return;
1161    }
1162
1163    SetStringFromAny(NULL, objPtr);
1164    stringPtr = GET_STRING(objPtr);
1165
1166    /*
1167     * If objPtr has a valid Unicode rep, then append the "unicode" to the
1168     * objPtr's Unicode rep, otherwise the UTF conversion of "unicode" to
1169     * objPtr's string rep.
1170     */
1171
1172    if (stringPtr->hasUnicode != 0) {
1173        AppendUnicodeToUnicodeRep(objPtr, unicode, length);
1174    } else {
1175        AppendUnicodeToUtfRep(objPtr, unicode, length);
1176    }
1177}
1178
1179/*
1180 *----------------------------------------------------------------------
1181 *
1182 * Tcl_AppendObjToObj --
1183 *
1184 *      This function appends the string rep of one object to another.
1185 *      "objPtr" cannot be a shared object.
1186 *
1187 * Results:
1188 *      None.
1189 *
1190 * Side effects:
1191 *      The string rep of appendObjPtr is appended to the string
1192 *      representation of objPtr.
1193 *
1194 *----------------------------------------------------------------------
1195 */
1196
1197void
1198Tcl_AppendObjToObj(
1199    Tcl_Obj *objPtr,            /* Points to the object to append to. */
1200    Tcl_Obj *appendObjPtr)      /* Object to append. */
1201{
1202    String *stringPtr;
1203    int length, numChars, allOneByteChars;
1204    char *bytes;
1205
1206    SetStringFromAny(NULL, objPtr);
1207
1208    /*
1209     * If objPtr has a valid Unicode rep, then get a Unicode string from
1210     * appendObjPtr and append it.
1211     */
1212
1213    stringPtr = GET_STRING(objPtr);
1214    if (stringPtr->hasUnicode != 0) {
1215        /*
1216         * If appendObjPtr is not of the "String" type, don't convert it.
1217         */
1218
1219        if (appendObjPtr->typePtr == &tclStringType) {
1220            stringPtr = GET_STRING(appendObjPtr);
1221            if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
1222                /*
1223                 * If appendObjPtr is a string obj with no valid Unicode rep,
1224                 * then fill its unicode rep.
1225                 */
1226
1227                FillUnicodeRep(appendObjPtr);
1228                stringPtr = GET_STRING(appendObjPtr);
1229            }
1230            AppendUnicodeToUnicodeRep(objPtr, stringPtr->unicode,
1231                    stringPtr->numChars);
1232        } else {
1233            bytes = TclGetStringFromObj(appendObjPtr, &length);
1234            AppendUtfToUnicodeRep(objPtr, bytes, length);
1235        }
1236        return;
1237    }
1238
1239    /*
1240     * Append to objPtr's UTF string rep. If we know the number of characters
1241     * in both objects before appending, then set the combined number of
1242     * characters in the final (appended-to) object.
1243     */
1244
1245    bytes = TclGetStringFromObj(appendObjPtr, &length);
1246
1247    allOneByteChars = 0;
1248    numChars = stringPtr->numChars;
1249    if ((numChars >= 0) && (appendObjPtr->typePtr == &tclStringType)) {
1250        stringPtr = GET_STRING(appendObjPtr);
1251        if ((stringPtr->numChars >= 0) && (stringPtr->numChars == length)) {
1252            numChars += stringPtr->numChars;
1253            allOneByteChars = 1;
1254        }
1255    }
1256
1257    AppendUtfToUtfRep(objPtr, bytes, length);
1258
1259    if (allOneByteChars) {
1260        stringPtr = GET_STRING(objPtr);
1261        stringPtr->numChars = numChars;
1262    }
1263}
1264
1265/*
1266 *----------------------------------------------------------------------
1267 *
1268 * AppendUnicodeToUnicodeRep --
1269 *
1270 *      This function appends the contents of "unicode" to the Unicode rep of
1271 *      "objPtr". objPtr must already have a valid Unicode rep.
1272 *
1273 * Results:
1274 *      None.
1275 *
1276 * Side effects:
1277 *      objPtr's internal rep is reallocated.
1278 *
1279 *----------------------------------------------------------------------
1280 */
1281
1282static void
1283AppendUnicodeToUnicodeRep(
1284    Tcl_Obj *objPtr,            /* Points to the object to append to. */
1285    const Tcl_UniChar *unicode, /* String to append. */
1286    int appendNumChars)         /* Number of chars of "unicode" to append. */
1287{
1288    String *stringPtr, *tmpString;
1289    size_t numChars;
1290
1291    if (appendNumChars < 0) {
1292        appendNumChars = 0;
1293        if (unicode) {
1294            while (unicode[appendNumChars] != 0) {
1295                appendNumChars++;
1296            }
1297        }
1298    }
1299    if (appendNumChars == 0) {
1300        return;
1301    }
1302
1303    SetStringFromAny(NULL, objPtr);
1304    stringPtr = GET_STRING(objPtr);
1305
1306    /*
1307     * If not enough space has been allocated for the unicode rep, reallocate
1308     * the internal rep object with additional space. First try to double the
1309     * required allocation; if that fails, try a more modest increase. See the
1310     * "TCL STRING GROWTH ALGORITHM" comment at the top of this file for an
1311     * explanation of this growth algorithm.
1312     */
1313
1314    numChars = stringPtr->numChars + appendNumChars;
1315
1316    if (STRING_UALLOC(numChars) >= stringPtr->uallocated) {
1317        stringPtr->uallocated = STRING_UALLOC(2 * numChars);
1318        tmpString = (String *) attemptckrealloc((char *)stringPtr,
1319                STRING_SIZE(stringPtr->uallocated));
1320        if (tmpString == NULL) {
1321            stringPtr->uallocated =
1322                    STRING_UALLOC(numChars + appendNumChars)
1323                    + TCL_GROWTH_MIN_ALLOC;
1324            tmpString = (String *) ckrealloc((char *)stringPtr,
1325                    STRING_SIZE(stringPtr->uallocated));
1326        }
1327        stringPtr = tmpString;
1328        SET_STRING(objPtr, stringPtr);
1329    }
1330
1331    /*
1332     * Copy the new string onto the end of the old string, then add the
1333     * trailing null.
1334     */
1335
1336    memcpy(stringPtr->unicode + stringPtr->numChars, unicode,
1337            appendNumChars * sizeof(Tcl_UniChar));
1338    stringPtr->unicode[numChars] = 0;
1339    stringPtr->numChars = numChars;
1340
1341    Tcl_InvalidateStringRep(objPtr);
1342}
1343
1344/*
1345 *----------------------------------------------------------------------
1346 *
1347 * AppendUnicodeToUtfRep --
1348 *
1349 *      This function converts the contents of "unicode" to UTF and appends
1350 *      the UTF to the string rep of "objPtr".
1351 *
1352 * Results:
1353 *      None.
1354 *
1355 * Side effects:
1356 *      objPtr's internal rep is reallocated.
1357 *
1358 *----------------------------------------------------------------------
1359 */
1360
1361static void
1362AppendUnicodeToUtfRep(
1363    Tcl_Obj *objPtr,            /* Points to the object to append to. */
1364    const Tcl_UniChar *unicode, /* String to convert to UTF. */
1365    int numChars)               /* Number of chars of "unicode" to convert. */
1366{
1367    Tcl_DString dsPtr;
1368    const char *bytes;
1369
1370    if (numChars < 0) {
1371        numChars = 0;
1372        if (unicode) {
1373            while (unicode[numChars] != 0) {
1374                numChars++;
1375            }
1376        }
1377    }
1378    if (numChars == 0) {
1379        return;
1380    }
1381
1382    Tcl_DStringInit(&dsPtr);
1383    bytes = Tcl_UniCharToUtfDString(unicode, numChars, &dsPtr);
1384    AppendUtfToUtfRep(objPtr, bytes, Tcl_DStringLength(&dsPtr));
1385    Tcl_DStringFree(&dsPtr);
1386}
1387
1388/*
1389 *----------------------------------------------------------------------
1390 *
1391 * AppendUtfToUnicodeRep --
1392 *
1393 *      This function converts the contents of "bytes" to Unicode and appends
1394 *      the Unicode to the Unicode rep of "objPtr". objPtr must already have a
1395 *      valid Unicode rep.
1396 *
1397 * Results:
1398 *      None.
1399 *
1400 * Side effects:
1401 *      objPtr's internal rep is reallocated.
1402 *
1403 *----------------------------------------------------------------------
1404 */
1405
1406static void
1407AppendUtfToUnicodeRep(
1408    Tcl_Obj *objPtr,            /* Points to the object to append to. */
1409    const char *bytes,          /* String to convert to Unicode. */
1410    int numBytes)               /* Number of bytes of "bytes" to convert. */
1411{
1412    Tcl_DString dsPtr;
1413    int numChars;
1414    Tcl_UniChar *unicode;
1415
1416    if (numBytes < 0) {
1417        numBytes = (bytes ? strlen(bytes) : 0);
1418    }
1419    if (numBytes == 0) {
1420        return;
1421    }
1422
1423    Tcl_DStringInit(&dsPtr);
1424    numChars = Tcl_NumUtfChars(bytes, numBytes);
1425    unicode = (Tcl_UniChar *)Tcl_UtfToUniCharDString(bytes, numBytes, &dsPtr);
1426    AppendUnicodeToUnicodeRep(objPtr, unicode, numChars);
1427    Tcl_DStringFree(&dsPtr);
1428}
1429
1430/*
1431 *----------------------------------------------------------------------
1432 *
1433 * AppendUtfToUtfRep --
1434 *
1435 *      This function appends "numBytes" bytes of "bytes" to the UTF string
1436 *      rep of "objPtr". objPtr must already have a valid String rep.
1437 *
1438 * Results:
1439 *      None.
1440 *
1441 * Side effects:
1442 *      objPtr's internal rep is reallocated.
1443 *
1444 *----------------------------------------------------------------------
1445 */
1446
1447static void
1448AppendUtfToUtfRep(
1449    Tcl_Obj *objPtr,            /* Points to the object to append to. */
1450    const char *bytes,          /* String to append. */
1451    int numBytes)               /* Number of bytes of "bytes" to append. */
1452{
1453    String *stringPtr;
1454    int newLength, oldLength;
1455
1456    if (numBytes < 0) {
1457        numBytes = (bytes ? strlen(bytes) : 0);
1458    }
1459    if (numBytes == 0) {
1460        return;
1461    }
1462
1463    /*
1464     * Copy the new string onto the end of the old string, then add the
1465     * trailing null.
1466     */
1467
1468    oldLength = objPtr->length;
1469    newLength = numBytes + oldLength;
1470
1471    stringPtr = GET_STRING(objPtr);
1472    if (newLength > (int) stringPtr->allocated) {
1473        /*
1474         * There isn't currently enough space in the string representation so
1475         * allocate additional space. First, try to double the length
1476         * required. If that fails, try a more modest allocation. See the "TCL
1477         * STRING GROWTH ALGORITHM" comment at the top of this file for an
1478         * explanation of this growth algorithm.
1479         */
1480
1481        if (Tcl_AttemptSetObjLength(objPtr, 2 * newLength) == 0) {
1482            Tcl_SetObjLength(objPtr,
1483                    newLength + numBytes + TCL_GROWTH_MIN_ALLOC);
1484        }
1485    }
1486
1487    /*
1488     * Invalidate the unicode data.
1489     */
1490
1491    stringPtr->numChars = -1;
1492    stringPtr->hasUnicode = 0;
1493
1494    memcpy(objPtr->bytes + oldLength, bytes, (size_t) numBytes);
1495    objPtr->bytes[newLength] = 0;
1496    objPtr->length = newLength;
1497}
1498
1499/*
1500 *----------------------------------------------------------------------
1501 *
1502 * Tcl_AppendStringsToObjVA --
1503 *
1504 *      This function appends one or more null-terminated strings to an
1505 *      object.
1506 *
1507 * Results:
1508 *      None.
1509 *
1510 * Side effects:
1511 *      The contents of all the string arguments are appended to the string
1512 *      representation of objPtr.
1513 *
1514 *----------------------------------------------------------------------
1515 */
1516
1517void
1518Tcl_AppendStringsToObjVA(
1519    Tcl_Obj *objPtr,            /* Points to the object to append to. */
1520    va_list argList)            /* Variable argument list. */
1521{
1522#define STATIC_LIST_SIZE 16
1523    String *stringPtr;
1524    int newLength, oldLength, attemptLength;
1525    register char *string, *dst;
1526    char *static_list[STATIC_LIST_SIZE];
1527    char **args = static_list;
1528    int nargs_space = STATIC_LIST_SIZE;
1529    int nargs, i;
1530
1531    if (Tcl_IsShared(objPtr)) {
1532        Tcl_Panic("%s called with shared object", "Tcl_AppendStringsToObj");
1533    }
1534
1535    SetStringFromAny(NULL, objPtr);
1536
1537    /*
1538     * Figure out how much space is needed for all the strings, and expand the
1539     * string representation if it isn't big enough. If no bytes would be
1540     * appended, just return. Note that on some platforms (notably OS/390) the
1541     * argList is an array so we need to use memcpy.
1542     */
1543
1544    nargs = 0;
1545    newLength = 0;
1546    oldLength = objPtr->length;
1547    while (1) {
1548        string = va_arg(argList, char *);
1549        if (string == NULL) {
1550            break;
1551        }
1552        if (nargs >= nargs_space) {
1553            /*
1554             * Expand the args buffer.
1555             */
1556
1557            nargs_space += STATIC_LIST_SIZE;
1558            if (args == static_list) {
1559                args = (void *) ckalloc(nargs_space * sizeof(char *));
1560                for (i = 0; i < nargs; ++i) {
1561                    args[i] = static_list[i];
1562                }
1563            } else {
1564                args = (void *) ckrealloc((void *) args,
1565                        nargs_space * sizeof(char *));
1566            }
1567        }
1568        newLength += strlen(string);
1569        args[nargs++] = string;
1570    }
1571    if (newLength == 0) {
1572        goto done;
1573    }
1574
1575    stringPtr = GET_STRING(objPtr);
1576    if (oldLength + newLength > (int) stringPtr->allocated) {
1577        /*
1578         * There isn't currently enough space in the string representation, so
1579         * allocate additional space. If the current string representation
1580         * isn't empty (i.e. it looks like we're doing a series of appends)
1581         * then try to allocate extra space to accomodate future growth: first
1582         * try to double the required memory; if that fails, try a more modest
1583         * allocation. See the "TCL STRING GROWTH ALGORITHM" comment at the
1584         * top of this file for an explanation of this growth algorithm.
1585         * Otherwise, if the current string representation is empty, exactly
1586         * enough memory is allocated.
1587         */
1588
1589        if (oldLength == 0) {
1590            Tcl_SetObjLength(objPtr, newLength);
1591        } else {
1592            attemptLength = 2 * (oldLength + newLength);
1593            if (Tcl_AttemptSetObjLength(objPtr, attemptLength) == 0) {
1594                attemptLength = oldLength + (2 * newLength) +
1595                        TCL_GROWTH_MIN_ALLOC;
1596                Tcl_SetObjLength(objPtr, attemptLength);
1597            }
1598        }
1599    }
1600
1601    /*
1602     * Make a second pass through the arguments, appending all the strings to
1603     * the object.
1604     */
1605
1606    dst = objPtr->bytes + oldLength;
1607    for (i = 0; i < nargs; ++i) {
1608        string = args[i];
1609        if (string == NULL) {
1610            break;
1611        }
1612        while (*string != 0) {
1613            *dst = *string;
1614            dst++;
1615            string++;
1616        }
1617    }
1618
1619    /*
1620     * Add a null byte to terminate the string. However, be careful: it's
1621     * possible that the object is totally empty (if it was empty originally
1622     * and there was nothing to append). In this case dst is NULL; just leave
1623     * everything alone.
1624     */
1625
1626    if (dst != NULL) {
1627        *dst = 0;
1628    }
1629    objPtr->length = oldLength + newLength;
1630
1631  done:
1632    /*
1633     * If we had to allocate a buffer from the heap, free it now.
1634     */
1635
1636    if (args != static_list) {
1637        ckfree((void *) args);
1638    }
1639#undef STATIC_LIST_SIZE
1640}
1641
1642/*
1643 *----------------------------------------------------------------------
1644 *
1645 * Tcl_AppendStringsToObj --
1646 *
1647 *      This function appends one or more null-terminated strings to an
1648 *      object.
1649 *
1650 * Results:
1651 *      None.
1652 *
1653 * Side effects:
1654 *      The contents of all the string arguments are appended to the string
1655 *      representation of objPtr.
1656 *
1657 *----------------------------------------------------------------------
1658 */
1659
1660void
1661Tcl_AppendStringsToObj(
1662    Tcl_Obj *objPtr,
1663    ...)
1664{
1665    va_list argList;
1666
1667    va_start(argList, objPtr);
1668    Tcl_AppendStringsToObjVA(objPtr, argList);
1669    va_end(argList);
1670}
1671
1672/*
1673 *----------------------------------------------------------------------
1674 *
1675 * Tcl_AppendFormatToObj --
1676 *
1677 *      This function appends a list of Tcl_Obj's to a Tcl_Obj according to
1678 *      the formatting instructions embedded in the format string. The
1679 *      formatting instructions are inspired by sprintf(). Returns TCL_OK when
1680 *      successful. If there's an error in the arguments, TCL_ERROR is
1681 *      returned, and an error message is written to the interp, if non-NULL.
1682 *
1683 * Results:
1684 *      A standard Tcl result.
1685 *
1686 * Side effects:
1687 *      None.
1688 *
1689 *----------------------------------------------------------------------
1690 */
1691
1692int
1693Tcl_AppendFormatToObj(
1694    Tcl_Interp *interp,
1695    Tcl_Obj *appendObj,
1696    const char *format,
1697    int objc,
1698    Tcl_Obj *const objv[])
1699{
1700    const char *span = format, *msg;
1701    int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
1702    int originalLength;
1703    static const char *mixedXPG =
1704            "cannot mix \"%\" and \"%n$\" conversion specifiers";
1705    static const char *badIndex[2] = {
1706        "not enough arguments for all format specifiers",
1707        "\"%n$\" argument index out of range"
1708    };
1709
1710    if (Tcl_IsShared(appendObj)) {
1711        Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj");
1712    }
1713    TclGetStringFromObj(appendObj, &originalLength);
1714
1715    /*
1716     * Format string is NUL-terminated.
1717     */
1718
1719    while (*format != '\0') {
1720        char *end;
1721        int gotMinus, gotHash, gotZero, gotSpace, gotPlus, sawFlag;
1722        int width, gotPrecision, precision, useShort, useWide, useBig;
1723        int newXpg, numChars, allocSegment = 0;
1724        Tcl_Obj *segment;
1725        Tcl_UniChar ch;
1726        int step = Tcl_UtfToUniChar(format, &ch);
1727
1728        format += step;
1729        if (ch != '%') {
1730            numBytes += step;
1731            continue;
1732        }
1733        if (numBytes) {
1734            Tcl_AppendToObj(appendObj, span, numBytes);
1735            numBytes = 0;
1736        }
1737
1738        /*
1739         * Saw a % : process the format specifier.
1740         *
1741         * Step 0. Handle special case of escaped format marker (i.e., %%).
1742         */
1743
1744        step = Tcl_UtfToUniChar(format, &ch);
1745        if (ch == '%') {
1746            span = format;
1747            numBytes = step;
1748            format += step;
1749            continue;
1750        }
1751
1752        /*
1753         * Step 1. XPG3 position specifier
1754         */
1755
1756        newXpg = 0;
1757        if (isdigit(UCHAR(ch))) {
1758            int position = strtoul(format, &end, 10);
1759            if (*end == '$') {
1760                newXpg = 1;
1761                objIndex = position - 1;
1762                format = end + 1;
1763                step = Tcl_UtfToUniChar(format, &ch);
1764            }
1765        }
1766        if (newXpg) {
1767            if (gotSequential) {
1768                msg = mixedXPG;
1769                goto errorMsg;
1770            }
1771            gotXpg = 1;
1772        } else {
1773            if (gotXpg) {
1774                msg = mixedXPG;
1775                goto errorMsg;
1776            }
1777            gotSequential = 1;
1778        }
1779        if ((objIndex < 0) || (objIndex >= objc)) {
1780            msg = badIndex[gotXpg];
1781            goto errorMsg;
1782        }
1783
1784        /*
1785         * Step 2. Set of flags.
1786         */
1787
1788        gotMinus = gotHash = gotZero = gotSpace = gotPlus = 0;
1789        sawFlag = 1;
1790        do {
1791            switch (ch) {
1792            case '-':
1793                gotMinus = 1;
1794                break;
1795            case '#':
1796                gotHash = 1;
1797                break;
1798            case '0':
1799                gotZero = 1;
1800                break;
1801            case ' ':
1802                gotSpace = 1;
1803                break;
1804            case '+':
1805                gotPlus = 1;
1806                break;
1807            default:
1808                sawFlag = 0;
1809            }
1810            if (sawFlag) {
1811                format += step;
1812                step = Tcl_UtfToUniChar(format, &ch);
1813            }
1814        } while (sawFlag);
1815
1816        /*
1817         * Step 3. Minimum field width.
1818         */
1819
1820        width = 0;
1821        if (isdigit(UCHAR(ch))) {
1822            width = strtoul(format, &end, 10);
1823            format = end;
1824            step = Tcl_UtfToUniChar(format, &ch);
1825        } else if (ch == '*') {
1826            if (objIndex >= objc - 1) {
1827                msg = badIndex[gotXpg];
1828                goto errorMsg;
1829            }
1830            if (TclGetIntFromObj(interp, objv[objIndex], &width) != TCL_OK) {
1831                goto error;
1832            }
1833            if (width < 0) {
1834                width = -width;
1835                gotMinus = 1;
1836            }
1837            objIndex++;
1838            format += step;
1839            step = Tcl_UtfToUniChar(format, &ch);
1840        }
1841
1842        /*
1843         * Step 4. Precision.
1844         */
1845
1846        gotPrecision = precision = 0;
1847        if (ch == '.') {
1848            gotPrecision = 1;
1849            format += step;
1850            step = Tcl_UtfToUniChar(format, &ch);
1851        }
1852        if (isdigit(UCHAR(ch))) {
1853            precision = strtoul(format, &end, 10);
1854            format = end;
1855            step = Tcl_UtfToUniChar(format, &ch);
1856        } else if (ch == '*') {
1857            if (objIndex >= objc - 1) {
1858                msg = badIndex[gotXpg];
1859                goto errorMsg;
1860            }
1861            if (TclGetIntFromObj(interp, objv[objIndex], &precision)
1862                    != TCL_OK) {
1863                goto error;
1864            }
1865
1866            /*
1867             * TODO: Check this truncation logic.
1868             */
1869
1870            if (precision < 0) {
1871                precision = 0;
1872            }
1873            objIndex++;
1874            format += step;
1875            step = Tcl_UtfToUniChar(format, &ch);
1876        }
1877
1878        /*
1879         * Step 5. Length modifier.
1880         */
1881
1882        useShort = useWide = useBig = 0;
1883        if (ch == 'h') {
1884            useShort = 1;
1885            format += step;
1886            step = Tcl_UtfToUniChar(format, &ch);
1887        } else if (ch == 'l') {
1888            format += step;
1889            step = Tcl_UtfToUniChar(format, &ch);
1890            if (ch == 'l') {
1891                useBig = 1;
1892                format += step;
1893                step = Tcl_UtfToUniChar(format, &ch);
1894            } else {
1895#ifndef TCL_WIDE_INT_IS_LONG
1896                useWide = 1;
1897#endif
1898            }
1899        }
1900
1901        format += step;
1902        span = format;
1903
1904        /*
1905         * Step 6. The actual conversion character.
1906         */
1907
1908        segment = objv[objIndex];
1909        if (ch == 'i') {
1910            ch = 'd';
1911        }
1912        switch (ch) {
1913        case '\0':
1914            msg = "format string ended in middle of field specifier";
1915            goto errorMsg;
1916        case 's': {
1917            numChars = Tcl_GetCharLength(segment);
1918            if (gotPrecision && (precision < numChars)) {
1919                segment = Tcl_GetRange(segment, 0, precision - 1);
1920                Tcl_IncrRefCount(segment);
1921                allocSegment = 1;
1922            }
1923            break;
1924        }
1925        case 'c': {
1926            char buf[TCL_UTF_MAX];
1927            int code, length;
1928
1929            if (TclGetIntFromObj(interp, segment, &code) != TCL_OK) {
1930                goto error;
1931            }
1932            length = Tcl_UniCharToUtf(code, buf);
1933            segment = Tcl_NewStringObj(buf, length);
1934            Tcl_IncrRefCount(segment);
1935            allocSegment = 1;
1936            break;
1937        }
1938
1939        case 'u':
1940            if (useBig) {
1941                msg = "unsigned bignum format is invalid";
1942                goto errorMsg;
1943            }
1944        case 'd':
1945        case 'o':
1946        case 'x':
1947        case 'X': {
1948            short int s = 0;    /* Silence compiler warning; only defined and
1949                                 * used when useShort is true. */
1950            long l;
1951            Tcl_WideInt w;
1952            mp_int big;
1953            int isNegative = 0;
1954
1955            if (useBig) {
1956                if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) {
1957                    goto error;
1958                }
1959                isNegative = (mp_cmp_d(&big, 0) == MP_LT);
1960            } else if (useWide) {
1961                if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
1962                    Tcl_Obj *objPtr;
1963
1964                    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
1965                        goto error;
1966                    }
1967                    mp_mod_2d(&big, (int) CHAR_BIT*sizeof(Tcl_WideInt), &big);
1968                    objPtr = Tcl_NewBignumObj(&big);
1969                    Tcl_IncrRefCount(objPtr);
1970                    Tcl_GetWideIntFromObj(NULL, objPtr, &w);
1971                    Tcl_DecrRefCount(objPtr);
1972                }
1973                isNegative = (w < (Tcl_WideInt)0);
1974            } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
1975                if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
1976                    Tcl_Obj *objPtr;
1977
1978                    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
1979                        goto error;
1980                    }
1981                    mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
1982                    objPtr = Tcl_NewBignumObj(&big);
1983                    Tcl_IncrRefCount(objPtr);
1984                    TclGetLongFromObj(NULL, objPtr, &l);
1985                    Tcl_DecrRefCount(objPtr);
1986                } else {
1987                    l = Tcl_WideAsLong(w);
1988                }
1989                if (useShort) {
1990                    s = (short int) l;
1991                    isNegative = (s < (short int)0);
1992                } else {
1993                    isNegative = (l < (long)0);
1994                }
1995            } else if (useShort) {
1996                s = (short int) l;
1997                isNegative = (s < (short int)0);
1998            } else {
1999                isNegative = (l < (long)0);
2000            }
2001
2002            segment = Tcl_NewObj();
2003            allocSegment = 1;
2004            Tcl_IncrRefCount(segment);
2005
2006            if ((isNegative || gotPlus) && (useBig || (ch == 'd'))) {
2007                Tcl_AppendToObj(segment, (isNegative ? "-" : "+"), 1);
2008            }
2009
2010            if (gotHash) {
2011                switch (ch) {
2012                case 'o':
2013                    Tcl_AppendToObj(segment, "0", 1);
2014                    precision--;
2015                    break;
2016                case 'x':
2017                case 'X':
2018                    Tcl_AppendToObj(segment, "0x", 2);
2019                    break;
2020                }
2021            }
2022
2023            switch (ch) {
2024            case 'd': {
2025                int length;
2026                Tcl_Obj *pure;
2027                const char *bytes;
2028
2029                if (useShort) {
2030                    pure = Tcl_NewIntObj((int)(s));
2031                } else if (useWide) {
2032                    pure = Tcl_NewWideIntObj(w);
2033                } else if (useBig) {
2034                    pure = Tcl_NewBignumObj(&big);
2035                } else {
2036                    pure = Tcl_NewLongObj(l);
2037                }
2038                Tcl_IncrRefCount(pure);
2039                bytes = TclGetStringFromObj(pure, &length);
2040
2041                /*
2042                 * Already did the sign above.
2043                 */
2044
2045                if (*bytes == '-') {
2046                    length--;
2047                    bytes++;
2048                }
2049
2050                /*
2051                 * Canonical decimal string reps for integers are composed
2052                 * entirely of one-byte encoded characters, so "length" is the
2053                 * number of chars.
2054                 */
2055
2056                if (gotPrecision) {
2057                    while (length < precision) {
2058                        Tcl_AppendToObj(segment, "0", 1);
2059                        length++;
2060                    }
2061                    gotZero = 0;
2062                }
2063                if (gotZero) {
2064                    length += Tcl_GetCharLength(segment);
2065                    while (length < width) {
2066                        Tcl_AppendToObj(segment, "0", 1);
2067                        length++;
2068                    }
2069                }
2070                Tcl_AppendToObj(segment, bytes, -1);
2071                Tcl_DecrRefCount(pure);
2072                break;
2073            }
2074
2075            case 'u':
2076            case 'o':
2077            case 'x':
2078            case 'X': {
2079                Tcl_WideUInt bits = (Tcl_WideUInt)0;
2080                int length, numBits = 4, numDigits = 0, base = 16;
2081                int index = 0, shift = 0;
2082                Tcl_Obj *pure;
2083                char *bytes;
2084
2085                if (ch == 'u') {
2086                    base = 10;
2087                }
2088                if (ch == 'o') {
2089                    base = 8;
2090                    numBits = 3;
2091                }
2092                if (useShort) {
2093                    unsigned short int us = (unsigned short int) s;
2094
2095                    bits = (Tcl_WideUInt) us;
2096                    while (us) {
2097                        numDigits++;
2098                        us /= base;
2099                    }
2100                } else if (useWide) {
2101                    Tcl_WideUInt uw = (Tcl_WideUInt) w;
2102
2103                    bits = uw;
2104                    while (uw) {
2105                        numDigits++;
2106                        uw /= base;
2107                    }
2108                } else if (useBig && big.used) {
2109                    int leftover = (big.used * DIGIT_BIT) % numBits;
2110                    mp_digit mask = (~(mp_digit)0) << (DIGIT_BIT-leftover);
2111
2112                    numDigits = 1 + ((big.used * DIGIT_BIT) / numBits);
2113                    while ((mask & big.dp[big.used-1]) == 0) {
2114                        numDigits--;
2115                        mask >>= numBits;
2116                    }
2117                } else if (!useBig) {
2118                    unsigned long int ul = (unsigned long int) l;
2119
2120                    bits = (Tcl_WideUInt) ul;
2121                    while (ul) {
2122                        numDigits++;
2123                        ul /= base;
2124                    }
2125                }
2126
2127                /*
2128                 * Need to be sure zero becomes "0", not "".
2129                 */
2130
2131                if ((numDigits == 0) && !((ch == 'o') && gotHash)) {
2132                    numDigits = 1;
2133                }
2134                pure = Tcl_NewObj();
2135                Tcl_SetObjLength(pure, numDigits);
2136                bytes = TclGetString(pure);
2137                length = numDigits;
2138                while (numDigits--) {
2139                    int digitOffset;
2140
2141                    if (useBig && big.used) {
2142                        if ((size_t) shift <
2143                                CHAR_BIT*sizeof(Tcl_WideUInt) - DIGIT_BIT) {
2144                            bits |= (((Tcl_WideUInt)big.dp[index++]) <<shift);
2145                            shift += DIGIT_BIT;
2146                        }
2147                        shift -= numBits;
2148                    }
2149                    digitOffset = (int) (bits % base);
2150                    if (digitOffset > 9) {
2151                        bytes[numDigits] = 'a' + digitOffset - 10;
2152                    } else {
2153                        bytes[numDigits] = '0' + digitOffset;
2154                    }
2155                    bits /= base;
2156                }
2157                if (useBig) {
2158                    mp_clear(&big);
2159                }
2160                if (gotPrecision) {
2161                    while (length < precision) {
2162                        Tcl_AppendToObj(segment, "0", 1);
2163                        length++;
2164                    }
2165                    gotZero = 0;
2166                }
2167                if (gotZero) {
2168                    length += Tcl_GetCharLength(segment);
2169                    while (length < width) {
2170                        Tcl_AppendToObj(segment, "0", 1);
2171                        length++;
2172                    }
2173                }
2174                Tcl_AppendObjToObj(segment, pure);
2175                Tcl_DecrRefCount(pure);
2176                break;
2177            }
2178
2179            }
2180            break;
2181        }
2182
2183        case 'e':
2184        case 'E':
2185        case 'f':
2186        case 'g':
2187        case 'G': {
2188#define MAX_FLOAT_SIZE 320
2189            char spec[2*TCL_INTEGER_SPACE + 9], *p = spec;
2190            double d;
2191            int length = MAX_FLOAT_SIZE;
2192            char *bytes;
2193
2194            if (Tcl_GetDoubleFromObj(interp, segment, &d) != TCL_OK) {
2195                /* TODO: Figure out ACCEPT_NAN here */
2196                goto error;
2197            }
2198            *p++ = '%';
2199            if (gotMinus) {
2200                *p++ = '-';
2201            }
2202            if (gotHash) {
2203                *p++ = '#';
2204            }
2205            if (gotZero) {
2206                *p++ = '0';
2207            }
2208            if (gotSpace) {
2209                *p++ = ' ';
2210            }
2211            if (gotPlus) {
2212                *p++ = '+';
2213            }
2214            if (width) {
2215                p += sprintf(p, "%d", width);
2216            }
2217            if (gotPrecision) {
2218                *p++ = '.';
2219                p += sprintf(p, "%d", precision);
2220                length += precision;
2221            }
2222
2223            /*
2224             * Don't pass length modifiers!
2225             */
2226
2227            *p++ = (char) ch;
2228            *p = '\0';
2229
2230            segment = Tcl_NewObj();
2231            allocSegment = 1;
2232            Tcl_SetObjLength(segment, length);
2233            bytes = TclGetString(segment);
2234            Tcl_SetObjLength(segment, sprintf(bytes, spec, d));
2235            break;
2236        }
2237        default:
2238            if (interp != NULL) {
2239                char buf[40];
2240
2241                sprintf(buf, "bad field specifier \"%c\"", ch);
2242                Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
2243            }
2244            goto error;
2245        }
2246
2247        switch (ch) {
2248        case 'E':
2249        case 'G':
2250        case 'X': {
2251            Tcl_SetObjLength(segment, Tcl_UtfToUpper(TclGetString(segment)));
2252        }
2253        }
2254
2255        numChars = Tcl_GetCharLength(segment);
2256        if (!gotMinus) {
2257            while (numChars < width) {
2258                Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
2259                numChars++;
2260            }
2261        }
2262        Tcl_AppendObjToObj(appendObj, segment);
2263        if (allocSegment) {
2264            Tcl_DecrRefCount(segment);
2265        }
2266        while (numChars < width) {
2267            Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
2268            numChars++;
2269        }
2270
2271        objIndex += gotSequential;
2272    }
2273    if (numBytes) {
2274        Tcl_AppendToObj(appendObj, span, numBytes);
2275        numBytes = 0;
2276    }
2277
2278    return TCL_OK;
2279
2280  errorMsg:
2281    if (interp != NULL) {
2282        Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
2283    }
2284  error:
2285    Tcl_SetObjLength(appendObj, originalLength);
2286    return TCL_ERROR;
2287}
2288
2289/*
2290 *---------------------------------------------------------------------------
2291 *
2292 * Tcl_Format--
2293 *
2294 * Results:
2295 *      A refcount zero Tcl_Obj.
2296 *
2297 * Side effects:
2298 *      None.
2299 *
2300 *---------------------------------------------------------------------------
2301 */
2302
2303Tcl_Obj *
2304Tcl_Format(
2305    Tcl_Interp *interp,
2306    const char *format,
2307    int objc,
2308    Tcl_Obj *const objv[])
2309{
2310    int result;
2311    Tcl_Obj *objPtr = Tcl_NewObj();
2312    result = Tcl_AppendFormatToObj(interp, objPtr, format, objc, objv);
2313    if (result != TCL_OK) {
2314        Tcl_DecrRefCount(objPtr);
2315        return NULL;
2316    }
2317    return objPtr;
2318}
2319
2320/*
2321 *---------------------------------------------------------------------------
2322 *
2323 * AppendPrintfToObjVA --
2324 *
2325 * Results:
2326 *
2327 * Side effects:
2328 *
2329 *---------------------------------------------------------------------------
2330 */
2331
2332static void
2333AppendPrintfToObjVA(
2334    Tcl_Obj *objPtr,
2335    const char *format,
2336    va_list argList)
2337{
2338    int code, objc;
2339    Tcl_Obj **objv, *list = Tcl_NewObj();
2340    const char *p;
2341    char *end;
2342
2343    p = format;
2344    Tcl_IncrRefCount(list);
2345    while (*p != '\0') {
2346        int size = 0, seekingConversion = 1, gotPrecision = 0;
2347        int lastNum = -1;
2348
2349        if (*p++ != '%') {
2350            continue;
2351        }
2352        if (*p == '%') {
2353            p++;
2354            continue;
2355        }
2356        do {
2357            switch (*p) {
2358
2359            case '\0':
2360                seekingConversion = 0;
2361                break;
2362            case 's': {
2363                const char *q, *end, *bytes = va_arg(argList, char *);
2364                seekingConversion = 0;
2365
2366                /*
2367                 * The buffer to copy characters from starts at bytes and ends
2368                 * at either the first NUL byte, or after lastNum bytes, when
2369                 * caller has indicated a limit.
2370                 */
2371
2372                end = bytes;
2373                while ((!gotPrecision || lastNum--) && (*end != '\0')) {
2374                    end++;
2375                }
2376
2377                /*
2378                 * Within that buffer, we trim both ends if needed so that we
2379                 * copy only whole characters, and avoid copying any partial
2380                 * multi-byte characters.
2381                 */
2382
2383                q = Tcl_UtfPrev(end, bytes);
2384                if (!Tcl_UtfCharComplete(q, (int)(end - q))) {
2385                    end = q;
2386                }
2387
2388                q = bytes + TCL_UTF_MAX;
2389                while ((bytes < end) && (bytes < q)
2390                        && ((*bytes & 0xC0) == 0x80)) {
2391                    bytes++;
2392                }
2393
2394                Tcl_ListObjAppendElement(NULL, list,
2395                        Tcl_NewStringObj(bytes , (int)(end - bytes)));
2396
2397                break;
2398            }
2399            case 'c':
2400            case 'i':
2401            case 'u':
2402            case 'd':
2403            case 'o':
2404            case 'x':
2405            case 'X':
2406                seekingConversion = 0;
2407                switch (size) {
2408                case -1:
2409                case 0:
2410                    Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj(
2411                            (long int)va_arg(argList, int)));
2412                    break;
2413                case 1:
2414                    Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj(
2415                            va_arg(argList, long int)));
2416                    break;
2417                }
2418                break;
2419            case 'e':
2420            case 'E':
2421            case 'f':
2422            case 'g':
2423            case 'G':
2424                Tcl_ListObjAppendElement(NULL, list, Tcl_NewDoubleObj(
2425                        va_arg(argList, double)));
2426                seekingConversion = 0;
2427                break;
2428            case '*':
2429                lastNum = (int)va_arg(argList, int);
2430                Tcl_ListObjAppendElement(NULL, list, Tcl_NewIntObj(lastNum));
2431                p++;
2432                break;
2433            case '0': case '1': case '2': case '3': case '4':
2434            case '5': case '6': case '7': case '8': case '9':
2435                lastNum = (int) strtoul(p, &end, 10);
2436                p = end;
2437                break;
2438            case '.':
2439                gotPrecision = 1;
2440                p++;
2441                break;
2442            /* TODO: support for wide (and bignum?) arguments */
2443            case 'l':
2444                size = 1;
2445                p++;
2446                break;
2447            case 'h':
2448                size = -1;
2449            default:
2450                p++;
2451            }
2452        } while (seekingConversion);
2453    }
2454    TclListObjGetElements(NULL, list, &objc, &objv);
2455    code = Tcl_AppendFormatToObj(NULL, objPtr, format, objc, objv);
2456    if (code != TCL_OK) {
2457        Tcl_AppendPrintfToObj(objPtr,
2458                "Unable to format \"%s\" with supplied arguments: %s",
2459                format, Tcl_GetString(list));
2460    }
2461    Tcl_DecrRefCount(list);
2462}
2463
2464/*
2465 *---------------------------------------------------------------------------
2466 *
2467 * Tcl_AppendPrintfToObj --
2468 *
2469 * Results:
2470 *      A standard Tcl result.
2471 *
2472 * Side effects:
2473 *      None.
2474 *
2475 *---------------------------------------------------------------------------
2476 */
2477
2478void
2479Tcl_AppendPrintfToObj(
2480    Tcl_Obj *objPtr,
2481    const char *format,
2482    ...)
2483{
2484    va_list argList;
2485
2486    va_start(argList, format);
2487    AppendPrintfToObjVA(objPtr, format, argList);
2488    va_end(argList);
2489}
2490
2491/*
2492 *---------------------------------------------------------------------------
2493 *
2494 * Tcl_ObjPrintf --
2495 *
2496 * Results:
2497 *      A refcount zero Tcl_Obj.
2498 *
2499 * Side effects:
2500 *      None.
2501 *
2502 *---------------------------------------------------------------------------
2503 */
2504
2505Tcl_Obj *
2506Tcl_ObjPrintf(
2507    const char *format,
2508    ...)
2509{
2510    va_list argList;
2511    Tcl_Obj *objPtr = Tcl_NewObj();
2512
2513    va_start(argList, format);
2514    AppendPrintfToObjVA(objPtr, format, argList);
2515    va_end(argList);
2516    return objPtr;
2517}
2518
2519/*
2520 *---------------------------------------------------------------------------
2521 *
2522 * TclStringObjReverse --
2523 *
2524 *      Implements the [string reverse] operation.
2525 *
2526 * Results:
2527 *      An unshared Tcl value which is the [string reverse] of the argument
2528 *      supplied.  When sharing rules permit, the returned value might be
2529 *      the argument with modifications done in place.
2530 *
2531 * Side effects:
2532 *      May allocate a new Tcl_Obj.
2533 *
2534 *---------------------------------------------------------------------------
2535 */
2536
2537Tcl_Obj *
2538TclStringObjReverse(
2539    Tcl_Obj *objPtr)
2540{
2541    String *stringPtr;
2542    int numChars = Tcl_GetCharLength(objPtr);
2543    int i = 0, lastCharIdx = numChars - 1;
2544    char *bytes;
2545
2546    if (numChars <= 1) {
2547        return objPtr;
2548    }
2549
2550    stringPtr = GET_STRING(objPtr);
2551    if (stringPtr->hasUnicode) {
2552        Tcl_UniChar *source = stringPtr->unicode;
2553
2554        if (Tcl_IsShared(objPtr)) {
2555            Tcl_UniChar *dest, ch = 0;
2556
2557            /*
2558             * Create a non-empty, pure unicode value, so we can coax
2559             * Tcl_SetObjLength into growing the unicode rep buffer.
2560             */
2561
2562            Tcl_Obj *resultPtr = Tcl_NewUnicodeObj(&ch, 1);
2563            Tcl_SetObjLength(resultPtr, numChars);
2564            dest = Tcl_GetUnicode(resultPtr);
2565
2566            while (i < numChars) {
2567                dest[i++] = source[lastCharIdx--];
2568            }
2569            return resultPtr;
2570        }
2571
2572        while (i < lastCharIdx) {
2573            Tcl_UniChar tmp = source[lastCharIdx];
2574            source[lastCharIdx--] = source[i];
2575            source[i++] = tmp;
2576        }
2577        Tcl_InvalidateStringRep(objPtr);
2578        return objPtr;
2579    }
2580
2581    bytes = TclGetString(objPtr);
2582    if (Tcl_IsShared(objPtr)) {
2583        char *dest;
2584        Tcl_Obj *resultPtr = Tcl_NewObj();
2585        Tcl_SetObjLength(resultPtr, numChars);
2586        dest = TclGetString(resultPtr);
2587        while (i < numChars) {
2588            dest[i++] = bytes[lastCharIdx--];
2589        }
2590        return resultPtr;
2591    }
2592
2593    while (i < lastCharIdx) {
2594        char tmp = bytes[lastCharIdx];
2595        bytes[lastCharIdx--] = bytes[i];
2596        bytes[i++] = tmp;
2597    }
2598    return objPtr;
2599}
2600
2601/*
2602 *---------------------------------------------------------------------------
2603 *
2604 * FillUnicodeRep --
2605 *
2606 *      Populate the Unicode internal rep with the Unicode form of its string
2607 *      rep. The object must alread have a "String" internal rep.
2608 *
2609 * Results:
2610 *      None.
2611 *
2612 * Side effects:
2613 *      Reallocates the String internal rep.
2614 *
2615 *---------------------------------------------------------------------------
2616 */
2617
2618static void
2619FillUnicodeRep(
2620    Tcl_Obj *objPtr)            /* The object in which to fill the unicode
2621                                 * rep. */
2622{
2623    String *stringPtr;
2624    size_t uallocated;
2625    char *srcEnd, *src = objPtr->bytes;
2626    Tcl_UniChar *dst;
2627
2628    stringPtr = GET_STRING(objPtr);
2629    if (stringPtr->numChars == -1) {
2630        stringPtr->numChars = Tcl_NumUtfChars(src, objPtr->length);
2631    }
2632    stringPtr->hasUnicode = (stringPtr->numChars > 0);
2633
2634    uallocated = STRING_UALLOC(stringPtr->numChars);
2635    if (uallocated > stringPtr->uallocated) {
2636        /*
2637         * If not enough space has been allocated for the unicode rep,
2638         * reallocate the internal rep object.
2639         *
2640         * There isn't currently enough space in the Unicode representation so
2641         * allocate additional space. If the current Unicode representation
2642         * isn't empty (i.e. it looks like we've done some appends) then
2643         * overallocate the space so that we won't have to do as much
2644         * reallocation in the future.
2645         */
2646
2647        if (stringPtr->uallocated > 0) {
2648            uallocated *= 2;
2649        }
2650        stringPtr = (String *) ckrealloc((char*) stringPtr,
2651                STRING_SIZE(uallocated));
2652        stringPtr->uallocated = uallocated;
2653    }
2654
2655    /*
2656     * Convert src to Unicode and store the coverted data in "unicode".
2657     */
2658
2659    srcEnd = src + objPtr->length;
2660    for (dst = stringPtr->unicode; src < srcEnd; dst++) {
2661        src += TclUtfToUniChar(src, dst);
2662    }
2663    *dst = 0;
2664
2665    SET_STRING(objPtr, stringPtr);
2666}
2667
2668/*
2669 *----------------------------------------------------------------------
2670 *
2671 * DupStringInternalRep --
2672 *
2673 *      Initialize the internal representation of a new Tcl_Obj to a copy of
2674 *      the internal representation of an existing string object.
2675 *
2676 * Results:
2677 *      None.
2678 *
2679 * Side effects:
2680 *      copyPtr's internal rep is set to a copy of srcPtr's internal
2681 *      representation.
2682 *
2683 *----------------------------------------------------------------------
2684 */
2685
2686static void
2687DupStringInternalRep(
2688    register Tcl_Obj *srcPtr,   /* Object with internal rep to copy. Must have
2689                                 * an internal rep of type "String". */
2690    register Tcl_Obj *copyPtr)  /* Object with internal rep to set. Must not
2691                                 * currently have an internal rep.*/
2692{
2693    String *srcStringPtr = GET_STRING(srcPtr);
2694    String *copyStringPtr = NULL;
2695
2696    /*
2697     * If the src obj is a string of 1-byte Utf chars, then copy the string
2698     * rep of the source object and create an "empty" Unicode internal rep for
2699     * the new object. Otherwise, copy Unicode internal rep, and invalidate
2700     * the string rep of the new object.
2701     */
2702
2703    if (srcStringPtr->hasUnicode == 0) {
2704        copyStringPtr = (String *) ckalloc(STRING_SIZE(STRING_UALLOC(0)));
2705        copyStringPtr->uallocated = STRING_UALLOC(0);
2706    } else {
2707        copyStringPtr = (String *) ckalloc(
2708                STRING_SIZE(srcStringPtr->uallocated));
2709        copyStringPtr->uallocated = srcStringPtr->uallocated;
2710
2711        memcpy(copyStringPtr->unicode, srcStringPtr->unicode,
2712                (size_t) srcStringPtr->numChars * sizeof(Tcl_UniChar));
2713        copyStringPtr->unicode[srcStringPtr->numChars] = 0;
2714    }
2715    copyStringPtr->numChars = srcStringPtr->numChars;
2716    copyStringPtr->hasUnicode = srcStringPtr->hasUnicode;
2717    copyStringPtr->allocated = srcStringPtr->allocated;
2718
2719    /*
2720     * Tricky point: the string value was copied by generic object management
2721     * code, so it doesn't contain any extra bytes that might exist in the
2722     * source object.
2723     */
2724
2725    copyStringPtr->allocated = copyPtr->length;
2726
2727    SET_STRING(copyPtr, copyStringPtr);
2728    copyPtr->typePtr = &tclStringType;
2729}
2730
2731/*
2732 *----------------------------------------------------------------------
2733 *
2734 * SetStringFromAny --
2735 *
2736 *      Create an internal representation of type "String" for an object.
2737 *
2738 * Results:
2739 *      This operation always succeeds and returns TCL_OK.
2740 *
2741 * Side effects:
2742 *      Any old internal reputation for objPtr is freed and the internal
2743 *      representation is set to "String".
2744 *
2745 *----------------------------------------------------------------------
2746 */
2747
2748static int
2749SetStringFromAny(
2750    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
2751    register Tcl_Obj *objPtr)   /* The object to convert. */
2752{
2753    /*
2754     * The Unicode object is optimized for the case where each UTF char in a
2755     * string is only one byte. In this case, we store the value of numChars,
2756     * but we don't copy the bytes to the unicodeObj->unicode.
2757     */
2758
2759    if (objPtr->typePtr != &tclStringType) {
2760        String *stringPtr;
2761
2762        if (objPtr->typePtr != NULL) {
2763            if (objPtr->bytes == NULL) {
2764                objPtr->typePtr->updateStringProc(objPtr);
2765            }
2766            TclFreeIntRep(objPtr);
2767        }
2768        objPtr->typePtr = &tclStringType;
2769
2770        /*
2771         * Allocate enough space for the basic String structure.
2772         */
2773
2774        stringPtr = (String *) ckalloc(STRING_SIZE(STRING_UALLOC(0)));
2775        stringPtr->numChars = -1;
2776        stringPtr->uallocated = STRING_UALLOC(0);
2777        stringPtr->hasUnicode = 0;
2778
2779        if (objPtr->bytes != NULL) {
2780            stringPtr->allocated = objPtr->length;
2781            objPtr->bytes[objPtr->length] = 0;
2782        } else {
2783            objPtr->length = 0;
2784        }
2785        SET_STRING(objPtr, stringPtr);
2786    }
2787    return TCL_OK;
2788}
2789
2790/*
2791 *----------------------------------------------------------------------
2792 *
2793 * UpdateStringOfString --
2794 *
2795 *      Update the string representation for an object whose internal
2796 *      representation is "String".
2797 *
2798 * Results:
2799 *      None.
2800 *
2801 * Side effects:
2802 *      The object's string may be set by converting its Unicode represention
2803 *      to UTF format.
2804 *
2805 *----------------------------------------------------------------------
2806 */
2807
2808static void
2809UpdateStringOfString(
2810    Tcl_Obj *objPtr)            /* Object with string rep to update. */
2811{
2812    int i, size;
2813    Tcl_UniChar *unicode;
2814    char dummy[TCL_UTF_MAX];
2815    char *dst;
2816    String *stringPtr;
2817
2818    stringPtr = GET_STRING(objPtr);
2819    if ((objPtr->bytes == NULL) || (stringPtr->allocated == 0)) {
2820        if (stringPtr->numChars <= 0) {
2821            /*
2822             * If there is no Unicode rep, or the string has 0 chars, then set
2823             * the string rep to an empty string.
2824             */
2825
2826            objPtr->bytes = tclEmptyStringRep;
2827            objPtr->length = 0;
2828            return;
2829        }
2830
2831        unicode = stringPtr->unicode;
2832
2833        /*
2834         * Translate the Unicode string to UTF. "size" will hold the amount of
2835         * space the UTF string needs.
2836         */
2837
2838        size = 0;
2839        for (i = 0; i < stringPtr->numChars; i++) {
2840            size += Tcl_UniCharToUtf((int) unicode[i], dummy);
2841        }
2842
2843        dst = (char *) ckalloc((unsigned) (size + 1));
2844        objPtr->bytes = dst;
2845        objPtr->length = size;
2846        stringPtr->allocated = size;
2847
2848        for (i = 0; i < stringPtr->numChars; i++) {
2849            dst += Tcl_UniCharToUtf(unicode[i], dst);
2850        }
2851        *dst = '\0';
2852    }
2853    return;
2854}
2855
2856/*
2857 *----------------------------------------------------------------------
2858 *
2859 * FreeStringInternalRep --
2860 *
2861 *      Deallocate the storage associated with a String data object's internal
2862 *      representation.
2863 *
2864 * Results:
2865 *      None.
2866 *
2867 * Side effects:
2868 *      Frees memory.
2869 *
2870 *----------------------------------------------------------------------
2871 */
2872
2873static void
2874FreeStringInternalRep(
2875    Tcl_Obj *objPtr)            /* Object with internal rep to free. */
2876{
2877    ckfree((char *) GET_STRING(objPtr));
2878}
2879
2880/*
2881 * Local Variables:
2882 * mode: c
2883 * c-basic-offset: 4
2884 * fill-column: 78
2885 * End:
2886 */
Note: See TracBrowser for help on using the repository browser.