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.
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.
GNU Bison uses it internally, to generate the C or C++ parser files.
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.
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
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)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With