文档章节

GNU M4 笔记

R
 ReJaVu
发布于 2013/12/15 09:14
字数 892
阅读 2736
收藏 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
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.1K
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
773
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
GNU M4 1.4.17 发布,Unix 宏处理器

GNU M4 1.4.17 发布,此版本更新内容如下: 修复了更新的 glibc 头; 解决了 mingw 转移大量文本的问题 改进了几个 gnulib 应用的可移植性 GNU M4 是一个实现了传统 Unix 的宏处理器,大部分...

oschina
2014/01/13
646
0

没有更多内容

加载失败,请刷新页面

加载更多

cmd中查询mysql表出现中文乱码

问题:在pycharm中正常的fetchall拉取数据,能够正常显示,而在cmd中直接select却出现中文乱码。 解决思路:右键查看cmd命令窗口属性得到,cmd窗口默认编码是gbk(如下图所示),而设置的mys...

fang_faye
10分钟前
0
0
centOS 安装Python3与python2并存

centOS 安装Python3与python2并存 如果本机安装了python2,尽量不要管他,使用python3运行python脚本就好,因为可能有程序依赖目前的python2环境, 比如yum!!!!! 不要动现有的python2环...

MedivhXu
36分钟前
1
0
Spring JdbcTemplate模板模式与回调结合分析

在看Spring的JdbcTemplate的时候,看到其将模板模式和回调模式结合使用的实现,可以精妙的解决很多的问题。详见Spring中涉及的设计模式总结中的关于模板模式和回调模式结合的具分析,本文利用...

宸明
今天
1
0
docker update:更新一个或多个容器的配置

更新容器的配置 docker update:更新一个或多个容器的配置。 具体内容请访问:https://docs.docker.com/engine/reference/commandline/update/#options 语法:docker update [OPTIONS] CONTA...

lwenhao
今天
3
0
unload事件

unload事件不触发的原因分析 1.代码位置不对,应该优先加载,不能放到回调函数中 2.浏览器不支持 3.最可能的原因,unload事件中触发的函数是一个异步执行的函数,浏览器是不允许在窗口关闭之后在...

狮子狗
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部