Tcl_GetEncoding(3tcl)

Tcl_GetEncoding(3tcl) πŸ’–

okay bestie so this is a page from the Tcl Library Procedures manual, and it's the one about encodings β€” you know, the thing that makes your bytes make sense. πŸ¦‹


✨ NAME ✨

Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_WinTCharToUtf, Tcl_WinUtfToTChar, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath, Tcl_GetDefaultEncodingDir, Tcl_SetDefaultEncodingDir β€” procedures for creating and using encodings


🌸 SYNOPSIS 🌸

#include <tcl.h>

Tcl_Encoding
Tcl_GetEncoding(interp, name)

void
Tcl_FreeEncoding(encoding)

int
Tcl_GetEncodingFromObj(interp, objPtr, encodingPtr)

char *
Tcl_ExternalToUtfDString(encoding, src, srcLen, dstPtr)

char *
Tcl_UtfToExternalDString(encoding, src, srcLen, dstPtr)

int
Tcl_ExternalToUtf(interp, encoding, src, srcLen, flags, statePtr,
                  dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr)

int
Tcl_UtfToExternal(interp, encoding, src, srcLen, flags, statePtr,
                  dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr)

char *
Tcl_WinTCharToUtf(tsrc, srcLen, dstPtr)

TCHAR *
Tcl_WinUtfToTChar(src, srcLen, dstPtr)

const char *
Tcl_GetEncodingName(encoding)

int
Tcl_SetSystemEncoding(interp, name)

const char *
Tcl_GetEncodingNameFromEnvironment(bufPtr)

void
Tcl_GetEncodingNames(interp)

Tcl_Encoding
Tcl_CreateEncoding(typePtr)

Tcl_Obj *
Tcl_GetEncodingSearchPath()

int
Tcl_SetEncodingSearchPath(searchPath)

const char *
Tcl_GetDefaultEncodingDir(void)

void
Tcl_SetDefaultEncodingDir(path)

πŸŽ€ ARGUMENTS πŸŽ€

  • Tcl_Interp *interp (in) β€” the interpreter you wanna use for reporting errors. Or NULL if you literally do not want error reporting at all, like a girl who refuses to be perceived. πŸ™ˆ
  • const char *name (in) β€” the name of the encoding you wanna load. that's it, that's the whole vibe check. ✨
  • Tcl_Encoding encoding (in) β€” the encoding you're querying, freeing, or using to convert text. hot tip: if encoding is NULL, the current system encoding gets used instead. iconic behavior honestly.
  • Tcl_Obj *objPtr (in) β€” the name of the encoding you want a token for.
  • Tcl_Encoding *encodingPtr (out) β€” points to storage where the encoding token is gonna be written. output girlie πŸ’…
  • const char *src (in) β€” depends which function you're in, bestie:
    • for the Tcl_ExternalToUtf functions, it's an array of bytes in the specified encoding that are to be converted to UTF-8.
    • for the Tcl_UtfToExternal and Tcl_WinUtfToTChar functions, it's an array of UTF-8 characters to be converted to the specified encoding.
  • const TCHAR *tsrc (in) β€” an array of Windows TCHAR characters to convert to UTF-8. Windows only, no cap. πŸͺŸ
  • int srcLen (in) β€” length of src or tsrc in bytes. and if the length is negative? then the encoding-specific length of the string is used instead. sneaky but valid. 😌
  • Tcl_DString *dstPtr (out) β€” pointer to an uninitialized or free Tcl_DString where the converted result will be stored.
  • int flags (in) β€” various flag bits OR-ed together. the trio of destiny:
    • TCL_ENCODING_START β€” says the source buffer is the first block in a (potentially multi-block) input stream. it tells the conversion routine to reset to an initial state and do any initialization that needs to happen before the first byte gets converted. 🏁
    • TCL_ENCODING_END β€” says the source buffer is the last block in a (potentially multi-block) input stream. it tells the conversion routine to do any finalization that needs to happen after the last byte is converted, and then reset to an initial state. 🎬
    • TCL_ENCODING_STOPONERROR β€” says the conversion routine should return immediately upon reading a source character that doesn't exist in the target encoding. otherwise, a default fallback character gets automatically substituted. no silent weirdness if you don't want it, periodt.
  • Tcl_EncodingState *statePtr (in/out) β€” used when you're converting a (generally long or indefinite length) byte stream piece-by-piece, which is the moodiest possible way to convert things. the conversion routine stores its current state in *statePtr after src (the buffer containing the current piece) has been converted; that state info must be passed back when converting the next piece of the stream, so the conversion routine knows what state it was in when it left off at the end of the last piece. it may be NULL, in which case the value specified for flags is ignored and the source buffer is assumed to contain the complete string to convert. 🧠
  • char *dst (out) β€” the buffer where the converted result will be stored. no more than dstLen bytes will be stored in dst, so like… respect the limit bestie.
  • int dstLen (in) β€” the maximum length of the output buffer dst, in bytes. πŸ“

  • int *srcReadPtr (out) β€” this one gets filled with the number of bytes from src that were actually converted, fr. Heads up though: it can be less than the original source length if something went sideways converting some of the source characters. Also, it's allowed to be NULL. πŸ’…
  • int *dstWrotePtr (out) β€” filled with how many bytes genuinely made it into the output buffer because of the conversion. Can also be NULL, no pressure.
  • int *dstCharsPtr (out) β€” filled with the number of characters that line up with the number of bytes that got stored in the output buffer. Yeah, it can be NULL too. Everybody here can be NULL, it's that kind of party. πŸŽ€
  • Tcl_DString *bufPtr (out) β€” storage for the prescribed system encoding name. That's where the name lives.
  • const Tcl_EncodingType *typePtr (in) β€” a structure that defines a brand new type of encoding. New encoding, who dis. ✨
  • Tcl_Obj *searchPath (in) β€” a list of filesystem directories where we go hunting for encoding data files.
  • const char *path (in) β€” a path to the location of the encoding file. Just the address, bestie.

🌈 INTRODUCTION 🌈

Okay so here's the whole vibe: these routines convert between Tcl's internal character representation, which is UTF-8, and the character representations used by all these different operating systems or file systems β€” think Unicode, ASCII, or Shift-JIS. πŸ¦‹

When we're out here operating on strings β€” like getting the names of files, or displaying characters with international fonts β€” those strings have to be translated into one or possibly multiple formats that the various system calls can actually use. No translation, no service. πŸ’€

Real example, because I know you love a real example: on a Japanese Unix workstation, a user might grab a filename that's represented in the EUC-JP file encoding, and then translate those characters over to the jisx0208 font encoding so the filename can actually show up in a Tk widget. That's the translation gap, and the entire purpose of the encoding package is to help bridge it. πŸŒ‰

And the way it bridges it? UTF-8 is the intermediate staging ground for all the various encodings. In that example up there, text gets translated into UTF-8 from whatever file encoding the operating system is using, and then translated from UTF-8 into whatever font encoding the display routines need. Middle-man UTF-8, iconic behavior honestly. πŸ‘‘

Some basic encodings are compiled right into Tcl. Others can be defined by the user, or dynamically loaded from encoding files in a platform-independent manner. Options, we love to see it. πŸ’–


✨ DESCRIPTION ✨

Tcl_GetEncoding finds an encoding given its name. That name could point to a built-in Tcl encoding, a user-defined encoding registered by calling Tcl_CreateEncoding, or a dynamically-loadable encoding file. The return value is a token that represents the encoding, and you can use it in subsequent calls to procedures like Tcl_GetEncodingName, Tcl_FreeEncoding, and Tcl_UtfToExternal. If the name didn't refer to any known or loadable encoding, NULL is returned and an error message gets returned in interp. 😭

The encoding package keeps a database of all encodings currently in use. The first time name is seen, Tcl_GetEncoding returns an encoding with a reference count of 1. If the same name gets requested again later, then the reference count for that encoding is incremented β€” and no cap, it skips the overhead of allocating a new encoding plus all its associated data structures. Reuse queen. ♻️

When an encoding isn't needed anymore, you should call Tcl_FreeEncoding to release it. And when an encoding is no longer in use anywhere β€” meaning it's been freed exactly as many times as it's been gotten β€” Tcl_FreeEncoding will release all the storage the encoding was using and delete it from the database. Balance restored. βš–οΈ

Tcl_GetEncodingFromObj treats the string representation of objPtr as an encoding name and finds an encoding with that name, exactly like Tcl_GetEncoding does. When an encoding is found, it gets cached within the objPtr value for future reference, the Tcl_Encoding token is written to the storage pointed to by encodingPtr, and the value TCL_OK is returned. If no such encoding is found, the value TCL_ERROR is returned, and no writing to *encodingPtr takes place. And just like with Tcl_GetEncoding, the caller should call Tcl_FreeEncoding on the resulting encoding token once that token will no longer be used. Clean up after yourself bestie. 🧹

Tcl_ExternalToUtfDString converts a source buffer src from the specified encoding into UTF-8. The converted bytes get stored in dstPtr, which is then null-terminated. The caller should eventually call Tcl_DStringFree to free any information stored in dstPtr. When converting, if any of the characters in the source buffer can't be represented in the target encoding, a default fallback character will be used. The return value is a pointer to the value stored in the DString. 🫢

Tcl_ExternalToUtf converts a source buffer src from the specified encoding into UTF-8. Up to srcLen bytes get converted from the source buffer, and up to dstLen converted bytes get stored in dst. In all cases, *srcReadPtr is filled with the number of bytes that were successfully converted from src, and *dstWrotePtr is filled with the corresponding number of bytes that were stored in dst. The return value is one of these, and you're gonna want to know which:

  • TCL_OK β€” all bytes of src were converted. Slay, no notes. ✨
  • TCL_CONVERT_NOSPACE β€” the destination buffer wasn't large enough for all of the converted data. As many characters as could fit were converted though, so it tried its best. πŸ˜”
  • TCL_CONVERT_MULTIBYTE β€” the last few bytes in the source buffer were the beginning of a multibyte sequence, but more bytes were needed to complete that sequence. A subsequent call to the conversion routine should pass a buffer containing the unconverted bytes that remained in src plus some further bytes from the source stream, so the formerly split-up multibyte sequence can get properly converted. It's giving "to be continued". πŸ“–
  • TCL_CONVERT_SYNTAX β€” the source buffer contained an invalid character sequence. This can happen if the input stream has been damaged, or if the input encoding method was misidentified. Ruh roh. 🚨
  • TCL_CONVERT_UNKNOWN β€” the source buffer contained a character that could not be represented in the target encoding, and TCL_ENCODING_STOPONERROR was specified.

Tcl_UtfToExternalDString converts a source buffer src from UTF-8 into the specified encoding. The converted bytes get stored in dstPtr, which is then terminated with the appropriate encoding-specific null. The caller should eventually call Tcl_DStringFree to free any information stored in dstPtr. When converting, if any of the characters in the source buffer can't be represented in the target encoding, a default fallback character will be used. The return value is a pointer to the value stored in the DString. πŸ’œ

Tcl_UtfToExternal converts a source buffer src from UTF-8 into the specified encoding. Up to srcLen bytes get converted from the source buffer, and up to dstLen converted bytes get stored in dst. In all cases, *srcReadPtr is filled with the number of bytes that were successfully converted from src, and *dstWrotePtr is filled with the corresponding number of bytes that were stored in dst. The return values are the same as the return values for Tcl_ExternalToUtf. Same energy, opposite direction. πŸ”

Tcl_WinUtfToTChar and Tcl_WinTCharToUtf are Windows-only convenience functions for converting between UTF-8 and Windows strings based on the TCHAR type, which is by convention a Unicode character on Windows NT. Windows exclusives, iykyk. πŸͺŸ

Tcl_GetEncodingName is roughly the inverse of Tcl_GetEncoding. Give it an encoding, and the return value is the name argument that was used to create that encoding. One thing though: the string returned by Tcl_GetEncodingName is only guaranteed to persist until the encoding is deleted, and the caller must not modify this string. Don't touch, just look. πŸ™ˆ

Tcl_SetSystemEncoding sets the default encoding that should be used whenever the user passes a NULL value for the encoding argument to any of the other encoding functions. If name is NULL, the system encoding gets reset to the default system encoding, binary. If the name didn't refer to any known or loadable encoding, TCL_ERROR is returned and an error message is left in interp. Otherwise, this procedure increments the reference count of the new system encoding, decrements the reference count of the old system encoding, and returns TCL_OK. In with the new, out with the old. πŸŽ€

Tcl_GetEncodingNameFromEnvironment gives the Tcl library a way to report the encoding name it believes is the correct one to use as the system encoding, based on system calls and an examination of the environment suitable for the platform. It accepts bufPtr, a pointer to an uninitialized or freed Tcl_DString, and writes the encoding name to it. The Tcl_DStringValue is returned. 🌸

Tcl_GetEncodingNames is the one that gives you the receipts, bestie πŸ’… β€” it sets the interp result to a list of the names of all the encodings that are currently defined or that can be dynamically loaded, and it goes hunting through the encoding path that you set with Tcl_SetDefaultEncodingDir.

⚠️ Real talk though: this procedure does not check that the dynamically-loadable encoding files actually contain valid data. It literally just checks that they exist. Vibe check only, no content review. 😭

✨ Tcl_CreateEncoding β€” making a whole new encoding ✨

Tcl_CreateEncoding defines a brand-new encoding and registers the C procedures that get called back to convert between that encoding and UTF-8. Once you make one, it's thereafter visible in the database that Tcl_GetEncoding uses. And just like with Tcl_GetEncoding, what you get back is a token representing the encoding, which you can pass into later calls to other encoding functions.

Tcl_CreateEncoding returns an encoding with a reference count of 1.

Now, the plot twist 🫒 β€” if an encoding with that name already exists, its entry in the database gets replaced with the new one. The token for the old encoding stays valid and keeps behaving exactly as before, but anybody using the new token will now call the new encoding procedures. Two tokens, two truths. iykyk.

The typePtr argument is where you spill all the tea about the encoding's name and the procedures that convert between it and UTF-8. It's defined like this:

typedef struct Tcl_EncodingType {
    const char *encodingName;
    Tcl_EncodingConvertProc *toUtfProc;
    Tcl_EncodingConvertProc *fromUtfProc;
    Tcl_EncodingFreeProc *freeProc;
    ClientData clientData;
    int nullSize;
} Tcl_EncodingType;

Okay so, field by field, no cap πŸŽ€:

  • encodingName β€” the string name for the encoding, so other procedures like Tcl_GetEncoding can refer to it.
  • toUtfProc β€” the callback procedure to invoke when converting text from this encoding into UTF-8.
  • fromUtfProc β€” the callback procedure to invoke when converting text from UTF-8 into this encoding.
  • freeProc β€” the callback to invoke when this encoding is deleted. This one may be NULL.
  • clientData β€” an arbitrary one-word value that gets passed to toUtfProc, fromUtfProc, and freeProc every single time they're called. Usually it's a pointer to a data structure holding encoding-specific info the callbacks can use. Example: two extremely similar encodings like ascii and macRoman could share the same callback procedure but use different clientData values to steer its behavior. πŸ‘‘
  • nullSize β€” how many zero bytes mean end-of-string in this encoding. It must be 1 (for single-byte or multi-byte encodings like ASCII or Shift-JIS) or 2 (for double-byte encodings like Unicode).
πŸ’€ Heads up: constant-sized encodings with 3 or more bytes per character (such as CNS11643) are not accepted.

πŸ¦‹ the callback procedures πŸ¦‹

The callback procedures toUtfProc and fromUtfProc should match the type Tcl_EncodingConvertProc:

typedef int Tcl_EncodingConvertProc(
        ClientData clientData,
        const char *src,
        int srcLen,
        int flags,
        Tcl_EncodingState *statePtr,
        char *dst,
        int dstLen,
        int *srcReadPtr,
        int *dstWrotePtr,
        int *dstCharsPtr);

toUtfProc and fromUtfProc get called by the Tcl_ExternalToUtf or Tcl_UtfToExternal family of functions to do the actual conversion β€” they're the ones doing the work behind the scenes, main character energy fr fr ✨.

The clientData parameter handed to these procedures is the same as the clientData field you specified to Tcl_CreateEncoding when the encoding was created. And the remaining arguments to the callback procedures are the same as the arguments documented at the top for Tcl_ExternalToUtf or Tcl_UtfToExternal, with these two exceptions:

  1. If the srcLen argument to one of those high-level functions is negative, the value passed to the callback procedure will be the appropriate encoding-specific string length of src.
  2. If any of the srcReadPtr, dstWrotePtr, or dstCharsPtr arguments to one of the high-level functions is NULL, the corresponding value passed to the callback procedure will be a non-NULL location.

The callback procedure freeProc, if it's non-NULL, should match the type Tcl_EncodingFreeProc:

typedef void Tcl_EncodingFreeProc(
        ClientData clientData);

This freeProc function gets called when the encoding is deleted πŸͺ¦. Its clientData parameter is the same as the clientData field you specified to Tcl_CreateEncoding when the encoding was created.


🌸 encoding search paths 🌸

Tcl_GetEncodingSearchPath and Tcl_SetEncodingSearchPath are called to access and set the list of filesystem directories that get searched for encoding data files.

The value returned by Tcl_GetEncodingSearchPath is the value stored by the last successful call to Tcl_SetEncodingSearchPath. If nobody ever called Tcl_SetEncodingSearchPath, Tcl computes an initial value based on the environment. And important: there is one encoding search path for the entire process, shared by all threads in the process. One path to rule them all, bestie πŸ‘‘

Tcl_SetEncodingSearchPath stores searchPath and returns TCL_OK β€” unless searchPath is not a valid Tcl list, in which case you get TCL_ERROR back. 😀

πŸ™ˆ Also: the elements of searchPath are not verified as existing readable filesystem directories. So when the search for encoding data files actually happens, any non-existent or non-readable filesystem directories on the searchPath are silently ignored. No warnings, no drama, just vibes.

⭐ the obsolete girlies ⭐

Tcl_GetDefaultEncodingDir and Tcl_SetDefaultEncodingDir are obsolete interfaces, and the best move is to replace them with calls to Tcl_GetEncodingSearchPath and Tcl_SetEncodingSearchPath. 🫢

They're called to access and set the first element of the searchPath list. And since Tcl searches searchPath for encoding data files in list order, these routines are basically establishing the β€œdefault” directory in which to find encoding data files. Cute, but deprecated β€” the search path functions ate and left no crumbs. πŸ’…

πŸ’Ύ ENCODING FILES πŸ’Ύ

Okay so here's the tea, bestie: precompiling every single encoding algorithm into Tcl would eat up all the space, and honestly? Not it. So a ton of encodings just chill on disk as dynamically-loadable encoding files. And the cute part is β€” this also lets you make your own extra encoding files and load them with the exact same mechanism. 🌸

These files carry the info about the tables and/or escape sequences used to map between an external encoding and Unicode. And the external encoding can be made of single-byte, multi-byte, or double-byte characters. Versatile icon behavior. ✨

Each dynamically-loadable encoding is a text file. The first line, starting with a # symbol, is a comment that gives a human-readable description of the file. Then the next line says what type of encoding file it is. It can be one of these letters:

  1. S β€” a single-byte encoding, where one character is always one byte long in the encoding. Example: iso8859-1, used by many European languages.
  2. D β€” a double-byte encoding, where one character is always two bytes long in the encoding. Example: big5, used for Chinese text.
  3. M β€” a multi-byte encoding, where one character may be either one or two bytes long. Certain bytes are lead bytes, indicating that another byte must follow and that together the two bytes represent one character. Other bytes are not lead bytes and represent themselves. Example: shiftjis, used by many Japanese computers.
  4. E β€” an escape-sequence encoding, specifying that certain sequences of bytes do not represent characters, but commands that describe how following bytes should be interpreted.

The rest of the lines in the file depend on the type. 🫢

Cases [1], [2], and [3] are collectively referred to as table-based encoding files. The lines in a table-based encoding file are in the same format as this example taken from the shiftjis encoding (and btw this is not the complete file, it's just a taste):

# Encoding file: shiftjis, multi-byte
M
003F 0 40
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D203E007F
0080000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
81
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
300030013002FF0CFF0E30FBFF1AFF1BFF1FFF01309B309C00B4FF4000A8FF3E
FFE3FF3F30FD30FE309D309E30034EDD30053006300730FC20152010FF0F005C
301C2016FF5C2026202520182019201C201DFF08FF0930143015FF3BFF3DFF5B
FF5D30083009300A300B300C300D300E300F30103011FF0B221200B100D70000
00F7FF1D2260FF1CFF1E22662267221E22342642264000B0203220332103FFE5
FF0400A200A3FF05FF03FF06FF0AFF2000A72606260525CB25CF25CE25C725C6
25A125A025B325B225BD25BC203B301221922190219121933013000000000000
000000000000000000000000000000002208220B2286228722822283222A2229
000000000000000000000000000000002227222800AC21D221D4220022030000
0000000000000000000000000000000000000000222022A52312220222072261
2252226A226B221A223D221D2235222B222C0000000000000000000000000000
212B2030266F266D266A2020202100B6000000000000000025EF000000000000

The third line of the file is three numbers. Let's break them down, because this is where it gets spicy 🌢️:

  • The first number is the fallback character (in base 16) to use when converting from UTF-8 to this encoding.
  • The second number is a 1 if this file represents the encoding for a symbol font, or 0 otherwise.
  • The last number (in base 10) is how many pages of data follow.

Subsequent lines in the example above are pages that describe how to map from the encoding into 2-byte Unicode. The first line in a page identifies the page number. Following it are 256 double-byte numbers, arranged as 16 rows of 16 numbers. So given a character in the encoding, the high byte of that character is used to select which page, and the low byte of that character is used as an index to select one of the double-byte numbers in that page β€” and the value you get is the corresponding Unicode character. ✨

By examination of the example above, one can see that the characters 0x7E and 0x8163 in shiftjis map to 203E and 2026 in Unicode, respectively. Look at us, doing forensics πŸ”πŸ’…

Following the first page will be all the other pages, each in the same format as the first: one number identifying the page followed by 256 double-byte Unicode characters. If a character in the encoding maps to the Unicode character 0000, it means that the character does not actually exist (ghost character, no cap πŸ‘»). And if all characters on a page would map to 0000, that page can be omitted entirely. Efficiency queen.


πŸŒ€ Case [4]: the escape-sequence era πŸŒ€

Case [4] is the escape-sequence encoding file. The lines in an this type of file are in the same format as this example taken from the iso2022-jp encoding:

# Encoding file: iso2022-jp, escape-driven
E
init           {}
final          {}
iso8859-1      \x1b(B
jis0201        \x1b(J
jis0208        \x1b$@
jis0208        \x1b$B
jis0212        \x1b$(D
gb2312         \x1b$A
ksc5601        \x1b$(C

In the file, the first column represents an option and the second column is the associated value. init is a string to emit or expect before the first character is converted, while final is a string to emit or expect after the last character. All other options are names of table-based encodings; the associated value is the escape-sequence that marks that encoding. πŸ¦‹

Tcl syntax is used for the values; in the above example, for instance, {} represents the empty string and \x1b represents character 27. iykyk.


πŸ”Ž So when does Tcl actually go looking for these files?

When Tcl_GetEncoding encounters an encoding name that has not been loaded, it attempts to load an encoding file called name.enc from the encoding subdirectory of each directory that Tcl searches for its script library. πŸ‘‘

Heads up bestie: if the encoding file exists, but is malformed, an error message will be left in interp. So like… check your files, okay? 😭

πŸ”‘ KEYWORDS πŸ”‘

  • utf
  • encoding
  • convert

And that's a wrap on this whole page, my love πŸŽ€ Slay. You just read the Tcl_GetEncoding(3tcl) page from Tcl 8.1 β€” go forth and encode responsibly, bestie πŸ’–βœ¨πŸ¦‹πŸ‘‘