четверг, 7 апреля 2016 г.

Cache': О непечатном

Как посмотреть что именно содержится в строке если команда write выводит какие-то непонятные непечатные символы?

Вопрос о просмотре значений строк далеко не праздный если для их получения использовались непечатные символы, которые не могут быть отображены напрямую на экране. Такие строки обычно получаются с использованием функций $char(), $zhex() и $listXXX(). Зачастую программисты используют один или больше разделителей относящихся к непечатным символам, например $c(1), $c(2), и так далее, чтобы не мешать обычным символам которые вводит пользователь.

В каше есть несколько способов увидеть содержание строк в привычном программисту виде. Первый - это использование системной встроенной команды zzdump или использование аналогичной ей написанной самостоятельно утилиты.

Команда zzdump выводит шестнадцатеричное представление строки в классическом общепринятом в среде программистов виде - с разбиением на колонки, с нумерацией строк и с приведением печатного представления или его печатной замены. Например первые строки дампа байткода рутины %DO:
>zzdump ^rOBJ("%DO")

0000: 94 1D 38 B6 37 1A 3B 42 01 00 0A 00 00 20 B4 02  ”.8¶7.;B..... ґ.
0010: B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  °°°°°°°°°°°°°°°°
0020: C1 11 AA 02 55 F2 03 FF A9 00 B0 B0 12 EA B0 81  Б.Є.Uт.я©.°°.к°Ѓ
0030: 21 06 13 FF 50 32 99 20 B8 B0 12 EA B0 81 21 02  !..яP2™ ё°.к°Ѓ!.
0040: 13 FF 50 32 99 20 B8 B0 12 EA 81 21 FF 50 12 99  .яP2™ ё°.кЃ!яP.™
0050: 22 89 22 98 23 8A 22 66 2F 02 3E 98 24 81 21 03  "‰"˜#Љ"f/.>˜$Ѓ!.
0060: FF 50 22 3E 98 25 B8 B0 AB 20 9B 22 21 89 22 01  яP">˜%ё°« ".
0070: 42 F1 03 9A 20 B8 B0 89 22 0C 9A 55 43 F1 05 89  Bс.љ ё°‰".љUCс.‰
0080: 22 48 98 22 B0 89 22 49 0C B5 05 4D 98 26 89 22  "H˜"°‰"I.µ.M˜&‰"
В большинстве случаев эта команда работает достаточно приемлемо, за исключением некоторых, когда не может дать печатного представления для какого-либо символа или терминал отображающий некоторый символ реагирует на него как на управляющий. Например при дампе байткода рутины %DATE:
>zzdump ^rOBJ("%DATE")

0000: B2 55 53 E2 34 1A 3B 42 01 00 0A 00 00 20 F8 05  ІUSв4.;B..... ш.
0010: B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  °°°°°°°°°°°°°°°°
0020: B0 B0 BD 26 44 61 74 65 3A 20 BE FF BD 90 20 85  °°Ѕ&Date: ѕяЅ

0030: 20 F1 05 AB 20 94 21 B8 B0 8A 20 21 3F 6E F1 06  с.« ”!ё°Љ !?nс.
0040: D5 F9 00 D4 20 00 B0 D5 59 00 AB 20 89 21 10 42  Хщ.Ф .°ХY.« ‰!.B
выводится неверный перенос строки и не дается печатного представления для нескольких байт.

Для компенсации погрешности лучше всего использовать либо самодельную функцию дампа, которую несложно написать используя функцию $zhex(), например. Кто хочет сделать также свой вариант такой функции - можете прислать, я размещу его на этой странице.
Или выводить, что много лучше, дампы во внешние файлы. Например
s dev="c:\temp\dump\date.dmp"
o dev:("WSN")
u dev
zzdump ^rOBJ("%DATE")
u 0
c dev
В этом случае мы не только можем полностью видеть корректный дамп, но и просматривать длинные дампы, использовать поиск.

Второй способ, довольно оригинальный и зачастую намного более читабельный и понимаемый программистом, это использование функции $$Quote^%cspQuote(expression) Она отличается тем, что выдает представление значения которое мог бы использовать программист в программе чтобы получить эту строку. Рассмотрим некоторые особенности функции.

Если аргумент - строка являющаяся каноническим представлением числа, то результат есть аргумент без изменений:
>w $$Quote^%cspQuote("123")
123
>w $$Quote^%cspQuote("123.12")
123.12
Если аргумент - строка являющаяся неканоническим представлением числа или любая другая, то в результат получаем строку взятую в кавычки:
>w $$Quote^%cspQuote("00123.12")
"00123.12"
>w $$Quote^%cspQuote("abcd")
"abcd"
Если в строке аргумента содержатся двойные кавычки, то они удваиваются с тем, чтобы получить в результате строку синтаксически корректную с точки зрения М:
w $$Quote^%cspQuote("ab ""123"" cd")
"ab ""123"" cd"
Если аргумент состоит только из непечатных символов, то в результате получаем строку, синтаксическую конструкцию в виде функции $char(), которую можно использовать в программе чтобы получить это строку:
>w $$Quote^%cspQuote($c(1,2,3,12,13,14))
$c(1,2,3,12,13,14)
Если аргумент состоит как из печатных, так и из непечатных символов, то в результат выводится синтаксическая конструкция М с использованием функции $char(), строк и оператора конкатенации, где в строках производится удвоение кавычек:
>w $$Quote^%cspQuote($lb("123",123))
$c(5,1)_"123"_$c(3,4)_"{"
>w $$Quote^%cspQuote($lb("123",123,"aa ""111"" bb"))
$c(5,1)_"123"_$c(3,4)_"{"_$c(13,1)_"aa ""111"" bb"
Фактически, результат этой функции используется в кодогенерации CSP страниц, в которых генерируется код на М и он должен корректно представить строку в виде М операций. Также, используя эту функцию, можно построить утилиту, генерирующую тело рутины которая может при исполнении создать заданную глобаль в требуемом виде. Стоит при этом обратить внимание на то, что непечатные символы в реальных глобалах могут встретиться также в значениях индексов ключей, что размер рутины должен быть ограничен и что генерируемая строка должна быть меньше 32 килобайт, хотя данные по которым она должна быть сгенерирована сами могут быть до 32 килобайт. Кто хочет сделать также свой вариант такой функции - можете прислать, я размещу его на этой странице. 

Комментариев нет:

Отправить комментарий