os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclStringObj.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* 
     2  * tclStringObj.c --
     3  *
     4  *	This file contains procedures 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 sequence
    11  *	of properly formed UTF-8 characters.  There is a one-to-one map between
    12  *	Unicode and UTF characters.  Because Unicode characters have a fixed
    13  *	width, operations such as indexing operate on Unicode data.  The String
    14  *	object is optimized for the case where each UTF char in a string is
    15  *	only one byte.  In this case, we store the value of numChars, but we
    16  *	don't store the Unicode data (unless Tcl_GetUnicode is explicitly
    17  *	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
    28  *	vs. allocated.
    29  *
    30  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
    31  * Copyright (c) 1999 by Scriptics Corporation.
    32  * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.  
    33  *
    34  * See the file "license.terms" for information on usage and redistribution
    35  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    36  *
    37  * RCS: @(#) $Id: tclStringObj.c,v 1.32.2.2 2006/09/24 21:15:11 msofer Exp $ */
    38 
    39 #include "tclInt.h"
    40 
    41 /*
    42  * Prototypes for procedures defined later in this file:
    43  */
    44 
    45 static void		AppendUnicodeToUnicodeRep _ANSI_ARGS_((
    46     			    Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode,
    47 			    int appendNumChars));
    48 static void		AppendUnicodeToUtfRep _ANSI_ARGS_((
    49     			    Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode,
    50 			    int numChars));
    51 static void		AppendUtfToUnicodeRep _ANSI_ARGS_((Tcl_Obj *objPtr,
    52     			    CONST char *bytes, int numBytes));
    53 static void		AppendUtfToUtfRep _ANSI_ARGS_((Tcl_Obj *objPtr,
    54     			    CONST char *bytes, int numBytes));
    55 
    56 static void		FillUnicodeRep _ANSI_ARGS_((Tcl_Obj *objPtr));
    57 
    58 static void		FreeStringInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
    59 static void		DupStringInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
    60 			    Tcl_Obj *copyPtr));
    61 static int		SetStringFromAny _ANSI_ARGS_((Tcl_Interp *interp,
    62 			    Tcl_Obj *objPtr));
    63 static void		UpdateStringOfString _ANSI_ARGS_((Tcl_Obj *objPtr));
    64 
    65 /*
    66  * The structure below defines the string Tcl object type by means of
    67  * procedures that can be invoked by generic object code.
    68  */
    69 
    70 Tcl_ObjType tclStringType = {
    71     "string",				/* name */
    72     FreeStringInternalRep,		/* freeIntRepPro */
    73     DupStringInternalRep,		/* dupIntRepProc */
    74     UpdateStringOfString,		/* updateStringProc */
    75     SetStringFromAny			/* setFromAnyProc */
    76 };
    77 
    78 /*
    79  * The following structure is the internal rep for a String object.
    80  * It keeps track of how much memory has been used and how much has been
    81  * allocated for the Unicode and UTF string to enable growing and
    82  * shrinking of the UTF and Unicode reps of the String object with fewer
    83  * mallocs.  To optimize string length and indexing operations, this
    84  * structure also stores the number of characters (same of UTF and Unicode!)
    85  * once that value has been computed.
    86  */
    87 
    88 typedef struct String {
    89     int numChars;		/* The number of chars in the string.
    90 				 * -1 means this value has not been
    91 				 * calculated. >= 0 means that there is a
    92 				 * valid Unicode rep, or that the number
    93 				 * of UTF bytes == the number of chars. */
    94     size_t allocated;		/* The amount of space actually allocated
    95 				 * for the UTF string (minus 1 byte for
    96 				 * the termination char). */
    97     size_t uallocated;		/* The amount of space actually allocated
    98 				 * for the Unicode string (minus 2 bytes for
    99 				 * the termination char). */
   100     int hasUnicode;		/* Boolean determining whether the string
   101 				 * has a Unicode representation. */
   102     Tcl_UniChar unicode[2];	/* The array of Unicode chars.  The actual
   103 				 * size of this field depends on the
   104 				 * 'uallocated' field above. */
   105 } String;
   106 
   107 #define STRING_UALLOC(numChars)	\
   108 		(numChars * sizeof(Tcl_UniChar))
   109 #define STRING_SIZE(ualloc) \
   110 	((unsigned) ((ualloc) \
   111                  ? sizeof(String) - sizeof(Tcl_UniChar) + (ualloc) \
   112                  : sizeof(String)))
   113 #define GET_STRING(objPtr) \
   114 		((String *) (objPtr)->internalRep.otherValuePtr)
   115 #define SET_STRING(objPtr, stringPtr) \
   116 		(objPtr)->internalRep.otherValuePtr = (VOID *) (stringPtr)
   117 
   118 /*
   119  * TCL STRING GROWTH ALGORITHM
   120  *
   121  * When growing strings (during an append, for example), the following growth
   122  * algorithm is used:
   123  *
   124  *   Attempt to allocate 2 * (originalLength + appendLength)
   125  *   On failure:
   126  *	attempt to allocate originalLength + 2*appendLength +
   127  *			TCL_GROWTH_MIN_ALLOC 
   128  *
   129  * This algorithm allows very good performance, as it rapidly increases the
   130  * memory allocated for a given string, which minimizes the number of
   131  * reallocations that must be performed.  However, using only the doubling
   132  * algorithm can lead to a significant waste of memory.  In particular, it
   133  * may fail even when there is sufficient memory available to complete the
   134  * append request (but there is not 2 * totalLength memory available).  So when
   135  * the doubling fails (because there is not enough memory available), the
   136  * algorithm requests a smaller amount of memory, which is still enough to
   137  * cover the request, but which hopefully will be less than the total available
   138  * memory.
   139  * 
   140  * The addition of TCL_GROWTH_MIN_ALLOC allows for efficient handling
   141  * of very small appends.  Without this extra slush factor, a sequence
   142  * of several small appends would cause several memory allocations.
   143  * As long as TCL_GROWTH_MIN_ALLOC is a reasonable size, we can
   144  * 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.
   150  *				Default is 1024 (1 kilobyte).
   151  */
   152 #ifndef TCL_GROWTH_MIN_ALLOC
   153 #define TCL_GROWTH_MIN_ALLOC	1024
   154 #endif
   155 
   156 
   157 /*
   158  *----------------------------------------------------------------------
   159  *
   160  * Tcl_NewStringObj --
   161  *
   162  *	This procedure 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 procedure just returns the
   167  *	result 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
   174  *	copy of the length bytes starting at "bytes". If "length" is
   175  *	negative, use bytes up to the first NULL byte; i.e., assume "bytes"
   176  *	points to a C-style NULL-terminated string. The object's type is set
   177  *	to NULL. An extra NULL is added to the end of the new object's byte
   178  *	array.
   179  *
   180  *----------------------------------------------------------------------
   181  */
   182 
   183 #ifdef TCL_MEM_DEBUG
   184 #undef Tcl_NewStringObj
   185 
   186 EXPORT_C Tcl_Obj *
   187 Tcl_NewStringObj(bytes, length)
   188     CONST char *bytes;		/* Points to the first of the length bytes
   189 				 * used to initialize the new object. */
   190     int length;			/* The number of bytes to copy from "bytes"
   191 				 * when initializing the new object. If 
   192 				 * negative, use bytes up to the first
   193 				 * NULL byte. */
   194 {
   195     return Tcl_DbNewStringObj(bytes, length, "unknown", 0);
   196 }
   197 
   198 #else /* if not TCL_MEM_DEBUG */
   199 
   200 EXPORT_C Tcl_Obj *
   201 Tcl_NewStringObj(bytes, length)
   202     CONST char *bytes;		/* Points to the first of the length bytes
   203 				 * used to initialize the new object. */
   204     int length;			/* The number of bytes to copy from "bytes"
   205 				 * when initializing the new object. If 
   206 				 * negative, use bytes up to the first
   207 				 * NULL byte. */
   208 {
   209     register Tcl_Obj *objPtr;
   210 
   211     if (length < 0) {
   212 	length = (bytes? strlen(bytes) : 0);
   213     }
   214     TclNewObj(objPtr);
   215     TclInitStringRep(objPtr, bytes, length);
   216     return objPtr;
   217 }
   218 #endif /* TCL_MEM_DEBUG */
   219 
   220 /*
   221  *----------------------------------------------------------------------
   222  *
   223  * Tcl_DbNewStringObj --
   224  *
   225  *	This procedure is normally called when debugging: i.e., when
   226  *	TCL_MEM_DEBUG is defined. It creates new string objects. It is the
   227  *	same as the Tcl_NewStringObj procedure above except that it calls
   228  *	Tcl_DbCkalloc directly with the file name and line number from its
   229  *	caller. This simplifies debugging since then the [memory active]
   230  *	command	will report the correct file name and line number when
   231  *	reporting objects that haven't been freed.
   232  *
   233  *	When TCL_MEM_DEBUG is not defined, this procedure just returns the
   234  *	result of calling Tcl_NewStringObj.
   235  *
   236  * Results:
   237  *	A newly created string object is returned that has ref count zero.
   238  *
   239  * Side effects:
   240  *	The new object's internal string representation will be set to a
   241  *	copy of the length bytes starting at "bytes". If "length" is
   242  *	negative, use bytes up to the first NULL byte; i.e., assume "bytes"
   243  *	points to a C-style NULL-terminated string. The object's type is set
   244  *	to NULL. An extra NULL is added to the end of the new object's byte
   245  *	array.
   246  *
   247  *----------------------------------------------------------------------
   248  */
   249 
   250 #ifdef TCL_MEM_DEBUG
   251 
   252 EXPORT_C Tcl_Obj *
   253 Tcl_DbNewStringObj(bytes, length, file, line)
   254     CONST char *bytes;		/* Points to the first of the length bytes
   255 				 * used to initialize the new object. */
   256     int length;			/* The number of bytes to copy from "bytes"
   257 				 * when initializing the new object. If 
   258 				 * negative, use bytes up to the first
   259 				 * NULL byte. */
   260     CONST char *file;		/* The name of the source file calling this
   261 				 * procedure; used for debugging. */
   262     int line;			/* Line number in the source file; used
   263 				 * for debugging. */
   264 {
   265     register Tcl_Obj *objPtr;
   266 
   267     if (length < 0) {
   268 	length = (bytes? strlen(bytes) : 0);
   269     }
   270     TclDbNewObj(objPtr, file, line);
   271     TclInitStringRep(objPtr, bytes, length);
   272     return objPtr;
   273 }
   274 
   275 #else /* if not TCL_MEM_DEBUG */
   276 
   277 EXPORT_C Tcl_Obj *
   278 Tcl_DbNewStringObj(bytes, length, file, line)
   279     CONST char *bytes;		/* Points to the first of the length bytes
   280 				 * used to initialize the new object. */
   281     register int length;	/* The number of bytes to copy from "bytes"
   282 				 * when initializing the new object. If 
   283 				 * negative, use bytes up to the first
   284 				 * NULL byte. */
   285     CONST char *file;		/* The name of the source file calling this
   286 				 * procedure; used for debugging. */
   287     int line;			/* Line number in the source file; used
   288 				 * for debugging. */
   289 {
   290     return Tcl_NewStringObj(bytes, length);
   291 }
   292 #endif /* TCL_MEM_DEBUG */
   293 
   294 /*
   295  *---------------------------------------------------------------------------
   296  *
   297  * Tcl_NewUnicodeObj --
   298  *
   299  *	This procedure is creates a new String object and initializes
   300  *	it from the given Unicode String.  If the Utf String is the same size
   301  *	as the Unicode string, don't duplicate the data.
   302  *
   303  * Results:
   304  *	The newly created object is returned.  This object will have no
   305  *	initial string representation.  The returned object has a ref count
   306  *	of 0.
   307  *
   308  * Side effects:
   309  *	Memory allocated for new object and copy of Unicode argument.
   310  *
   311  *---------------------------------------------------------------------------
   312  */
   313 
   314 EXPORT_C Tcl_Obj *
   315 Tcl_NewUnicodeObj(unicode, numChars)
   316     CONST Tcl_UniChar *unicode;	/* The unicode string used to initialize
   317 				 * the new object. */
   318     int numChars;		/* Number of characters in the unicode
   319 				 * string. */
   320 {
   321     Tcl_Obj *objPtr;
   322     String *stringPtr;
   323     size_t uallocated;
   324 
   325     if (numChars < 0) {
   326 	numChars = 0;
   327 	if (unicode) {
   328 	    while (unicode[numChars] != 0) { numChars++; }
   329 	}
   330     }
   331     uallocated = STRING_UALLOC(numChars);
   332 
   333     /*
   334      * Create a new obj with an invalid string rep.
   335      */
   336 
   337     TclNewObj(objPtr);
   338     Tcl_InvalidateStringRep(objPtr);
   339     objPtr->typePtr = &tclStringType;
   340 
   341     stringPtr = (String *) ckalloc(STRING_SIZE(uallocated));
   342     stringPtr->numChars = numChars;
   343     stringPtr->uallocated = uallocated;
   344     stringPtr->hasUnicode = (numChars > 0);
   345     stringPtr->allocated = 0;
   346     memcpy((VOID *) stringPtr->unicode, (VOID *) unicode, uallocated);
   347     stringPtr->unicode[numChars] = 0;
   348     SET_STRING(objPtr, stringPtr);
   349     return objPtr;
   350 }
   351 
   352 /*
   353  *----------------------------------------------------------------------
   354  *
   355  * Tcl_GetCharLength --
   356  *
   357  *	Get the length of the Unicode string from the Tcl object.
   358  *
   359  * Results:
   360  *	Pointer to unicode string representing the unicode object.
   361  *
   362  * Side effects:
   363  *	Frees old internal rep.  Allocates memory for new "String"
   364  *	internal rep.
   365  *
   366  *----------------------------------------------------------------------
   367  */
   368 
   369 EXPORT_C int
   370 Tcl_GetCharLength(objPtr)
   371     Tcl_Obj *objPtr;	/* The String object to get the num chars of. */
   372 {
   373     String *stringPtr;
   374     
   375     SetStringFromAny(NULL, objPtr);
   376     stringPtr = GET_STRING(objPtr);
   377 
   378     /*
   379      * If numChars is unknown, then calculate the number of characaters
   380      * while populating the Unicode string.
   381      */
   382     
   383     if (stringPtr->numChars == -1) {
   384 	register int i = objPtr->length;
   385 	register unsigned char *str = (unsigned char *) objPtr->bytes;
   386 
   387 	/*
   388 	 * This is a speed sensitive function, so run specially over the
   389 	 * string to count continuous ascii characters before resorting
   390 	 * to the Tcl_NumUtfChars call.  This is a long form of:
   391 	 stringPtr->numChars = Tcl_NumUtfChars(objPtr->bytes, objPtr->length);
   392 	*/
   393 
   394 	while (i && (*str < 0xC0)) { i--; str++; }
   395 	stringPtr->numChars = objPtr->length - i;
   396 	if (i) {
   397 	    stringPtr->numChars += Tcl_NumUtfChars(objPtr->bytes
   398 		    + (objPtr->length - i), i);
   399 	}
   400 
   401  	if (stringPtr->numChars == objPtr->length) {
   402 
   403 	    /*
   404 	     * Since we've just calculated the number of chars, and all
   405 	     * UTF chars are 1-byte long, we don't need to store the
   406 	     * unicode string.
   407 	     */
   408 
   409 	    stringPtr->hasUnicode = 0;
   410 
   411 	} else {
   412     
   413 	    /*
   414 	     * Since we've just calucalated the number of chars, and not
   415 	     * all UTF chars are 1-byte long, go ahead and populate the
   416 	     * unicode string.
   417 	     */
   418 
   419 	    FillUnicodeRep(objPtr);
   420 
   421 	    /*
   422 	     * We need to fetch the pointer again because we have just
   423 	     * reallocated the structure to make room for the Unicode data.
   424 	     */
   425 	    
   426 	    stringPtr = GET_STRING(objPtr);
   427 	}
   428     }
   429     return stringPtr->numChars;
   430 }
   431 
   432 /*
   433  *----------------------------------------------------------------------
   434  *
   435  * Tcl_GetUniChar --
   436  *
   437  *	Get the index'th Unicode character from the String object.  The
   438  *	index is assumed to be in the appropriate range.
   439  *
   440  * Results:
   441  *	Returns the index'th Unicode character in the Object.
   442  *
   443  * Side effects:
   444  *	Fills unichar with the index'th Unicode character.
   445  *
   446  *----------------------------------------------------------------------
   447  */
   448 
   449 EXPORT_C Tcl_UniChar
   450 Tcl_GetUniChar(objPtr, index)
   451     Tcl_Obj *objPtr;	/* The object to get the Unicode charater from. */
   452     int index;		/* Get the index'th Unicode character. */
   453 {
   454     Tcl_UniChar unichar;
   455     String *stringPtr;
   456     
   457     SetStringFromAny(NULL, objPtr);
   458     stringPtr = GET_STRING(objPtr);
   459 
   460     if (stringPtr->numChars == -1) {
   461 
   462 	/*
   463 	 * We haven't yet calculated the length, so we don't have the
   464 	 * Unicode str.  We need to know the number of chars before we
   465 	 * can do indexing.
   466 	 */
   467 
   468 	Tcl_GetCharLength(objPtr);
   469 
   470 	/*
   471 	 * We need to fetch the pointer again because we may have just
   472 	 * reallocated the structure.
   473 	 */
   474 	
   475 	stringPtr = GET_STRING(objPtr);
   476     }
   477     if (stringPtr->hasUnicode == 0) {
   478 
   479 	/*
   480 	 * All of the characters in the Utf string are 1 byte chars,
   481 	 * so we don't store the unicode char.  We get the Utf string
   482 	 * and convert the index'th byte to a Unicode character.
   483 	 */
   484 
   485 	unichar = (Tcl_UniChar) objPtr->bytes[index];
   486     } else {
   487 	unichar = stringPtr->unicode[index];
   488     }
   489     return unichar;
   490 }
   491 
   492 /*
   493  *----------------------------------------------------------------------
   494  *
   495  * Tcl_GetUnicode --
   496  *
   497  *	Get the Unicode form of the String object.  If
   498  *	the object is not already a String object, it will be converted
   499  *	to one.  If the String object does not have a Unicode rep, then
   500  *	one is create from the UTF string format.
   501  *
   502  * Results:
   503  *	Returns a pointer to the object's internal Unicode string.
   504  *
   505  * Side effects:
   506  *	Converts the object to have the String internal rep.
   507  *
   508  *----------------------------------------------------------------------
   509  */
   510 
   511 EXPORT_C Tcl_UniChar *
   512 Tcl_GetUnicode(objPtr)
   513     Tcl_Obj *objPtr;	/* The object to find the unicode string for. */
   514 {
   515     String *stringPtr;
   516     
   517     SetStringFromAny(NULL, objPtr);
   518     stringPtr = GET_STRING(objPtr);
   519     
   520     if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
   521 
   522 	/*
   523 	 * We haven't yet calculated the length, or all of the characters
   524 	 * in the Utf string are 1 byte chars (so we didn't store the
   525 	 * unicode str).  Since this function must return a unicode string,
   526 	 * and one has not yet been stored, force the Unicode to be
   527 	 * calculated and stored now.
   528 	 */
   529 
   530 	FillUnicodeRep(objPtr);
   531 
   532 	/*
   533 	 * We need to fetch the pointer again because we have just
   534 	 * reallocated the structure to make room for the Unicode data.
   535 	 */
   536 	
   537 	stringPtr = GET_STRING(objPtr);
   538     }
   539     return stringPtr->unicode;
   540 }
   541 
   542 /*
   543  *----------------------------------------------------------------------
   544  *
   545  * Tcl_GetUnicodeFromObj --
   546  *
   547  *	Get the Unicode form of the String object with length.  If
   548  *	the object is not already a String object, it will be converted
   549  *	to one.  If the String object does not have a Unicode rep, then
   550  *	one is create from the UTF string format.
   551  *
   552  * Results:
   553  *	Returns a pointer to the object's internal Unicode string.
   554  *
   555  * Side effects:
   556  *	Converts the object to have the String internal rep.
   557  *
   558  *----------------------------------------------------------------------
   559  */
   560 
   561 EXPORT_C Tcl_UniChar *
   562 Tcl_GetUnicodeFromObj(objPtr, lengthPtr)
   563     Tcl_Obj *objPtr;	/* The object to find the unicode string for. */
   564     int *lengthPtr;	/* If non-NULL, the location where the
   565 			 * string rep's unichar length should be
   566 			 * stored. If NULL, no length is stored. */
   567 {
   568     String *stringPtr;
   569     
   570     SetStringFromAny(NULL, objPtr);
   571     stringPtr = GET_STRING(objPtr);
   572     
   573     if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
   574 
   575 	/*
   576 	 * We haven't yet calculated the length, or all of the characters
   577 	 * in the Utf string are 1 byte chars (so we didn't store the
   578 	 * unicode str).  Since this function must return a unicode string,
   579 	 * and one has not yet been stored, force the Unicode to be
   580 	 * calculated and stored now.
   581 	 */
   582 
   583 	FillUnicodeRep(objPtr);
   584 
   585 	/*
   586 	 * We need to fetch the pointer again because we have just
   587 	 * reallocated the structure to make room for the Unicode data.
   588 	 */
   589 	
   590 	stringPtr = GET_STRING(objPtr);
   591     }
   592 
   593     if (lengthPtr != NULL) {
   594 	*lengthPtr = stringPtr->numChars;
   595     }
   596     return stringPtr->unicode;
   597 }
   598 
   599 /*
   600  *----------------------------------------------------------------------
   601  *
   602  * Tcl_GetRange --
   603  *
   604  *	Create a Tcl Object that contains the chars between first and last
   605  *	of the object indicated by "objPtr".  If the object is not already
   606  *	a String object, convert it to one.  The first and last indices
   607  *	are assumed to be in the appropriate range.
   608  *
   609  * Results:
   610  *	Returns a new Tcl Object of the String type.
   611  *
   612  * Side effects:
   613  *	Changes the internal rep of "objPtr" to the String type.
   614  *
   615  *----------------------------------------------------------------------
   616  */
   617 
   618 EXPORT_C Tcl_Obj *
   619 Tcl_GetRange(objPtr, first, last)
   620     Tcl_Obj *objPtr;		/* The Tcl object to find the range of. */
   621     int first;			/* First index of the range. */
   622     int last;			/* Last index of the range. */
   623 {
   624     Tcl_Obj *newObjPtr;		/* The Tcl object to find the range of. */
   625     String *stringPtr;
   626     
   627     SetStringFromAny(NULL, objPtr);
   628     stringPtr = GET_STRING(objPtr);
   629 
   630     if (stringPtr->numChars == -1) {
   631     
   632 	/*
   633 	 * We haven't yet calculated the length, so we don't have the
   634 	 * Unicode str.  We need to know the number of chars before we
   635 	 * can do indexing.
   636 	 */
   637 
   638 	Tcl_GetCharLength(objPtr);
   639 
   640 	/*
   641 	 * We need to fetch the pointer again because we may have just
   642 	 * reallocated the structure.
   643 	 */
   644 	
   645 	stringPtr = GET_STRING(objPtr);
   646     }
   647 
   648     if (objPtr->bytes && stringPtr->numChars == objPtr->length) {
   649 	char *str = Tcl_GetString(objPtr);
   650 
   651 	/*
   652 	 * All of the characters in the Utf string are 1 byte chars,
   653 	 * so we don't store the unicode char.  Create a new string
   654 	 * object containing the specified range of chars.
   655 	 */
   656 	
   657 	newObjPtr = Tcl_NewStringObj(&str[first], last-first+1);
   658 
   659 	/*
   660 	 * Since we know the new string only has 1-byte chars, we
   661 	 * can set it's numChars field.
   662 	 */
   663 	
   664 	SetStringFromAny(NULL, newObjPtr);
   665 	stringPtr = GET_STRING(newObjPtr);
   666 	stringPtr->numChars = last-first+1;
   667     } else {
   668 	newObjPtr = Tcl_NewUnicodeObj(stringPtr->unicode + first,
   669 		last-first+1);
   670     }
   671     return newObjPtr;
   672 }
   673 
   674 /*
   675  *----------------------------------------------------------------------
   676  *
   677  * Tcl_SetStringObj --
   678  *
   679  *	Modify an object to hold a string that is a copy of the bytes
   680  *	indicated by the byte pointer and length arguments. 
   681  *
   682  * Results:
   683  *	None.
   684  *
   685  * Side effects:
   686  *	The object's string representation will be set to a copy of
   687  *	the "length" bytes starting at "bytes". If "length" is negative, use
   688  *	bytes up to the first NULL byte; i.e., assume "bytes" points to a
   689  *	C-style NULL-terminated string. The object's old string and internal
   690  *	representations are freed and the object's type is set NULL.
   691  *
   692  *----------------------------------------------------------------------
   693  */
   694 
   695 EXPORT_C void
   696 Tcl_SetStringObj(objPtr, bytes, length)
   697     register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
   698     CONST char *bytes;		/* Points to the first of the length bytes
   699 				 * used to initialize the object. */
   700     register int length;	/* The number of bytes to copy from "bytes"
   701 				 * when initializing the object. If 
   702 				 * negative, use bytes up to the first
   703 				 * NULL byte.*/
   704 {
   705     register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
   706 
   707     /*
   708      * Free any old string rep, then set the string rep to a copy of
   709      * the length bytes starting at "bytes".
   710      */
   711 
   712     if (Tcl_IsShared(objPtr)) {
   713 	panic("Tcl_SetStringObj called with shared object");
   714     }
   715 
   716     /*
   717      * Set the type to NULL and free any internal rep for the old type.
   718      */
   719 
   720     if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
   721 	oldTypePtr->freeIntRepProc(objPtr);
   722     }
   723     objPtr->typePtr = NULL;
   724 
   725     Tcl_InvalidateStringRep(objPtr);
   726     if (length < 0) {
   727 	length = (bytes? strlen(bytes) : 0);
   728     }
   729     TclInitStringRep(objPtr, bytes, length);
   730 }
   731 
   732 /*
   733  *----------------------------------------------------------------------
   734  *
   735  * Tcl_SetObjLength --
   736  *
   737  *	This procedure changes the length of the string representation
   738  *	of an object.
   739  *
   740  * Results:
   741  *	None.
   742  *
   743  * Side effects:
   744  *	If the size of objPtr's string representation is greater than
   745  *	length, then it is reduced to length and a new terminating null
   746  *	byte is stored in the strength.  If the length of the string
   747  *	representation is greater than length, the storage space is
   748  *	reallocated to the given length; a null byte is stored at the
   749  *	end, but other bytes past the end of the original string
   750  *	representation are undefined.  The object's internal
   751  *	representation is changed to "expendable string".
   752  *
   753  *----------------------------------------------------------------------
   754  */
   755 
   756 EXPORT_C void
   757 Tcl_SetObjLength(objPtr, length)
   758     register Tcl_Obj *objPtr;	/* Pointer to object.  This object must
   759 				 * not currently be shared. */
   760     register int length;	/* Number of bytes desired for string
   761 				 * representation of object, not including
   762 				 * terminating null byte. */
   763 {
   764     String *stringPtr;
   765 
   766     if (Tcl_IsShared(objPtr)) {
   767 	panic("Tcl_SetObjLength called with shared object");
   768     }
   769     SetStringFromAny(NULL, objPtr);
   770     
   771     stringPtr = GET_STRING(objPtr);
   772     
   773     /* Check that we're not extending a pure unicode string */
   774     
   775     if (length > (int) stringPtr->allocated && 
   776 	    (objPtr->bytes != NULL || stringPtr->hasUnicode == 0)) {
   777 	char *new;
   778 
   779 	/*
   780 	 * Not enough space in current string. Reallocate the string
   781 	 * space and free the old string.
   782 	 */
   783 	if (objPtr->bytes != tclEmptyStringRep && objPtr->bytes != NULL) {
   784 	    new = (char *) ckrealloc((char *)objPtr->bytes,
   785 		    (unsigned)(length+1));
   786 	} else {
   787 	    new = (char *) ckalloc((unsigned) (length+1));
   788 	    if (objPtr->bytes != NULL && objPtr->length != 0) {
   789 		memcpy((VOID *) new, (VOID *) objPtr->bytes,
   790 			(size_t) objPtr->length);
   791 		Tcl_InvalidateStringRep(objPtr);
   792 	    }
   793 	}
   794 	objPtr->bytes = new;
   795 	stringPtr->allocated = length;
   796 	/* Invalidate the unicode data. */
   797 	stringPtr->hasUnicode = 0;
   798     }
   799     
   800     if (objPtr->bytes != NULL) {
   801         objPtr->length = length;
   802         if (objPtr->bytes != tclEmptyStringRep) {
   803             /* Ensure the string is NULL-terminated */
   804             objPtr->bytes[length] = 0;
   805         }
   806         /* Invalidate the unicode data. */
   807         stringPtr->numChars = -1;
   808         stringPtr->hasUnicode = 0;
   809     } else {
   810         /* Changing length of pure unicode string */
   811         size_t uallocated = STRING_UALLOC(length);
   812         if (uallocated > stringPtr->uallocated) {
   813             stringPtr = (String *) ckrealloc((char*) stringPtr,
   814                     STRING_SIZE(uallocated));
   815             SET_STRING(objPtr, stringPtr);
   816             stringPtr->uallocated = uallocated;
   817         }
   818         stringPtr->numChars = length;
   819         stringPtr->hasUnicode = (length > 0);
   820         /* Ensure the string is NULL-terminated */
   821         stringPtr->unicode[length] = 0;
   822         stringPtr->allocated = 0;
   823         objPtr->length = 0;
   824     }
   825 }
   826 
   827 /*
   828  *----------------------------------------------------------------------
   829  *
   830  * Tcl_AttemptSetObjLength --
   831  *
   832  *	This procedure changes the length of the string representation
   833  *	of an object.  It uses the attempt* (non-panic'ing) memory allocators.
   834  *
   835  * Results:
   836  *	1 if the requested memory was allocated, 0 otherwise.
   837  *
   838  * Side effects:
   839  *	If the size of objPtr's string representation is greater than
   840  *	length, then it is reduced to length and a new terminating null
   841  *	byte is stored in the strength.  If the length of the string
   842  *	representation is greater than length, the storage space is
   843  *	reallocated to the given length; a null byte is stored at the
   844  *	end, but other bytes past the end of the original string
   845  *	representation are undefined.  The object's internal
   846  *	representation is changed to "expendable string".
   847  *
   848  *----------------------------------------------------------------------
   849  */
   850 
   851 EXPORT_C int
   852 Tcl_AttemptSetObjLength(objPtr, length)
   853     register Tcl_Obj *objPtr;	/* Pointer to object.  This object must
   854 				 * not currently be shared. */
   855     register int length;	/* Number of bytes desired for string
   856 				 * representation of object, not including
   857 				 * terminating null byte. */
   858 {
   859     String *stringPtr;
   860 
   861     if (Tcl_IsShared(objPtr)) {
   862 	panic("Tcl_AttemptSetObjLength called with shared object");
   863     }
   864     SetStringFromAny(NULL, objPtr);
   865         
   866     stringPtr = GET_STRING(objPtr);
   867 
   868     /* Check that we're not extending a pure unicode string */
   869 
   870     if (length > (int) stringPtr->allocated && 
   871 	    (objPtr->bytes != NULL || stringPtr->hasUnicode == 0)) {
   872 	char *new;
   873 
   874 	/*
   875 	 * Not enough space in current string. Reallocate the string
   876 	 * space and free the old string.
   877 	 */
   878 	if (objPtr->bytes != tclEmptyStringRep && objPtr->bytes != NULL) {
   879 	    new = (char *) attemptckrealloc((char *)objPtr->bytes,
   880 		    (unsigned)(length+1));
   881 	    if (new == NULL) {
   882 		return 0;
   883 	    }
   884 	} else {
   885 	    new = (char *) attemptckalloc((unsigned) (length+1));
   886 	    if (new == NULL) {
   887 		return 0;
   888 	    }
   889 	    if (objPtr->bytes != NULL && objPtr->length != 0) {
   890  	    	memcpy((VOID *) new, (VOID *) objPtr->bytes,
   891  		    	(size_t) objPtr->length);
   892  	    	Tcl_InvalidateStringRep(objPtr);
   893 	    }
   894 	}
   895 	objPtr->bytes = new;
   896 	stringPtr->allocated = length;
   897 	/* Invalidate the unicode data. */
   898 	stringPtr->hasUnicode = 0;
   899     }
   900     
   901     if (objPtr->bytes != NULL) {
   902 	objPtr->length = length;
   903 	if (objPtr->bytes != tclEmptyStringRep) {
   904 	    /* Ensure the string is NULL-terminated */
   905 	    objPtr->bytes[length] = 0;
   906 	}
   907 	/* Invalidate the unicode data. */
   908 	stringPtr->numChars = -1;
   909 	stringPtr->hasUnicode = 0;
   910     } else {
   911 	/* Changing length of pure unicode string */
   912 	size_t uallocated = STRING_UALLOC(length);
   913 	if (uallocated > stringPtr->uallocated) {
   914 	    stringPtr = (String *) attemptckrealloc((char*) stringPtr,
   915 		    STRING_SIZE(uallocated));
   916 	    if (stringPtr == NULL) {
   917 	        return 0;
   918 	    }
   919 	    SET_STRING(objPtr, stringPtr);
   920 	    stringPtr->uallocated = uallocated;
   921 	}
   922 	stringPtr->numChars = length;
   923 	stringPtr->hasUnicode = (length > 0);
   924 	/* Ensure the string is NULL-terminated */
   925 	stringPtr->unicode[length] = 0;
   926 	stringPtr->allocated = 0;
   927 	objPtr->length = 0;
   928     }
   929     return 1;
   930 }
   931 
   932 /*
   933  *---------------------------------------------------------------------------
   934  *
   935  * TclSetUnicodeObj --
   936  *
   937  *	Modify an object to hold the Unicode string indicated by "unicode".
   938  *
   939  * Results:
   940  *	None.
   941  *
   942  * Side effects:
   943  *	Memory allocated for new "String" internal rep.
   944  *
   945  *---------------------------------------------------------------------------
   946  */
   947 
   948 EXPORT_C void
   949 Tcl_SetUnicodeObj(objPtr, unicode, numChars)
   950     Tcl_Obj *objPtr;		/* The object to set the string of. */
   951     CONST Tcl_UniChar *unicode;	/* The unicode string used to initialize
   952 				 * the object. */
   953     int numChars;		/* Number of characters in the unicode
   954 				 * string. */
   955 {
   956     Tcl_ObjType *typePtr;
   957     String *stringPtr;
   958     size_t uallocated;
   959 
   960     if (numChars < 0) {
   961 	numChars = 0;
   962 	if (unicode) {
   963 	    while (unicode[numChars] != 0) { numChars++; }
   964 	}
   965     }
   966     uallocated = STRING_UALLOC(numChars);
   967 
   968     /*
   969      * Free the internal rep if one exists, and invalidate the string rep.
   970      */
   971 
   972     typePtr = objPtr->typePtr;
   973     if ((typePtr != NULL) && (typePtr->freeIntRepProc) != NULL) {
   974 	(*typePtr->freeIntRepProc)(objPtr);
   975     }
   976     objPtr->typePtr = &tclStringType;
   977 
   978     /*
   979      * Allocate enough space for the String structure + Unicode string.
   980      */
   981 	
   982     stringPtr = (String *) ckalloc(STRING_SIZE(uallocated));
   983     stringPtr->numChars = numChars;
   984     stringPtr->uallocated = uallocated;
   985     stringPtr->hasUnicode = (numChars > 0);
   986     stringPtr->allocated = 0;
   987     memcpy((VOID *) stringPtr->unicode, (VOID *) unicode, uallocated);
   988     stringPtr->unicode[numChars] = 0;
   989     SET_STRING(objPtr, stringPtr);
   990     Tcl_InvalidateStringRep(objPtr);
   991     return;
   992 }
   993 
   994 /*
   995  *----------------------------------------------------------------------
   996  *
   997  * Tcl_AppendToObj --
   998  *
   999  *	This procedure appends a sequence of bytes to an object.
  1000  *
  1001  * Results:
  1002  *	None.
  1003  *
  1004  * Side effects:
  1005  *	The bytes at *bytes are appended to the string representation
  1006  *	of objPtr.
  1007  *
  1008  *----------------------------------------------------------------------
  1009  */
  1010 
  1011 EXPORT_C void
  1012 Tcl_AppendToObj(objPtr, bytes, length)
  1013     register Tcl_Obj *objPtr;	/* Points to the object to append to. */
  1014     CONST char *bytes;		/* Points to the bytes to append to the
  1015 				 * object. */
  1016     register int length;	/* The number of bytes to append from
  1017 				 * "bytes". If < 0, then append all bytes
  1018 				 * up to NULL byte. */
  1019 {
  1020     String *stringPtr;
  1021 
  1022     if (Tcl_IsShared(objPtr)) {
  1023 	panic("Tcl_AppendToObj called with shared object");
  1024     }
  1025     
  1026     SetStringFromAny(NULL, objPtr);
  1027 
  1028     if (length < 0) {
  1029 	length = (bytes ? strlen(bytes) : 0);
  1030     }
  1031     if (length == 0) {
  1032 	return;
  1033     }
  1034 
  1035     /*
  1036      * If objPtr has a valid Unicode rep, then append the Unicode
  1037      * conversion of "bytes" to the objPtr's Unicode rep, otherwise
  1038      * append "bytes" to objPtr's string rep.
  1039      */
  1040 
  1041     stringPtr = GET_STRING(objPtr);
  1042     if (stringPtr->hasUnicode != 0) {
  1043 	AppendUtfToUnicodeRep(objPtr, bytes, length);
  1044 
  1045 	stringPtr = GET_STRING(objPtr);
  1046     } else {
  1047 	AppendUtfToUtfRep(objPtr, bytes, length);
  1048     }
  1049 }
  1050 
  1051 /*
  1052  *----------------------------------------------------------------------
  1053  *
  1054  * Tcl_AppendUnicodeToObj --
  1055  *
  1056  *	This procedure appends a Unicode string to an object in the
  1057  *	most efficient manner possible.  Length must be >= 0.
  1058  *
  1059  * Results:
  1060  *	None.
  1061  *
  1062  * Side effects:
  1063  *	Invalidates the string rep and creates a new Unicode string.
  1064  *
  1065  *----------------------------------------------------------------------
  1066  */
  1067 
  1068 EXPORT_C void
  1069 Tcl_AppendUnicodeToObj(objPtr, unicode, length)
  1070     register Tcl_Obj *objPtr;	/* Points to the object to append to. */
  1071     CONST Tcl_UniChar *unicode;	/* The unicode string to append to the
  1072 			         * object. */
  1073     int length;			/* Number of chars in "unicode". */
  1074 {
  1075     String *stringPtr;
  1076 
  1077     if (Tcl_IsShared(objPtr)) {
  1078 	panic("Tcl_AppendUnicodeToObj called with shared object");
  1079     }
  1080 
  1081     if (length == 0) {
  1082 	return;
  1083     }
  1084 
  1085     SetStringFromAny(NULL, objPtr);
  1086     stringPtr = GET_STRING(objPtr);
  1087 
  1088     /*
  1089      * If objPtr has a valid Unicode rep, then append the "unicode"
  1090      * to the objPtr's Unicode rep, otherwise the UTF conversion of
  1091      * "unicode" to objPtr's string rep.
  1092      */
  1093 
  1094     if (stringPtr->hasUnicode != 0) {
  1095 	AppendUnicodeToUnicodeRep(objPtr, unicode, length);
  1096     } else {
  1097 	AppendUnicodeToUtfRep(objPtr, unicode, length);
  1098     }
  1099 }
  1100 
  1101 /*
  1102  *----------------------------------------------------------------------
  1103  *
  1104  * Tcl_AppendObjToObj --
  1105  *
  1106  *	This procedure appends the string rep of one object to another.
  1107  *	"objPtr" cannot be a shared object.
  1108  *
  1109  * Results:
  1110  *	None.
  1111  *
  1112  * Side effects:
  1113  *	The string rep of appendObjPtr is appended to the string 
  1114  *	representation of objPtr.
  1115  *
  1116  *----------------------------------------------------------------------
  1117  */
  1118 
  1119 EXPORT_C void
  1120 Tcl_AppendObjToObj(objPtr, appendObjPtr)
  1121     Tcl_Obj *objPtr;		/* Points to the object to append to. */
  1122     Tcl_Obj *appendObjPtr;	/* Object to append. */
  1123 {
  1124     String *stringPtr;
  1125     int length, numChars, allOneByteChars;
  1126     char *bytes;
  1127 
  1128     SetStringFromAny(NULL, objPtr);
  1129 
  1130     /*
  1131      * If objPtr has a valid Unicode rep, then get a Unicode string
  1132      * from appendObjPtr and append it.
  1133      */
  1134 
  1135     stringPtr = GET_STRING(objPtr);
  1136     if (stringPtr->hasUnicode != 0) {
  1137 	
  1138 	/*
  1139 	 * If appendObjPtr is not of the "String" type, don't convert it.
  1140 	 */
  1141 
  1142 	if (appendObjPtr->typePtr == &tclStringType) {
  1143 	    stringPtr = GET_STRING(appendObjPtr);
  1144 	    if ((stringPtr->numChars == -1)
  1145 		    || (stringPtr->hasUnicode == 0)) {
  1146 		
  1147 		/*
  1148 		 * If appendObjPtr is a string obj with no valid Unicode
  1149 		 * rep, then fill its unicode rep.
  1150 		 */
  1151 
  1152 		FillUnicodeRep(appendObjPtr);
  1153 		stringPtr = GET_STRING(appendObjPtr);
  1154 	    }
  1155 	    AppendUnicodeToUnicodeRep(objPtr, stringPtr->unicode,
  1156 		    stringPtr->numChars);
  1157 	} else {
  1158 	    bytes = Tcl_GetStringFromObj(appendObjPtr, &length);
  1159 	    AppendUtfToUnicodeRep(objPtr, bytes, length);
  1160 	}
  1161 	return;
  1162     }
  1163 
  1164     /*
  1165      * Append to objPtr's UTF string rep.  If we know the number of
  1166      * characters in both objects before appending, then set the combined
  1167      * number of characters in the final (appended-to) object.
  1168      */
  1169 
  1170     bytes = Tcl_GetStringFromObj(appendObjPtr, &length);
  1171 
  1172     allOneByteChars = 0;
  1173     numChars = stringPtr->numChars;
  1174     if ((numChars >= 0) && (appendObjPtr->typePtr == &tclStringType)) {
  1175 	stringPtr = GET_STRING(appendObjPtr);
  1176 	if ((stringPtr->numChars >= 0) && (stringPtr->numChars == length)) {
  1177 	    numChars += stringPtr->numChars;
  1178 	    allOneByteChars = 1;
  1179 	}
  1180     }
  1181 
  1182     AppendUtfToUtfRep(objPtr, bytes, length);
  1183 
  1184     if (allOneByteChars) {
  1185 	stringPtr = GET_STRING(objPtr);
  1186 	stringPtr->numChars = numChars;
  1187     }
  1188 }
  1189 
  1190 /*
  1191  *----------------------------------------------------------------------
  1192  *
  1193  * AppendUnicodeToUnicodeRep --
  1194  *
  1195  *	This procedure appends the contents of "unicode" to the Unicode
  1196  *	rep of "objPtr".  objPtr must already have a valid Unicode rep.
  1197  *
  1198  * Results:
  1199  *	None.
  1200  *
  1201  * Side effects:
  1202  *	objPtr's internal rep is reallocated.
  1203  *
  1204  *----------------------------------------------------------------------
  1205  */
  1206 
  1207 static void
  1208 AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars)
  1209     Tcl_Obj *objPtr;	        /* Points to the object to append to. */
  1210     CONST Tcl_UniChar *unicode; /* String to append. */
  1211     int appendNumChars;	        /* Number of chars of "unicode" to append. */
  1212 {
  1213     String *stringPtr, *tmpString;
  1214     size_t numChars;
  1215 
  1216     if (appendNumChars < 0) {
  1217 	appendNumChars = 0;
  1218 	if (unicode) {
  1219 	    while (unicode[appendNumChars] != 0) { appendNumChars++; }
  1220 	}
  1221     }
  1222     if (appendNumChars == 0) {
  1223 	return;
  1224     }
  1225 
  1226     SetStringFromAny(NULL, objPtr);
  1227     stringPtr = GET_STRING(objPtr);
  1228 
  1229     /*
  1230      * If not enough space has been allocated for the unicode rep,
  1231      * reallocate the internal rep object with additional space.  First
  1232      * try to double the required allocation; if that fails, try a more
  1233      * modest increase.  See the "TCL STRING GROWTH ALGORITHM" comment at
  1234      * the top of this file for an explanation of this growth algorithm.
  1235      */
  1236 
  1237     numChars = stringPtr->numChars + appendNumChars;
  1238 
  1239     if (STRING_UALLOC(numChars) >= stringPtr->uallocated) {
  1240      	stringPtr->uallocated = STRING_UALLOC(2 * numChars);
  1241 	tmpString = (String *) attemptckrealloc((char *)stringPtr,
  1242 		STRING_SIZE(stringPtr->uallocated));
  1243 	if (tmpString == NULL) {
  1244 	    stringPtr->uallocated =
  1245 	        STRING_UALLOC(numChars + appendNumChars) 
  1246 		+ TCL_GROWTH_MIN_ALLOC;
  1247 	    tmpString = (String *) ckrealloc((char *)stringPtr,
  1248 		    STRING_SIZE(stringPtr->uallocated));
  1249 	}
  1250 	stringPtr = tmpString;
  1251 	SET_STRING(objPtr, stringPtr);
  1252     }
  1253 
  1254     /*
  1255      * Copy the new string onto the end of the old string, then add the
  1256      * trailing null.
  1257      */
  1258 
  1259     memcpy((VOID*) (stringPtr->unicode + stringPtr->numChars), unicode,
  1260 	    appendNumChars * sizeof(Tcl_UniChar));
  1261     stringPtr->unicode[numChars] = 0;
  1262     stringPtr->numChars = numChars;
  1263 
  1264     Tcl_InvalidateStringRep(objPtr);
  1265 }
  1266 
  1267 /*
  1268  *----------------------------------------------------------------------
  1269  *
  1270  * AppendUnicodeToUtfRep --
  1271  *
  1272  *	This procedure converts the contents of "unicode" to UTF and
  1273  *	appends the UTF to the string rep of "objPtr".
  1274  *
  1275  * Results:
  1276  *	None.
  1277  *
  1278  * Side effects:
  1279  *	objPtr's internal rep is reallocated.
  1280  *
  1281  *----------------------------------------------------------------------
  1282  */
  1283 
  1284 static void
  1285 AppendUnicodeToUtfRep(objPtr, unicode, numChars)
  1286     Tcl_Obj *objPtr;	        /* Points to the object to append to. */
  1287     CONST Tcl_UniChar *unicode; /* String to convert to UTF. */
  1288     int numChars;	        /* Number of chars of "unicode" to convert. */
  1289 {
  1290     Tcl_DString dsPtr;
  1291     CONST char *bytes;
  1292     
  1293     if (numChars < 0) {
  1294 	numChars = 0;
  1295 	if (unicode) {
  1296 	    while (unicode[numChars] != 0) { numChars++; }
  1297 	}
  1298     }
  1299     if (numChars == 0) {
  1300 	return;
  1301     }
  1302 
  1303     Tcl_DStringInit(&dsPtr);
  1304     bytes = Tcl_UniCharToUtfDString(unicode, numChars, &dsPtr);
  1305     AppendUtfToUtfRep(objPtr, bytes, Tcl_DStringLength(&dsPtr));
  1306     Tcl_DStringFree(&dsPtr);
  1307 }
  1308 
  1309 /*
  1310  *----------------------------------------------------------------------
  1311  *
  1312  * AppendUtfToUnicodeRep --
  1313  *
  1314  *	This procedure converts the contents of "bytes" to Unicode and
  1315  *	appends the Unicode to the Unicode rep of "objPtr".  objPtr must
  1316  *	already have a valid Unicode rep.
  1317  *
  1318  * Results:
  1319  *	None.
  1320  *
  1321  * Side effects:
  1322  *	objPtr's internal rep is reallocated.
  1323  *
  1324  *----------------------------------------------------------------------
  1325  */
  1326 
  1327 static void
  1328 AppendUtfToUnicodeRep(objPtr, bytes, numBytes)
  1329     Tcl_Obj *objPtr;	/* Points to the object to append to. */
  1330     CONST char *bytes;	/* String to convert to Unicode. */
  1331     int numBytes;	/* Number of bytes of "bytes" to convert. */
  1332 {
  1333     Tcl_DString dsPtr;
  1334     int numChars;
  1335     Tcl_UniChar *unicode;
  1336 
  1337     if (numBytes < 0) {
  1338 	numBytes = (bytes ? strlen(bytes) : 0);
  1339     }
  1340     if (numBytes == 0) {
  1341 	return;
  1342     }
  1343     
  1344     Tcl_DStringInit(&dsPtr);
  1345     numChars = Tcl_NumUtfChars(bytes, numBytes);
  1346     unicode = (Tcl_UniChar *)Tcl_UtfToUniCharDString(bytes, numBytes, &dsPtr);
  1347     AppendUnicodeToUnicodeRep(objPtr, unicode, numChars);
  1348     Tcl_DStringFree(&dsPtr);
  1349 }
  1350 
  1351 /*
  1352  *----------------------------------------------------------------------
  1353  *
  1354  * AppendUtfToUtfRep --
  1355  *
  1356  *	This procedure appends "numBytes" bytes of "bytes" to the UTF string
  1357  *	rep of "objPtr".  objPtr must already have a valid String rep.
  1358  *
  1359  * Results:
  1360  *	None.
  1361  *
  1362  * Side effects:
  1363  *	objPtr's internal rep is reallocated.
  1364  *
  1365  *----------------------------------------------------------------------
  1366  */
  1367 
  1368 static void
  1369 AppendUtfToUtfRep(objPtr, bytes, numBytes)
  1370     Tcl_Obj *objPtr;	/* Points to the object to append to. */
  1371     CONST char *bytes;	/* String to append. */
  1372     int numBytes;	/* Number of bytes of "bytes" to append. */
  1373 {
  1374     String *stringPtr;
  1375     int newLength, oldLength;
  1376 
  1377     if (numBytes < 0) {
  1378 	numBytes = (bytes ? strlen(bytes) : 0);
  1379     }
  1380     if (numBytes == 0) {
  1381 	return;
  1382     }
  1383 
  1384     /*
  1385      * Copy the new string onto the end of the old string, then add the
  1386      * trailing null.
  1387      */
  1388 
  1389     oldLength = objPtr->length;
  1390     newLength = numBytes + oldLength;
  1391 
  1392     stringPtr = GET_STRING(objPtr);
  1393     if (newLength > (int) stringPtr->allocated) {
  1394 
  1395 	/*
  1396 	 * There isn't currently enough space in the string representation
  1397 	 * so allocate additional space.  First, try to double the length
  1398 	 * required.  If that fails, try a more modest allocation.  See the
  1399 	 * "TCL STRING GROWTH ALGORITHM" comment at the top of this file for an
  1400 	 * explanation of this growth algorithm.
  1401 	 */
  1402 
  1403 	if (Tcl_AttemptSetObjLength(objPtr, 2 * newLength) == 0) {
  1404 	    Tcl_SetObjLength(objPtr,
  1405 		    newLength + numBytes + TCL_GROWTH_MIN_ALLOC);
  1406 	}
  1407     }
  1408 
  1409     /*
  1410      * Invalidate the unicode data.
  1411      */
  1412     
  1413     stringPtr->numChars = -1;
  1414     stringPtr->hasUnicode = 0;
  1415     
  1416     memcpy((VOID *) (objPtr->bytes + oldLength), (VOID *) bytes,
  1417 	    (size_t) numBytes);
  1418     objPtr->bytes[newLength] = 0;
  1419     objPtr->length = newLength;
  1420 }
  1421 
  1422 /*
  1423  *----------------------------------------------------------------------
  1424  *
  1425  * Tcl_AppendStringsToObjVA --
  1426  *
  1427  *	This procedure appends one or more null-terminated strings
  1428  *	to an object.
  1429  *
  1430  * Results:
  1431  *	None.
  1432  *
  1433  * Side effects:
  1434  *	The contents of all the string arguments are appended to the
  1435  *	string representation of objPtr.
  1436  *
  1437  *----------------------------------------------------------------------
  1438  */
  1439 
  1440 EXPORT_C void
  1441 Tcl_AppendStringsToObjVA (objPtr, argList)
  1442     Tcl_Obj *objPtr;		/* Points to the object to append to. */
  1443     va_list argList;		/* Variable argument list. */
  1444 {
  1445 #define STATIC_LIST_SIZE 16
  1446     String *stringPtr;
  1447     int newLength, oldLength, attemptLength;
  1448     register char *string, *dst;
  1449     char *static_list[STATIC_LIST_SIZE];
  1450     char **args = static_list;
  1451     int nargs_space = STATIC_LIST_SIZE;
  1452     int nargs, i;
  1453 
  1454     if (Tcl_IsShared(objPtr)) {
  1455 	panic("Tcl_AppendStringsToObj called with shared object");
  1456     }
  1457 
  1458     SetStringFromAny(NULL, objPtr);
  1459 
  1460     /*
  1461      * Figure out how much space is needed for all the strings, and
  1462      * expand the string representation if it isn't big enough. If no
  1463      * bytes would be appended, just return.  Note that on some platforms
  1464      * (notably OS/390) the argList is an array so we need to use memcpy.
  1465      */
  1466 
  1467     nargs = 0;
  1468     newLength = 0;
  1469     oldLength = objPtr->length;
  1470     while (1) {
  1471 	string = va_arg(argList, char *);
  1472 	if (string == NULL) {
  1473 	    break;
  1474 	}
  1475  	if (nargs >= nargs_space) {
  1476  	    /* 
  1477  	     * Expand the args buffer
  1478  	     */
  1479  	    nargs_space += STATIC_LIST_SIZE;
  1480  	    if (args == static_list) {
  1481  	    	args = (void *)ckalloc(nargs_space * sizeof(char *));
  1482  		for (i = 0; i < nargs; ++i) {
  1483  		    args[i] = static_list[i];
  1484  		}
  1485  	    } else {
  1486  		args = (void *)ckrealloc((void *)args,
  1487 			nargs_space * sizeof(char *));
  1488  	    }
  1489  	}
  1490 	newLength += strlen(string);
  1491 	args[nargs++] = string;
  1492     }
  1493     if (newLength == 0) {
  1494 	goto done;
  1495     }
  1496 
  1497     stringPtr = GET_STRING(objPtr);
  1498     if (oldLength + newLength > (int) stringPtr->allocated) {
  1499 
  1500 	/*
  1501 	 * There isn't currently enough space in the string
  1502 	 * representation, so allocate additional space.  If the current
  1503 	 * string representation isn't empty (i.e. it looks like we're
  1504 	 * doing a series of appends) then try to allocate extra space to
  1505 	 * accomodate future growth: first try to double the required memory;
  1506 	 * if that fails, try a more modest allocation.  See the "TCL STRING
  1507 	 * GROWTH ALGORITHM" comment at the top of this file for an explanation
  1508 	 * of this growth algorithm.  Otherwise, if the current string
  1509 	 * representation is empty, exactly enough memory is allocated.
  1510 	 */
  1511 
  1512 	if (oldLength == 0) {
  1513 	    Tcl_SetObjLength(objPtr, newLength);
  1514 	} else {
  1515 	    attemptLength = 2 * (oldLength + newLength);
  1516 	    if (Tcl_AttemptSetObjLength(objPtr, attemptLength) == 0) {
  1517 		attemptLength = oldLength + (2 * newLength) +
  1518 		    TCL_GROWTH_MIN_ALLOC;
  1519 		Tcl_SetObjLength(objPtr, attemptLength);
  1520 	    }
  1521 	}
  1522     }
  1523 
  1524     /*
  1525      * Make a second pass through the arguments, appending all the
  1526      * strings to the object.
  1527      */
  1528 
  1529     dst = objPtr->bytes + oldLength;
  1530     for (i = 0; i < nargs; ++i) {
  1531  	string = args[i];
  1532 	if (string == NULL) {
  1533 	    break;
  1534 	}
  1535 	while (*string != 0) {
  1536 	    *dst = *string;
  1537 	    dst++;
  1538 	    string++;
  1539 	}
  1540     }
  1541 
  1542     /*
  1543      * Add a null byte to terminate the string.  However, be careful:
  1544      * it's possible that the object is totally empty (if it was empty
  1545      * originally and there was nothing to append).  In this case dst is
  1546      * NULL; just leave everything alone.
  1547      */
  1548 
  1549     if (dst != NULL) {
  1550 	*dst = 0;
  1551     }
  1552     objPtr->length = oldLength + newLength;
  1553 
  1554     done:
  1555     /*
  1556      * If we had to allocate a buffer from the heap, 
  1557      * free it now.
  1558      */
  1559  
  1560     if (args != static_list) {
  1561      	ckfree((void *)args);
  1562     }
  1563 #undef STATIC_LIST_SIZE
  1564 }
  1565 
  1566 /*
  1567  *----------------------------------------------------------------------
  1568  *
  1569  * Tcl_AppendStringsToObj --
  1570  *
  1571  *	This procedure appends one or more null-terminated strings
  1572  *	to an object.
  1573  *
  1574  * Results:
  1575  *	None.
  1576  *
  1577  * Side effects:
  1578  *	The contents of all the string arguments are appended to the
  1579  *	string representation of objPtr.
  1580  *
  1581  *----------------------------------------------------------------------
  1582  */
  1583 
  1584 EXPORT_C void
  1585 Tcl_AppendStringsToObj TCL_VARARGS_DEF(Tcl_Obj *,arg1)
  1586 {
  1587     register Tcl_Obj *objPtr;
  1588     va_list argList;
  1589 
  1590     objPtr = TCL_VARARGS_START(Tcl_Obj *,arg1,argList);
  1591     Tcl_AppendStringsToObjVA(objPtr, argList);
  1592     va_end(argList);
  1593 }
  1594 
  1595 /*
  1596  *---------------------------------------------------------------------------
  1597  *
  1598  * FillUnicodeRep --
  1599  *
  1600  *	Populate the Unicode internal rep with the Unicode form of its string
  1601  *	rep.  The object must alread have a "String" internal rep.
  1602  *
  1603  * Results:
  1604  *	None.
  1605  *
  1606  * Side effects:
  1607  *	Reallocates the String internal rep.
  1608  *
  1609  *---------------------------------------------------------------------------
  1610  */
  1611 
  1612 static void
  1613 FillUnicodeRep(objPtr)
  1614     Tcl_Obj *objPtr;	/* The object in which to fill the unicode rep. */
  1615 {
  1616     String *stringPtr;
  1617     size_t uallocated;
  1618     char *src, *srcEnd;
  1619     Tcl_UniChar *dst;
  1620     src = objPtr->bytes;
  1621     
  1622     stringPtr = GET_STRING(objPtr);
  1623     if (stringPtr->numChars == -1) {
  1624 	stringPtr->numChars = Tcl_NumUtfChars(src, objPtr->length);
  1625     }
  1626     stringPtr->hasUnicode = (stringPtr->numChars > 0);
  1627 
  1628     uallocated = STRING_UALLOC(stringPtr->numChars);
  1629     if (uallocated > stringPtr->uallocated) {
  1630     
  1631 	/*
  1632 	 * If not enough space has been allocated for the unicode rep,
  1633 	 * reallocate the internal rep object.
  1634 	 */
  1635 
  1636 	/*
  1637 	 * There isn't currently enough space in the Unicode
  1638 	 * representation so allocate additional space.  If the current
  1639 	 * Unicode representation isn't empty (i.e. it looks like we've
  1640 	 * done some appends) then overallocate the space so
  1641 	 * that we won't have to do as much reallocation in the future.
  1642 	 */
  1643 
  1644 	if (stringPtr->uallocated > 0) {
  1645 	    uallocated *= 2;
  1646 	}
  1647 	stringPtr = (String *) ckrealloc((char*) stringPtr,
  1648 		STRING_SIZE(uallocated));
  1649 	stringPtr->uallocated = uallocated;
  1650     }
  1651 
  1652     /*
  1653      * Convert src to Unicode and store the coverted data in "unicode".
  1654      */
  1655     
  1656     srcEnd = src + objPtr->length;
  1657     for (dst = stringPtr->unicode; src < srcEnd; dst++) {
  1658 	src += TclUtfToUniChar(src, dst);
  1659     }
  1660     *dst = 0;
  1661     
  1662     SET_STRING(objPtr, stringPtr);
  1663 }
  1664 
  1665 /*
  1666  *----------------------------------------------------------------------
  1667  *
  1668  * DupStringInternalRep --
  1669  *
  1670  *	Initialize the internal representation of a new Tcl_Obj to a
  1671  *	copy of the internal representation of an existing string object.
  1672  *
  1673  * Results:
  1674  *	None.
  1675  *
  1676  * Side effects:
  1677  *	copyPtr's internal rep is set to a copy of srcPtr's internal
  1678  *	representation.
  1679  *
  1680  *----------------------------------------------------------------------
  1681  */
  1682 
  1683 static void
  1684 DupStringInternalRep(srcPtr, copyPtr)
  1685     register Tcl_Obj *srcPtr;	/* Object with internal rep to copy.  Must
  1686 				 * have an internal rep of type "String". */
  1687     register Tcl_Obj *copyPtr;	/* Object with internal rep to set.  Must
  1688 				 * not currently have an internal rep.*/
  1689 {
  1690     String *srcStringPtr = GET_STRING(srcPtr);
  1691     String *copyStringPtr = NULL;
  1692 
  1693     /*
  1694      * If the src obj is a string of 1-byte Utf chars, then copy the
  1695      * string rep of the source object and create an "empty" Unicode
  1696      * internal rep for the new object.  Otherwise, copy Unicode
  1697      * internal rep, and invalidate the string rep of the new object.
  1698      */
  1699     
  1700     if (srcStringPtr->hasUnicode == 0) {
  1701     	copyStringPtr = (String *) ckalloc(STRING_SIZE(STRING_UALLOC(0)));
  1702 	copyStringPtr->uallocated = STRING_UALLOC(0);
  1703     } else {
  1704 	copyStringPtr = (String *) ckalloc(
  1705 	    STRING_SIZE(srcStringPtr->uallocated));
  1706 	copyStringPtr->uallocated = srcStringPtr->uallocated;
  1707 
  1708 	memcpy((VOID *) copyStringPtr->unicode,
  1709 		(VOID *) srcStringPtr->unicode,
  1710 		(size_t) srcStringPtr->numChars * sizeof(Tcl_UniChar));
  1711 	copyStringPtr->unicode[srcStringPtr->numChars] = 0;
  1712     }
  1713     copyStringPtr->numChars = srcStringPtr->numChars;
  1714     copyStringPtr->hasUnicode = srcStringPtr->hasUnicode;
  1715     copyStringPtr->allocated = srcStringPtr->allocated;
  1716 
  1717     /*
  1718      * Tricky point: the string value was copied by generic object
  1719      * management code, so it doesn't contain any extra bytes that
  1720      * might exist in the source object.
  1721      */
  1722 
  1723     copyStringPtr->allocated = copyPtr->length;
  1724 
  1725     SET_STRING(copyPtr, copyStringPtr);
  1726     copyPtr->typePtr = &tclStringType;
  1727 }
  1728 
  1729 /*
  1730  *----------------------------------------------------------------------
  1731  *
  1732  * SetStringFromAny --
  1733  *
  1734  *	Create an internal representation of type "String" for an object.
  1735  *
  1736  * Results:
  1737  *	This operation always succeeds and returns TCL_OK.
  1738  *
  1739  * Side effects:
  1740  *	Any old internal reputation for objPtr is freed and the
  1741  *	internal representation is set to "String".
  1742  *
  1743  *----------------------------------------------------------------------
  1744  */
  1745 
  1746 static int
  1747 SetStringFromAny(interp, objPtr)
  1748     Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
  1749     register Tcl_Obj *objPtr;	/* The object to convert. */
  1750 {
  1751     /*
  1752      * The Unicode object is optimized for the case where each UTF char
  1753      * in a string is only one byte.  In this case, we store the value of
  1754      * numChars, but we don't copy the bytes to the unicodeObj->unicode.
  1755      */
  1756 
  1757     if (objPtr->typePtr != &tclStringType) {
  1758 	String *stringPtr;
  1759 
  1760 	if (objPtr->typePtr != NULL) {
  1761 	    if (objPtr->bytes == NULL) {
  1762 		objPtr->typePtr->updateStringProc(objPtr);
  1763 	    }
  1764 	    if ((objPtr->typePtr->freeIntRepProc) != NULL) {
  1765 		(*objPtr->typePtr->freeIntRepProc)(objPtr);
  1766 	    }
  1767 	}
  1768 	objPtr->typePtr = &tclStringType;
  1769 
  1770 	/*
  1771 	 * Allocate enough space for the basic String structure.
  1772 	 */
  1773 
  1774 	stringPtr = (String *) ckalloc(STRING_SIZE(STRING_UALLOC(0)));
  1775 	stringPtr->numChars = -1;
  1776 	stringPtr->uallocated = STRING_UALLOC(0);
  1777 	stringPtr->hasUnicode = 0;
  1778 
  1779 	if (objPtr->bytes != NULL) {
  1780 	    stringPtr->allocated = objPtr->length;	    
  1781  	    objPtr->bytes[objPtr->length] = 0;
  1782 	} else {
  1783 	    objPtr->length = 0;
  1784 	}
  1785 	SET_STRING(objPtr, stringPtr);
  1786     }
  1787     return TCL_OK;
  1788 }
  1789 
  1790 /*
  1791  *----------------------------------------------------------------------
  1792  *
  1793  * UpdateStringOfString --
  1794  *
  1795  *	Update the string representation for an object whose internal
  1796  *	representation is "String".
  1797  *
  1798  * Results:
  1799  *	None.
  1800  *
  1801  * Side effects:
  1802  *	The object's string may be set by converting its Unicode
  1803  *	represention to UTF format.
  1804  *
  1805  *----------------------------------------------------------------------
  1806  */
  1807 
  1808 static void
  1809 UpdateStringOfString(objPtr)
  1810     Tcl_Obj *objPtr;		/* Object with string rep to update. */
  1811 {
  1812     int i, size;
  1813     Tcl_UniChar *unicode;
  1814     char dummy[TCL_UTF_MAX];
  1815     char *dst;
  1816     String *stringPtr;
  1817 
  1818     stringPtr = GET_STRING(objPtr);
  1819     if ((objPtr->bytes == NULL) || (stringPtr->allocated == 0)) {
  1820 
  1821 	if (stringPtr->numChars <= 0) {
  1822 
  1823 	    /*
  1824 	     * If there is no Unicode rep, or the string has 0 chars,
  1825 	     * then set the string rep to an empty string.
  1826 	     */
  1827 
  1828 	    objPtr->bytes = tclEmptyStringRep;
  1829 	    objPtr->length = 0;
  1830 	    return;
  1831 	}
  1832 
  1833 	unicode = stringPtr->unicode;
  1834 
  1835 	/*
  1836 	 * Translate the Unicode string to UTF.  "size" will hold the
  1837 	 * amount of space the UTF string needs.
  1838 	 */
  1839 
  1840 	size = 0;
  1841 	for (i = 0; i < stringPtr->numChars; i++) {
  1842 	    size += Tcl_UniCharToUtf((int) unicode[i], dummy);
  1843 	}
  1844 	
  1845 	dst = (char *) ckalloc((unsigned) (size + 1));
  1846 	objPtr->bytes = dst;
  1847 	objPtr->length = size;
  1848 	stringPtr->allocated = size;
  1849 
  1850 	for (i = 0; i < stringPtr->numChars; i++) {
  1851 	    dst += Tcl_UniCharToUtf(unicode[i], dst);
  1852 	}
  1853 	*dst = '\0';
  1854     }
  1855     return;
  1856 }
  1857 
  1858 /*
  1859  *----------------------------------------------------------------------
  1860  *
  1861  * FreeStringInternalRep --
  1862  *
  1863  *	Deallocate the storage associated with a String data object's
  1864  *	internal representation.
  1865  *
  1866  * Results:
  1867  *	None.
  1868  *
  1869  * Side effects:
  1870  *	Frees memory. 
  1871  *
  1872  *----------------------------------------------------------------------
  1873  */
  1874 
  1875 static void
  1876 FreeStringInternalRep(objPtr)
  1877     Tcl_Obj *objPtr;		/* Object with internal rep to free. */
  1878 {
  1879     ckfree((char *) GET_STRING(objPtr));
  1880 }