我在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 stack
和if an integer push #digits_in_that_integer onto the stack
。
(因为%l
使用strlen
在manpages中编写)从堆栈中弹出一个字符串(弹出一个字符串:保持弹出,直到堆栈为空),并且然后将弹出的字符串长度推回堆栈。
所以,我的问题是%l push strlen(pop)
的含义是什么,它在说什么长度?
加分问题:如果是参数化的terminfo字符串(在上面提到的第二个项目符号点中)弹出一个字符串的方法,对吗?
编辑:正如 Thomas Dickey 指出的,现在我指的是this man page of terminfo。
答案 0 :(得分:2)
尽管页面标题为 “Linux联机帮助页” ,但所引用的手册页是Solaris(SVr4),已被X / Open Curses淘汰。两者都没有提供必要的细节; ncurses的解释填写了细节:
tparm
的参数是“长”。但是一些参数必须是字符串(即char*
),以支持标签功能。tparm
时,long
似乎足以容纳指针(即char*
,字符串)和{ {1}}不常见。关于“足够大”的假设不一定正确(参见20岁64-Bit Programming Models: Why LP64?中的讨论),但这是对<stdarg.h>
的假设。tparm
时,ncurses会分析能力字符串,以确定某个特定参数是否会被解释为字符串(是否与tparm
或%l
匹配),每当使用该参数时,它都会提供字符串。terminfo
manual page)。实际上,ncurses对能力字符串使用两次传递:
_nc_tparm_analyze
)中,它会逐步查看字符串以查看哪个参数将被压入堆栈,以及何时看到%s
或{{1 },将数组%l
中的位置标记为字符串。_nc_tparm_internal
(由varargs共享 - 和固定长度参数列表函数分别为%s
和tparm
)。使用该数组,它知道是将零参数作为数字零处理还是空字符串。参考source-code,如果要求弹出字符串,其中给出了一个数字(或者如果堆栈上没有任何内容),ncurses会传回一个空字符串。所有这些都依赖于对p_is_s[]
的正确调用,因为没有可移植的方法来确定传递到函数的参数数量,实际上他们的类型< / strong>即可。与tiparm
不同,编译器没有帮助。但是如果参数列表与能力字符串匹配,ncurses将(可能......)匹配它。 SVr4 curses没有这样做(参见例如tparm.c
on illumos-gate)。
在给定的示例中,tparm
printf
(在功能字符串后引用%p1%l
的第一个参数),以及< / LI>
%p1
获取其长度和堆栈中的数字可用于计算,例如,
tparm
通过使用 strlen
格式化数字,向其添加1(将结果推入堆栈),或只是使用(堆栈中没有任何内容)等等。
要输出字符串及其长度,再次假设该字符串是第一个参数,那么您可以在功能字符串中多次引用它
%p1%l%{1}%+
输出字符串的长度,冒号( %d
)分隔符和字符串本身。 %p1%l%d:%p1%s
的“输出”当然是另一个字符串,打算使用:
或tparm
打印,因为它可能嵌入了padding信息(请参阅Output Functions在terminfo function manual page)。
为terminfo定义的操作来自SVr4,该版本于1988年正式宣布,但实际上花了几年时间才成为现实。没有为字符串连接或子字符串定义操作;应用程序必须为自己做这样的事情。 terminfo 做什么是对数字进行参数化,并且(不是事后的想法)规定在适当的位置插入字符串。