Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there noteworthy uses of m4 besides autoconf? [closed]

Does someone know of any uses of m4 besides autoconf (preferably in a c or c++ environment) that is more than just an academic excerise, because it helped solve a problem that would otherwise (for example with a 'standard' preprocessor) have been difficult to solve.

I ask this because I am thinking about a way to do a project in c++ where I want to reduce or minimize redundancies by using scripts, preprocessors, whatevers.

like image 969
René Nyffenegger Avatar asked Feb 18 '11 12:02

René Nyffenegger


4 Answers

I have once used m4 to generate a C++ header file from a text file containing a simple version string (MAJOR.MINOR.MICRO-STATUS), and information from subversion, for a Windows Visual Studio project.

m4 was the smallest macro engine that I could easily embed and use for this specific goal.

It looked like this:

#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__ */

Although it worked perfectly, this really was an experiment that I did not reiterate, mainly because I now prefer using CMake's builtin capabilities to handle that stuff directly and generate my Visual Studio project files.

like image 72
SirDarius Avatar answered Sep 19 '22 12:09

SirDarius


GNU Bison uses it internally, to generate the C or C++ parser files.

like image 44
Peter Eisentraut Avatar answered Sep 19 '22 12:09

Peter Eisentraut


I once used it to generate pieces of a fiendish SQL query. Printed, the query ran to almost 20 pages--roughly 1200 lines, I think. I'm pretty sure I couldn't have done it without m4, and I'm thankful I won't have to do it ever again.


(Responding to a comment . . .)

IIRC (from 30 years ago), the query drove a report of plaintiffs. Plaintiffs were categorized by combinations of events their history.

The SQL engine couldn't build a view on a view, and didn't support user-defined functions. Some long expressions for derived tables, subselects, etc., either

  • should have been identical, but were not, or
  • should have been subtly different (needed '-' instead of '+', or 'shsapnm' instead of 'shsgpnm'), but were different in the wrong way.

The hard part wasn't the programming.

The first hard part was figuring out which of, say, three slightly different subselects was the right one, or whether we really needed three different ones, or whether we really needed the existing three plus one or two more. (I think the answer eventually turned out to be "all of the above".) Related reports needed some of the same subselects; m4 + make guaranteed they were the same.

The second hard part was building test data that could show the query was working right in the face of all the various, complex plaintiff histories. I think Joe Celko steered me toward some commercial software Boeing was using at the time--it took some user-defined criteria and and generated a test harness and stubs for every possible combination or permutation. I don't remember its name. (I think this is it: Logic Gem)

like image 41
Mike Sherrill 'Cat Recall' Avatar answered Sep 20 '22 12:09

Mike Sherrill 'Cat Recall'


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.

like image 34
Maxim Egorushkin Avatar answered Sep 21 '22 12:09

Maxim Egorushkin