AnsiUpperCase/AnsiLowerCase проблема под Linux

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение NTFS » 21.08.2013 12:11:25

Собственно, древний как сам FPC баг - только я думал, что он давно исправлен (последние несколько лет сидел на FPC 2.2, не обновлялся за отсутствием необходимости).

Недавно поставил на новый комп FPC 2.6.0 - и о ужас, все та же проблема.

Суть: не преобразуется регистр у русских букв Я и Ч в кодировке CP1251.
Остальные буквы проходят нормально.

Проблема только под Linux, FPC под Windows нормально работает.

Тестовая программа:

Код: Выделить всё
program test ;
uses SysUtils ;
var s:string ;
begin
  s:='Чя - Яч - аБвГдЕ' ;
  Writeln(AnsiLowerCase(s)) ;
  Writeln(AnsiUpperCase(s)) ;
end.


Вывод тестовой программы:

Чя - Яч - абвгде
ЧY - Яч - АБВГДЕ


WTF? Написать собственный AnsiLowerCase не предлагать - это было сделано в тот же день, как я нашел эту проблему :-) мне нужно, что встроенная функция нормально работала.

Добавлено спустя 3 минуты 22 секунды:
Еще было что-то подобное с сортировкой русской буквы Г, которая выходила после Ф, но это видел только раз, только на конкретной системе и только внутри UDF для Firebird :-) спишем на звезды. А вот проблема из 0 - стабильна, воспроизводима и удручающа.
NTFS
постоялец
 
Сообщения: 388
Зарегистрирован: 05.11.2007 14:57:50
Откуда: Краснодар

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение SeZuka » 22.08.2013 04:28:01

Уж не знаю как там под линухом, но в винде фпс вызывает winapi-функцию для преобразования регистра, так что дело может вовсе не в фпс...
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение NTFS » 22.08.2013 18:46:30

Под Windows все отлично... эта проблема в Linux проявляется
NTFS
постоялец
 
Сообщения: 388
Зарегистрирован: 05.11.2007 14:57:50
Откуда: Краснодар

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение Ism » 22.08.2013 19:31:35

Садисты, в модулях UTF8

Используйте всегда LConvEncoding и UTF8UpperCase
http://wiki.freepascal.org/LCL_Unicode_Support/ru
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение NTFS » 22.08.2013 20:45:13

С какой это радости в модулях UTF8, если я использую FPC без Lazarus?

Или FPC 2.6 стал юникодным?

То, что в UTF8 нормально Я и Ч обрабатываются, я в курсе. Мне CP1251 нуно.

Добавлено спустя 1 минуту 21 секунду:
Повторю еще раз: проблема не в преобразовании регистра. Корректно работающий вариант AnsiUpperCase для CP-1251 я сделал много лет назад. Мне в принципе интересно, можно ли заставить правильно работать AnsiUpperCase из SysUtils под Linux.
NTFS
постоялец
 
Сообщения: 388
Зарегистрирован: 05.11.2007 14:57:50
Откуда: Краснодар

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение Ism » 22.08.2013 22:05:39

Ansi это не cp1251 и не обязан работать с русским
http://ru.wikipedia.org/wiki/ANSI_%28%D ... 8%D1%8F%29

WideUpperCase
http://www.freepascal.org/docs-html/rtl ... rcase.html
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение NTFS » 23.08.2013 00:53:35

Я согласен. Я скажу больше - FreePascal не обязан не только работать с cp1251, но и вообще не обязан никому и ничего. Потому что он четко обозначен как as-is. Следовательно, я не наезжаю на разработчиков FPC с криками "Волки позорные, моргала выкалю!", а интересуюсь у сообщества. Не может быть, чтобы никто не работал с cp1251 под Linux. Данные-то чаще всего в этой кодировочке поступают. Или никто не делал под Linux ничего сложнее калькулятора, или все натыкались на эту проблему, плевались, писали за 15 минут свой собственный кошерный AnsiUpperCase и забывали об этой проблеме.
NTFS
постоялец
 
Сообщения: 388
Зарегистрирован: 05.11.2007 14:57:50
Откуда: Краснодар

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение Ism » 23.08.2013 05:29:39

Всё есть
1 AnsiToUtf8 - UTF8Decode - WideUpperCase и обратно, стандартные функции fpc
2 Использовать synapse с iconv.dll, там можно гонять кодировки как угодно без сбоев одной функцией, работает под linux
3 Используйте lconvencoding или выдерите оттуда функцию, она проста

Все операции нужно делать в utf8 или widestring, остальные варианты уже не поддерживаются или глючат
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение NTFS » 23.08.2013 10:45:51

Если я правильно понял ваш ответ, он таков:
"Хочешь работать под Linux с кириллицей - используй UTF или пиши свои функции. Все остальное ересь" Так?
NTFS
постоялец
 
Сообщения: 388
Зарегистрирован: 05.11.2007 14:57:50
Откуда: Краснодар

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение Ism » 23.08.2013 11:33:48

Вы читали предыдущий пост ? Есть сомнения в вашей вменяемости
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение NTFS » 23.08.2013 15:56:15

Меньше агрессии :-) я просто уточнял. Ситуация, как бы нетривиальная. Я все же думаю, что это баг.

Добавлено спустя 1 минуту 28 секунд:
31 буква в норме... 2 в пролете.
NTFS
постоялец
 
Сообщения: 388
Зарегистрирован: 05.11.2007 14:57:50
Откуда: Краснодар

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение Ism » 23.08.2013 16:06:33

Я тоже с этим сталкивался, причина - модуль в UTF8 , а значит код передавал однобайтоваые обрезки юникодовых символов и не ругался.
Решение - код модуля в CP1251 , тогда все Ansi функции должны работать
Вообще FPC юникодная система и использовать Ansi как минимум ошибка
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: AnsiUpperCase/AnsiLowerCase проблема под Linux

Сообщение SeZuka » 24.08.2013 08:41:51

NTFS писал(а):Я все же думаю, что это баг

Это не баг, посмотрели бы исходники. Как я уже писал выше, для винды вызываются API функции CharLowerBuff и CharUpperBuff, а для линукса используются таблицы преобразования регистра LowerCaseTable и UpperCaseTable, так вот эта таблицы для символов начиная с #192 заполняются для кодовой страницы ISO 8859-1. Если посмотрите эту таблицу, то увидите что на месте Ч и ч стоят символы × и ÷ которые естественно никуда не преобразуются, а как были так и остаются в тексте, примерно то же самое и для Я и я, только для я соответствует символ ÿ, и для верхнего регистра подставляется Y.
Так что можно сказать что FPC не имеет встроенной поддержки CP1251.
Для тех кому лень рыться в исходниках, скопипастил их. Сами функции:
Код: Выделить всё
function AnsiUpperCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
  begin
    result:=widestringmanager.UpperAnsiStringProc(s);
  end;

function AnsiLowerCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
  begin
    result:=widestringmanager.LowerAnsiStringProc(s);
  end;

Установка менеджера для линукса:
Код: Выделить всё
procedure InitInternationalGeneric;
  begin
    fillchar(SysLocale,sizeof(SysLocale),0);
   
    { keep these routines out of the executable? }
{$ifndef FPC_NOGENERICANSIROUTINES}
    { don't override a previously installed widestring manager }
    if not assigned(widestringmanager.UpperAnsiStringProc) then
      widestringmanager.UpperAnsiStringProc:=@GenericAnsiUpperCase;
    if not assigned(widestringmanager.LowerAnsiStringProc) then
      widestringmanager.LowerAnsiStringProc:=@GenericAnsiLowerCase;   
    if not assigned(widestringmanager.CompareStrAnsiStringProc) then
      widestringmanager.CompareStrAnsiStringProc:=@GenericAnsiCompareStr;
    if not assigned(widestringmanager.CompareTextAnsiStringProc) then
      widestringmanager.CompareTextAnsiStringProc:=@GenericAnsiCompareText;
    if not assigned(widestringmanager.StrCompAnsiStringProc) then
      widestringmanager.StrCompAnsiStringProc:=@GenericAnsiStrComp;
    if not assigned(widestringmanager.StrICompAnsiStringProc) then
      widestringmanager.StrICompAnsiStringProc:=@GenericAnsiStrIComp;
    if not assigned(widestringmanager.StrLCompAnsiStringProc) then
      widestringmanager.StrLCompAnsiStringProc:=@GenericAnsiStrLComp;
    if not assigned(widestringmanager.StrLICompAnsiStringProc) then
      widestringmanager.StrLICompAnsiStringProc:=@GenericAnsiStrLIComp;
    if not assigned(widestringmanager.StrLowerAnsiStringProc) then
      widestringmanager.StrLowerAnsiStringProc:=@GenericAnsiStrLower;
    if not assigned(widestringmanager.StrUpperAnsiStringProc) then
      widestringmanager.StrUpperAnsiStringProc:=@GenericAnsiStrUpper;
{$endif FPC_NOGENERICANSIROUTINES}   
  end;

Сами функции преобразования:
Код: Выделить всё
function GenericAnsiUpperCase(const s: string): string;
  var
    len, i: integer;
begin
  len := length(s);
  SetLength(result, len);
  for i := 1 to len do
     result[i] := UpperCaseTable[ord(s[i])];
end;

function GenericAnsiLowerCase(const s: string): string;
  var
    len, i: integer;
begin
  len := length(s);
  SetLength(result, len);
  for i := 1 to len do
     result[i] := LowerCaseTable[ord(s[i])];
end;

Заполнение таблиц преобразования:
Код: Выделить всё
Procedure InitAnsi;
Var
  i : longint;
begin
  {  Fill table entries 0 to 127  }
  for i := 0 to 96 do
    UpperCaseTable[i] := chr(i);
  for i := 97 to 122 do
    UpperCaseTable[i] := chr(i - 32);
  for i := 123 to 191 do
    UpperCaseTable[i] := chr(i);
  Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));

  for i := 0 to 64 do
    LowerCaseTable[i] := chr(i);
  for i := 65 to 90 do
    LowerCaseTable[i] := chr(i + 32);
  for i := 91 to 191 do
    LowerCaseTable[i] := chr(i);
  Move (CPISO88591LCT,LowerCaseTable[192],SizeOf(CPISO88591UCT));
end;

Ну и сами таблицы преобразования для ISO 8859-1:
Код: Выделить всё
   { upper case translation table for character set ISO 8859/1  Latin 1  }
   CPISO88591UCT: array[192..255] of char =
   ( #192, #193, #194, #195, #196, #197, #198, #199,
     #200, #201, #202, #203, #204, #205, #206, #207,
     #208, #209, #210, #211, #212, #213, #214, #215,
     #216, #217, #218, #219, #220, #221, #222, #223,
     #192, #193, #194, #195, #196, #197, #198, #199,
     #200, #201, #202, #203, #204, #205, #206, #207,
     #208, #209, #210, #211, #212, #213, #214, #247,
     #216, #217, #218, #219, #220, #221, #222, #89 );

   { lower case translation table for character set ISO 8859/1  Latin 1  }
   CPISO88591LCT: array[192..255] of char =
   ( #224, #225, #226, #227, #228, #229, #230, #231,
     #232, #233, #234, #235, #236, #237, #238, #239,
     #240, #241, #242, #243, #244, #245, #246, #215,
     #248, #249, #250, #251, #252, #253, #254, #223,
     #224, #225, #226, #227, #228, #229, #230, #231,
     #232, #233, #234, #235, #236, #237, #238, #239,
     #240, #241, #242, #243, #244, #245, #246, #247,
     #248, #249, #250, #251, #252, #253, #254, #255 );
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05


Вернуться в Free Pascal Compiler

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

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

Рейтинг@Mail.ru
cron