8

有人知道m4除了 autoconf 之外的任何用途(最好在 ac 或 c++ 环境中),这不仅仅是一个学术练习,因为它有助于解决一个本来很难解决的问题(例如使用“标准”预处理器) .

我问这个是因为我正在考虑用 C++ 做一个项目的方法,我想通过使用脚本、预处理器等来减少或最小化冗余。

4

9 回答 9

5

GNU Bison 在内部使用它来生成 C 或 C++ 解析器文件。

于 2011-02-18T18:27:42.663 回答
5

我曾经使用 m4 从包含简单版本字符串 (MAJOR.MINOR.MICRO-STATUS) 的文本文件生成 C++ 头文件,以及来自 subversion 的信息,用于 Windows Visual Studio 项目。

m4 是我可以轻松嵌入并用于此特定目标的最小宏引擎。

它看起来像这样:

#ifndef __VERSION_H__
#define __VERSION_H__
divert(-1)
define(`CPP_DEFINE', `#define $1 $2')
define(`VERSION', include(`version.txt'))
define(`MY_SOFTWARE_MAJOR', regexp(VERSION, `\([0-9]+\)\.[0-9]+\.[0-9]+', `\1'))
define(`MY_SOFTWARE_MINOR', regexp(VERSION, `[0-9]+\.\([0-9]\)+\.[0-9]+', `\1'))
define(`MY_SOFTWARE_MICRO', regexp(VERSION, `[0-9]+\.[0-9]+\.\([0-9]\)+', `\1'))
define(`MY_SOFTWARE_STATUS', regexp(VERSION, `\(-\w+\)', `\1'))
define(`SVN_REV', `regexp(esyscmd(svnversion -n), `[0-9]+', `\&')')
ifelse(len(SVN_REV), 0, `define(`NO_SVN')')
divert
CPP_DEFINE(MY_SOFTWARE_VERSION, format(`"%s.%s.%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO))
CPP_DEFINE(PRODUCT_VERSION, format(`"%s.%s.%s%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, MY_SOFTWARE_STATUS))
CPP_DEFINE(COPYRIGHT_NOTICE, `"Copyright (C) 2008 - Me"')
ifdef(`NO_SVN', `
CPP_DEFINE(ABOUT_VERSION, format(`"My Software Version %s.%s.%s%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, MY_SOFTWARE_STATUS))
CPP_DEFINE(FILE_VERSION, format(`"%s.%s.%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO))
CPP_DEFINE(INFO_VERSION, format(``%s,%s,%s,0'', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO))
', `
CPP_DEFINE(ABOUT_VERSION, format(`"My Software Version %s.%s.%s.%s%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, SVN_REV, MY_SOFTWARE_STATUS))
CPP_DEFINE(FILE_VERSION, format(`"%s.%s.%s.%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, SVN_REV))
CPP_DEFINE(INFO_VERSION, format(``%s,%s,%s,%s'', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, SVN_REV))
')
#endif /* __VERSION_H__ */

虽然效果很好,但这确实是一个我没有重复的实验,主要是因为我现在更喜欢使用 CMake 的内置功能来直接处理这些东西并生成我的 Visual Studio 项目文件。

于 2011-02-18T13:22:01.147 回答
4

我曾经用它来生成一段可怕的 SQL 查询。打印出来的查询大约有 20 页——我想大概有 1200 行。我很确定如果没有 m4,我就无法做到这一点,我很庆幸我再也不必这样做了。


(回复评论……)

IIRC(从 30 年前开始),该查询推动了原告的报告。原告按其历史事件的组合进行分类。

SQL 引擎无法在视图上构建视图,并且不支持用户定义的函数。派生表、子选择等的一些长表达式

  • 应该是相同的,但不是,或者
  • 应该有微妙的不同(需要'-'而不是'+',或'shsapnm'而不是'shsgpnm'),但以错误的方式不同。

困难的部分不是编程。

第一个困难的部分是找出三个稍微不同的子选择中的哪一个是正确,或者我们是否真的需要三个不同的子选择,或者我们是否真的需要现有的三个加上一个或两个。(我认为答案最终证明是“以上所有”。)相关报告需要一些相同的子选择;m4 + make 保证它们是相同的。

第二个困难的部分是构建测试数据,可以显示查询在面对所有各种复杂的原告历史时正常工作。我认为 Joe Celko 引导我使用波音当时使用的一些商业软件——它采用了一些用户定义的标准,并为每种可能的组合或排列生成了一个测试工具和存根。我不记得它的名字了。(我认为就是这样:逻辑宝石

于 2011-02-18T14:32:46.930 回答
3

I've used m4 and was impressed by its capabilities, this what C preprocessor should be. I used it to generate GNU makefiles from simpler project descriptions.

于 2011-02-18T13:59:38.230 回答
3

Sendmail 提供了一个基于 M4 的基础架构来生成配置文件。我使用过的大多数 sendmail 安装都提供此作为配置 sendmail 的推荐方法。

于 2011-02-18T15:00:33.417 回答
3

我使用 m4 生成包含结构声明列表的 C/C++ 文件。根据结构的丑陋程度以及如果你做得对,m4 文件可能比 C/C++ 文件更容易阅读和编辑。

于 2011-07-01T20:14:17.067 回答
1

GTK+ 的官方 C++ 绑定库gtkmm - 一个出色的项目,它使 GTK+ GUI 的强大功能和范围可通过更现代的 C++ 访问 -m4用作其工具集的一部分,用于轻松生成包装代码。

(我与任何 G* 项目没有任何关系。我很喜欢gtkmm它,但觉得它并没有它可能/应该有的那么出名,尤其是与某些明显的替代品相比。另外,在m4我研究它之前,我不知道是 K&R这个!整洁。)

于 2016-04-24T12:18:33.803 回答
0

我已经使用 M4 自动生成 DDL 脚本来定义您的 SQL 表、C++ 代码和标题来访问它们,以及驱动程序来测试它。我想我们还更新了脚本以同时备份和重新填充表格,但我这样做已经 15 年多了。

于 2011-02-18T17:13:26.027 回答
0

我同时使用 cpp 和 m4 来替换文件中的标记并为不同的目标平台生成打包文件。现在我将使用 ruby​​ erb 来执行此操作。在 sun 时,我使用 m4 预处理头文件

于 2011-05-05T05:54:58.907 回答