m4 宏使用可变数量的选项卡来排列一列

m4 宏使用可变数量的选项卡来排列一列

这是我到目前为止的宏:

define(`debug_macro', `
#ifndef $1_DEBUG
#define $1_DEBUG'forloop(`i',`1',eval(5-(len($1)/4+ifelse(eval(len($1)%4 == 0)), `0', `1')),`   ')dnl`0
#endif

')

目标是在_DEBUG0字符之间放置正确数量的制表符,以便它们全部对齐。可能缺少括号或引号,但希望您能明白我的意思。

我正在使用 Xcode,并将选项卡设置为 4。以下是我为适应这一点所做的更改:

divert(`-1')
# forloop(var, from, to, stmt)
define(`forloop',
`pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')')
define(`_forloop',
`$4`'ifelse($1, `$3', ,
`define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')
divert`'dnl
changecom()dnl
define(`debug_macro', `
#ifndef $1_DEBUG
#define $1_DEBUG`'forloop(`i', `1', ifelse(eval(len($1) >= 16), 1, 1, eval(5-(len($1)/4+ifelse(eval(len($1)%4 > 1), 0, `0', `1')))),`   ')0
#endif

')
changecom()dnl

由于我在系统上找不到“forloop.m4”,所以我只是将其包含在内。除以 4 轮,因此我添加了余数大于 1 时的检查。我还更改了单个制表符的空格运行。

对于感兴趣的人,我使用这个宏来定义常量,我用它来打开应用程序不同区域的调试。该文件已签入 git。然后有一个未签入的个人文件,如下所示:

//#define NETWORK_DEBUG  1

该文件在包含上述文件之前包含在 myapp.pch 文件中。这样每个程序员都可以根据自己的喜好打开或关闭自己的调试区域。

答案1

缩进最简单的方法是使用空格,而不是制表符。尤其是非标准宽度的选项卡(只要选项卡有标准宽度,它就是 8)。

使用制表符缩进的第二个最简单的方法是生成一个包含空格的文件并调用unexpand用制表符替换空格。

话虽这么说,您可以在 m4 中做到这一点,但您必须更加熟悉它。逐步构建您的表达式:让一件作品发挥作用,然后继续下一件。

forloop不是标准的 m4 宏。我想你的意思是forloopGNU m4 手册中介绍的宏。这是 GNU m4 附带的示例代码(手册没有明确说明);要在您的代码中使用它,您需要明确包含它。发行版可能会或可能不会附带它,因此您最好将其与您的代码一起分发。

您的代码中存在几个语法问题。

  • 您已将调用留forloop在任何引号之外,因此它是在评估时评估的define,而不是在评估时debug_macro评估的。
  • ifelse宏不会仅根据第一个参数的值进行选择,而是比较其前两个参数 - 它更像是一个 case 宏:调用应该是ifelse(…, 0, 0, 1)or ifelse(… == 0, 1, 0, 1)
  • #开始发表评论。 M4 会忽略评论后的所有内容。更改评论分隔符当您定义debug_macro宏时。

只要参数不太长,以下代码就可以工作:

include(`/usr/share/doc/m4/examples/forloop.m4')dnl
changecom()dnl
define(`debug_macro', `
#ifndef $1_DEBUG
#define $1_DEBUG`'forloop(`i',`1',eval(5-(len($1)/4+ifelse(eval(len($1)%4), 0, `0', `1'))),`    ')0
#endif

')dnl
changecom('#')dnl

如果参数使最大循环索引变为0或更小,则循环执行约2 32次(m4 使用32 位模运算)。在这种情况下,您需要进行额外的测试。下面的代码在参数太长时插入单个制表符。

include(`/usr/share/doc/m4/examples/forloop.m4')dnl
changecom()dnl
define(`debug_macro', `
#ifndef $1_DEBUG
#define $1_DEBUG`'forloop(`i', `1', ifelse(eval(len($1) >= 16), 1, 1, eval(5-(len($1)/4+ifelse(eval(len($1)%4), 0, `0', `1')))),`       ')0
#endif

')dnl
changecom('#')dnl

相关内容