简体   繁体   English

terminfo参数化字符串中的`%l`编码

[英]`%l` encoding in terminfo parameterized strings

I am implementing a parser in C++ for parameterized strings(which are used for specifying some terminal capabilities for a terminal). 我在C ++中为参数化的字符串(用于指定终端的某些终端功能)实现一个解析器。 Then I came across this % encoding on the man page of terminfo: 然后我在terminfo的手册页上遇到了这种% encoding

                                 %l   push strlen(pop)

So, my question is, that whenever we are pushing anything onto the stack, it is when any these following % encodings are encountered: 因此,我的问题是,每当我们将任何内容压入堆栈时,就是遇到以下任何% 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)

And whenever these are encountered and their results are computed and when the results are about to be pushed onto the stack, then either an integer(including 0 or 1 for bool results) or a character are going to be pushed onto the stack , then does %l encoding mean any or none of the following: 并且每当遇到这些错误并计算它们的结果以及将结果推入堆栈时, 则将整数(对于bool结果包括0或1)或一个字符都将推入堆栈 ,然后执行%l encoding表示以下任何一项或全部都不是:

  • pop a single value from the stack and if a character push 1 onto stack and if an integer push #digits_in_that_integer onto the stack . 从堆栈中弹出一个值, if a character push 1 onto stackif an integer push #digits_in_that_integer onto the stack

  • (since %l is written in manpages using strlen ) pop a string from the stack (to pop a string: keep popping untill the stack is empty), and then push back the length of popped string onto the stack. (因为%l是使用strlen手册页中编写的),从堆栈中弹出一个字符串(以弹出字符串:一直弹出直到堆栈为空),然后将弹出的字符串的长度推回堆栈中。

So, my question is what does %l push strlen(pop) mean, which length is it talking about ? 所以,我的问题是%l push strlen(pop)是什么意思,它在说什么长度?

Bonus question: Is the way to pop a string in case of parameterized strings of terminfo (in the 2nd bullet point mentioned above), correct ? 额外的问题:在terminfo的参数化字符串(在上述第二个要点中)的情况下,弹出字符串的方法正确吗?

Edit: As pointed by Thomas Dickey , now I am referring to this man page of terminfo . 编辑:正如Thomas Dickey指出的那样,现在我指的是terminfo的手册页

Notwithstanding the page title "Linux Manpages Online" , the manual page referred to is Solaris (SVr4), which was obsoleted by X/Open Curses. 尽管页面标题为“ Linux在线联机手册 ,但所指的手册页是Solaris(SVr4),它已被X / Open Curses淘汰。 Neither gives the necessary details; 没有给出必要的细节; ncurses' interpretation fills in the details: ncurses的解释填写了以下详细信息:

  • SVr4 (and X/Open, which regurgitates that information without adding clarity) says that the parameters for tparm are "long". SVr4(和X / Open,在不增加清晰度的情况下重新提供信息)表示tparm的参数很长。 But some of the parameters have to be strings (ie, char* ), to support the label capabilities. 但是某些参数必须是字符串(即char* )才能支持标签功能。
  • at the time that tparm was first documented, long seemed big enough to hold a pointer (ie, char* , a string ), and <stdarg.h> was not common practice. 在首次记录tparm时, long似乎足够大以容纳指针(即char*string ),并且<stdarg.h>并不常见。 That assumption about "big enough" isn't necessarily true (see the discussion in the 20-year-old 64-Bit Programming Models: Why LP64? ), but it's the assumption made for tparm . 关于“足够大”的假设不一定正确(请参阅20年历史的64位编程模型中的讨论:为什么选择LP64? ),但这是对tparm所做的假设。
  • for the platforms you're most interested in, assume you have LP64 (or LP32). 对于您最感兴趣的平台,假定您具有LP64(或LP32)。
  • when you call tparm , ncurses analyzes the capability string to determine whether a particular parameter is going to be interpreted as a string (whether it matches up with %l or %s ), and whenever that parameter is used, it provides the string. 当您调用tparm ,ncurses会分析功能字符串,以确定某个特定参数是否将被解释为字符串(无论它与%l还是%s匹配),并且无论何时使用该参数,它都会提供该字符串。
  • ncurses uses a stack for the series of operations (refer to Parameterized Strings in the terminfo manual page ). ncurses使用堆栈进行一系列操作(请参阅terminfo手册页中的参数化字符串 )。

Actually, ncurses uses two passes over the capability string: 实际上,ncurses在功能字符串上使用两次传递:

  1. In the first pass (see _nc_tparm_analyze in source-code), it steps through the string to see which parameter would be pushed onto the stack, and when it sees a %l or %s , marks that position in an array p_is_s[] as a string. 在第一遍中(请参见源代码中的_nc_tparm_analyze ),它逐步遍历字符串以查看将哪个参数压入堆栈,并在看到%l%s时将其在数组p_is_s[]中的位置标记为一个字符串。
  2. Then in the second pass, ncurses uses _nc_tparm_internal (shared by varargs- and a fixed-length argument list functions tiparm and tparm , respectively). 然后在第二遍中,ncurses使用_nc_tparm_internal (分别由varargs-和定长参数列表函数tiparmtparm )。 Using the array, it knows whether to handle a zero-parameter as a numeric zero, or an empty string. 使用数组,它知道是将零参数处理为数字零还是将空字符串处理。 Referring to the source-code , if asked to pop a string where a number was given (or if nothing remains on the stack), ncurses passes back an empty string. 参考源代码 ,如果要求弹出一个给出了数字的字符串 (或者堆栈上没有剩余内容),则ncurses传回一个空字符串。

All of that relies upon a correct call to tparm , since there is no portable way to determine the number of parameters passed to a function, nor actually their types . 所有这些都依赖于对tparm的正确调用,因为没有可移植的方法来确定传递函数的参数的数量,也不能确定它们的类型 Unlike printf , there is no help from the compiler. printf不同,编译器没有帮助。 But if the parameter list matches the capability string, ncurses will (probably...) match it. 但是,如果参数列表与功能字符串匹配,则ncurses将(可能...)与之匹配。 SVr4 curses does not do this (see for example tparm.c on illumos-gate ). SVr4 curses不会这样做(例如,请参见illumos-gate上的tparm.c )。

In the given example, %p1%l 在给定的示例中, %p1%l

  • ncurses expects that a string was pushed onto the stack, eg, using %p1 (to refer to the first parameter of tparm after the capability string), and ncurses期望将字符串压入堆栈,例如,使用%p1 (以引用功能字符串之后的tparm的第一个参数),并且
  • ncurses pops the string value off the stack, ncurses将字符串值弹出堆栈,
  • calls strlen to get its length and 调用strlen以获取其长度,
  • pushes that length (as a number) onto the stack. 将长度(作为数字)压入堆栈。

That number on the stack can be used in a calculation, eg, 堆栈中的该数字可用于计算,例如,

%p1%l%{1}%+

to add 1 to it (pushing the result onto the stack), or just used (nothing on the stack) by formatting a number with %d , etc. 向其添加1(将结果推入堆栈),或通过使用%d格式化数字等方式使用 (堆栈中什么都没有)。

To output a string and its length, again suppose the string is the first parameter, then you can refer to it more than once in the capability string like this 要输出一个字符串及其长度,再次假设该字符串是第一个参数,那么您可以在功能字符串中多次引用它,如下所示

%p1%l%d:%p1%s

to output a string's length, a colon ( : ) separator and the string itself. 以输出字符串的长度,冒号( : )分离器和字符串本身。 The "output" of tparm is of course another string, intended to be printed using putp or tputs because it may have embedded padding information (see Output Functions in the terminfo function manual page ). 所述的“输出” tparm当然另一个字符串,意在使用被打印的putptputs ,因为它可以具有嵌入填充信息(参见输出功能的terminfo函数手册页 )。

The operations defined for terminfo came from SVr4, which was officially announced in 1988, though in practice it took several years to become an actuality. 为terminfo定义的操作来自SVr4,该SVr4于1988年正式宣布,尽管实际上它花了几年时间才成为现实。 There are no operations defined for string concatenation or substrings; 没有为字符串连接或子字符串定义任何操作; applications have to do that sort of thing for themselves. 应用程序必须自己做这种事情。 What terminfo does is to parameterize the numbers, and (not quite as an afterthought) provide for inserting strings in appropriate places. terminfo的作用是对数字进行参数化,并且(不完全是事后的想法)可以在适当的位置插入字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM