OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Четверг, 28 Март, 2024 13:56

Часовой пояс: UTC + 3 часа




Форум закрыт Эта тема закрыта, вы не можете редактировать и оставлять сообщения в ней.  [ Сообщений: 46 ]  На страницу 1, 2, 3  След.
Автор Сообщение
СообщениеДобавлено: Вторник, 23 Октябрь, 2012 18:24 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
В инструкцию по сборке приложения 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 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
Как отправную точку предлагаю приложенный интерфейс. Содержит автомат для обработки октетов и процедуры конверсии из массива литер и файлов ("A file is a sequence of bytes.").

Реализацию начинал ЕИЕ, заканчивал ТЕЭ. Но она крайне не идеальна --- как-то я сподобился глядя прямо в стандарт проглядеть обработку указанных прямо там ошибочных ситуаций. Для означенной же тулзы должно быть всё строго реализовано.


Вложения:
xxxUtf8-docu.pdf [44.69 КБ]
Скачиваний: 588
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 23 Октябрь, 2012 19:33 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Вроде бы нормальный интерфейс.

Про 32 бит выше не понял - это где оно используется?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 23 Октябрь, 2012 21:11 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
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.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 24 Октябрь, 2012 01:02 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 473
Откуда: KZ
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 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
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 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
Насчёт интерфейса общего преобразователя: в 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 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
Альтернативный вариант использованию iconv --- политерные преобразования через mbtowc и обратно, LANG система учитывает. LinLog так сделан.

Решение самое простое получается. Вопрос только в производительности. Может и забить на ней?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 24 Октябрь, 2012 13:11 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
Итого, для задачи поддержки преобразования определённой пользователем (системой) кодировки <-> UCS-2, рассмотрено три решения:
1) Использовать общую реализацию конвертера на ББ.
Минус: для реализации ОС-зависимых компонентов (которые в идеале должны быть как можно ближе к системе) используется нетривиальный ОС-независимый компонент.
Проблема: требуется по переменной LANG выбирать метод преобразования. Если детерминированного решения нет, придётся перекладывать на пользователя, например, вводя дополнительную переменную окружения как параметр для ББ-приложений.

2) Использовать системную библиотеку iconv.
Проблема (как выше): требуется отображать значение переменной LANG в обозначение кодировки для iconv.

3) Использовать преобразования mbtowc/wctomb и их цепочечные аналоги.
Плюс: означенной выше проблемы нет --- setlocale(LC_ALL...) настраивает библиотеку на исп-е настроек по соотв. переменным окружения.
Минус: общее политерное решение "медленное". Цепочечные функции допустимы там, где wchar_t двухбайтовый; все системы с GNU libc отпадают.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 24 Октябрь, 2012 14:10 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 473
Откуда: KZ
Евгений Темиргалеев писал(а):
Итого, для задачи поддержки преобразования определённой пользователем (системой) кодировки <-> 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 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
Alexander Shiryaev писал(а):
Предлагаю сделать абстрактный модуль (см. EncCodecs выше), и его использовать в HostFiles и т д, а реализацию (Hook или Directory) сделать в отдельном модуле (как Dates/HostDates, Log/StdLog и т.д.)

Реализации могут быть разные. Для Linux -- на основе mbtowc, для OpenBSD -- iconv (т.к. mbtowc там всё рввно не работает).
Мне кажется сомнительной идея всунуть в ОС-зависимый HostFiles абстрактный EncCodecs, реализация которого будет ОС-зависимая. Сразу реализацию по месту и всунуть.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 24 Октябрь, 2012 15:07 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
Alexander Shiryaev писал(а):
Переменную LANG можно рассматривать в виде "страна.псевдонимКодировки". При невозможности извлечения псевдонима кодировки (неправильном значении переменной LANG) считать, что кодировка ASCII (так же, как и в случае LANG=C).

iconv_open умеет опредлять кодировку по её псевдониму. См "iconv -l".
Только псевдонимы отличаются. У iconv "UTF-8". А в LANG у меня "utf8".
Код:
$locale
LANG=ru_RU.utf8


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 24 Октябрь, 2012 15:42 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 473
Откуда: KZ
Евгений Темиргалеев писал(а):
Alexander Shiryaev писал(а):
Предлагаю сделать абстрактный модуль (см. EncCodecs выше), и его использовать в HostFiles и т д, а реализацию (Hook или Directory) сделать в отдельном модуле (как Dates/HostDates, Log/StdLog и т.д.)

Реализации могут быть разные. Для Linux -- на основе mbtowc, для OpenBSD -- iconv (т.к. mbtowc там всё рввно не работает).
Мне кажется сомнительной идея всунуть в ОС-зависимый HostFiles абстрактный EncCodecs, реализация которого будет ОС-зависимая. Сразу реализацию по месту и всунуть.


В оригинальной Host для Windows везде так.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 24 Октябрь, 2012 15:46 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 473
Откуда: KZ
Евгений Темиргалеев писал(а):
Alexander Shiryaev писал(а):
Переменную LANG можно рассматривать в виде "страна.псевдонимКодировки". При невозможности извлечения псевдонима кодировки (неправильном значении переменной LANG) считать, что кодировка ASCII (так же, как и в случае LANG=C).

iconv_open умеет опредлять кодировку по её псевдониму. См "iconv -l".
Только псевдонимы отличаются. У iconv "UTF-8". А в LANG у меня "utf8".
Код:
$locale
LANG=ru_RU.utf8


Да, действительно.. мои предположения о псевдонимах кодировок не совсем верны.


Последний раз редактировалось Alexander Shiryaev Среда, 24 Октябрь, 2012 16:12, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 24 Октябрь, 2012 15:50 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 473
Откуда: KZ
Посмотрел реализацию преобразования UCS-2 -> UTF-8 в XhtmlStdFileWriters.
Наверное так и надо делать.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 25 Октябрь, 2012 01:13 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 473
Откуда: KZ
Реализовал преобразование кодировок на КП (пока только 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 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
Как реализована обработка ошибок?

Из из стандарта тесты некорректных последовательностей прогоните. Приведённый ниже декодер их не обрабатывает. Наверное, что-то упускаю из вида, но не вижу между ними принципиальной разницы.
Код:
   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;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 25 Октябрь, 2012 22:32 

Зарегистрирован: Суббота, 26 Ноябрь, 2005 02:12
Сообщения: 473
Откуда: KZ
Код:
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 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
Кони, лмя.
Цитата:
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 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4625
Откуда: Россия, Орёл
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.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Форум закрыт Эта тема закрыта, вы не можете редактировать и оставлять сообщения в ней.  [ Сообщений: 46 ]  На страницу 1, 2, 3  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB