在terminfo参数化字符串

时间:2017-07-29 18:51:16

标签: terminal c++14 ncurses terminfo termcap

我在C ++中为参数化字符串实现了一个解析器(用于为终端指定一些终端功能)。然后我在man page的terminfo:

上遇到了这个% encoding
                                 %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用于bool结果)或字符在堆栈,然后%l encoding表示以下任何一个或不包含:

  • 从堆栈中弹出一个值if a character push 1 onto stackif an integer push #digits_in_that_integer onto the stack

  • (因为%l使用strlenmanpages中编写)从堆栈中弹出一个字符串(弹出一个字符串:保持弹出,直到堆栈为空),并且然后将弹出的字符串长度推回堆栈。

所以,我的问题是%l push strlen(pop)的含义是什么,它在说什么长度?

加分问题:如果是参数化的terminfo字符串(在上面提到的第二个项目符号点中)弹出一个字符串的方法,对吗?

编辑:正如 Thomas Dickey 指出的,现在我指的是this man page of terminfo

1 个答案:

答案 0 :(得分:2)

尽管页面标题为 “Linux联机帮助页” ,但所引用的手册页是Solaris(SVr4),已被X / Open Curses淘汰。两者都没有提供必要的细节; ncurses的解释填写了细节:

  • SVr4(以及X / Open,在不增加清晰度的情况下反刍该信息)表示tparm的参数是“长”。但是一些参数必须是字符串(即char*),以支持标签功能。
  • 在首次记录tparm时,long似乎足以容纳指针(即char*字符串)和{ {1}}不常见。关于“足够大”的假设不一定正确(参见20岁64-Bit Programming Models: Why LP64?中的讨论),但这是对<stdarg.h>的假设。
  • 对于您最感兴趣的平台,假设您有LP64(或LP32)。
  • 当您致电tparm时,ncurses会分析能力字符串,以确定某个特定参数是否会被解释为字符串(是否与tparm%l匹配),每当使用该参数时,它都会提供字符串。
  • ncurses使用堆栈进行一系列操作(请参阅Parameterized Strings中的terminfo manual page)。

实际上,ncurses对能力字符串使用两次传递:

  1. 在第一遍(参见源代码中的_nc_tparm_analyze)中,它会逐步查看字符串以查看哪个参数将被压入堆栈,以及何时看到%s或{{1 },将数组%l中的位置标记为字符串。
  2. 然后在第二遍中,ncurses使用_nc_tparm_internal(由varargs共享 - 和固定长度参数列表函数分别为%stparm)。使用该数组,它知道是将零参数作为数字零处理还是空字符串。参考source-code,如果要求弹出字符串,其中给出了一个数字(或者如果堆栈上没有任何内容),ncurses会传回一个空字符串。
  3. 所有这些都依赖于对p_is_s[]的正确调用,因为没有可移植的方法来确定传递函数的参数数量,实际上他们的类型< / strong>即可。与tiparm不同,编译器没有帮助。但是如果参数列表与能力字符串匹配,ncurses将(可能......)匹配它。 SVr4 curses没有这样做(参见例如tparm.c on illumos-gate)。

    在给定的示例中,tparm

    • ncurses希望将字符串推送到堆栈上,例如,使用printf(在功能字符串后引用%p1%l的第一个参数),以及< / LI>
    • ncurses弹出堆栈中的字符串值,
    • 调用%p1获取其长度和
    • 将该长度(作为数字)推入堆栈。

    堆栈中的数字可用于计算,例如,

    tparm

    通过使用 strlen 格式化数字,向其添加1(将结果推入堆栈),或只是使用(堆栈中没有任何内容)等等。

    要输出字符串及其长度,再次假设该字符串是第一个参数,那么您可以在功能字符串中多次引用它

    %p1%l%{1}%+
    

    输出字符串的长度,冒号( %d )分隔符和字符串本身。 %p1%l%d:%p1%s 的“输出”当然是另一个字符串,打算使用:tparm打印,因为它可能嵌入了padding信息(请参阅Output Functionsterminfo function manual page)。

    为terminfo定义的操作来自SVr4,该版本于1988年正式宣布,但实际上花了几年时间才成为现实。没有为字符串连接或子字符串定义操作;应用程序必须为自己做这样的事情。 terminfo 做什么是对数字进行参数化,并且(不是事后的想法)规定在适当的位置插入字符串。