GNU M4 笔记
博客专区 > ReJaVu 的博客 > 博客详情
GNU M4 笔记
ReJaVu 发表于4年前
GNU M4 笔记
  • 发表于 4年前
  • 阅读 2550
  • 收藏 8
  • 点赞 1
  • 评论 1

新睿云服务器60天免费使用,快来体验!>>>   

摘要: 简短的 M4 笔记,详细参看官方手册:https://www.gnu.org/software/m4/manual/m4.html

认识 GNU M4

m4 是个宏处理器,像 C 语言的宏一样,用来替换文本。

在终端上输入 m4 [文件名] ,这时候 m4 读取文件,然后输出结果。 如果不指定文件名,就将标准输入作为指令。

为了方便演示,在代码块里面,没有“=>”的是输入,有“=>”的是输出。现在打开 m4,输入

	hello world
	=>hello world

在这里输出的结果和输入一样。接着我们定义宏 hello,

	define(`hello',`hi')
	=>
	hello world
	=>hi world

可见 hello 已经被替换成 hi 了。define 是 m4 的内置宏,它用来定义一个宏。 这里将 hello 定义成 hi,在输入 hello world 的时候就进行了宏调用。 如果想阻止调用,可以使用引用(quoting):

	define(`hello',`hi')
	=>
	`hello' world
	=>hello world
	``hello'' world
	=>`hello' world

使用一对“`'”将字符引用之后 m4 就不会试图对它进行替换,仅仅看作是字符串。 空的引用“`'”表现出来的是 null string。顾名思义,null string 不包含任何字符。

m4 将 null string、空格、新行和其它一些特殊符号(除了下划线“_”、左括号“(”、“ ` ”字符)之间的词分割成 token。默认地,m4 原封不动地输出字符串(以“`'”括起)、特殊字符和注释,并试图查找该 token 是否是定义过的宏,如果没有定义过就照样输出,否则进行宏展开。所以,

	hello world
	=>hello world <-- “hello”和“world”都没定义过,按原来输出
	define(`hello',`hi') <-- 定义宏 hello
	=>
	hello world
	=>hi world <-- hello 已定义,展开
	helloworld
	=>helloworld <-- helloworld 未定义,按原来输出
	hello`'world
	=>hiworld <-- 空字符串“`'” 类似空格可以分割 token,注意这里两个词之间没空格
	he`'llo
	=>hello <-- he  和 llo 未定义,按原来输出,null string 不占空间
	`hello' world
	=>hello world <-- 引用为字符串,不展开

m4 展开一个宏之后,还会再检查展开后的输出是宏与否,并反复如此:

	define(`hello',`hi')
	=>
	define(`hi',`你好')
	hello world
	=>你好 world

一个死循环 :)

	define(`hello',`this is hello')
	hello world

接着来看 define 这个内置宏,

	define(`hello',`hi')
	=>

在这里调用了 define,紧随其后在括号里用逗号分开是给它的两个参数。第一个参数是宏名,第二个是展开体。 默认地,define 宏输出一个新行,如果想要删除一个新行,可以在 define 后面添加 dnl 宏,dnl 表示 delete new line,也是一个内置宏。

自定义的宏可以使用$1,$2 ... $n 引用参数:

	define(`echo',`$1 $2')
	=>
	echo(para1)
	=>para1 
	echo(para1,para2)
	=>para1 para2

对宏的参数使用引用(quote)可以控制是否展开参数。来看 GNU M4 官方手册上的一个例子:

	define(`active', `ACT, IVE')
	=>
	define(`show', `$1 $1')
	=>
	show(active)
	=>ACT ACT
	show(`active')
	=>ACT, IVE ACT, IVE
	show(``active'')
	=>active active

根据手册上的说法,当宏的参数没有引用一层的时候,在宏展开前先尝试展开参数;引用一层时,在宏展开之后展开参数;引用两层时不展开。

结合上面的例子,

	define(`active', `ACT, IVE')
	=>
	define(`show', `$1 $1')
	=>
	show(active) --> show(ACT,IVE)
	=>ACT ACT
	show(`active') --> active active
	=>ACT, IVE ACT, IVE
	show(``active'') --> `active' `active'
	=>active active

另外我发现,对于 define 宏的第一个参数如果不加引用会:

	define(a,`b')
	=>
	a
	=>b
	define(a,`c')
	=>
	a
	=>c
	b
	=>c

如果加了两层引用我找不到宏名是什么:

	define(``a'',`b')
	=>
	a
	=>a
	`a'
	=>a
	``a''
	=>`a'

所以,define 的第一个参数还是别用两层引用吧。

标签: m4 m4 入门 m4 教程
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 2
博文 4
码字总数 4487
评论 (1)
王洪敏
我来和楼主交流下文章最后一个疑问

define(``a'',`b')
defn(``a'')
即可
×
ReJaVu
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: