【问题标题】:Are there noteworthy uses of m4 besides autoconf? [closed]除了 autoconf 之外,m4 还有什么值得注意的用途吗? [关闭]
【发布时间】:2011-02-18 12:53:21
【问题描述】:

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

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

【问题讨论】:

  • 它曾经(也许现在仍然是)用于 sendmail 配置文件。这可能是反对 M4 和 sendmail 的论据。

标签: c++ c preprocessor autoconf m4


【解决方案1】:

我曾经使用 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 项目文件。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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


      (回复评论……)

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

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

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

      困难的部分不是编程。

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

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

      【讨论】:

      • 恐怖!是说查询可以用凡人的话来概括的东西吗? ;-)
      • @underscore_d:不在评论中,但我扩展了答案。
      • 真是个故事!如果可以的话,我会再次 +1。谢谢!将来我将不得不更多地考虑m4make;我敢打赌,我使用电子表格和公式来生成批处理文件、SQL 脚本、重复的 C++ 片段(其中它自己的宏不太符合要求)等等可能会更好地服务于某些东西更像这样。尽管如此,它绝对是 IMO 电子表格的唯一有效用途之一,呵呵。
      • @underscore_d youtube.com/watch?v=RkGUowLRF5s ,或者总结一下,“可以想象的最可怕的查询”。这就是真正要说的,“可以想象的最可怕的查询”:)
      【解决方案4】:

      我使用过m4,对其功能印象深刻,这就是 C 预处理器应该具备的功能。我用它从更简单的项目描述中生成 GNU makefile。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

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

            (我与任何 G* 项目没有任何关系。我非常喜欢 gtkmm,但觉得它并没有它可能/应该有的知名度,尤其是与某些明显的替代品相比。另外,我不知道 @ 987654324@ 是 K&R,直到我为此进行了研究!整洁。)

            【讨论】:

              【解决方案8】:

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

              【讨论】:

                【解决方案9】:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-10-14
                  • 2010-10-25
                  • 1970-01-01
                  • 2014-04-25
                  • 2018-12-03
                  • 2010-12-04
                  • 1970-01-01
                  相关资源
                  最近更新 更多