Feature Request #4053

Add support for GNU M4 macro processor

Added by Xotic750 over 7 years ago. Updated about 7 years ago.

Status:NewStart date:2012-07-06
Priority:NormalDue date:
Assignee:-% Done:

0%

Category:-
Target version:-

Description

As an alternative to using the C PreProcessor for macro handling, I would like to see GNU M4 macro processor available as this is far more flexible and appropriate for dealing with NML.

I'm not sure what needs to be done to give the user a choice of one or the other but as start:

Makefile_def:

Requires as a minimum the following added to the Programme Definitions section:

M4 ?= m4
M4_FLAGS ?= -s -E - <

Makefile_nml:

Requires a mechanism whereby the user can call the following:

$(_E) "[M4] $(NML_FILE)"
$(_V) $(M4) -D REPO_REVISION=$(REPO_REVISION) $(M4_FLAGS) $(MAIN_SRC_FILE) > $(NML_FILE)

History

#1 Updated by Xotic750 over 7 years ago

A change to the original suggestion:

Also add the ability to use the standard quadrigraphs as defined by Autoconf, allowing the user to change the default quotes used by M4 and escape other special characters.

http://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Quadrigraphs.html#Quadrigraphs

Makefile_def:

Requires the addition of the following:

SED            ?= sed
SED_QUADS      ?=-e 's/@<:@/[/g' -e 's/@:>@/]/g' -e 's/@:>@/]/g' -e 's/@S|@/$/g' -e 's/@%:@/#/g' -e 's/@{:@/(/g' -e 's/@:}@/)/g' -e 's/@&t@//g'

Makefile_nml:

Should be changed from original suggestion to:

$(_E) "[M4] $(NML_FILE)"
$(_V) $(M4) -D REPO_REVISION=$(REPO_REVISION) $(M4_FLAGS) $(MAIN_SRC_FILE) | $(SED) $(SED_QUADS) > (NML_FILE)

#2 Updated by planetmaker over 7 years ago

So you're effectively suggesting to add the following ADDITIONAL dependencies:

-autoconf
-m4

which in the envisioned use are also incompatible to the existing NML rule, thus requiring either a big complication of the build framework (if an option) or a branch, similar to nfo vs nml?

#3 Updated by Xotic750 over 7 years ago

I am suggesting allowing the user to choose m4 as an alternative preprocessor (additional dependency by choice).

I am suggesting to use sed (already used in the Makefiles) to perform quadrigraphs and not depend on autoconf, but use the same format as defined in their documents.

Then something like the following I think would be possible,

Makefile_def:

Add, to the Programme Definitions section:

SED            ?= sed
SED_QUADS      ?= -e 's/@<:@/[/g' -e 's/@:>@/]/g' -e 's/@S|@/$$/g' -e 's/@%:@/\#/g' -e 's/@{:@/(/g' -e 's/@:}@/)/g' -e 's/@&t@//g'

This alone causes no issues to the current working framework that I can ascertain.

Makefile_m4nml:

This would be a direct copy of Makefile_nml

but would contain

$(_E) "[M4] $(NML_FILE)"
$(_V) $(M4) -D REPO_REVISION=$(REPO_REVISION) $(M4_FLAGS) $(MAIN_SRC_FILE) | $(SED) $(SED_QUADS) > (NML_FILE)

instead of

$(_E) "[CPP] $(NML_FILE)"
$(_V) $(CC) -D REPO_REVISION=$(REPO_REVISION) $(CC_FLAGS) $(MAIN_SRC_FILE) > $(NML_FILE)

Again I see no issues to the current working framework that I can ascertain.

Makefile

Finally, to give the user a choice of preprocessot to be used, I see something like adding an include to this file. Like

@# Comment out Makefile_nml and uncomment Makefile_m4nml to use GNU M4 as the preprocessor
  1. target nml
    include $(SCRIPT_DIR)/Makefile_nml
    #include $(SCRIPT_DIR)/Makefile_m4nml@

Again I see no issues to the current working framework that I can ascertain.

- -
I don't know where this envisioned use or NML rule exists that these changes would be incompatible?

I don't think this causes any big complication to the build framework or would require a branch?

#4 Updated by Xotic750 over 7 years ago

Ok, an issue I have discovered is that if the M4 script exits with a value other than 0 and because the output is piped to sed, then make continues rather than exiting. So, to remedy this you will also need to set the shell option for pipefail.

http://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin
http://www.gnu.org/software/bash/manual/bashref.html#Pipelines

set -o pipefail

Once this is set then all works as expected.

The way I have implemented it currently is to add to Makefile_def

PIPEFAIL ?= set -o pipefail

Then change Makefile_m4nml to read as:

$(_V) $(PIPEFAIL); $(M4) -D REPO_REVISION=$(REPO_REVISION) $(M4_FLAGS) $(MAIN_SRC_FILE) | $(SED) $(SED_QUADS) > $(NML_FILE)

Not sure that this would be the correct way to do it within a Makefile, but it works.

#5 Updated by Xotic750 about 7 years ago

This has been implemented in the OpenGFX+ Trains m4_experiment branch as a working example.

http://dev.openttdcoop.org/projects/ogfx-trains/repository/show?rev=m4_experiment

Also available in: Atom PDF