Кодирование `%l` в параметризованных строках terminfo

Я реализую парсер на С++ для параметризованных строк (которые используются для указания некоторых возможностей терминала для терминала). Затем я наткнулся на это % encoding на справочной странице terminfo:

                                 %l   push strlen(pop)

Итак, мой вопрос заключается в том, что всякий раз, когда мы помещаем что-либо в стек, это происходит, когда встречаются следующие % encodings:

%p[1-9]        push ith parm
%’c’           push char constant c
%{nn}          push decimal constant nn
%l             push strlen(pop)
%+ %− %* %/ %m (arithmetic):   push(pop integer2 op pop integer1)
%& %| %^ (bit operations):     push(pop integer2 op pop integer1)
%= %> %< (logical operations): push(pop integer2 op pop integer1)
%A %O (logical operations):    and, or
%! %~ (unary operations):      push(op pop)

И всякий раз, когда они встречаются и их результаты вычисляются, и когда результаты должны быть помещены в стек, тогда либо целое число (включая 0 или 1 для логических результатов), либо символ будут помещены в стек. , то означает ли %l encoding что-либо из следующего:

  • извлечь одно значение из стека и if a character push 1 onto stack и if an integer push #digits_in_that_integer onto the stack.

  • (поскольку %l написано в справочных страницах с использованием strlen) извлечь строку из стека (чтобы извлечь строку : продолжайте выталкивать до тех пор, пока стек не станет пустым), а затем поместите длину извлеченной строки обратно в стек.

Итак, мой вопрос: что означает %l push strlen(pop), о какой длине идет речь?

Дополнительный вопрос: правильный ли способ извлечения строки в случае параметризованных строк terminfo (во втором пункте, упомянутом выше)?

Изменить: как указал Томас Дики, теперь я имею в виду этого человека страница термининформации.


person tkhurana96    schedule 29.07.2017    source источник


Ответы (1)


Несмотря на название страницы "Linux Manpages Online", упомянутая страница руководства относится к Solaris (SVr4), которая устарела благодаря X/Open Curses. Ни один из них не дает необходимых деталей; Интерпретация ncurses уточняет детали:

  • SVr4 (и X/Open, который повторяет эту информацию, не добавляя ясности) говорит, что параметры для tparm являются "длинными". Но некоторые параметры должны быть строками (например, char*), чтобы поддерживать возможности меток.
  • в то время, когда tparm был впервые задокументирован, long казалось достаточно большим, чтобы содержать указатель (т. е. char*, строку), а <stdarg.h> не было обычной практикой. Это предположение о «достаточно большом» не обязательно верно (см. noreferrer">64-битные модели программирования: почему LP64?), но это предположение сделано для tparm.
  • для платформ, которые вас больше всего интересуют, предположим, что у вас есть LP64 (или LP32).
  • когда вы вызываете tparm, ncurses анализирует строку возможностей, чтобы определить, будет ли конкретный параметр интерпретироваться как строка (соответствует ли он %l или %s), и всякий раз, когда этот параметр используется, он предоставляет строку.
  • ncurses использует стек для серии операций (см. Параметризованные строки в terminfo справочная страница).

На самом деле, ncurses использует два прохода по строке возможностей:

  1. При первом проходе (см. _nc_tparm_analyze в исходном коде), он проходит через строку, чтобы увидеть, какой параметр будет помещен в стек, и когда он видит %l или %s, помечает эту позицию в массиве p_is_s[] как строку.
  2. Затем во втором проходе ncurses использует _nc_tparm_internal< /a> (совместно используется функциями varargs и списка аргументов фиксированной длины tiparm и tparm соответственно). Используя массив, он знает, следует ли обрабатывать нулевой параметр как числовой ноль или как пустую строку. Ссылаясь на исходный код , если его просят извлечь строку, где было задано число (или если в стеке ничего не осталось), ncurses возвращает пустую строку.

Все это зависит от правильного вызова tparm, поскольку нет переносимого способа определить количество параметров, переданных в функцию, а также их типы. В отличие от printf здесь нет помощи от компилятора. Но если список параметров соответствует строке возможностей, ncurses (вероятно...) будет соответствовать ей. Проклятия SVr4 этого не делают (см., например, tparm.c на illumos-gate).

В данном примере %p1%l

  • ncurses ожидает, что строка была помещена в стек, например, используя %p1 (для ссылки на первый параметр tparm после строки возможностей), и
  • ncurses извлекает строковое значение из стека,
  • вызывает strlen, чтобы получить его длину и
  • помещает эту длину (как число) в стек.

Это число в стеке можно использовать в вычислениях, например,

%p1%l%{1}%+

добавить к нему 1 (поместить результат в стек) или просто использовать (ничего в стеке) путем форматирования числа с помощью %d и т. д.

Чтобы вывести строку и ее длину, снова предположим, что строка является первым параметром, тогда вы можете ссылаться на нее более одного раза в строке возможностей, подобной этой.

%p1%l%d:%p1%s

для вывода длины строки, двоеточия (:) и самой строки. «Вывод» tparm, конечно же, представляет собой другую строку, предназначенную для печати с использованием putp или tputs, поскольку в нее может быть встроен padding (см. Функции вывода в страница руководства по функциям terminfo).

Операции, определенные для terminfo, пришли из SVr4, который был официально анонсирован в 1988 году, хотя на практике потребовалось несколько лет, чтобы он стал реальностью. Не определены операции для конкатенации строк или подстрок; приложения должны делать такие вещи для себя. Что terminfo делает, так это параметризует числа и (не совсем задним числом) обеспечивает вставку строк в соответствующие места.

person Thomas Dickey    schedule 29.07.2017
comment
спасибо за ответ, теперь я имею в виду эту справочную страницу, было бы здорово если бы вы уточнили, что ncurses анализирует строку возможностей, чтобы определить, будет ли конкретный параметр интерпретироваться как строка (совпадает ли он с %l или %s), и всякий раз, когда этот параметр используется, он предоставляет string с еще одним примером, спасибо :) - person tkhurana96; 30.07.2017
comment
Фактически, эта справочная страница является примером того, как не форматировать справочную страницу, которая Я подробно обсуждал здесь. Я добавил авторитетную ссылку в свой ответ. - person Thomas Dickey; 30.07.2017