diff options
Diffstat (limited to 'generic/tclEncoding.c')
| -rw-r--r-- | generic/tclEncoding.c | 461 | 
1 files changed, 253 insertions, 208 deletions
| diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 441e099..d246cb2 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -7,8 +7,6 @@   *   * See the file "license.terms" for information on usage and redistribution of   * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclEncoding.c,v 1.66 2009/02/10 22:49:55 nijtmans Exp $   */  #include "tclInt.h" @@ -184,6 +182,7 @@ TCL_DECLARE_MUTEX(encodingMutex)  static Tcl_Encoding defaultEncoding;  static Tcl_Encoding systemEncoding; +Tcl_Encoding tclIdentityEncoding;  /*   * The following variable is used in the sparse matrix code for a @@ -272,7 +271,7 @@ static int		Iso88591ToUtfProc(ClientData clientData,  			    int *dstCharsPtr);  /* - * A Tcl_ObjType for holding a cached Tcl_Encoding in the otherValuePtr field + * A Tcl_ObjType for holding a cached Tcl_Encoding in the twoPtrValue.ptr1 field   * of the intrep. This should help the lifetime of encodings be more useful.   * See concerns raised in [Bug 1077262].   */ @@ -295,7 +294,7 @@ static const Tcl_ObjType encodingType = {   *	Standard Tcl return code.   *   * Side effects: - * 	Caches the Tcl_Encoding value as the internal rep of (*objPtr). + *	Caches the Tcl_Encoding value as the internal rep of (*objPtr).   *   *----------------------------------------------------------------------   */ @@ -307,6 +306,7 @@ Tcl_GetEncodingFromObj(      Tcl_Encoding *encodingPtr)  {      const char *name = Tcl_GetString(objPtr); +      if (objPtr->typePtr != &encodingType) {  	Tcl_Encoding encoding = Tcl_GetEncoding(interp, name); @@ -314,7 +314,7 @@ Tcl_GetEncodingFromObj(  	    return TCL_ERROR;  	}  	TclFreeIntRep(objPtr); -	objPtr->internalRep.otherValuePtr = (void *) encoding; +	objPtr->internalRep.twoPtrValue.ptr1 = encoding;  	objPtr->typePtr = &encodingType;      }      *encodingPtr = Tcl_GetEncoding(NULL, name); @@ -335,7 +335,8 @@ static void  FreeEncodingIntRep(      Tcl_Obj *objPtr)  { -    Tcl_FreeEncoding((Tcl_Encoding) objPtr->internalRep.otherValuePtr); +    Tcl_FreeEncoding(objPtr->internalRep.twoPtrValue.ptr1); +    objPtr->typePtr = NULL;  }  /* @@ -353,8 +354,7 @@ DupEncodingIntRep(      Tcl_Obj *srcPtr,      Tcl_Obj *dupPtr)  { -    dupPtr->internalRep.otherValuePtr = (void *) -	    Tcl_GetEncoding(NULL, srcPtr->bytes); +    dupPtr->internalRep.twoPtrValue.ptr1 = Tcl_GetEncoding(NULL, srcPtr->bytes);  }  /* @@ -453,8 +453,8 @@ TclSetLibraryPath(   *   * FillEncodingFileMap --   * - * 	Called to bring the encoding file map in sync with the current value - * 	of the encoding search path. + *	Called to bring the encoding file map in sync with the current value + *	of the encoding search path.   *   *	Scan the directories on the encoding search path, find the *.enc   *	files, and store the found pathnames in a map associated with the @@ -507,12 +507,12 @@ FillEncodingFileMap(void)  	Tcl_ListObjGetElements(NULL, matchFileList, &numFiles, &filev);  	for (j=0; j<numFiles; j++) { -	    Tcl_Obj *encodingName, *file; +	    Tcl_Obj *encodingName, *fileObj; -	    file = TclPathPart(NULL, filev[j], TCL_PATH_TAIL); -	    encodingName = TclPathPart(NULL, file, TCL_PATH_ROOT); +	    fileObj = TclPathPart(NULL, filev[j], TCL_PATH_TAIL); +	    encodingName = TclPathPart(NULL, fileObj, TCL_PATH_ROOT);  	    Tcl_DictObjPut(NULL, map, encodingName, directory); -	    Tcl_DecrRefCount(file); +	    Tcl_DecrRefCount(fileObj);  	    Tcl_DecrRefCount(encodingName);  	}  	Tcl_DecrRefCount(matchFileList); @@ -544,6 +544,9 @@ void  TclInitEncodingSubsystem(void)  {      Tcl_EncodingType type; +    TableEncodingData *dataPtr; +    unsigned size; +    unsigned short i;      if (encodingsInitialized) {  	return; @@ -565,7 +568,7 @@ TclInitEncodingSubsystem(void)      type.freeProc	= NULL;      type.nullSize	= 1;      type.clientData	= NULL; -    Tcl_CreateEncoding(&type); +    tclIdentityEncoding = Tcl_CreateEncoding(&type);      type.encodingName	= "utf-8";      type.toUtfProc	= UtfExtToUtfIntProc; @@ -590,44 +593,37 @@ TclInitEncodingSubsystem(void)       * code to duplicate the structure of a table encoding here.       */ -    { -	TableEncodingData *dataPtr = (TableEncodingData *) -		ckalloc(sizeof(TableEncodingData)); -	unsigned size; -	unsigned short i; - -	memset(dataPtr, 0, sizeof(TableEncodingData)); -	dataPtr->fallback = '?'; - -	size = 256*(sizeof(unsigned short *) + sizeof(unsigned short)); -	dataPtr->toUnicode = (unsigned short **) ckalloc(size); -	memset(dataPtr->toUnicode, 0, size); -	dataPtr->fromUnicode = (unsigned short **) ckalloc(size); -	memset(dataPtr->fromUnicode, 0, size); - -	dataPtr->toUnicode[0] = (unsigned short *) (dataPtr->toUnicode + 256); -	dataPtr->fromUnicode[0] = (unsigned short *) -		(dataPtr->fromUnicode + 256); -	for (i=1 ; i<256 ; i++) { -	    dataPtr->toUnicode[i] = emptyPage; -	    dataPtr->fromUnicode[i] = emptyPage; -	} +    dataPtr = ckalloc(sizeof(TableEncodingData)); +    memset(dataPtr, 0, sizeof(TableEncodingData)); +    dataPtr->fallback = '?'; -	for (i=0 ; i<256 ; i++) { -	    dataPtr->toUnicode[0][i] = i; -	    dataPtr->fromUnicode[0][i] = i; -	} +    size = 256*(sizeof(unsigned short *) + sizeof(unsigned short)); +    dataPtr->toUnicode = ckalloc(size); +    memset(dataPtr->toUnicode, 0, size); +    dataPtr->fromUnicode = ckalloc(size); +    memset(dataPtr->fromUnicode, 0, size); -	type.encodingName	= "iso8859-1"; -	type.toUtfProc		= Iso88591ToUtfProc; -	type.fromUtfProc	= Iso88591FromUtfProc; -	type.freeProc		= TableFreeProc; -	type.nullSize		= 1; -	type.clientData		= dataPtr; -	defaultEncoding	= Tcl_CreateEncoding(&type); -	systemEncoding	= Tcl_GetEncoding(NULL, type.encodingName); +    dataPtr->toUnicode[0] = (unsigned short *) (dataPtr->toUnicode + 256); +    dataPtr->fromUnicode[0] = (unsigned short *) (dataPtr->fromUnicode + 256); +    for (i=1 ; i<256 ; i++) { +	dataPtr->toUnicode[i] = emptyPage; +	dataPtr->fromUnicode[i] = emptyPage;      } +    for (i=0 ; i<256 ; i++) { +	dataPtr->toUnicode[0][i] = i; +	dataPtr->fromUnicode[0][i] = i; +    } + +    type.encodingName	= "iso8859-1"; +    type.toUtfProc	= Iso88591ToUtfProc; +    type.fromUtfProc	= Iso88591FromUtfProc; +    type.freeProc	= TableFreeProc; +    type.nullSize	= 1; +    type.clientData	= dataPtr; +    defaultEncoding	= Tcl_CreateEncoding(&type); +    systemEncoding	= Tcl_GetEncoding(NULL, type.encodingName); +      encodingsInitialized = 1;  } @@ -656,6 +652,7 @@ TclFinalizeEncodingSubsystem(void)      Tcl_MutexLock(&encodingMutex);      encodingsInitialized = 0;      FreeEncoding(systemEncoding); +    FreeEncoding(tclIdentityEncoding);      hPtr = Tcl_FirstHashEntry(&encodingTable, &search);      while (hPtr != NULL) { @@ -666,7 +663,7 @@ TclFinalizeEncodingSubsystem(void)  	 * cleaned up.  	 */ -	FreeEncoding((Tcl_Encoding) Tcl_GetHashValue(hPtr)); +	FreeEncoding(Tcl_GetHashValue(hPtr));  	hPtr = Tcl_FirstHashEntry(&encodingTable, &search);      } @@ -679,15 +676,15 @@ TclFinalizeEncodingSubsystem(void)   *   * Tcl_GetDefaultEncodingDir --   * - * 	Legacy public interface to retrieve first directory in the encoding - * 	searchPath. + *	Legacy public interface to retrieve first directory in the encoding + *	searchPath.   *   * Results:   *	The directory pathname, as a string, or NULL for an empty encoding   *	search path.   *   * Side effects: - * 	None. + *	None.   *   *-------------------------------------------------------------------------   */ @@ -712,14 +709,14 @@ Tcl_GetDefaultEncodingDir(void)   *   * Tcl_SetDefaultEncodingDir --   * - * 	Legacy public interface to set the first directory in the encoding - * 	search path. + *	Legacy public interface to set the first directory in the encoding + *	search path.   *   * Results: - * 	None. + *	None.   *   * Side effects: - * 	Modifies the encoding search path. + *	Modifies the encoding search path.   *   *-------------------------------------------------------------------------   */ @@ -779,7 +776,7 @@ Tcl_GetEncoding(      hPtr = Tcl_FindHashEntry(&encodingTable, name);      if (hPtr != NULL) { -	encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr); +	encodingPtr = Tcl_GetHashValue(hPtr);  	encodingPtr->refCount++;  	Tcl_MutexUnlock(&encodingMutex);  	return (Tcl_Encoding) encodingPtr; @@ -838,12 +835,14 @@ static void  FreeEncoding(      Tcl_Encoding encoding)  { -    Encoding *encodingPtr; +    Encoding *encodingPtr = (Encoding *) encoding; -    encodingPtr = (Encoding *) encoding;      if (encodingPtr == NULL) {  	return;      } +    if (encodingPtr->refCount<=0) { +	Tcl_Panic("FreeEncoding: refcount problem !!!"); +    }      encodingPtr->refCount--;      if (encodingPtr->refCount == 0) {  	if (encodingPtr->freeProc != NULL) { @@ -852,8 +851,8 @@ FreeEncoding(  	if (encodingPtr->hPtr != NULL) {  	    Tcl_DeleteHashEntry(encodingPtr->hPtr);  	} -	ckfree((char *) encodingPtr->name); -	ckfree((char *) encodingPtr); +	ckfree(encodingPtr->name); +	ckfree(encodingPtr);      }  } @@ -923,9 +922,10 @@ Tcl_GetEncodingNames(      Tcl_MutexLock(&encodingMutex);      for (hPtr = Tcl_FirstHashEntry(&encodingTable, &search); hPtr != NULL;  	    hPtr = Tcl_NextHashEntry(&search)) { -	Encoding *encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr); +	Encoding *encodingPtr = Tcl_GetHashValue(hPtr); +  	Tcl_CreateHashEntry(&table, -		(char *) Tcl_NewStringObj(encodingPtr->name, -1), &dummy); +		Tcl_NewStringObj(encodingPtr->name, -1), &dummy);      }      Tcl_MutexUnlock(&encodingMutex); @@ -938,7 +938,7 @@ Tcl_GetEncodingNames(      Tcl_DictObjFirst(NULL, map, &mapSearch, &name, NULL, &done);      for (; !done; Tcl_DictObjNext(&mapSearch, &name, NULL, &done)) { -	Tcl_CreateHashEntry(&table, (char *) name, &dummy); +	Tcl_CreateHashEntry(&table, name, &dummy);      }      /* @@ -981,13 +981,13 @@ Tcl_GetEncodingNames(  int  Tcl_SetSystemEncoding(      Tcl_Interp *interp,		/* Interp for error reporting, if not NULL. */ -    const char *name)		/* The name of the desired encoding, or NULL +    const char *name)		/* The name of the desired encoding, or NULL/""  				 * to reset to default encoding. */  {      Tcl_Encoding encoding;      Encoding *encodingPtr; -    if (name == NULL) { +    if (!name || !*name) {  	Tcl_MutexLock(&encodingMutex);  	encoding = defaultEncoding;  	encodingPtr = (Encoding *) encoding; @@ -1052,13 +1052,13 @@ Tcl_CreateEncoding(  	 * reference goes away.  	 */ -	encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr); +	encodingPtr = Tcl_GetHashValue(hPtr);  	encodingPtr->hPtr = NULL;      } -    name = ckalloc((unsigned) strlen(typePtr->encodingName) + 1); +    name = ckalloc(strlen(typePtr->encodingName) + 1); -    encodingPtr = (Encoding *) ckalloc(sizeof(Encoding)); +    encodingPtr = ckalloc(sizeof(Encoding));      encodingPtr->name		= strcpy(name, typePtr->encodingName);      encodingPtr->toUtfProc	= typePtr->toUtfProc;      encodingPtr->fromUtfProc	= typePtr->fromUtfProc; @@ -1112,7 +1112,7 @@ Tcl_ExternalToUtfDString(  {      char *dst;      Tcl_EncodingState state; -    Encoding *encodingPtr; +    const Encoding *encodingPtr;      int flags, dstLen, result, soFar, srcRead, dstWrote, dstChars;      Tcl_DStringInit(dstPtr); @@ -1202,7 +1202,7 @@ Tcl_ExternalToUtf(  				 * correspond to the bytes stored in the  				 * output buffer. */  { -    Encoding *encodingPtr; +    const Encoding *encodingPtr;      int result, srcRead, dstWrote, dstChars;      Tcl_EncodingState state; @@ -1278,7 +1278,7 @@ Tcl_UtfToExternalDString(  {      char *dst;      Tcl_EncodingState state; -    Encoding *encodingPtr; +    const Encoding *encodingPtr;      int flags, dstLen, result, soFar, srcRead, dstWrote, dstChars;      Tcl_DStringInit(dstPtr); @@ -1370,7 +1370,7 @@ Tcl_UtfToExternal(  				 * correspond to the bytes stored in the  				 * output buffer. */  { -    Encoding *encodingPtr; +    const Encoding *encodingPtr;      int result, srcRead, dstWrote, dstChars;      Tcl_EncodingState state; @@ -1427,7 +1427,7 @@ Tcl_UtfToExternal(   *   *---------------------------------------------------------------------------   */ - +#undef Tcl_FindExecutable  void  Tcl_FindExecutable(      const char *argv0)		/* The value of the application's argv[0] @@ -1446,9 +1446,9 @@ Tcl_FindExecutable(   *	Open the file believed to hold data for the encoding, "name".   *   * Results: - * 	Returns the readable Tcl_Channel from opening the file, or NULL if the - * 	file could not be successfully opened. If NULL was returned, an error - * 	message is left in interp's result object, unless interp was NULL. + *	Returns the readable Tcl_Channel from opening the file, or NULL if the + *	file could not be successfully opened. If NULL was returned, an error + *	message is left in interp's result object, unless interp was NULL.   *   * Side effects:   *	Channel may be opened. Information about the filesystem may be cached @@ -1491,6 +1491,7 @@ OpenEncodingFileChannel(  	}  	if (!verified) {  	    const char *dirString = Tcl_GetString(directory); +  	    for (i=0; i<numDirs && !verified; i++) {  		if (strcmp(dirString, Tcl_GetString(dir[i])) == 0) {  		    verified = 1; @@ -1543,7 +1544,8 @@ OpenEncodingFileChannel(      }      if ((NULL == chan) && (interp != NULL)) { -	Tcl_AppendResult(interp, "unknown encoding \"", name, "\"", NULL); +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"unknown encoding \"%s\"", name));  	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL);      }      Tcl_DecrRefCount(fileNameObj); @@ -1617,7 +1619,9 @@ LoadEncodingFile(  	break;      }      if ((encoding == NULL) && (interp != NULL)) { -	Tcl_AppendResult(interp, "invalid encoding file \"", name, "\"", NULL); +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"invalid encoding file \"%s\"", name)); +	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL);      }      Tcl_Close(NULL, chan); @@ -1656,11 +1660,11 @@ LoadTableEncoding(      Tcl_DString lineString;      Tcl_Obj *objPtr;      char *line; -    int i, hi, lo, numPages, symbol, fallback; +    int i, hi, lo, numPages, symbol, fallback, len;      unsigned char used[256];      unsigned size;      TableEncodingData *dataPtr; -    unsigned short *pageMemPtr; +    unsigned short *pageMemPtr, *page;      Tcl_EncodingType encType;      /* @@ -1707,7 +1711,7 @@ LoadTableEncoding(  #undef PAGESIZE  #define PAGESIZE    (256 * sizeof(unsigned short)) -    dataPtr = (TableEncodingData *) ckalloc(sizeof(TableEncodingData)); +    dataPtr = ckalloc(sizeof(TableEncodingData));      memset(dataPtr, 0, sizeof(TableEncodingData));      dataPtr->fallback = fallback; @@ -1719,7 +1723,7 @@ LoadTableEncoding(       */      size = 256 * sizeof(unsigned short *) + numPages * PAGESIZE; -    dataPtr->toUnicode = (unsigned short **) ckalloc(size); +    dataPtr->toUnicode = ckalloc(size);      memset(dataPtr->toUnicode, 0, size);      pageMemPtr = (unsigned short *) (dataPtr->toUnicode + 256); @@ -1777,29 +1781,26 @@ LoadTableEncoding(  	}      }      size = 256 * sizeof(unsigned short *) + numPages * PAGESIZE; -    dataPtr->fromUnicode = (unsigned short **) ckalloc(size); +    dataPtr->fromUnicode = ckalloc(size);      memset(dataPtr->fromUnicode, 0, size);      pageMemPtr = (unsigned short *) (dataPtr->fromUnicode + 256);      for (hi = 0; hi < 256; hi++) {  	if (dataPtr->toUnicode[hi] == NULL) {  	    dataPtr->toUnicode[hi] = emptyPage; -	} else { -	    for (lo = 0; lo < 256; lo++) { -		int ch; - -		ch = dataPtr->toUnicode[hi][lo]; -		if (ch != 0) { -		    unsigned short *page; - -		    page = dataPtr->fromUnicode[ch >> 8]; -		    if (page == NULL) { -			page = pageMemPtr; -			pageMemPtr += 256; -			dataPtr->fromUnicode[ch >> 8] = page; -		    } -		    page[ch & 0xff] = (unsigned short) ((hi << 8) + lo); +	    continue; +	} +	for (lo = 0; lo < 256; lo++) { +	    int ch = dataPtr->toUnicode[hi][lo]; + +	    if (ch != 0) { +		page = dataPtr->fromUnicode[ch >> 8]; +		if (page == NULL) { +		    page = pageMemPtr; +		    pageMemPtr += 256; +		    dataPtr->fromUnicode[ch >> 8] = page;  		} +		page[ch & 0xff] = (unsigned short) ((hi << 8) + lo);  	    }  	}      } @@ -1818,8 +1819,6 @@ LoadTableEncoding(  	}      }      if (symbol) { -	unsigned short *page; -  	/*  	 * Make a special symbol encoding that not only maps the symbol  	 * characters from their Unicode code points down into page 0, but @@ -1827,7 +1826,7 @@ LoadTableEncoding(  	 * is so that a symbol font can be used to display a simple string  	 * like "abcd" and have alpha, beta, chi, delta show up, rather than  	 * have "unknown" chars show up because strictly speaking the symbol -	 * font doesn't have glyphs for those low ascii chars. +	 * font doesn't have glyphs for those low ASCII chars.  	 */  	page = dataPtr->fromUnicode[0]; @@ -1852,57 +1851,77 @@ LoadTableEncoding(       */      Tcl_DStringInit(&lineString); -    do { -	int len; + +    /* +     * Skip leading empty lines. +     */ + +    while ((len = Tcl_Gets(chan, &lineString)) == 0) { +	/* empty body */ +    } +    if (len < 0) { +	goto doneParse; +    } + +    /* +     * Require that it starts with an 'R'. +     */ + +    line = Tcl_DStringValue(&lineString); +    if (line[0] != 'R') { +	goto doneParse; +    } + +    /* +     * Read lines from the encoding until EOF. +     */ + +    for (TclDStringClear(&lineString); +	    (len = Tcl_Gets(chan, &lineString)) >= 0; +	    TclDStringClear(&lineString)) { +	const unsigned char *p; +	int to, from;  	/* -	 * Skip leading empty lines. +	 * Skip short lines.  	 */ -	while ((len = Tcl_Gets(chan, &lineString)) == 0) { -	    /* empty body */ +	if (len < 5) { +	    continue;  	} -	if (len < 0) { -	    break; -	} -	line = Tcl_DStringValue(&lineString); -	if (line[0] != 'R') { -	    break; -	} -	for (Tcl_DStringSetLength(&lineString, 0); -		(len = Tcl_Gets(chan, &lineString)) >= 0; -		Tcl_DStringSetLength(&lineString, 0)) { -	    unsigned char *p; -	    int to, from; +	/* +	 * Parse the line as a sequence of hex digits. +	 */ -	    if (len < 5) { -		continue; -	    } -	    p = (unsigned char *) Tcl_DStringValue(&lineString); -	    to = (staticHex[p[0]] << 12) + (staticHex[p[1]] << 8) +	p = (const unsigned char *) Tcl_DStringValue(&lineString); +	to = (staticHex[p[0]] << 12) + (staticHex[p[1]] << 8) +		+ (staticHex[p[2]] << 4) + staticHex[p[3]]; +	if (to == 0) { +	    continue; +	} +	for (p += 5, len -= 5; len >= 0 && *p; p += 5, len -= 5) { +	    from = (staticHex[p[0]] << 12) + (staticHex[p[1]] << 8)  		    + (staticHex[p[2]] << 4) + staticHex[p[3]]; -	    if (to == 0) { -	    	continue; -	    } -	    for (p += 5, len -= 5; len >= 0 && *p; p += 5, len -= 5) { -		from = (staticHex[p[0]] << 12) + (staticHex[p[1]] << 8) -			+ (staticHex[p[2]] << 4) + staticHex[p[3]]; -	    	if (from == 0) { -		    continue; -		} -		dataPtr->fromUnicode[from >> 8][from & 0xff] = to; +	    if (from == 0) { +		continue;  	    } +	    dataPtr->fromUnicode[from >> 8][from & 0xff] = to;  	} -    } while (0); +    } +  doneParse:      Tcl_DStringFree(&lineString); +    /* +     * Package everything into an encoding structure. +     */ +      encType.encodingName    = name;      encType.toUtfProc	    = TableToUtfProc;      encType.fromUtfProc	    = TableFromUtfProc;      encType.freeProc	    = TableFreeProc;      encType.nullSize	    = (type == ENCODING_DOUBLEBYTE) ? 2 : 1; -    encType.clientData	    = (ClientData) dataPtr; +    encType.clientData	    = dataPtr;      return Tcl_CreateEncoding(&encType);  } @@ -1957,6 +1976,7 @@ LoadEscapeEncoding(  	}  	line = Tcl_DStringValue(&lineString);  	if (Tcl_SplitList(NULL, line, &argc, &argv) != TCL_OK) { +	    Tcl_DStringFree(&lineString);  	    continue;  	}  	if (argc >= 2) { @@ -1984,8 +2004,8 @@ LoadEscapeEncoding(  		 */  		e = (Encoding *) Tcl_GetEncoding(NULL, est.name); -		if (e && e->toUtfProc != TableToUtfProc && -			e->toUtfProc != Iso88591ToUtfProc) { +		if ((e != NULL) && (e->toUtfProc != TableToUtfProc) +			&& (e->toUtfProc != Iso88591ToUtfProc)) {  		   Tcl_FreeEncoding((Tcl_Encoding) e);  		   e = NULL;  		} @@ -1993,17 +2013,17 @@ LoadEscapeEncoding(  		Tcl_DStringAppend(&escapeData, (char *) &est, sizeof(est));  	    }  	} -	ckfree((char *) argv); +	ckfree(argv);  	Tcl_DStringFree(&lineString);      }      size = sizeof(EscapeEncodingData) - sizeof(EscapeSubTable)  	    + Tcl_DStringLength(&escapeData); -    dataPtr = (EscapeEncodingData *) ckalloc(size); +    dataPtr = ckalloc(size);      dataPtr->initLen = strlen(init); -    strcpy(dataPtr->init, init); +    memcpy(dataPtr->init, init, (unsigned) dataPtr->initLen + 1);      dataPtr->finalLen = strlen(final); -    strcpy(dataPtr->final, final); +    memcpy(dataPtr->final, final, (unsigned) dataPtr->finalLen + 1);      dataPtr->numSubTables =  	    Tcl_DStringLength(&escapeData) / sizeof(EscapeSubTable);      memcpy(dataPtr->subTables, Tcl_DStringValue(&escapeData), @@ -2021,12 +2041,16 @@ LoadEscapeEncoding(  	dataPtr->prefixBytes[UCHAR(dataPtr->final[0])] = 1;      } +    /* +     * Package everything into an encoding structure. +     */ +      type.encodingName	= name;      type.toUtfProc	= EscapeToUtfProc;      type.fromUtfProc    = EscapeFromUtfProc;      type.freeProc	= EscapeFreeProc;      type.nullSize	= 1; -    type.clientData	= (ClientData) dataPtr; +    type.clientData	= dataPtr;      return Tcl_CreateEncoding(&type);  } @@ -2158,6 +2182,7 @@ UtfIntToUtfExtProc(   *   *-------------------------------------------------------------------------   */ +  static int  UtfExtToUtfIntProc(      ClientData clientData,	/* Not used. */ @@ -2238,7 +2263,7 @@ UtfToUtfProc(  				 * versa. */  {      const char *srcStart, *srcEnd, *srcClose; -    char *dstStart, *dstEnd; +    const char *dstStart, *dstEnd;      int result, numChars;      Tcl_UniChar ch; @@ -2349,7 +2374,7 @@ UnicodeToUtfProc(  				 * output buffer. */  {      const char *srcStart, *srcEnd; -    char *dstEnd, *dstStart; +    const char *dstEnd, *dstStart;      int result, numChars;      Tcl_UniChar ch; @@ -2371,10 +2396,12 @@ UnicodeToUtfProc(  	    result = TCL_CONVERT_NOSPACE;  	    break;  	} +  	/* -	 * Special case for 1-byte utf chars for speed.  Make sure we -	 * work with Tcl_UniChar-size data. +	 * Special case for 1-byte utf chars for speed. Make sure we work with +	 * Tcl_UniChar-size data.  	 */ +  	ch = *(Tcl_UniChar *)src;  	if (ch && ch < 0x80) {  	    *dst++ = (ch & 0xFF); @@ -2464,11 +2491,13 @@ UtfToUnicodeProc(  	    break;          }  	src += TclUtfToUniChar(src, &ch); +  	/* -	 * Need to handle this in a way that won't cause misalignment -	 * by casting dst to a Tcl_UniChar. [Bug 1122671] +	 * Need to handle this in a way that won't cause misalignment by +	 * casting dst to a Tcl_UniChar. [Bug 1122671]  	 * XXX: This hard-codes the assumed size of Tcl_UniChar as 2.  	 */ +  #ifdef WORDS_BIGENDIAN  	*dst++ = (ch >> 8);  	*dst++ = (ch & 0xFF); @@ -2529,12 +2558,12 @@ TableToUtfProc(  				 * output buffer. */  {      const char *srcStart, *srcEnd; -    char *dstEnd, *dstStart, *prefixBytes; +    const char *dstEnd, *dstStart, *prefixBytes;      int result, byte, numChars;      Tcl_UniChar ch; -    unsigned short **toUnicode; -    unsigned short *pageZero; -    TableEncodingData *dataPtr; +    const unsigned short *const *toUnicode; +    const unsigned short *pageZero; +    TableEncodingData *dataPtr = clientData;      srcStart = src;      srcEnd = src + srcLen; @@ -2542,8 +2571,7 @@ TableToUtfProc(      dstStart = dst;      dstEnd = dst + dstLen - TCL_UTF_MAX; -    dataPtr = (TableEncodingData *) clientData; -    toUnicode = dataPtr->toUnicode; +    toUnicode = (const unsigned short *const *) dataPtr->toUnicode;      prefixBytes = dataPtr->prefixBytes;      pageZero = toUnicode[0]; @@ -2575,9 +2603,11 @@ TableToUtfProc(  	    }  	    ch = (Tcl_UniChar) byte;  	} +  	/*  	 * Special case for 1-byte utf chars for speed.  	 */ +  	if (ch && ch < 0x80) {  	    *dst++ = (char) ch;  	} else { @@ -2638,17 +2668,16 @@ TableFromUtfProc(  				 * output buffer. */  {      const char *srcStart, *srcEnd, *srcClose; -    char *dstStart, *dstEnd, *prefixBytes; +    const char *dstStart, *dstEnd, *prefixBytes;      Tcl_UniChar ch;      int result, len, word, numChars; -    TableEncodingData *dataPtr; -    unsigned short **fromUnicode; +    TableEncodingData *dataPtr = clientData; +    const unsigned short *const *fromUnicode;      result = TCL_OK; -    dataPtr = (TableEncodingData *) clientData;      prefixBytes = dataPtr->prefixBytes; -    fromUnicode = dataPtr->fromUnicode; +    fromUnicode = (const unsigned short *const *) dataPtr->fromUnicode;      srcStart = src;      srcEnd = src + srcLen; @@ -2760,7 +2789,7 @@ Iso88591ToUtfProc(  				 * output buffer. */  {      const char *srcStart, *srcEnd; -    char *dstEnd, *dstStart; +    const char *dstEnd, *dstStart;      int result, numChars;      srcStart = src; @@ -2778,9 +2807,11 @@ Iso88591ToUtfProc(  	    break;  	}  	ch = (Tcl_UniChar) *((unsigned char *) src); +  	/*  	 * Special case for 1-byte utf chars for speed.  	 */ +  	if (ch && ch < 0x80) {  	    *dst++ = (char) ch;  	} else { @@ -2839,7 +2870,7 @@ Iso88591FromUtfProc(  				 * output buffer. */  {      const char *srcStart, *srcEnd, *srcClose; -    char *dstStart, *dstEnd; +    const char *dstStart, *dstEnd;      int result, numChars;      result = TCL_OK; @@ -2922,16 +2953,15 @@ TableFreeProc(      ClientData clientData)	/* TableEncodingData that specifies  				 * encoding. */  { -    TableEncodingData *dataPtr; +    TableEncodingData *dataPtr = clientData;      /*       * Make sure we aren't freeing twice on shutdown. [Bug 219314]       */ -    dataPtr = (TableEncodingData *) clientData; -    ckfree((char *) dataPtr->toUnicode); -    ckfree((char *) dataPtr->fromUnicode); -    ckfree((char *) dataPtr); +    ckfree(dataPtr->toUnicode); +    ckfree(dataPtr->fromUnicode); +    ckfree(dataPtr);  }  /* @@ -2980,12 +3010,11 @@ EscapeToUtfProc(  				 * output buffer. */  {      EscapeEncodingData *dataPtr = clientData; -    char *prefixBytes, *tablePrefixBytes; -    unsigned short **tableToUnicode; -    Encoding *encodingPtr; +    const char *prefixBytes, *tablePrefixBytes, *srcStart, *srcEnd; +    const unsigned short *const *tableToUnicode; +    const Encoding *encodingPtr;      int state, result, numChars; -    const char *srcStart, *srcEnd; -    char *dstStart, *dstEnd; +    const char *dstStart, *dstEnd;      result = TCL_OK;      tablePrefixBytes = NULL;	/* lint. */ @@ -3015,7 +3044,7 @@ EscapeToUtfProc(  	if (prefixBytes[byte]) {  	    unsigned left, len, longest;  	    int checked, i; -	    EscapeSubTable *subTablePtr; +	    const EscapeSubTable *subTablePtr;  	    /*  	     * Saw the beginning of an escape sequence. @@ -3115,7 +3144,8 @@ EscapeToUtfProc(  	    encodingPtr = GetTableEncoding(dataPtr, state);  	    tableDataPtr = encodingPtr->clientData;  	    tablePrefixBytes = tableDataPtr->prefixBytes; -	    tableToUnicode = tableDataPtr->toUnicode; +	    tableToUnicode = (const unsigned short *const*) +		    tableDataPtr->toUnicode;  	}  	if (tablePrefixBytes[byte]) { @@ -3191,13 +3221,13 @@ EscapeFromUtfProc(  				 * output buffer. */  {      EscapeEncodingData *dataPtr = clientData; -    Encoding *encodingPtr; +    const Encoding *encodingPtr;      const char *srcStart, *srcEnd, *srcClose; -    char *dstStart, *dstEnd; +    const char *dstStart, *dstEnd;      int state, result, numChars; -    TableEncodingData *tableDataPtr; -    char *tablePrefixBytes; -    unsigned short **tableFromUnicode; +    const TableEncodingData *tableDataPtr; +    const char *tablePrefixBytes; +    const unsigned short *const *tableFromUnicode;      result = TCL_OK; @@ -3232,7 +3262,8 @@ EscapeFromUtfProc(      encodingPtr = GetTableEncoding(dataPtr, state);      tableDataPtr = encodingPtr->clientData;      tablePrefixBytes = tableDataPtr->prefixBytes; -    tableFromUnicode = tableDataPtr->fromUnicode; +    tableFromUnicode = (const unsigned short *const *) +	    tableDataPtr->fromUnicode;      for (numChars = 0; src < srcEnd; numChars++) {  	unsigned len; @@ -3253,13 +3284,13 @@ EscapeFromUtfProc(  	if ((word == 0) && (ch != 0)) {  	    int oldState; -	    EscapeSubTable *subTablePtr; +	    const EscapeSubTable *subTablePtr;  	    oldState = state;  	    for (state = 0; state < dataPtr->numSubTables; state++) {  		encodingPtr = GetTableEncoding(dataPtr, state);  		tableDataPtr = encodingPtr->clientData; -	    	word = tableDataPtr->fromUnicode[(ch >> 8)][ch & 0xff]; +		word = tableDataPtr->fromUnicode[(ch >> 8)][ch & 0xff];  		if (word != 0) {  		    break;  		} @@ -3276,8 +3307,9 @@ EscapeFromUtfProc(  		word = tableDataPtr->fallback;  	    } -	    tablePrefixBytes = tableDataPtr->prefixBytes; -	    tableFromUnicode = tableDataPtr->fromUnicode; +	    tablePrefixBytes = (const char *) tableDataPtr->prefixBytes; +	    tableFromUnicode = (const unsigned short *const *) +		    tableDataPtr->fromUnicode;  	    /*  	     * The state variable has the value of oldState when word is 0. @@ -3385,12 +3417,26 @@ EscapeFreeProc(      if (dataPtr == NULL) {  	return;      } -    subTablePtr = dataPtr->subTables; -    for (i = 0; i < dataPtr->numSubTables; i++) { -	FreeEncoding((Tcl_Encoding) subTablePtr->encodingPtr); -	subTablePtr++; + +    /* +     * The subTables should be freed recursively in normal operation but not +     * during TclFinalizeEncodingSubsystem because they are also present as a +     * weak reference in the toplevel encodingTable (i.e., they don't have a +     * +1 refcount for this), and unpredictable nuking order could remove them +     * from under the following loop's feet. [Bug 2891556] +     * +     * The encodingsInitialized flag, being reset on entry to TFES, can serve +     * as a "not in finalization" test. +     */ + +    if (encodingsInitialized) { +	subTablePtr = dataPtr->subTables; +	for (i = 0; i < dataPtr->numSubTables; i++) { +	    FreeEncoding((Tcl_Encoding) subTablePtr->encodingPtr); +	    subTablePtr++; +	}      } -    ckfree((char *) dataPtr); +    ckfree(dataPtr);  }  /* @@ -3496,41 +3542,41 @@ InitializeEncodingSearchPath(  {      const char *bytes;      int i, numDirs, numBytes; -    Tcl_Obj *libPath, *encodingObj, *searchPath; +    Tcl_Obj *libPathObj, *encodingObj, *searchPathObj;      TclNewLiteralStringObj(encodingObj, "encoding"); -    TclNewObj(searchPath); +    TclNewObj(searchPathObj);      Tcl_IncrRefCount(encodingObj); -    Tcl_IncrRefCount(searchPath); -    libPath = TclGetLibraryPath(); -    Tcl_IncrRefCount(libPath); -    Tcl_ListObjLength(NULL, libPath, &numDirs); +    Tcl_IncrRefCount(searchPathObj); +    libPathObj = TclGetLibraryPath(); +    Tcl_IncrRefCount(libPathObj); +    Tcl_ListObjLength(NULL, libPathObj, &numDirs);      for (i = 0; i < numDirs; i++) { -	Tcl_Obj *directory, *path; +	Tcl_Obj *directoryObj, *pathObj;  	Tcl_StatBuf stat; -	Tcl_ListObjIndex(NULL, libPath, i, &directory); -	path = Tcl_FSJoinToPath(directory, 1, &encodingObj); -	Tcl_IncrRefCount(path); -	if ((0 == Tcl_FSStat(path, &stat)) && S_ISDIR(stat.st_mode)) { -	    Tcl_ListObjAppendElement(NULL, searchPath, path); +	Tcl_ListObjIndex(NULL, libPathObj, i, &directoryObj); +	pathObj = Tcl_FSJoinToPath(directoryObj, 1, &encodingObj); +	Tcl_IncrRefCount(pathObj); +	if ((0 == Tcl_FSStat(pathObj, &stat)) && S_ISDIR(stat.st_mode)) { +	    Tcl_ListObjAppendElement(NULL, searchPathObj, pathObj);  	} -	Tcl_DecrRefCount(path); +	Tcl_DecrRefCount(pathObj);      } -    Tcl_DecrRefCount(libPath); +    Tcl_DecrRefCount(libPathObj);      Tcl_DecrRefCount(encodingObj);      *encodingPtr = libraryPath.encoding;      if (*encodingPtr) {  	((Encoding *)(*encodingPtr))->refCount++;      } -    bytes = Tcl_GetStringFromObj(searchPath, &numBytes); +    bytes = Tcl_GetStringFromObj(searchPathObj, &numBytes);      *lengthPtr = numBytes; -    *valuePtr = ckalloc((unsigned) numBytes + 1); +    *valuePtr = ckalloc(numBytes + 1);      memcpy(*valuePtr, bytes, (size_t) numBytes + 1); -    Tcl_DecrRefCount(searchPath); +    Tcl_DecrRefCount(searchPathObj);  }  /* @@ -3540,4 +3586,3 @@ InitializeEncodingSearchPath(   * fill-column: 78   * End:   */ - | 
