文档章节

GNU M4 笔记

R
 ReJaVu
发布于 2013/12/15 09:14
字数 892
阅读 2854
收藏 8

认识 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 的第一个参数还是别用两层引用吧。

© 著作权归作者所有

共有 人打赏支持
R
粉丝 2
博文 4
码字总数 3906
作品 0
益阳
程序员
私信 提问
加载中

评论(1)

王洪敏
王洪敏
我来和楼主交流下文章最后一个疑问

define(``a'',`b')
defn(``a'')
即可
详解linux下auto工具制作Makefile源码包(工具安装篇)

详解linux下auto工具制作Makefile源码包(工具安装篇) 水木杨 一、引子 最近学习安装源码包,然后公司开发也需要制作源码包,所以就稍微学习了一下automake与autoconf制作configure以及Mak...

慎道
2011/07/14
0
0
php为redis创造编译环境出错解决办法

执行/usr/local/webserver/php/bin/phpize时出现错误:Configuring for: PHP Api Version: 20041225 Zend Module Api No: 20060613 Zend Extension Api No: 220060519 Cannot find autoconf.......

山鹰sniper
2014/07/17
0
0
cmake ..这一步就报错,m4,autoconf和automake都安装了啊

make: *** [aclocal.m4] 错误 127 CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /app/bin/QConf/deps/gdbm/build-aux/missing aclocal-1.14 -I m4 /app/bin/QConf/deps/gdbm/build-aux/m......

GreatQing
2015/11/06
2.6K
0
PHP动态编译出现Cannot find autoconf

在安装完PHP后,想动态编译PHP的memcache扩展库 cd memcache-2.2.5/ /usr/local/webserver/php/bin/phpize ./configure --with-php-config=/usr/local/webserver/php/bin/php-config 但是执行......

晨曦之光
2012/03/09
820
0
gnu m4 和 m4 有什么区别呢?

gnu m4 和 m4 有什么区别呢?在/usr/bin下有gm4和m4,两个文件大小相同。

RickHuang
2011/08/24
1K
2

没有更多内容

加载失败,请刷新页面

加载更多

Linux 权限

权限 0 000 --- 无权限 1 001 --x 执行权限 2 010 -w- 写权限 3 011 -wx 写和执行 4 100 r-- 读权限 5 101 r-x 读和执行 6 110 rw- 读和写 7 111 rwx 读写执行 755 : rwxr-xr-x 660 : rw-r...

忙碌的小蜜蜂
17分钟前
0
0
21分钟教会你分析MaxCompute账单

21分钟教会你分析MaxCompute账单 背景 阿里云大计算服务MaxCompute是一款商业化的大数据分析平台,其计算资源有预付费和后付费两种计费方式。并且产品每天按照project为维度进行计量计费(账...

阿里云云栖社区
20分钟前
0
0
Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践

本文使用 HTTP 和 DNS 两种校验方式对 Docker 下 linuxserver/letsencrypt 项目进行了实践。生成SpringBoot可用证书,使用 Nginx 的 htpasswd 来对网站进行密码保护,并测试使用 fail2ban 防...

java菜分享
21分钟前
0
0
代码吃鸡:Python-Robocode

最近看到一个很有“未来感”的新闻: 一辆特斯拉在拉斯维加斯出了车祸,撞“死”了一个……emmmm……机器人。不知道是意外还是炒作,又或者是这位机器人故意碰瓷,反正人们也无法从受害者口中...

crossin
25分钟前
0
0
什么是公网IP、内网IP和NAT转换?

搞网络通信应用开发的程序员,可能会经常听到外网IP(即互联网IP地址)和内网IP(即局域网IP地址),但他们的区别是什么? 1、引言 搞网络通信应用开发的程序员,可能会经常听到外网IP(即互联网I...

Linux就该这么学
35分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部