Terminal `%l`terminfo参数化字符串中的编码 我在C++中为参数化字符串实现了一个解析器(用于指定终端的一些终端能力)。然后我遇到了这个%encoding终端: %l push strlen(pop)

Terminal `%l`terminfo参数化字符串中的编码 我在C++中为参数化字符串实现了一个解析器(用于指定终端的一些终端能力)。然后我遇到了这个%encoding终端: %l push strlen(pop),terminal,c++14,ncurses,terminfo,termcap,Terminal,C++14,Ncurses,Terminfo,Termcap,所以,我的问题是,每当我们将任何东西推到堆栈上时,都会遇到以下任何%编码: %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) %& %|

所以,我的问题是,每当我们将任何东西推到堆栈上时,都会遇到以下任何
%编码

%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)
%p[1-9]按参数推送
%'c'推字符常数c
%{nn}推送十进制常数nn
%l推动斯特伦(流行音乐)
%+ %− %* %/ %m(算术):推送(pop整数2操作pop整数1)
%&%|%^(位运算):推送(pop整数2操作pop整数1)
%=%>%<(逻辑操作):推送(pop integer2操作pop integer1)
%%O(逻辑操作):和,或
%! %~ (一元操作):推送(op pop)
每当遇到这些问题并计算其结果时,当结果即将推送到堆栈上时,则整数(包括bool结果的0或1)或字符将被推送到堆栈上,那么
%l编码
是否意味着以下任何一项或任何一项:

  • 从堆栈中弹出一个值,
    如果字符将1推到堆栈上
    如果整数将该整数中的#位_推到堆栈上

  • (因为
    %l
    是使用
    strlen
    编写的)从堆栈中弹出字符串(要弹出字符串:一直弹出直到堆栈为空),然后将弹出字符串的长度推回堆栈

那么,我的问题是
%l push strlen(pop)
是什么意思,它指的是什么长度?

附加问题:如果是terminfo的参数化字符串(在上面提到的第二个要点中),弹出字符串的方法是否正确


编辑:正如Thomas Dickey所指出的,现在我指的是。

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

  • SVr4(和X/Open,在不增加清晰度的情况下反刍这些信息)表示,的参数是“长的”。但是一些参数必须是字符串(即,
    char*
    ),以支持标签功能
  • tparm
    首次被记录时,
    long
    似乎足够大,可以容纳一个指针(即
    char*
    ,一个字符串),并且
    不是常见的做法。关于“足够大”的假设不一定正确(见20岁时的讨论),但这是为
    tparm
    做出的假设
  • 对于您最感兴趣的平台,假设您有LP64(或LP32)
  • 调用
    tparm
    时,ncurses分析功能字符串以确定特定参数是否将被解释为字符串(它是否与
    %l
    %s
    匹配),并且无论何时使用该参数,它都会提供该字符串
  • ncurses为一系列操作使用堆栈(请参阅中的)
实际上,ncurses在功能字符串上使用两次传递:

  • 在第一个过程中(请参见源代码中),它逐步遍历字符串以查看哪个参数将被推送到堆栈上,当它看到
    %l
    %s
    时,将数组中的位置
    p_is_s[]
    标记为字符串
  • 然后在第二步中,ncurses使用(分别由varargs和固定长度的参数列表函数
    tiparm
    和共享)。使用数组,它知道是将零参数处理为数字零还是空字符串。对于,如果要求弹出给定数字的字符串(或者如果堆栈中没有任何内容),ncurses会传回一个空字符串
  • 所有这些都依赖于对
    tparm
    的正确调用,因为没有可移植的方法来确定传递给函数的参数的数量,也没有实际的类型。与
    printf
    不同,编译器没有提供任何帮助。但是,如果参数列表与功能字符串匹配,ncurses将(可能…)与之匹配。SVr4诅咒不会这样做(参见示例)

    在给定示例中,
    %p1%l

    • ncurses期望将字符串推送到堆栈上,例如,使用
      %p1
      (参考能力字符串后
      tparm
      的第一个参数),以及
    • ncurses从堆栈中弹出字符串值
    • 调用strlen以获取其长度和长度
    • 将该长度(作为数字)推送到堆栈上
    堆栈上的数字可用于计算,例如

    %p1%l%{1}%+
    
    若要向其添加1(将结果推送到堆栈上),或仅使用(堆栈上无任何内容),请使用
    %d
    等格式设置数字

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

    %p1%l%d:%p1%s
    
    要输出字符串的长度,请使用冒号(
    )分隔符和字符串本身。
    tparm
    的“输出”当然是另一个字符串,打算使用
    putp
    tputs
    打印,因为它可能包含嵌入式信息(请参见中的)


    为terminfo定义的操作来自SVr4,该操作于1988年正式宣布,但在实践中,它花了几年时间才成为现实。没有为字符串连接或子字符串定义任何操作;应用程序必须自己做这类事情。terminfo所做的是将数字参数化,并(不是事后才想到)在适当的位置插入字符串。

    谢谢你的回答,现在我是了