"Русификация" REXX

Автор: Тимур Козимиров

Источник: RDM/2

Дата: 25.02.1999

При работе с REXX в OS/2 я постоянно сталкиваюсь с двумя проблемами. Часто надо преобразовать какой-либо текст из 866 кодовой страницы в KOI8 и наоборот. Средствами REXX такое можно сделать, но приходится городить примерно подобные конструкции:

   Table866 = 'стучу все буковки из таблицы 866'

   Table878 = 'аналогично, но для KOI8-R'

   trn_str = TRANSLATE(source_str, Table878, Table866)

Кроме того, очень часто надо преобразовать строку в верхний регистр. Функция UPPER здесь не помощница - там только первая половина таблицы переводится (равно как и в любом другом языке или системе программирования). Опять приходится прибегать к набору таблиц перевода и функции TRANSLATE. Неудобно...

Вот я и решил создать две функции, использующие вызовы OS/2 API WinCpTranslateString и WinUpper соответственно для этих задач. В поставке Virtual Pascal 1.1 for OS/2 есть пример написания собственных DLL-ей для использования в REXX. Часовой эксперимент увенчался успехом и я могу теперь предложить вам этот набор - rxcpage.zip. Распакуйте его, там три файла - исходник библиотеки на Паскале, сама DLL и пример программы на REXX, использующей мои функции.

Внутри DLL содержатся описания трех функций:

  • RxCpLoadFuncs - для загрузки функций в память
  • RxCpTranslate - для перевода строки из одной кодировки в другую (можно использовать любую кодировку, которая упоминается в каталоге \LANGUAGE\CODEPAGE - там их около сотни).
  • RxUpCase - для перевода строки в верхний регистр в соответствии с текущей кодировкой

Ну вот, собственно говоря, и все... Ах да! Чуть не забыл... Если вы хотите использовать эти функции в разных программах, то просто киньте RXCPAGE.DLL в какой-нибудь из каталогов, перечисленных в LIBPATH (гуру - простите, но может кто-то этого не знает). Пишите мне, если есть какие-либо вопросы.

Теперь о том как это все делалось... В каталоге \VP10\EXAMPLES\REXX есть пример REXXEXT.PAS. В принципе, там все понятно и без подробных объяснений, для меня, правда, остался невыясненным вопрос как поступать с пропущенными параметрами в середине вызова - может кто и подскажет попозже. В общем так... Для создания библиотеки необходимо подключить модуль Os2Rexx - там содержатся описания структур передачи данных и функция регистрации экспортируемых функций. Не забудьте указать директиву $CDecl+ - чтобы все функции имели формат вызова C-style. Заголовок всех экспортируемых функций должен быть одинаковым (за исключением названия, конечно). Все что та или иная функция будет возвращать сохраняется в структуре типа RxString - не забудьте указывать длину возвращаемого значения в этой же структуре.

По сути дела, при написании своей DLL-ки, я просто скопировал этот файл в другой и кое-что там переименовал. Ключевым моментом является собственно использование API'шных функций WinCpTranslateString и WinUpper (импортируемых в модуле Os2PmApi). У меня они используются без всяких дополнительных проверок, но есть и кое-какие грабли. Так например, функция WinCpTranslateString присваивает символам получаемой строки, которых нет в кодировке, в которую надо перевести, код 255 - это может привести к возможным осложнениям (так, например в 1251 буква "я" имеет тоже этот код - благодарите создателя за это).

Вот как теперь выглядит перекодировка на REXX:

/* Small REXX using the REXX functions defined in the RXCPAGE.DLL */

   call RxFuncAdd 'RxCpLoadFuncs', 'RXCPAGE', 'RxCpLoadFuncs'

   call RxCpLoadFuncs

/* RxCpTranslate(source, cpage_source, cpage_dest)

returns "source" string converted from one codepage (cpage_source) to another (cpage_dest)

You can use codepages from C:\LANGUAGE\CODEPAGE directory */

   say RxCpTranslate('This is a test... Это тест...', "866", "1251")

   say RxCpTranslate('This is a test... Это тест...', 866, 878)

/* RxUpCase(source) returns "source" string in upper case using current codepage - replacement for UPPER function */

   say RxUpCase('Hello! Привет!')

   Exit

В заключение хочу сказать, что создание модулей расширения REXX является относительно несложным делом и доступно, в принципе, даже неквалифицированным программистам (себя я отношу именно к ним).