OberonCore https://forum.oberoncore.ru/ |
|
Lin Console: средство преобразования UCS-2 <-> UTF-8 https://forum.oberoncore.ru/viewtopic.php?f=133&t=4130 |
Страница 1 из 3 |
Автор: | Евгений Темиргалеев [ Вторник, 23 Октябрь, 2012 18:24 ] |
Заголовок сообщения: | Lin Console: средство преобразования UCS-2 <-> UTF-8 |
В инструкцию по сборке приложения ElfLinker-Link примером статической сборки приведено приложение с параметрами, чтобы заодно показать новую схему передачи параметров. Код: MODULE Example2; IMPORT Getenv, Log, LinSimpleLog; PROCEDURE Do; VAR name: ARRAY 256 OF CHAR; res: INTEGER; BEGIN Getenv.Get("моёИмя", name, res); ASSERT(res IN {0..1}, 100); IF res = 0 THEN Log.String("Здравствуй, " + name + ", друг мой!"); Log.Ln ELSE Log.String("Здравствуй, друг!"); Log.Ln END END Do; BEGIN LinSimpleLog.Open; Do END Example2. Код: env моёИмя=Иоанн ./example ... Здравствуй, Иоанн, друг мой! При написании Getenv выявилась следующая специфика: http://www.gnu.org/software/libc/manual ... Char-Intro --- здесь говорится, что кодировка utf-8 (multibyte characters) дефакто стандарт для внешнего представления текстов (сериализация в цепочки байт), для внутреннего представления удобнее применять wide characters, которые где-как (в некоторых UNIX-системах 16 битыне), но в GNU 32-битные без вариантов. Таким образом Код: PtrWSTR* = POINTER TO ARRAY [untagged] OF CHAR; д. б. на самом деле PtrWSTR* = POINTER TO ARRAY [untagged] OF INTEGER; т.е. средствами конверсии multibyte string <-> wide char string библиотеки GNU libc Блэкбоксовые цепочки ARRAY OF CHAR напрямую обрабатывать мы не можем. В примере выше (Getenv), сляпанном для пробы, они используются совместно с PROCEDURE Ucs2ToUcs4 (IN s2: ARRAY OF CHAR; OUT s4: ARRAY OF INTEGER) и PROCEDURE Ucs4ToUcs2 (IN s4: ARRAY OF INTEGER; OUT s2: ARRAY OF CHAR), что есть мега-костыль.В GNU есть общее средство преобразования литер (http://www.gnu.org/software/libc/manual ... Conversion). Оно поддерживает кучи кодировок (зависит от конфигурации), в т.ч. и UCS-2. Но оно слишком общее и внешнее, нам же надо только UCS-2 <-> UTF-8, поэтому его использование считаю нецелесообразным. Гораздо лучшим решением видится написать модуль на КП, содержащий достаточный минимум средств. Вопрос насущный упирается в его интерфейс. |
Автор: | Евгений Темиргалеев [ Вторник, 23 Октябрь, 2012 18:33 ] | ||
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 | ||
Как отправную точку предлагаю приложенный интерфейс. Содержит автомат для обработки октетов и процедуры конверсии из массива литер и файлов ("A file is a sequence of bytes."). Реализацию начинал ЕИЕ, заканчивал ТЕЭ. Но она крайне не идеальна --- как-то я сподобился глядя прямо в стандарт проглядеть обработку указанных прямо там ошибочных ситуаций. Для означенной же тулзы должно быть всё строго реализовано.
|
Автор: | Илья Ермаков [ Вторник, 23 Октябрь, 2012 19:33 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Вроде бы нормальный интерфейс. Про 32 бит выше не понял - это где оно используется? |
Автор: | Евгений Темиргалеев [ Вторник, 23 Октябрь, 2012 21:11 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
http://www.gnu.org/software/libc/manual ... Char-Intro Цитата: The ISO C90 standard, where wchar_t was introduced, does not say anything specific about the representation. It only requires that this type is capable of storing all elements of the basic character set. Therefore it would be legitimate to define wchar_t as char, which might make sense for embedded systems.
But in the GNU C Library wchar_t is always 32 bits wide and, therefore, capable of representing all UCS-4 values and, therefore, covering all of ISO 10646. Some Unix systems define wchar_t as a 16-bit type and thereby follow Unicode very strictly. This definition is perfectly fine with the standard, but it also means that to represent all characters from Unicode and ISO 10646 one has to use UTF-16 surrogate characters, which is in fact a multi-wide-character encoding. But resorting to multi-wide-character encoding contradicts the purpose of the wchar_t type. |
Автор: | Alexander Shiryaev [ Среда, 24 Октябрь, 2012 01:02 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
1. На самом деле кодировка указывается в переменной LANG (например, ru_RU.UTF-8, ru_RU.KOI8-R) и не обязательно может быть UTF-8. (Если LANG не определена или LANG=C, то подразумевается кодировка ASCII). Эта кодировка используется для ввода/вывода на консоль, в именах файлов, в переменных окружения и т.д. Много кто использует кодировку, отличную от UTF-8. В России под Linux/FreeBSD часто используют KOI8-R. В Японии -- SJIS и т.д, в Китае -- GB2312 и т.д. Много кто (в Европе и т.д.) пользуется кодировками ISO8859-* У меня кодировка всегда была KOI8-R. 2. У нас преобразования ARRAY OF CHAR <-> ARRAY OF SHORTCHAR нужны, как минимум, в HostFiles, в HostConsole, после Libc.getenv. Кроме того, преобразования кодировок могут понадобиться при написании программ, в которых осуществляется взаимодействие с внешним миром, например, по сети. 3. Для преобразования кодировок можно написать подсистему на КП, а можно воспользоваться существующей библиотекой libiconv. Список поддерживаемых кодировок libiconv можно посмотреть, выполнив "iconv -l". В Linux также работают mbtowcs (используется, кодировка определённая в LANG). Некоторые кодировки определены здесь: http://www.unicode.org/Public/MAPPINGS/ (все основные, не CJK (не китайские-японские-корейские)). Если писать свою подсистему, то она будет менее эффективной, чем libiconv. Но не так существенно. Кое-что есть в подсистеме Unicode, но там много того, что не нужно, и не всё из того, что нужно. 4. Поэтому можно сделать абстрактный модуль EncCodecs: Код: MODULE EncCodecs; TYPE Encoding* = ARRAY 32 OF CHAR; Directory* = POINTER TO ABSTRACT RECORD END; Encoder* = POINTER TO ABSTRACT RECORD END; Decoder* = POINTER TO ABSTRACT RECORD END; VAR dir-: Directory; (* Directory *) PROCEDURE (dir: Directory) NewEncoder* (enc: Encoding): Encoder, NEW, ABSTRACT; PROCEDURE (dir: Directory) NewDecoder* (enc: Encoding): Decoder, NEW, ABSTRACT; (* Encoder *) PROCEDURE (e: Encoder) Encode* (IN f: ARRAY OF CHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF SHORTCHAR; VAR tW: INTEGER), NEW, ABSTRACT; (* у энкодера нет состояния, сброс не нужен *) (* Decoder *) PROCEDURE (d: Decoder) Decode* (IN f: ARRAY OF SHORTCHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF CHAR; VAR tW: INTEGER; OUT state: BOOLEAN), NEW, ABSTRACT; PROCEDURE (d: Decoder) Reset*, NEW, ABSTRACT; (* сброс состояния декодера *) PROCEDURE SetDir* (d: Directory); BEGIN dir := d END SetDir; END EncCodecs. И конкретную реализацию на основе libiconv (для OpenBSD) или mbtowc (для Linux) -- в HostEncCodecs. А в будущем сделать реализацию на КП: EncStdCodecs: Код: MODULE EncStdCodecs; IMPORT Meta, Codecs := EncCodecs, Aliases := EncStdAliases; TYPE Directory* = POINTER TO RECORD (Codecs.Directory) END; (* Directory *) PROCEDURE (dir: Directory) NewEncoder* (enc: Codecs.Encoding): Codecs.Encoder; VAR modName: ARRAY LEN(Codecs.Encoding) + 16 OF CHAR; item: Meta.Item; ok: BOOLEAN; item0: RECORD (Meta.Value) fun: PROCEDURE (): Codecs.Encoder END; e: Codecs.Encoder; BEGIN e := NIL; Aliases.GetModName(enc, modName, ok); IF ok THEN Meta.Lookup(modName, item); IF item.obj = Meta.modObj THEN item.Lookup("NewEncoder", item); IF item.obj = Meta.procObj THEN item.GetVal(item0, ok); IF ok THEN e := item0.fun() END END END END; RETURN e END NewEncoder; PROCEDURE (dir: Directory) NewDecoder* (enc: Codecs.Encoding): Codecs.Decoder; VAR modName: ARRAY LEN(Codecs.Encoding) + 16 OF CHAR; item: Meta.Item; ok: BOOLEAN; item0: RECORD (Meta.Value) fun: PROCEDURE (): Codecs.Decoder END; d: Codecs.Decoder; BEGIN d := NIL; Aliases.GetModName(enc, modName, ok); IF ok THEN Meta.Lookup(modName, item); IF item.obj = Meta.modObj THEN item.Lookup("NewDecoder", item); IF item.obj = Meta.procObj THEN item.GetVal(item0, ok); IF ok THEN d := item0.fun() END END END END; RETURN d END NewDecoder; PROCEDURE Init; VAR dir: Directory; BEGIN NEW(dir); Codecs.SetDir(dir) END Init; BEGIN Init END EncStdCodecs. Enc/Mod: Codecs, StdAliases, StdCodecs, StdMap_ascii, StdMap_utf_8, StdMap_utf_16be, StdMap_utf_16le и генерируемые автоматичеки из таблиц на сайте unicode.org и csets: StdMap_iso8859_1, StdMap_iso8859_2, StdMap_iso8859_3, StdMap_iso8859_4, StdMap_iso8859_5, StdMap_iso8859_6, StdMap_iso8859_7, StdMap_iso8859_8, StdMap_iso8859_9, StdMap_iso8859_10, StdMap_iso8859_11, StdMap_iso8859_13, StdMap_iso8859_14, StdMap_iso8859_15, StdMap_iso8859_16, StdMap_cp037, StdMap_cp1026, StdMap_cp1140.txt StdMap_cp1250, StdMap_cp1251, StdMap_cp1252, StdMap_cp1253, StdMap_cp1254, StdMap_cp1255, StdMap_cp1256, StdMap_cp1257, StdMap_cp1258, StdMap_cp424, StdMap_cp437, StdMap_cp500, StdMap_cp720, StdMap_cp737, StdMap_cp775, StdMap_cp850, StdMap_cp852, StdMap_cp855, StdMap_cp856, StdMap_cp857, StdMap_cp858, StdMap_cp860, StdMap_cp861, StdMap_cp862, StdMap_cp863, StdMap_cp864, StdMap_cp865, StdMap_cp866, StdMap_cp869, StdMap_cp874, StdMap_cp936, StdMap_cp949, StdMap_mac_centraleurope, StdMap_mac_cyrillic, StdMap_mac_greek, StdMap_mac_iceland, StdMap_viscii, StdMap_mac_roman, StdMap_mac_turkish, StdMap_koi8_r, StdMap_koi8_u, StdMap_georgian_academy, StdMap_georgian_ps, StdMap_atarist, StdMap_hp_roman8, StdMap_kps9566, StdMap_kz1048, StdMap_ptcp154 ( Не указаны модули CJK (в том числе CP932, CP950) ) Модуль StdAliases также должен генерироваться автоматически. Модули StdMap_ascii, StdMap_utf_* -- реализовывать вручную. Пример автоматически сгенерированного модуля: Код: MODULE EncStdMap_cp1251; (* This file was generated automatically *) (* Source: http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT *) IMPORT Codecs := EncCodecs; TYPE Encoder = POINTER TO RECORD (Codecs.Encoder) END; Decoder = POINTER TO RECORD (Codecs.Decoder) END; (* Encoder *) PROCEDURE (e: Encoder) Encode (IN f: ARRAY OF CHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF SHORTCHAR; VAR tW: INTEGER); VAR x, y: INTEGER; BEGIN WHILE fLen > 0 DO x := ORD(f[fR]); CASE x OF | 00H..7FH: y := x | 0A0H: y := 0A0H | 0A4H: y := 0A4H | 0A6H..0A7H: y := x | 0A9H: y := 0A9H | 0ABH..0AEH: y := x | 0B0H..0B1H: y := x | 0B5H..0B7H: y := x | 0BBH: y := 0BBH | 0401H: y := 0A8H | 0402H..0403H: y := x - 0382H | 0404H: y := 0AAH | 0405H: y := 0BDH | 0406H: y := 0B2H | 0407H: y := 0AFH | 0408H: y := 0A3H | 0409H: y := 8AH | 040AH: y := 8CH | 040BH: y := 8EH | 040CH: y := 8DH | 040EH: y := 0A1H | 040FH: y := 8FH | 0410H..044FH: y := x - 0350H | 0451H: y := 0B8H | 0452H: y := 90H | 0453H: y := 83H | 0454H: y := 0BAH | 0455H: y := 0BEH | 0456H: y := 0B3H | 0457H: y := 0BFH | 0458H: y := 0BCH | 0459H: y := 9AH | 045AH: y := 9CH | 045BH: y := 9EH | 045CH: y := 9DH | 045EH: y := 0A2H | 045FH: y := 9FH | 0490H: y := 0A5H | 0491H: y := 0B4H | 2013H..2014H: y := x - 1F7DH | 2018H..2019H: y := x - 1F87H | 201AH: y := 82H | 201CH..201DH: y := x - 1F89H | 201EH: y := 84H | 2020H..2021H: y := x - 1F9AH | 2022H: y := 95H | 2026H: y := 85H | 2030H: y := 89H | 2039H: y := 8BH | 203AH: y := 9BH | 20ACH: y := 88H | 2116H: y := 0B9H | 2122H: y := 99H ELSE RETURN END; t[tW] := SHORT(CHR(y)); INC(tW); INC(fR); DEC(fLen) END END Encode; PROCEDURE NewEncoder* (): Codecs.Encoder; VAR e: Encoder; BEGIN NEW(e); RETURN e END NewEncoder; (* Decoder *) PROCEDURE (d: Decoder) Decode (IN f: ARRAY OF SHORTCHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF CHAR; VAR tW: INTEGER; OUT state: BOOLEAN); BEGIN HALT(126) (* not implemented *) END Decode; PROCEDURE (d: Decoder) Reset; BEGIN HALT(126) (* not implemented *) END Reset; PROCEDURE NewDecoder* (): Codecs.Decoder; VAR d: Decoder; BEGIN NEW(d); RETURN d END NewDecoder; END EncStdMap_cp1251. Черновик StdMap_utf_8: Код: MODULE EncMap_utf_8;
IMPORT Codecs := EncCodecs; TYPE Encoder = POINTER TO RECORD (Codecs.Encoder) END; Decoder = POINTER TO RECORD (Codecs.Decoder) END; (* Encoder *) PROCEDURE (e: Encoder) Encode (IN f: ARRAY OF CHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF SHORTCHAR; VAR tW: INTEGER); VAR x: INTEGER; BEGIN WHILE fLen > 0 DO x := ORD(f[fR]); (* http://www.lemoda.net/c/ucs2-to-utf8/index.html *) CASE x OF 00H..7FH: t[tW] := SHORT(CHR(x)); INC(tW) | 80H..7FFH: t[tW] := SHORT(CHR(x DIV 64 + 192)); t[tW+1] := SHORT(CHR(x MOD 64 + 128)); INC(tW, 2) | 800H..0FFFFH: t[tW] := SHORT(CHR(x DIV 4096 + 224)); t[tW+1] := SHORT(CHR((x DIV 64) MOD 64 + 128)); t[tW+2] := SHORT(CHR(x MOD 64 + 128)); INC(tW, 3) ELSE RETURN END; INC(fR); DEC(fLen) END END Encode; PROCEDURE NewEncoder* (): Codecs.Encoder; VAR e: Encoder; BEGIN NEW(e); RETURN e END NewEncoder; (* Decoder *) PROCEDURE (d: Decoder) Decode (IN f: ARRAY OF SHORTCHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF CHAR; VAR tW: INTEGER; OUT state: BOOLEAN); BEGIN HALT(126) (* not implemented *) END Decode; PROCEDURE (d: Decoder) Reset; BEGIN HALT(126) (* not implemented *) END Reset; PROCEDURE NewDecoder* (): Codecs.Decoder; VAR d: Decoder; BEGIN NEW(d); RETURN d END NewDecoder; END EncMap_utf_8. |
Автор: | Евгений Темиргалеев [ Среда, 24 Октябрь, 2012 09:11 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Alexander Shiryaev писал(а): 1. На самом деле кодировка указывается в переменной LANG 1) Если мы будем рассчитывать на поддержку не utf8 кодировок на POSIX-системах (или как там называются которые на libc), тогда нужно использовать родное для системы общее средство из libc (http://www.gnu.org/software/libc/manual ... Conversion, которое и есть iconv), а не городить своего.... Это не значит, что ББ-я реализация общего средства не нужна, но в контексте данной задачи оно теряет смысл. Ибо сложность решений не сопоставима: простой модуль UCS2-UTF8, причём средства преобразования в определённых случаях могут быть напрямую внедрены в потребный модули типа HostFiles, и общее параметризированное решение с которым такой штуки никак не выйдет. Плюс верно подмеченное Вами соображение насчёт производительности. Недетерминированным остаётся только предположение: в системе есть таблицы для преобразования (стандартная для ОС многобайтовая кодировка, которая для пользователя обычно и сидит в LANG без изменения) <-> UCS-2. Мне кажется, с большой вероятностью на это можно рассчитывать. И мне пока не понятно, как преобразовать значение LANG в имя кодировки для iconv. Разве что переложить этот вопрос на пользователя. 2) Известен. В Lin*Log реализован, реализация его в HostFiles упирается в поставленный вопрос. 3) Alexander Shiryaev писал(а): В Linux также работают mbtowcs (используется, кодировка определённая в LANG). Пример из первого сообщения именно их и использует. Но для ББ в общем случае не применимы. Т.к. wc в GNU 32битные.
|
Автор: | Евгений Темиргалеев [ Среда, 24 Октябрь, 2012 10:59 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Насчёт интерфейса общего преобразователя: в GNU док-ции iconv сказано что энто дело появилось в стандарте XGP2. Так может поглядеть один из этих стандартов и реализовать интерфейс оттуда? iconv рассчитан на работу с буферами, что вроде и есть самый минимум. Но для ББ характерны случаи цепочек литер в массивах и "неограниченные" последовательности на входе выходе (Files.File). Вопрос в том, включать ли это в интерфейс преобразователя для оптимальности или делать вспомогательным модулем. --- Черновик StdMap_utf_8: (* http://www.lemoda.net/c/ucs2-to-utf8/index.html *) Из CASE нужно убрать ELSE. Подобное есть и в XhtmlStdFileWriters (что, по-моему, сейчас все и копируют ). |
Автор: | Евгений Темиргалеев [ Среда, 24 Октябрь, 2012 12:03 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Альтернативный вариант использованию iconv --- политерные преобразования через mbtowc и обратно, LANG система учитывает. LinLog так сделан. Решение самое простое получается. Вопрос только в производительности. Может и забить на ней? |
Автор: | Евгений Темиргалеев [ Среда, 24 Октябрь, 2012 13:11 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Итого, для задачи поддержки преобразования определённой пользователем (системой) кодировки <-> UCS-2, рассмотрено три решения: 1) Использовать общую реализацию конвертера на ББ. Минус: для реализации ОС-зависимых компонентов (которые в идеале должны быть как можно ближе к системе) используется нетривиальный ОС-независимый компонент. Проблема: требуется по переменной LANG выбирать метод преобразования. Если детерминированного решения нет, придётся перекладывать на пользователя, например, вводя дополнительную переменную окружения как параметр для ББ-приложений. 2) Использовать системную библиотеку iconv. Проблема (как выше): требуется отображать значение переменной LANG в обозначение кодировки для iconv. 3) Использовать преобразования mbtowc/wctomb и их цепочечные аналоги. Плюс: означенной выше проблемы нет --- setlocale(LC_ALL...) настраивает библиотеку на исп-е настроек по соотв. переменным окружения. Минус: общее политерное решение "медленное". Цепочечные функции допустимы там, где wchar_t двухбайтовый; все системы с GNU libc отпадают. |
Автор: | Alexander Shiryaev [ Среда, 24 Октябрь, 2012 14:10 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Евгений Темиргалеев писал(а): Итого, для задачи поддержки преобразования определённой пользователем (системой) кодировки <-> UCS-2, рассмотрено три решения: 1) Использовать общую реализацию конвертера на ББ. Минус: для реализации ОС-зависимых компонентов (которые в идеале должны быть как можно ближе к системе) используется нетривиальный ОС-независимый компонент. Проблема: требуется по переменной LANG выбирать метод преобразования. Если детерминированного решения нет, придётся перекладывать на пользователя, например, вводя дополнительную переменную окружения как параметр для ББ-приложений. 2) Использовать системную библиотеку iconv. Проблема (как выше): требуется отображать значение переменной LANG в обозначение кодировки для iconv. 3) Использовать преобразования mbtowc/wctomb и их цепочечные аналоги. Плюс: означенной выше проблемы нет --- setlocale(LC_ALL...) настраивает библиотеку на исп-е настроек по соотв. переменным окружения. Минус: общее политерное решение "медленное". Цепочечные функции допустимы там, где wchar_t двухбайтовый; все системы с GNU libc отпадают. Предлагаю сделать абстрактный модуль (см. EncCodecs выше), и его использовать в HostFiles и т д, а реализацию (Hook или Directory) сделать в отдельном модуле (как Dates/HostDates, Log/StdLog и т.д.) Реализации могут быть разные. Для Linux -- на основе mbtowc, для OpenBSD -- iconv (т.к. mbtowc там всё рввно не работает). mbtowc можно использовать и для посимвольного преобразования. Это конечно медленнее, но не критично. Надо будет -- есть возможность сделать быстрее. Переменную LANG можно рассматривать в виде "страна.псевдонимКодировки". При невозможности извлечения псевдонима кодировки (неправильном значении переменной LANG) считать, что кодировка ASCII (так же, как и в случае LANG=C). iconv_open умеет опредлять кодировку по её псевдониму. См "iconv -l". Если делать реализацию на КП, то этим должен заниматься отдельный модуль (см. EncStdAliases выше), который должен генерироваться автоматически. На входе генератора может быть что-то типа: Код: ASCII: 646 ANSI_X3.4-1968 ANSI_X3.4-1986 ASCII CP367 IBM367 ISO-IR-6 ISO646-US ISO_646.IRV:1991 US US-ASCII CSASCII UTF-8: UTF-8 ISO8858-1: CP819 IBM819 ISO-8859-1 ISO-IR-100 ISO8859-1 ISO_8859-1 ISO_8859-1:1987 L1 LATIN1 CSISOLATIN1 ISO8859-2: ISO-8859-2 ISO-IR-101 ISO8859-2 ISO_8859-2 ISO_8859-2:1987 L2 LATIN2 CSISOLATIN2 ISO8859-3: ISO-8859-3 ISO-IR-109 ISO8859-3 ISO_8859-3 ISO_8859-3:1988 L3 LATIN3 CSISOLATIN3 ISO8859-4: ISO-8859-4 ISO-IR-110 ISO8859-4 ISO_8859-4 ISO_8859-4:1988 L4 LATIN4 CSISOLATIN4 ISO8859-5: CYRILLIC ISO-8859-5 ISO-IR-144 ISO8859-5 ISO_8859-5 ISO_8859-5:1988 CSISOLATINCYRILLIC ISO8859-6: ARABIC ASMO-708 ECMA-114 ISO-8859-6 ISO-IR-127 ISO8859-6 ISO_8859-6 ISO_8859-6:1987 CSISOLATINARABIC ISO8859-7: ECMA-118 ELOT_928 GREEK GREEK8 ISO-8859-7 ISO-IR-126 ISO8859-7 ISO_8859-7 ISO_8859-7:1987 ISO_8859-7:2003 CSISOLATINGREEK ISO8859-8: HEBREW ISO-8859-8 ISO-IR-138 ISO8859-8 ISO_8859-8 ISO_8859-8:1988 CSISOLATINHEBREW ISO8859-9: ISO-8859-9 ISO-IR-148 ISO8859-9 ISO_8859-9 ISO_8859-9:1989 L5 LATIN5 CSISOLATIN5 ISO8859-10: ISO-8859-10 ISO-IR-157 ISO8859-10 ISO_8859-10 ISO_8859-10:1992 L6 LATIN6 CSISOLATIN6 ISO8859-11: ISO-8859-11 ISO8859-11 ISO_8859-11 ISO8859-13: ISO-8859-13 ISO-IR-179 ISO8859-13 ISO_8859-13 L7 LATIN7 ISO8859-14: ISO-8859-14 ISO-CELTIC ISO-IR-199 ISO8859-14 ISO_8859-14 ISO_8859-14:1998 L8 LATIN8 ISO8859-15: ISO-8859-15 ISO-IR-203 ISO8859-15 ISO_8859-15 ISO_8859-15:1998 LATIN-9 ISO8859-16: ISO-8859-16 ISO-IR-226 ISO8859-16 ISO_8859-16 ISO_8859-16:2001 L10 LATIN10 KOI8-R: KOI8-R CSKOI8R KOI8-U: KOI8-U CP1250: CP1250 MS-EE WINDOWS-1250 CP1251: CP1251 MS-CYRL WINDOWS-1251 CP1252: CP1252 MS-ANSI WINDOWS-1252 CP1253: CP1253 MS-GREEK WINDOWS-1253 CP1254: CP1254 MS-TURK WINDOWS-1254 CP1255: CP1255 MS-HEBR WINDOWS-1255 CP1256: CP1256 MS-ARAB WINDOWS-1256 CP1257: CP1257 WINBALTRIM WINDOWS-1257 CP1258: CP1258 WINDOWS-1258 CP850: 850 CP850 IBM850 CSPC850MULTILINGUAL CP862: 862 CP862 IBM862 CSPC862LATINHEBREW CP866: 866 CP866 IBM866 CSIBM866 CP1131: CP1131 MAC-ROMAN: MAC MACINTOSH MACROMAN CSMACINTOSH MAC-CENTRALEUROPE: MACCENTRALEUROPE MAC-ICELAND: MACICELAND MAC-CYRILLIC: MACCYRILLIC MAC-GREEK: MACGREEK MAC-TURKISH: MACTURKISH GEORGIAN-ACADEMY: GEORGIAN-ACADEMY GEORGIAN-PS: GEORGIAN-PS PTCP154: CP154 CYRILLIC-ASIAN PT154 PTCP154 CSPTCP154 KZ1048: KZ-1048 RK1048 STRK1048-2002 CSKZ1048 CP1133: CP1133 IBM-CP1133 CP874: CP874 WINDOWS-874 CP936: CP936 MS936 WINDOWS-936 CP949: CP949 UHC CP856: CP856 CP1046: CP1046 CP1124: CP1124 CP1129: CP1129 CP1161: CP1161 IBM-1161 IBM1161 CSIBM1161 CP1162: CP1162 IBM-1162 IBM1162 CSIBM1162 CP1163: CP1163 IBM-1163 IBM1163 CSIBM1163 CP437: 437 CP437 IBM437 CSPC8CODEPAGE437 CP737: CP737 CP775: CP775 IBM775 CSPC775BALTIC CP852: 852 CP852 IBM852 CSPCP852 CP853: CP853 CP855: 855 CP855 IBM855 CSIBM855 CP857: 857 CP857 IBM857 CSIBM857 CP858: CP858 CP860: 860 CP860 IBM860 CSIBM860 CP861: 861 CP-IS CP861 IBM861 CSIBM861 CP863: 863 CP863 IBM863 CSIBM863 CP864: CP864 IBM864 CSIBM864 CP865: 865 CP865 IBM865 CSIBM865 CP869: 869 CP-GR CP869 IBM869 CSIBM869 CP1125: CP1125 VISCII: VISCII VISCII1.1-1 CSVISCII ATARIST: ATARI ATARIST # unicode.org/Public/MAPPINGS/VENDORS/MISC/KPS9566.TXT: KPS9566: KPS9566 CP720: CP720 На выходе -- Код: MODULE EncStdAliases; (* Generated automatically *) CONST modPrefix = "EncStdMap_"; PROCEDURE GetModName* (s: ARRAY OF CHAR; OUT r: ARRAY OF CHAR; OUT ok: BOOLEAN); VAR x: INTEGER; BEGIN x := 0; WHILE (x < LEN(s)) & (s[x] # 0X) DO IF (s[x] >= 'a') & (s[x] <= 'z') THEN s[x] := CHR(ORD(s[x]) - ORD('a') + ORD('A')) END; INC(x) END; x := -1; CASE s[0] OF | 'A': CASE s[1] OF | 'S': CASE s[2] OF | 'C': IF s[3] = 'I' THEN IF s[4] = 'I' THEN IF s[5] = 0X THEN x := 0 END END END | 'M': IF s[3] = 'O' THEN IF s[4] = '-' THEN IF s[5] = '7' THEN IF s[6] = '0' THEN IF s[7] = '8' THEN IF s[8] = 0X THEN x := 7 END END END END END END ELSE END | 'R': IF s[2] = 'A' THEN IF s[3] = 'B' THEN IF s[4] = 'I' THEN IF s[5] = 'C' THEN IF s[6] = 0X THEN x := 7 END END END END END | 'T': IF s[2] = 'A' THEN IF s[3] = 'R' THEN IF s[4] = 'I' THEN CASE s[5] OF | 0X: x := 69 | 'S': IF s[6] = 'T' THEN IF s[7] = 0X THEN x := 69 END END ELSE END END END END | 'N': IF s[2] = 'S' THEN IF s[3] = 'I' THEN IF s[4] = '_' THEN IF s[5] = 'X' THEN IF s[6] = '3' THEN IF s[7] = '.' THEN IF s[8] = '4' THEN IF s[9] = '-' THEN IF s[10] = '1' THEN IF s[11] = '9' THEN CASE s[12] OF | '8': IF s[13] = '6' THEN IF s[14] = 0X THEN x := 0 END END | '6': IF s[13] = '8' THEN IF s[14] = 0X THEN x := 0 END END ELSE END END END END END END END END END END END ELSE END | 'C': CASE s[1] OF | 'Y': IF s[2] = 'R' THEN IF s[3] = 'I' THEN IF s[4] = 'L' THEN IF s[5] = 'L' THEN IF s[6] = 'I' THEN IF s[7] = 'C' THEN CASE s[8] OF | 0X: x := 6 | '-': IF s[9] = 'A' THEN IF s[10] = 'S' THEN IF s[11] = 'I' THEN IF s[12] = 'A' THEN IF s[13] = 'N' THEN IF s[14] = 0X THEN x := 40 END END END END END END ELSE END END END END END END END | 'P': CASE s[2] OF | '-': CASE s[3] OF | 'I': IF s[4] = 'S' THEN IF s[5] = 0X THEN x := 62 END END | 'G': IF s[4] = 'R' THEN IF s[5] = 0X THEN x := 66 END END ELSE END | '1': CASE s[3] OF | '1': CASE s[4] OF | '3': CASE s[5] OF | '1': IF s[6] = 0X THEN x := 31 END | '3': IF s[6] = 0X THEN x := 42 END ELSE END | '2': CASE s[5] OF | '9': IF s[6] = 0X THEN x := 49 END | '5': IF s[6] = 0X THEN x := 67 END | '4': IF s[6] = 0X THEN x := 48 END ELSE END | '6': CASE s[5] OF | '1': IF s[6] = 0X THEN x := 50 END | '3': IF s[6] = 0X THEN x := 52 END | '2': IF s[6] = 0X THEN x := 51 END ELSE END ELSE END | '0': IF s[4] = '4' THEN IF s[5] = '6' THEN IF s[6] = 0X THEN x := 47 END END END | '2': IF s[4] = '5' THEN CASE s[5] OF | '1': IF s[6] = 0X THEN x := 20 END | '0': IF s[6] = 0X THEN x := 19 END | '3': IF s[6] = 0X THEN x := 22 END | '2': IF s[6] = 0X THEN x := 21 END | '5': IF s[6] = 0X THEN x := 24 END | '4': IF s[6] = 0X THEN x := 23 END | '7': IF s[6] = 0X THEN x := 26 END | '6': IF s[6] = 0X THEN x := 25 END | '8': IF s[6] = 0X THEN x := 27 END ELSE END END | '5': IF s[4] = '4' THEN IF s[5] = 0X THEN x := 40 END END ELSE END | '3': IF s[3] = '6' THEN IF s[4] = '7' THEN IF s[5] = 0X THEN x := 0 END END END | '4': IF s[3] = '3' THEN IF s[4] = '7' THEN IF s[5] = 0X THEN x := 53 END END END | '7': CASE s[3] OF | '3': IF s[4] = '7' THEN IF s[5] = 0X THEN x := 54 END END | '2': IF s[4] = '0' THEN IF s[5] = 0X THEN x := 71 END END | '7': IF s[4] = '5' THEN IF s[5] = 0X THEN x := 55 END END ELSE END | '9': CASE s[3] OF | '3': IF s[4] = '6' THEN IF s[5] = 0X THEN x := 44 END END | '4': IF s[4] = '9' THEN IF s[5] = 0X THEN x := 45 END END ELSE END | '8': CASE s[3] OF | '1': IF s[4] = '9' THEN IF s[5] = 0X THEN x := 2 END END | '5': CASE s[4] OF | '0': IF s[5] = 0X THEN x := 28 END | '3': IF s[5] = 0X THEN x := 57 END | '2': IF s[5] = 0X THEN x := 56 END | '5': IF s[5] = 0X THEN x := 58 END | '7': IF s[5] = 0X THEN x := 59 END | '6': IF s[5] = 0X THEN x := 46 END | '8': IF s[5] = 0X THEN x := 60 END ELSE END | '7': IF s[4] = '4' THEN IF s[5] = 0X THEN x := 43 END END | '6': CASE s[4] OF | '1': IF s[5] = 0X THEN x := 62 END | '0': IF s[5] = 0X THEN x := 61 END | '3': IF s[5] = 0X THEN x := 63 END | '2': IF s[5] = 0X THEN x := 29 END | '5': IF s[5] = 0X THEN x := 65 END | '4': IF s[5] = 0X THEN x := 64 END | '6': IF s[5] = 0X THEN x := 30 END | '9': IF s[5] = 0X THEN x := 66 END ELSE END ELSE END ELSE END | 'S': CASE s[2] OF | 'A': IF s[3] = 'S' THEN IF s[4] = 'C' THEN IF s[5] = 'I' THEN IF s[6] = 'I' THEN IF s[7] = 0X THEN x := 0 END END END END END | 'I': CASE s[3] OF | 'S': IF s[4] = 'O' THEN IF s[5] = 'L' THEN IF s[6] = 'A' THEN IF s[7] = 'T' THEN IF s[8] = 'I' THEN IF s[9] = 'N' THEN CASE s[10] OF | 'A': IF s[11] = 'R' THEN IF s[12] = 'A' THEN IF s[13] = 'B' THEN IF s[14] = 'I' THEN IF s[15] = 'C' THEN IF s[16] = 0X THEN x := 7 END END END END END END | 'C': IF s[11] = 'Y' THEN IF s[12] = 'R' THEN IF s[13] = 'I' THEN IF s[14] = 'L' THEN IF s[15] = 'L' THEN IF s[16] = 'I' THEN IF s[17] = 'C' THEN IF s[18] = 0X THEN x := 6 END END END END END END END END | 'G': IF s[11] = 'R' THEN IF s[12] = 'E' THEN IF s[13] = 'E' THEN IF s[14] = 'K' THEN IF s[15] = 0X THEN x := 8 END END END END END | 'H': IF s[11] = 'E' THEN IF s[12] = 'B' THEN IF s[13] = 'R' THEN IF s[14] = 'E' THEN IF s[15] = 'W' THEN IF s[16] = 0X THEN x := 9 END END END END END END | '1': IF s[11] = 0X THEN x := 2 END | '3': IF s[11] = 0X THEN x := 4 END | '2': IF s[11] = 0X THEN x := 3 END | '5': IF s[11] = 0X THEN x := 10 END | '4': IF s[11] = 0X THEN x := 5 END | '6': IF s[11] = 0X THEN x := 11 END ELSE END END END END END END END | 'B': IF s[4] = 'M' THEN CASE s[5] OF | '1': IF s[6] = '1' THEN IF s[7] = '6' THEN CASE s[8] OF | '1': IF s[9] = 0X THEN x := 50 END | '3': IF s[9] = 0X THEN x := 52 END | '2': IF s[9] = 0X THEN x := 51 END ELSE END END END | '8': CASE s[6] OF | '5': CASE s[7] OF | '5': IF s[8] = 0X THEN x := 58 END | '7': IF s[8] = 0X THEN x := 59 END ELSE END | '6': CASE s[7] OF | '1': IF s[8] = 0X THEN x := 62 END | '0': IF s[8] = 0X THEN x := 61 END | '3': IF s[8] = 0X THEN x := 63 END | '5': IF s[8] = 0X THEN x := 65 END | '4': IF s[8] = 0X THEN x := 64 END | '6': IF s[8] = 0X THEN x := 30 END | '9': IF s[8] = 0X THEN x := 66 END ELSE END ELSE END ELSE END END ELSE END | 'K': CASE s[3] OF | 'Z': IF s[4] = '1' THEN IF s[5] = '0' THEN IF s[6] = '4' THEN IF s[7] = '8' THEN IF s[8] = 0X THEN x := 41 END END END END END | 'O': IF s[4] = 'I' THEN IF s[5] = '8' THEN IF s[6] = 'R' THEN IF s[7] = 0X THEN x := 17 END END END END ELSE END | 'M': IF s[3] = 'A' THEN IF s[4] = 'C' THEN IF s[5] = 'I' THEN IF s[6] = 'N' THEN IF s[7] = 'T' THEN IF s[8] = 'O' THEN IF s[9] = 'S' THEN IF s[10] = 'H' THEN IF s[11] = 0X THEN x := 32 END END END END END END END END END | 'P': CASE s[3] OF | 'C': CASE s[4] OF | '8': CASE s[5] OF | 'C': IF s[6] = 'O' THEN IF s[7] = 'D' THEN IF s[8] = 'E' THEN IF s[9] = 'P' THEN IF s[10] = 'A' THEN IF s[11] = 'G' THEN IF s[12] = 'E' THEN IF s[13] = '4' THEN IF s[14] = '3' THEN IF s[15] = '7' THEN IF s[16] = 0X THEN x := 53 END END END END END END END END END END END | '5': IF s[6] = '0' THEN IF s[7] = 'M' THEN IF s[8] = 'U' THEN IF s[9] = 'L' THEN IF s[10] = 'T' THEN IF s[11] = 'I' THEN IF s[12] = 'L' THEN IF s[13] = 'I' THEN IF s[14] = 'N' THEN IF s[15] = 'G' THEN IF s[16] = 'U' THEN IF s[17] = 'A' THEN IF s[18] = 'L' THEN IF s[19] = 0X THEN x := 28 END END END END END END END END END END END END END END | '6': IF s[6] = '2' THEN IF s[7] = 'L' THEN IF s[8] = 'A' THEN IF s[9] = 'T' THEN IF s[10] = 'I' THEN IF s[11] = 'N' THEN IF s[12] = 'H' THEN IF s[13] = 'E' THEN IF s[14] = 'B' THEN IF s[15] = 'R' THEN IF s[16] = 'E' THEN IF s[17] = 'W' THEN IF s[18] = 0X THEN x := 29 END END END END END END END END END END END END END ELSE END | '7': IF s[5] = '7' THEN IF s[6] = '5' THEN IF s[7] = 'B' THEN IF s[8] = 'A' THEN IF s[9] = 'L' THEN IF s[10] = 'T' THEN IF s[11] = 'I' THEN IF s[12] = 'C' THEN IF s[13] = 0X THEN x := 55 END END END END END END END END END | 'P': IF s[5] = '8' THEN IF s[6] = '5' THEN IF s[7] = '2' THEN IF s[8] = 0X THEN x := 56 END END END END ELSE END | 'T': IF s[4] = 'C' THEN IF s[5] = 'P' THEN IF s[6] = '1' THEN IF s[7] = '5' THEN IF s[8] = '4' THEN IF s[9] = 0X THEN x := 40 END END END END END END ELSE END | 'V': IF s[3] = 'I' THEN IF s[4] = 'S' THEN IF s[5] = 'C' THEN IF s[6] = 'I' THEN IF s[7] = 'I' THEN IF s[8] = 0X THEN x := 68 END END END END END END ELSE END ELSE END | 'E': CASE s[1] OF | 'C': IF s[2] = 'M' THEN IF s[3] = 'A' THEN IF s[4] = '-' THEN IF s[5] = '1' THEN IF s[6] = '1' THEN CASE s[7] OF | '8': IF s[8] = 0X THEN x := 8 END | '4': IF s[8] = 0X THEN x := 7 END ELSE END END END END END END | 'L': IF s[2] = 'O' THEN IF s[3] = 'T' THEN IF s[4] = '_' THEN IF s[5] = '9' THEN IF s[6] = '2' THEN IF s[7] = '8' THEN IF s[8] = 0X THEN x := 8 END END END END END END END ELSE END | 'G': CASE s[1] OF | 'R': IF s[2] = 'E' THEN IF s[3] = 'E' THEN IF s[4] = 'K' THEN CASE s[5] OF | 0X: x := 8 | '8': IF s[6] = 0X THEN x := 8 END ELSE END END END END | 'E': IF s[2] = 'O' THEN IF s[3] = 'R' THEN IF s[4] = 'G' THEN IF s[5] = 'I' THEN IF s[6] = 'A' THEN IF s[7] = 'N' THEN IF s[8] = '-' THEN CASE s[9] OF | 'A': IF s[10] = 'C' THEN IF s[11] = 'A' THEN IF s[12] = 'D' THEN IF s[13] = 'E' THEN IF s[14] = 'M' THEN IF s[15] = 'Y' THEN IF s[16] = 0X THEN x := 38 END END END END END END END | 'P': IF s[10] = 'S' THEN IF s[11] = 0X THEN x := 39 END END ELSE END END END END END END END END ELSE END | 'I': CASE s[1] OF | 'S': IF s[2] = 'O' THEN CASE s[3] OF | '8': IF s[4] = '8' THEN IF s[5] = '5' THEN IF s[6] = '9' THEN IF s[7] = '-' THEN CASE s[8] OF | '1': CASE s[9] OF | 0X: x := 2 | '1': IF s[10] = 0X THEN x := 12 END | '0': IF s[10] = 0X THEN x := 11 END | '3': IF s[10] = 0X THEN x := 13 END | '5': IF s[10] = 0X THEN x := 15 END | '4': IF s[10] = 0X THEN x := 14 END | '6': IF s[10] = 0X THEN x := 16 END ELSE END | '3': IF s[9] = 0X THEN x := 4 END | '2': IF s[9] = 0X THEN x := 3 END | '5': IF s[9] = 0X THEN x := 6 END | '4': IF s[9] = 0X THEN x := 5 END | '7': IF s[9] = 0X THEN x := 8 END | '6': IF s[9] = 0X THEN x := 7 END | '9': IF s[9] = 0X THEN x := 10 END | '8': IF s[9] = 0X THEN x := 9 END ELSE END END END END END | '-': CASE s[4] OF | 'I': IF s[5] = 'R' THEN IF s[6] = '-' THEN CASE s[7] OF | '1': CASE s[8] OF | '1': IF s[9] = '0' THEN IF s[10] = 0X THEN x := 5 END END | '0': CASE s[9] OF | '9': IF s[10] = 0X THEN x := 4 END | '1': IF s[10] = 0X THEN x := 3 END | '0': IF s[10] = 0X THEN x := 2 END ELSE END | '3': IF s[9] = '8' THEN IF s[10] = 0X THEN x := 9 END END | '2': CASE s[9] OF | '7': IF s[10] = 0X THEN x := 7 END | '6': IF s[10] = 0X THEN x := 8 END ELSE END | '5': IF s[9] = '7' THEN IF s[10] = 0X THEN x := 11 END END | '4': CASE s[9] OF | '8': IF s[10] = 0X THEN x := 10 END | '4': IF s[10] = 0X THEN x := 6 END ELSE END | '7': IF s[9] = '9' THEN IF s[10] = 0X THEN x := 13 END END | '9': IF s[9] = '9' THEN IF s[10] = 0X THEN x := 14 END END ELSE END | '2': CASE s[8] OF | '0': IF s[9] = '3' THEN IF s[10] = 0X THEN x := 15 END END | '2': IF s[9] = '6' THEN IF s[10] = 0X THEN x := 16 END END ELSE END | '6': IF s[8] = 0X THEN x := 0 END ELSE END END END | '8': IF s[5] = '8' THEN IF s[6] = '5' THEN IF s[7] = '9' THEN IF s[8] = '-' THEN CASE s[9] OF | '1': CASE s[10] OF | 0X: x := 2 | '1': IF s[11] = 0X THEN x := 12 END | '0': IF s[11] = 0X THEN x := 11 END | '3': IF s[11] = 0X THEN x := 13 END | '5': IF s[11] = 0X THEN x := 15 END | '4': IF s[11] = 0X THEN x := 14 END | '6': IF s[11] = 0X THEN x := 16 END ELSE END | '3': IF s[10] = 0X THEN x := 4 END | '2': IF s[10] = 0X THEN x := 3 END | '5': IF s[10] = 0X THEN x := 6 END | '4': IF s[10] = 0X THEN x := 5 END | '7': IF s[10] = 0X THEN x := 8 END | '6': IF s[10] = 0X THEN x := 7 END | '9': IF s[10] = 0X THEN x := 10 END | '8': IF s[10] = 0X THEN x := 9 END ELSE END END END END END | 'C': IF s[5] = 'E' THEN IF s[6] = 'L' THEN IF s[7] = 'T' THEN IF s[8] = 'I' THEN IF s[9] = 'C' THEN IF s[10] = 0X THEN x := 14 END END END END END END ELSE END | '_': CASE s[4] OF | '8': IF s[5] = '8' THEN IF s[6] = '5' THEN IF s[7] = '9' THEN IF s[8] = '-' THEN CASE s[9] OF | '1': CASE s[10] OF | 0X: x := 2 | '1': IF s[11] = 0X THEN x := 12 END | '0': CASE s[11] OF | 0X: x := 11 | ':': IF s[12] = '1' THEN IF s[13] = '9' THEN IF s[14] = '9' THEN IF s[15] = '2' THEN IF s[16] = 0X THEN x := 11 END END END END END ELSE END | '3': IF s[11] = 0X THEN x := 13 END | '5': CASE s[11] OF | 0X: x := 15 | ':': IF s[12] = '1' THEN IF s[13] = '9' THEN IF s[14] = '9' THEN IF s[15] = '8' THEN IF s[16] = 0X THEN x := 15 END END END END END ELSE END | '4': CASE s[11] OF | 0X: x := 14 | ':': IF s[12] = '1' THEN IF s[13] = '9' THEN IF s[14] = '9' THEN IF s[15] = '8' THEN IF s[16] = 0X THEN x := 14 END END END END END ELSE END | '6': CASE s[11] OF | 0X: x := 16 | ':': IF s[12] = '2' THEN IF s[13] = '0' THEN IF s[14] = '0' THEN IF s[15] = '1' THEN IF s[16] = 0X THEN x := 16 END END END END END ELSE END | ':': IF s[11] = '1' THEN IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '7' THEN IF s[15] = 0X THEN x := 2 END END END END END ELSE END | '3': CASE s[10] OF | 0X: x := 4 | ':': IF s[11] = '1' THEN IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '8' THEN IF s[15] = 0X THEN x := 4 END END END END END ELSE END | '2': CASE s[10] OF | 0X: x := 3 | ':': IF s[11] = '1' THEN IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '7' THEN IF s[15] = 0X THEN x := 3 END END END END END ELSE END | '5': CASE s[10] OF | 0X: x := 6 | ':': IF s[11] = '1' THEN IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '8' THEN IF s[15] = 0X THEN x := 6 END END END END END ELSE END | '4': CASE s[10] OF | 0X: x := 5 | ':': IF s[11] = '1' THEN IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '8' THEN IF s[15] = 0X THEN x := 5 END END END END END ELSE END | '7': CASE s[10] OF | 0X: x := 8 | ':': CASE s[11] OF | '1': IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '7' THEN IF s[15] = 0X THEN x := 8 END END END END | '2': IF s[12] = '0' THEN IF s[13] = '0' THEN IF s[14] = '3' THEN IF s[15] = 0X THEN x := 8 END END END END ELSE END ELSE END | '6': CASE s[10] OF | 0X: x := 7 | ':': IF s[11] = '1' THEN IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '7' THEN IF s[15] = 0X THEN x := 7 END END END END END ELSE END | '9': CASE s[10] OF | 0X: x := 10 | ':': IF s[11] = '1' THEN IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '9' THEN IF s[15] = 0X THEN x := 10 END END END END END ELSE END | '8': CASE s[10] OF | 0X: x := 9 | ':': IF s[11] = '1' THEN IF s[12] = '9' THEN IF s[13] = '8' THEN IF s[14] = '8' THEN IF s[15] = 0X THEN x := 9 END END END END END ELSE END ELSE END END END END END | '6': IF s[5] = '4' THEN IF s[6] = '6' THEN IF s[7] = '.' THEN IF s[8] = 'I' THEN IF s[9] = 'R' THEN IF s[10] = 'V' THEN IF s[11] = ':' THEN IF s[12] = '1' THEN IF s[13] = '9' THEN IF s[14] = '9' THEN IF s[15] = '1' THEN IF s[16] = 0X THEN x := 0 END END END END END END END END END END END END ELSE END | '6': IF s[4] = '4' THEN IF s[5] = '6' THEN IF s[6] = '-' THEN IF s[7] = 'U' THEN IF s[8] = 'S' THEN IF s[9] = 0X THEN x := 0 END END END END END END ELSE END END | 'B': IF s[2] = 'M' THEN CASE s[3] OF | '-': CASE s[4] OF | '1': IF s[5] = '1' THEN IF s[6] = '6' THEN CASE s[7] OF | '1': IF s[8] = 0X THEN x := 50 END | '3': IF s[8] = 0X THEN x := 52 END | '2': IF s[8] = 0X THEN x := 51 END ELSE END END END | 'C': IF s[5] = 'P' THEN IF s[6] = '1' THEN IF s[7] = '1' THEN IF s[8] = '3' THEN IF s[9] = '3' THEN IF s[10] = 0X THEN x := 42 END END END END END END ELSE END | '1': IF s[4] = '1' THEN IF s[5] = '6' THEN CASE s[6] OF | '1': IF s[7] = 0X THEN x := 50 END | '3': IF s[7] = 0X THEN x := 52 END | '2': IF s[7] = 0X THEN x := 51 END ELSE END END END | '3': IF s[4] = '6' THEN IF s[5] = '7' THEN IF s[6] = 0X THEN x := 0 END END END | '4': IF s[4] = '3' THEN IF s[5] = '7' THEN IF s[6] = 0X THEN x := 53 END END END | '7': IF s[4] = '7' THEN IF s[5] = '5' THEN IF s[6] = 0X THEN x := 55 END END END | '8': CASE s[4] OF | '1': IF s[5] = '9' THEN IF s[6] = 0X THEN x := 2 END END | '5': CASE s[5] OF | '0': IF s[6] = 0X THEN x := 28 END | '2': IF s[6] = 0X THEN x := 56 END | '5': IF s[6] = 0X THEN x := 58 END | '7': IF s[6] = 0X THEN x := 59 END ELSE END | '6': CASE s[5] OF | '1': IF s[6] = 0X THEN x := 62 END | '0': IF s[6] = 0X THEN x := 61 END | '3': IF s[6] = 0X THEN x := 63 END | '2': IF s[6] = 0X THEN x := 29 END | '5': IF s[6] = 0X THEN x := 65 END | '4': IF s[6] = 0X THEN x := 64 END | '6': IF s[6] = 0X THEN x := 30 END | '9': IF s[6] = 0X THEN x := 66 END ELSE END ELSE END ELSE END END ELSE END | 'H': IF s[1] = 'E' THEN IF s[2] = 'B' THEN IF s[3] = 'R' THEN IF s[4] = 'E' THEN IF s[5] = 'W' THEN IF s[6] = 0X THEN x := 9 END END END END END END | 'K': CASE s[1] OF | 'P': IF s[2] = 'S' THEN IF s[3] = '9' THEN IF s[4] = '5' THEN IF s[5] = '6' THEN IF s[6] = '6' THEN IF s[7] = 0X THEN x := 70 END END END END END END | 'Z': IF s[2] = '-' THEN IF s[3] = '1' THEN IF s[4] = '0' THEN IF s[5] = '4' THEN IF s[6] = '8' THEN IF s[7] = 0X THEN x := 41 END END END END END END | 'O': IF s[2] = 'I' THEN IF s[3] = '8' THEN IF s[4] = '-' THEN CASE s[5] OF | 'R': IF s[6] = 0X THEN x := 17 END | 'U': IF s[6] = 0X THEN x := 18 END ELSE END END END END ELSE END | 'V': IF s[1] = 'I' THEN IF s[2] = 'S' THEN IF s[3] = 'C' THEN IF s[4] = 'I' THEN IF s[5] = 'I' THEN CASE s[6] OF | 0X: x := 68 | '1': IF s[7] = '.' THEN IF s[8] = '1' THEN IF s[9] = '-' THEN IF s[10] = '1' THEN IF s[11] = 0X THEN x := 68 END END END END END ELSE END END END END END END | 'M': CASE s[1] OF | 'A': IF s[2] = 'C' THEN CASE s[3] OF | 0X: x := 32 | 'C': CASE s[4] OF | 'Y': IF s[5] = 'R' THEN IF s[6] = 'I' THEN IF s[7] = 'L' THEN IF s[8] = 'L' THEN IF s[9] = 'I' THEN IF s[10] = 'C' THEN IF s[11] = 0X THEN x := 35 END END END END END END END | 'E': IF s[5] = 'N' THEN IF s[6] = 'T' THEN IF s[7] = 'R' THEN IF s[8] = 'A' THEN IF s[9] = 'L' THEN IF s[10] = 'E' THEN IF s[11] = 'U' THEN IF s[12] = 'R' THEN IF s[13] = 'O' THEN IF s[14] = 'P' THEN IF s[15] = 'E' THEN IF s[16] = 0X THEN x := 33 END END END END END END END END END END END END ELSE END | 'G': IF s[4] = 'R' THEN IF s[5] = 'E' THEN IF s[6] = 'E' THEN IF s[7] = 'K' THEN IF s[8] = 0X THEN x := 36 END END END END END | 'I': CASE s[4] OF | 'C': IF s[5] = 'E' THEN IF s[6] = 'L' THEN IF s[7] = 'A' THEN IF s[8] = 'N' THEN IF s[9] = 'D' THEN IF s[10] = 0X THEN x := 34 END END END END END END | 'N': IF s[5] = 'T' THEN IF s[6] = 'O' THEN IF s[7] = 'S' THEN IF s[8] = 'H' THEN IF s[9] = 0X THEN x := 32 END END END END END ELSE END | 'R': IF s[4] = 'O' THEN IF s[5] = 'M' THEN IF s[6] = 'A' THEN IF s[7] = 'N' THEN IF s[8] = 0X THEN x := 32 END END END END END | 'T': IF s[4] = 'U' THEN IF s[5] = 'R' THEN IF s[6] = 'K' THEN IF s[7] = 'I' THEN IF s[8] = 'S' THEN IF s[9] = 'H' THEN IF s[10] = 0X THEN x := 37 END END END END END END END ELSE END END | 'S': CASE s[2] OF | '9': IF s[3] = '3' THEN IF s[4] = '6' THEN IF s[5] = 0X THEN x := 44 END END END | '-': CASE s[3] OF | 'A': CASE s[4] OF | 'R': IF s[5] = 'A' THEN IF s[6] = 'B' THEN IF s[7] = 0X THEN x := 25 END END END | 'N': IF s[5] = 'S' THEN IF s[6] = 'I' THEN IF s[7] = 0X THEN x := 21 END END END ELSE END | 'C': IF s[4] = 'Y' THEN IF s[5] = 'R' THEN IF s[6] = 'L' THEN IF s[7] = 0X THEN x := 20 END END END END | 'E': IF s[4] = 'E' THEN IF s[5] = 0X THEN x := 19 END END | 'G': IF s[4] = 'R' THEN IF s[5] = 'E' THEN IF s[6] = 'E' THEN IF s[7] = 'K' THEN IF s[8] = 0X THEN x := 22 END END END END END | 'H': IF s[4] = 'E' THEN IF s[5] = 'B' THEN IF s[6] = 'R' THEN IF s[7] = 0X THEN x := 24 END END END END | 'T': IF s[4] = 'U' THEN IF s[5] = 'R' THEN IF s[6] = 'K' THEN IF s[7] = 0X THEN x := 23 END END END END ELSE END ELSE END ELSE END | 'L': CASE s[1] OF | 'A': IF s[2] = 'T' THEN IF s[3] = 'I' THEN IF s[4] = 'N' THEN CASE s[5] OF | '-': IF s[6] = '9' THEN IF s[7] = 0X THEN x := 15 END END | '1': CASE s[6] OF | 0X: x := 2 | '0': IF s[7] = 0X THEN x := 16 END ELSE END | '3': IF s[6] = 0X THEN x := 4 END | '2': IF s[6] = 0X THEN x := 3 END | '5': IF s[6] = 0X THEN x := 10 END | '4': IF s[6] = 0X THEN x := 5 END | '7': IF s[6] = 0X THEN x := 13 END | '6': IF s[6] = 0X THEN x := 11 END | '8': IF s[6] = 0X THEN x := 14 END ELSE END END END END | '1': CASE s[2] OF | 0X: x := 2 | '0': IF s[3] = 0X THEN x := 16 END ELSE END | '3': IF s[2] = 0X THEN x := 4 END | '2': IF s[2] = 0X THEN x := 3 END | '5': IF s[2] = 0X THEN x := 10 END | '4': IF s[2] = 0X THEN x := 5 END | '7': IF s[2] = 0X THEN x := 13 END | '6': IF s[2] = 0X THEN x := 11 END | '8': IF s[2] = 0X THEN x := 14 END ELSE END | 'P': IF s[1] = 'T' THEN CASE s[2] OF | '1': IF s[3] = '5' THEN IF s[4] = '4' THEN IF s[5] = 0X THEN x := 40 END END END | 'C': IF s[3] = 'P' THEN IF s[4] = '1' THEN IF s[5] = '5' THEN IF s[6] = '4' THEN IF s[7] = 0X THEN x := 40 END END END END END ELSE END END | 'S': IF s[1] = 'T' THEN IF s[2] = 'R' THEN IF s[3] = 'K' THEN IF s[4] = '1' THEN IF s[5] = '0' THEN IF s[6] = '4' THEN IF s[7] = '8' THEN IF s[8] = '-' THEN IF s[9] = '2' THEN IF s[10] = '0' THEN IF s[11] = '0' THEN IF s[12] = '2' THEN IF s[13] = 0X THEN x := 41 END END END END END END END END END END END END END | 'R': IF s[1] = 'K' THEN IF s[2] = '1' THEN IF s[3] = '0' THEN IF s[4] = '4' THEN IF s[5] = '8' THEN IF s[6] = 0X THEN x := 41 END END END END END END | 'U': CASE s[1] OF | 'H': IF s[2] = 'C' THEN IF s[3] = 0X THEN x := 45 END END | 'S': CASE s[2] OF | 0X: x := 0 | '-': IF s[3] = 'A' THEN IF s[4] = 'S' THEN IF s[5] = 'C' THEN IF s[6] = 'I' THEN IF s[7] = 'I' THEN IF s[8] = 0X THEN x := 0 END END END END END END ELSE END | 'T': IF s[2] = 'F' THEN IF s[3] = '-' THEN IF s[4] = '8' THEN IF s[5] = 0X THEN x := 1 END END END END ELSE END | '4': IF s[1] = '3' THEN IF s[2] = '7' THEN IF s[3] = 0X THEN x := 53 END END END | 'W': IF s[1] = 'I' THEN IF s[2] = 'N' THEN CASE s[3] OF | 'B': IF s[4] = 'A' THEN IF s[5] = 'L' THEN IF s[6] = 'T' THEN IF s[7] = 'R' THEN IF s[8] = 'I' THEN IF s[9] = 'M' THEN IF s[10] = 0X THEN x := 26 END END END END END END END | 'D': IF s[4] = 'O' THEN IF s[5] = 'W' THEN IF s[6] = 'S' THEN IF s[7] = '-' THEN CASE s[8] OF | '9': IF s[9] = '3' THEN IF s[10] = '6' THEN IF s[11] = 0X THEN x := 44 END END END | '1': IF s[9] = '2' THEN IF s[10] = '5' THEN CASE s[11] OF | '1': IF s[12] = 0X THEN x := 20 END | '0': IF s[12] = 0X THEN x := 19 END | '3': IF s[12] = 0X THEN x := 22 END | '2': IF s[12] = 0X THEN x := 21 END | '5': IF s[12] = 0X THEN x := 24 END | '4': IF s[12] = 0X THEN x := 23 END | '7': IF s[12] = 0X THEN x := 26 END | '6': IF s[12] = 0X THEN x := 25 END | '8': IF s[12] = 0X THEN x := 27 END ELSE END END END | '8': IF s[9] = '7' THEN IF s[10] = '4' THEN IF s[11] = 0X THEN x := 43 END END END ELSE END END END END END ELSE END END END | '6': IF s[1] = '4' THEN IF s[2] = '6' THEN IF s[3] = 0X THEN x := 0 END END END | '8': CASE s[1] OF | '5': CASE s[2] OF | '0': IF s[3] = 0X THEN x := 28 END | '2': IF s[3] = 0X THEN x := 56 END | '5': IF s[3] = 0X THEN x := 58 END | '7': IF s[3] = 0X THEN x := 59 END ELSE END | '6': CASE s[2] OF | '1': IF s[3] = 0X THEN x := 62 END | '0': IF s[3] = 0X THEN x := 61 END | '3': IF s[3] = 0X THEN x := 63 END | '2': IF s[3] = 0X THEN x := 29 END | '5': IF s[3] = 0X THEN x := 65 END | '6': IF s[3] = 0X THEN x := 30 END | '9': IF s[3] = 0X THEN x := 66 END ELSE END ELSE END ELSE END; ok := TRUE; CASE x OF -1: ok := FALSE | 0: r := modPrefix + "ascii" | 1: r := modPrefix + "utf_8" | 2: r := modPrefix + "iso8858_1" | 3: r := modPrefix + "iso8859_2" | 4: r := modPrefix + "iso8859_3" | 5: r := modPrefix + "iso8859_4" | 6: r := modPrefix + "iso8859_5" | 7: r := modPrefix + "iso8859_6" | 8: r := modPrefix + "iso8859_7" | 9: r := modPrefix + "iso8859_8" | 10: r := modPrefix + "iso8859_9" | 11: r := modPrefix + "iso8859_10" | 12: r := modPrefix + "iso8859_11" | 13: r := modPrefix + "iso8859_13" | 14: r := modPrefix + "iso8859_14" | 15: r := modPrefix + "iso8859_15" | 16: r := modPrefix + "iso8859_16" | 17: r := modPrefix + "koi8_r" | 18: r := modPrefix + "koi8_u" | 19: r := modPrefix + "cp1250" | 20: r := modPrefix + "cp1251" | 21: r := modPrefix + "cp1252" | 22: r := modPrefix + "cp1253" | 23: r := modPrefix + "cp1254" | 24: r := modPrefix + "cp1255" | 25: r := modPrefix + "cp1256" | 26: r := modPrefix + "cp1257" | 27: r := modPrefix + "cp1258" | 28: r := modPrefix + "cp850" | 29: r := modPrefix + "cp862" | 30: r := modPrefix + "cp866" | 31: r := modPrefix + "cp1131" | 32: r := modPrefix + "mac_roman" | 33: r := modPrefix + "mac_centraleurope" | 34: r := modPrefix + "mac_iceland" | 35: r := modPrefix + "mac_cyrillic" | 36: r := modPrefix + "mac_greek" | 37: r := modPrefix + "mac_turkish" | 38: r := modPrefix + "georgian_academy" | 39: r := modPrefix + "georgian_ps" | 40: r := modPrefix + "ptcp154" | 41: r := modPrefix + "kz1048" | 42: r := modPrefix + "cp1133" | 43: r := modPrefix + "cp874" | 44: r := modPrefix + "cp936" | 45: r := modPrefix + "cp949" | 46: r := modPrefix + "cp856" | 47: r := modPrefix + "cp1046" | 48: r := modPrefix + "cp1124" | 49: r := modPrefix + "cp1129" | 50: r := modPrefix + "cp1161" | 51: r := modPrefix + "cp1162" | 52: r := modPrefix + "cp1163" | 53: r := modPrefix + "cp437" | 54: r := modPrefix + "cp737" | 55: r := modPrefix + "cp775" | 56: r := modPrefix + "cp852" | 57: r := modPrefix + "cp853" | 58: r := modPrefix + "cp855" | 59: r := modPrefix + "cp857" | 60: r := modPrefix + "cp858" | 61: r := modPrefix + "cp860" | 62: r := modPrefix + "cp861" | 63: r := modPrefix + "cp863" | 64: r := modPrefix + "cp864" | 65: r := modPrefix + "cp865" | 66: r := modPrefix + "cp869" | 67: r := modPrefix + "cp1125" | 68: r := modPrefix + "viscii" | 69: r := modPrefix + "atarist" | 70: r := modPrefix + "kps9566" | 71: r := modPrefix + "cp720" END END GetModName; END EncStdAliases. iconv оптимальнее реализации на КП не из-за производительности (CASE работает быстро), а из-за памяти. libiconv ~ 1 МиБ на все кодировки из списка "iconv -l", а на КП только один энкодер CP936 занимает ~ 400 КиБ. Это из-за того, что в КП нет констант-массивов. Хотя может быть можно использовать строковые константы.. Реализацию на КП сделать не сложно. Там почти все модули должны генерироваться автоматически из таблиц, таких как на сайте unicode.org. Всё формально. Но нужно ли это делать -- спорный вопрос. Поэтому и предлагаю сделать абстрактный модуль (наподобие EncCodecs, см. выше), чтобы не зависеть от конкретной реализации. |
Автор: | Евгений Темиргалеев [ Среда, 24 Октябрь, 2012 15:03 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Alexander Shiryaev писал(а): Предлагаю сделать абстрактный модуль (см. EncCodecs выше), и его использовать в HostFiles и т д, а реализацию (Hook или Directory) сделать в отдельном модуле (как Dates/HostDates, Log/StdLog и т.д.) Мне кажется сомнительной идея всунуть в ОС-зависимый HostFiles абстрактный EncCodecs, реализация которого будет ОС-зависимая. Сразу реализацию по месту и всунуть.
Реализации могут быть разные. Для Linux -- на основе mbtowc, для OpenBSD -- iconv (т.к. mbtowc там всё рввно не работает). |
Автор: | Евгений Темиргалеев [ Среда, 24 Октябрь, 2012 15:07 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Alexander Shiryaev писал(а): Переменную LANG можно рассматривать в виде "страна.псевдонимКодировки". При невозможности извлечения псевдонима кодировки (неправильном значении переменной LANG) считать, что кодировка ASCII (так же, как и в случае LANG=C). Только псевдонимы отличаются. У iconv "UTF-8". А в LANG у меня "utf8". iconv_open умеет опредлять кодировку по её псевдониму. См "iconv -l". Код: $locale
LANG=ru_RU.utf8 |
Автор: | Alexander Shiryaev [ Среда, 24 Октябрь, 2012 15:42 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Евгений Темиргалеев писал(а): Alexander Shiryaev писал(а): Предлагаю сделать абстрактный модуль (см. EncCodecs выше), и его использовать в HostFiles и т д, а реализацию (Hook или Directory) сделать в отдельном модуле (как Dates/HostDates, Log/StdLog и т.д.) Мне кажется сомнительной идея всунуть в ОС-зависимый HostFiles абстрактный EncCodecs, реализация которого будет ОС-зависимая. Сразу реализацию по месту и всунуть.Реализации могут быть разные. Для Linux -- на основе mbtowc, для OpenBSD -- iconv (т.к. mbtowc там всё рввно не работает). В оригинальной Host для Windows везде так. |
Автор: | Alexander Shiryaev [ Среда, 24 Октябрь, 2012 15:46 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Евгений Темиргалеев писал(а): Alexander Shiryaev писал(а): Переменную LANG можно рассматривать в виде "страна.псевдонимКодировки". При невозможности извлечения псевдонима кодировки (неправильном значении переменной LANG) считать, что кодировка ASCII (так же, как и в случае LANG=C). Только псевдонимы отличаются. У iconv "UTF-8". А в LANG у меня "utf8". iconv_open умеет опредлять кодировку по её псевдониму. См "iconv -l". Код: $locale LANG=ru_RU.utf8 Да, действительно.. мои предположения о псевдонимах кодировок не совсем верны. |
Автор: | Alexander Shiryaev [ Среда, 24 Октябрь, 2012 15:50 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Посмотрел реализацию преобразования UCS-2 -> UTF-8 в XhtmlStdFileWriters. Наверное так и надо делать. |
Автор: | Alexander Shiryaev [ Четверг, 25 Октябрь, 2012 01:13 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Реализовал преобразование кодировок на КП (пока только UTF-8, однобайтовые (SBCS)). EncCodecs: Код: MODULE EncCodecs; TYPE Encoding* = ARRAY 32 OF CHAR; Directory* = POINTER TO ABSTRACT RECORD END; Encoder* = POINTER TO ABSTRACT RECORD END; Decoder* = POINTER TO ABSTRACT RECORD END; VAR dir-: Directory; (* Directory *) PROCEDURE (dir: Directory) NewEncoder* (enc: Encoding): Encoder, NEW, ABSTRACT; PROCEDURE (dir: Directory) NewDecoder* (enc: Encoding): Decoder, NEW, ABSTRACT; (* Encoder *) (* pre: fR >= 0, fLen >= 0, tW >= 0 *) (* post: fLen = 0: ok fLen > 0: error at f[fR] *) PROCEDURE (e: Encoder) Encode* (IN f: ARRAY OF CHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF SHORTCHAR; VAR tW: INTEGER), NEW, ABSTRACT; (* Decoder *) (* pre: d not in error state, fR >= 0, fLen >= 0, tW >= 0 *) (* post: fLen = 0: ok, state: d has state fLen > 0: error at f[fR] *) PROCEDURE (d: Decoder) Decode* (IN f: ARRAY OF SHORTCHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF CHAR; VAR tW: INTEGER; OUT state: BOOLEAN), NEW, ABSTRACT; PROCEDURE (d: Decoder) Reset*, NEW, ABSTRACT; PROCEDURE SetDir* (d: Directory); BEGIN dir := d END SetDir; END EncCodecs. EncStdMap_utf_8: Код: MODULE EncStdMap_utf_8; IMPORT Codecs := EncCodecs; TYPE Encoder = POINTER TO RECORD (Codecs.Encoder) END; Decoder = POINTER TO RECORD (Codecs.Decoder) b: INTEGER; st: INTEGER (* 0 - no state, 1 - one char expected, 2 - two chars expected, -1 - error *) END; (* Encoder *) PROCEDURE (e: Encoder) Encode (IN f: ARRAY OF CHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF SHORTCHAR; VAR tW: INTEGER); VAR x: INTEGER; BEGIN WHILE fLen > 0 DO x := ORD(f[fR]); (* XhtmlStdFileWriters.Char *) (* http://www.lemoda.net/c/ucs2-to-utf8/index.html *) CASE x OF 00H..7FH: t[tW] := SHORT(CHR(x)); INC(tW) | 80H..7FFH: t[tW] := SHORT(CHR(x DIV 64 + 192)); t[tW+1] := SHORT(CHR(x MOD 64 + 128)); INC(tW, 2) | 800H..0FFFFH: t[tW] := SHORT(CHR(x DIV 4096 + 224)); t[tW+1] := SHORT(CHR((x DIV 64) MOD 64 + 128)); t[tW+2] := SHORT(CHR(x MOD 64 + 128)); INC(tW, 3) END; INC(fR); DEC(fLen) END END Encode; PROCEDURE NewEncoder* (): Codecs.Encoder; VAR e: Encoder; BEGIN NEW(e); RETURN e END NewEncoder; (* Decoder *) PROCEDURE (d: Decoder) Decode (IN f: ARRAY OF SHORTCHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF CHAR; VAR tW: INTEGER; OUT state: BOOLEAN); VAR x: INTEGER; BEGIN WHILE fLen > 0 DO x := ORD(f[fR]); (* http://www.lemoda.net/c/utf8-to-ucs2/index.html *) CASE d.st OF 0: IF x < 128 THEN t[tW] := CHR(x); INC(tW) ELSIF x >= 224 THEN d.b := x MOD 16; INC(d.st, 2) ELSIF x >= 192 THEN d.b := x MOD 32; INC(d.st) ELSE DEC(d.st); RETURN END | 1: t[tW] := CHR(d.b * 64 + x MOD 64); INC(tW); DEC(d.st) | 2: d.b := d.b * 64 + x MOD 64; DEC(d.st) END; INC(fR); DEC(fLen) END; CASE d.st OF 0: state := FALSE | 1,2: state := TRUE END END Decode; PROCEDURE (d: Decoder) Reset; BEGIN d.st := 0 END Reset; PROCEDURE NewDecoder* (): Codecs.Decoder; VAR d: Decoder; BEGIN NEW(d); d.Reset; RETURN d END NewDecoder; END EncStdMap_utf_8. Пример использования: Код: MODULE TestEnc2;
IMPORT Codecs := EncCodecs, EncStdCodecs, Log; PROCEDURE Do* (IN enc: ARRAY OF CHAR); VAR e: Codecs.Encoder; d: Codecs.Decoder; fR, fLen, tW: INTEGER; ss: ARRAY 100 OF SHORTCHAR; s: ARRAY 100 OF CHAR; st: BOOLEAN; BEGIN e := Codecs.dir.NewEncoder(enc$); ASSERT(e # NIL, 100); d := Codecs.dir.NewDecoder(enc$); ASSERT(d # NIL, 101); fR := 0; fLen := 7; tW := 0; e.Encode("АбВгДеЁ", fR, fLen, ss, tW); ASSERT(fLen = 0, 102); fR := 0; fLen := tW; tW := 0; d.Decode(ss, fR, fLen, s, tW, st); ASSERT(fLen = 0, 103); ASSERT(~st, 104); s[tW] := 0X; Log.String(s); Log.Ln END Do; END TestEnc2. (!)"TestEnc2.Do('UTF-8')" (!)"TestEnc2.Do('KOI8-R')" (!)"TestEnc2.Do('CP1251')" (!)"TestEnc2.Do('CP866')" |
Автор: | Евгений Темиргалеев [ Четверг, 25 Октябрь, 2012 08:10 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Как реализована обработка ошибок? Из из стандарта тесты некорректных последовательностей прогоните. Приведённый ниже декодер их не обрабатывает. Наверное, что-то упускаю из вида, но не вижу между ними принципиальной разницы. Код: PROCEDURE (VAR d: CharDecoder) Start*, NEW;
BEGIN d.state := 0; d.ch := 0X END Start; PROCEDURE (VAR d: CharDecoder) HandleOctet* (b: SHORTCHAR), NEW; VAR bits: SET; BEGIN IF d.state = 0 THEN IF b <= 7FX THEN (* 0xxxxxxx *) d.ch := b; (* d.state := 0 *) ELSE bits := BITS(ORD(b)); IF bits * {6..7} = {7} THEN (* 10xxxxxx *) d.state := wrongLeadingOctet ELSIF bits * {5..7} = {6..7} THEN (* 110xxxxx *) d.ch := CHR(ORD(bits * {0..4})); d.state := -1 ELSIF bits * {4..7} = {5..7} THEN (* 1110xxxx *) d.ch := CHR(ORD(bits * {0..3})); d.state := -2 ELSE d.state := sequenceTooLong END END ELSIF d.state < 0 THEN IF BITS(ORD(b)) * {7, 6} = {7} THEN (* 10xxxxxx *) d.ch := CHR(64 * ORD(d.ch) + ORD(b) MOD 64); INC(d.state) ELSE d.state := wrongFollowingOctet END ELSE (* d.state > 0 *) HALT(20) END END HandleOctet; PROCEDURE (VAR d: CharDecoder) Stop*, NEW; BEGIN IF d.state < 0 THEN d.state := unexpectedEnd END END Stop; |
Автор: | Alexander Shiryaev [ Четверг, 25 Октябрь, 2012 22:32 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Код: PROCEDURE (d: Decoder) Decode (IN f: ARRAY OF SHORTCHAR; VAR fR, fLen: INTEGER; VAR t: ARRAY OF CHAR; VAR tW: INTEGER; OUT state: BOOLEAN); VAR x: INTEGER; BEGIN WHILE fLen > 0 DO x := ORD(f[fR]); CASE d.st OF 0: CASE x OF 0..127: t[tW] := CHR(x); INC(tW) | 192..223: d.b := x MOD 32; d.st := 1 | 224..239: d.b := x MOD 16; d.st := 2 ELSE (* unexpected shortchar *) d.st := -1; RETURN END | 1: IF (x >= 128) & (x < 192) THEN t[tW] := CHR(d.b * 64 + x MOD 64); INC(tW); d.st := 0 ELSE (* unexpected shortchar *) d.st := -1; RETURN END | 2: IF (x >= 128) & (x < 192) THEN d.b := d.b * 64 + x MOD 64; d.st := 1 ELSE (* unexpected shortchar *) d.st := -1; RETURN END END; INC(fR); DEC(fLen) END; CASE d.st OF 0: state := FALSE | 1,2: state := TRUE END END Decode; Тест: Код: MODULE TestEnc3; (* Test UTF-8 encoder/decoder *) IMPORT Codecs := EncCodecs, EncStdCodecs, Log; PROCEDURE Do*; VAR s: ARRAY 65536 OF CHAR; ss: ARRAY 65536 * 3 OF SHORTCHAR; i: INTEGER; fR, fLen, tW: INTEGER; st: BOOLEAN; e: Codecs.Encoder; d: Codecs.Decoder; BEGIN i := 0; WHILE i < 65536 DO s[i] := CHR(i); INC(i) END; e := Codecs.dir.NewEncoder("UTF-8"); ASSERT(e # NIL, 100); d := Codecs.dir.NewDecoder("UTF-8"); ASSERT(e # NIL, 101); fR := 0; fLen := 65536; tW := 0; e.Encode(s, fR, fLen, ss, tW); ASSERT(fLen = 0, 102); Log.Int(tW); Log.Ln; i := 0; WHILE i < 65536 DO s[i] := 0X; INC(i) END; fR := 0; fLen := tW; tW := 0; d.Decode(ss, fR, fLen, s, tW, st); ASSERT(fLen = 0, 103); ASSERT(~st, 104); ASSERT(tW = 65536, 105); i := 0; WHILE i < 65536 DO ASSERT(s[i] = CHR(i), 106); INC(i) END END Do; END TestEnc3. (!)TestEnc3.Do Реализовал генератор для двухбайтовых (DBCS) кодировок (пока только CP936, CP949, KPS9566). Остались CJK. |
Автор: | Евгений Темиргалеев [ Четверг, 25 Октябрь, 2012 23:27 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
Кони, лмя. Цитата: int wctomb (char *string, wchar_t wchar) If wchar is L'\0', it returns 0, also storing '\0' in *string. Код: PROCEDURE Init; VAR res: LinLibc.PtrSTR; x: INTEGER; s: ARRAY 32 OF SHORTCHAR; BEGIN res := LinLibc.setlocale(LinLibc.LC_ALL, ""); x := LinLibc.wctomb(s[0], 0); Log.Int(x); ASSERT(x = 0, 0); END Init; Код: 1
**** * BlackBox * trap #000 - Conv1.Init (pc=000002B4, fp=FFB6C240) - Conv1.$$ (pc=0000000A, fp=FFB6C250) ... |
Автор: | Евгений Темиргалеев [ Четверг, 25 Октябрь, 2012 23:34 ] |
Заголовок сообщения: | Re: Lin Console: средство преобразования UCS-2 <-> UTF-8 |
1) Александр, запишите постусловие для state (как-то не очень сочетаются OUT state: BOOLEAN и d.st := -1; RETURN из середины (не зря Вирт это дело в О-7 убрал)) 2) Что выдает Ваш декодер для C0H 80H ? (см. http://www.ietf.org/rfc/rfc3629.txt, 10 Security Considerations) 3) Проверки через SET эффективнее, чем арифметические (хотя преобразования могут выглядеть громоздко). BITS(x) * {6, 7} = {7} --> MOV reg, x ; AND reg, 192 ; CMP reg, 128 ; усл. переход (x >= 128) & (x < 192) --> MOV reg, x ; CMP x, 128 ; усл. переход1 ; CMP x, 192 ; усл. переход 2 И всякие x MOD 32 в идеале надо писать тоже через SET. Потому что set * по определению есть AND, а для MOD 2^n это хотя и ожидаемая, но оптимизация. Аналогично x * 2^n и x DIV 2^n в идеале писать через ASH. |
Страница 1 из 3 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |