/[dtapublic]/projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclstringobj.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclstringobj.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.66  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25