1248 lines · 40.8 KB · Text
RawDownload
.HTML "Hello World or Καλημέρα κόσμε or こんにちは 世界.TLHello World.bror.br.ft RΚαλημέρα κόσμε.ft.bror.br\f(Jpこんにちは 世界\fP.AURob PikeKen Thompson.sprob,ken@plan9.bell-labs.com.AB.FSOriginally appeared, in a slightly different form, in.IProc. of the Winter 1993 USENIX Conf.,.Rpp. 43-50,San Diego.FEPlan 9 from Bell Labs has recently been converted from ASCIIto an ASCII-compatible variant of the Unicode Standard, a 16-bit character set.In this paper we explain the reasons for the change,describe the character set and representation we chose,and present the programming models and software changesthat support the new text format.Although we stopped short of full internationalization\(emforexample, system error messages are in Unixese, not Japanese\(emwebelieve Plan 9 is the first system to treat the representationof all major languages on a uniform, equal footing throughout all itssoftware..AE.SHIntroduction.PPThe world is multilingual but most computer systemsare based on English and ASCII.The first release of Plan 9 [Pike90], a new distributed operatingsystem from Bell Laboratories, seemed a good occasionto correct this chauvinism.It is easier to make such deep changes when building new systems thanby refitting old ones..PPThe ANSI C standard [ANSIC] contains some guidance on the matter of`wide' and `multi-byte' characters but falls far short ofsolving the myriad associated problems.We could find no literature on how to convert a.I systemto larger character sets, although some individual.I programshad been converted.This paper reports what we discovered as weexplored the problem of representing multilingualtext at all levels of an operating system,from the file system and kernel throughthe applications and up to the window systemand display..PPPlan 9 has not been `internationalized':its manuals are in English,its error messages are in English,and it can display text that goes from left to right only.But before we can address these other problems,we need to handle, uniformly and comfortably,the textual representation of all the major written languages.That subproblem is richer than we had anticipated..SHStandards.PPOur first step was to select a standard.At the time (January 1992),there were only two viable options:ISO 10646 [ISO10646] and Unicode [Unicode].The documents describing both proposals were still in the draft stage..PPThe draft of ISO 10646 was notvery attractive to us.It defined a sparse set of 32-bit characters,which would behard to implementand have punitive storage requirements.Also, the draft attempted tomollify national interests by allocating16-bit subspaces to national committeesto partition individually.The suggested mode of use was to``flip'' between separate nationalstandards to implement the international standard.This did not strike us as a sound basis for a character set.As well, transmitting 32-bit values in a byte stream,such as in pipes, would be expensive and hard to implement.Since the standard does not define a byte order for suchtransmission, the byte stream would also have to carrystate to enable the values to be recovered..PPThe Unicode Standard is a proposal by a consortium of mostly Americancomputer companies formedto protest the technicalfailings of ISO 10646.It defines a uniform 16-bit code based on theprinciple of unification:two characters are the same if they look thesame even though they are from differentlanguages.This principle, called Han unification,allows the large Japanese, Chinese, and Koreancharacter sets to be packed comfortably into a 16-bit representation..PPWe chose the Unicode Standard for its technical merits and because itscode space was better defined.Moreover,the Unicode Consortium was derailing theISO 10646 standard.(Now, in 1995,ISO 10646 is a standardwith one 16-bit group defined,which is almost exactly the Unicode Standard.As most people expected, the two standards bodiesreached a détente andISO 10646 and Unicode represent the same character set.).PPThe Unicode Standard defines an adequate character setbut an unreasonable representation.It states that all charactersare 16 bits wide and are communicated and stored in16-bit units.It also reserves a pair of characters(hexadecimal FFFE and FEFF) to detect byte orderin transmitted text, requiring state in the byte stream.(The Unicode Consortium was thinking of files, not pipes.)To adopt this encoding,we would have had to convert all text goinginto and out of Plan 9 between ASCII and Unicode, which cannot be done.Within a single program, in command of all its input and output,it is possible to define characters as 16-bit quantities;in the context of a networked system withhundreds of applications on diverse machinesby different manufacturers,it is impossible..PPWe needed a way to adapt the Unicode Standard to the tools-and-pipesmodel of text processing embodied by the Unix system.To do that, weneeded an ASCII-compatible textualrepresentation of Unicode characters for transmissionand storage.In the draft ISO standard there was an informative(non-required)Annexcalled UTFthat provided a byte stream encodingof the 32-bit ISO code.The encoding uses multibyte sequences composedfrom the 190 printable characters of Latin-1to represent character values largerthan 159..PPThe UTF encoding has several good properties.By far the most important is thata byte in the ASCII range 0-127 representsitself in UTF.Thus UTF is backward compatible with ASCII..PPUTF has other advantages.It is a byte encoding and istherefore byte-order independent.ASCII control characters appear in the byte streamonly as themselves, never as an element of a sequenceencoding another character,so newline bytes separate lines of UTF text.Finally, ANSI C's.CW strcmpfunction applied to UTF strings preserves the ordering of Unicode characters..PPTo encode and decode UTF is expensive (involving multiplication,division, and modulo operations) but workable.UTF's major disadvantage is that the encodingis not self-synchronizing.It is in general impossible to find the characterboundaries in a UTF string without reading fromthe beginning of the string, although in practicecontrol characters such as newlines,tabs, and blanks provide synchronization points..PPIn August 1992,X-Open circulated a proposal for another UTF-likebyte encoding of Unicode characters.Their major concern was that an embedded characterin a file name(in particular a slash)could be part of an escape sequence in UTF andtherefore confuse a traditional file system.Their proposal would allow all 7-bit ASCII charactersto represent themselves.I "and only themselves"in text.Multibyte sequences would contain only characterswith the high bit set.We proposed a modification to the new UTF thatwould address our synchronization problem.Our proposal, which was  originally known informally as UTF-2 and FSS-UTF,is now referred to as UTF-8 and has been approved by ISO to becomeAnnex P to ISO 10646..PPThe model for text in Plan 9 is chosen from thesethree standards*:.FS* ``That's the nice thing about standards\(emthere's so many to choose from.'' \- Andy Tannenbaum (no, the other one).FEthe Unicode character set encoded as a byte stream byUTF-8, from(soon to be) Annex P of ISO 10646.Although this mixture may seem like a precarious position for us to adopt,it is not as bad as it sounds.ISO 10646 and the Unicode Standard have converged,other systems such as Linux have adopted the same character set and encoding,and the general feeling seems to be that Unicode and UTF-8 will be accepted as the wayto exchange text between systems.The prognosis for wide acceptance is good..PPThere are a couple of aspects of the Unicode Standard we have not faced.One is the issue of right-to-left text such as Hebrew or Arabic.Since that is an issue of display, not representation, we believewe can defer that problem for the moment without affecting ourability to solve it later.Another issue is diacriticals and `combining characters',which cause overstriking of multiple Unicode characters.Although necessary for some scripts, such as Thai, Arabic, and Hebrew,such characters confuse the issues for Latin languages because theygenerate multiple representations for accented characters.ISO 10646 describes three levels of implementation;in Plan 9 we decided not to address the issue.Again, this can be labeled as a display issue and its finer points are still being debated,so we felt comfortable deferring.  Mañana..PPAlthough we converted Plan 9 in the altruistic interests ofserving foreign languages, we have found the large characterset attractive for other reasons.  The Unicode Standard includes manycharacters\(emmathematical symbols, scientific notation,more general punctuation, and more\(emthat we now usedaily in our work.  We no longer test our imaginationsto find ways to include non-ASCII symbols in our text;why type.CW :-)when you can use the character ☺?Most compelling is the ability to absorb documentsand data that contain non-ASCII characters; our browser for theOxford English Dictionarylets us see the dictionary as it really is, with pronunciationin the IPA font, foreign phrases properly rendered, and so on,.I "in plain text..PPIn the rest of this paper, except whenstated otherwise, the term `UTF' refers to the UTF-8 encodingof Unicode characters as adopted by Plan 9..SHC Compiler.PPThe first program to be converted to UTFwas the C Compiler.There are two levels of conversion.On the syntactic level,input to the C compileris UTF; on the semantic level,the C language needs to definehow compiled programs manipulatethe UTF set..PPThe syntactic part is simple.The ANSI C language standard defines thesource character set to be ASCII.Since UTF is backward compatible with ASCII,the compiler needs little change.The only places where a larger character setis allowed are in character constants, strings, and comments.Since 7-bit ASCII characters can represent onlythemselves in UTF,the compiler does not have to be careful while lookingfor the termination of a string or comment..PPThe Plan 9 compiler extends ANSI C to treat any Unicodecharacter with a value outside of the ASCII range asan alphabetic.To a Greek programmer or an English mathematician,α is a sensible and now valid variable name..PPOn the semantic level, ANSI C allows,but does not tie down,the notion of a.I "wide characterand admits string and character constantsof this type.We chose the wide character type to be.CW unsigned.CW short .In the libraries, the word.CW Runeis defined by a.CW typedefto be equivalent to.CW unsigned.CW shortand isused to signify a Unicode character..PPThere are surprises; for example:.P1L'x'	\f1is 120\fP\&'x'	\f1is 120\fPL'ÿ'	\f1is 255\fP\&'ÿ'	\f1is -1, stdio \fPEOF\f1 (if \fPchar\f1 is signed)\fPL'\f1α\fP'	\f1is 945\fP\&'\f1α\fP'	\f1is illegal\fP.P2In the string constants,.P1"\f(Jpこんにちは 世界\fP"L"\f(Jpこんにちは 世界\fP",.P2the former is an array of.CW charswith 22 elementsand a null byte,while the latter is an array of.CW unsigned.CW shorts.CW Runes ) (with 8 elements and a null.CW Rune ..PPThe Plan 9 library provides an output conversion function,.CW print(analogous to.CW printf ),with formats.CW %c ,.CW %C ,.CW %s ,and.CW %S .Since.CW printproduces text, its output is always UTF.The character conversion.CW %c(lower case) masks its argumentto 8 bits before converting to UTF.Thus.CW L'ÿ'and.CW 'ÿ'printed under.CW %cwill be identical,but.CW L'\f1α\fP'will print as the Unicodecharacter with decimal value 177.The character conversion.CW %C(upper case) masks its argumentto 16 bits before converting to UTF.Thus.CW L'ÿ'and.CW L'\f1α\fP'will print correctly under.CW %C ,but.CW 'ÿ'will not.The conversion.CW %s(lower case)expects a pointer to.CW charand copies UTF sequences up to a null byte.The conversion.CW %S(upper case) expects a pointer to.CW Runeandperforms sequential.CW %Cconversions until a null.CW Runeis encountered..PPAnother problem in format conversionis the definition of.CW %10s :does the number refer to bytes or characters?We decided that such formats were mostoften used to align output columns andso made the number count characters.Some programs, however, use the countto place blank-padded stringsin fixed-sized arrays.These programs must be found and corrected..PPHere is a complete example:.P1#include <u.h> char c[] = "\f(Jpこんにちは 世界\fP";Rune s[] = L"\f(Jpこんにちは 世界\fP"; main(void){	print("%d, %d\en", sizeof(c), sizeof(s));	print("%s\en", c);	print("%S\en", s);}.P2.PPThis program prints.CW 23,.CW 18and then two identical lines ofUTF text.In practice,.CW %Sand.CW L"..."are rare in programs; one reason isthat most formatted I/O is done in unconverted UTF..SHRamifications.PPAll programs in Plan 9 now read and write text as UTF, not ASCII.This change breaks two deep-rooted symmetries implicit in most C programs:.IP 1.A character is no longer a.CW char ..IP 2.The internal representation (Rune) of a character now differs from itsexternal representation (UTF)..PPIn the sections that follow,we show how these issues were faced in the layers ofsystem software from the operating system up to the applications.The effects are wide-reaching and often surprising..SHOperating system.PPSince UTF is the only format for text in Plan 9,the interface to the operating system had to be converted to UTF.Text strings cross the interface in several places:command arguments,file names,user names (people can log in using their native name),error messages,and miscellaneous minor places such as commands to the I/O system.Little change was required: null-terminated UTF stringsare equivalent to null-terminated ASCII strings for most purposesof the operating system.The library routines described in the next section made thatchange straightforward..PPThe window system, once called.CW 8.5 ,is now rightfully called.CW 8½ ..SHLibraries.PPA header file included by all programs (see [Pike92]) declaresthe.CW Runetype to hold 16-bit character values:.P1typedef unsigned short Rune;.P2Also defined are several constants relevant to UTF:.P1enum{    UTFmax    = 3,    /* maximum bytes per rune */    Runesync  = 0x80, /* can't appear in UTF sequence (<) */    Runeself  = 0x80, /* rune==UTF sequence (<) */    Runeerror = 0x80, /* decoding error in UTF */};.P2(With the original UTF,.CW Runesyncwas hexadecimal 21 and.CW Runeselfwas A0.).CW UTFmaxbytes are sufficientto hold the UTF encoding of any Unicode character.Characters of value less than.CW Runesync

Lines 1–500 of 1248.