2

My goal is to create a m4 macro, that reads a value from a file (BUILD), increases it and then saves the output into the file. I came up with the following solution (BUILD.m4):

define(`__buildnumber__',`esyscmd(cat BUILD)')dnl
define(`counter',__buildnumber__)dnl
popdef(__buildnumber__)dnl
define(`count',`define(`counter',eval(counter+1))counter')dnl
count dnl

When BUILD contains 3 then running m4 BUILD.m4 outputs 4. Which is great!

However, when I call it like this m4 BUILD.m4 > BUILD the BUILD file always contains 1.

If I pipe to another file m4 BUILD.m4 > B it works and the B file will contain 4 when BUILD was 3.

I suspect it has to do with the > output redirection. When comparing both variants with debug tracing it seems like the one with the redirection into the same file can not read from the file anymore.

Variant redirection to different file:

% m4 -dtaeq BUILD.m4 > B
m4trace: -1- define(`__buildnumber__', `esyscmd(`cat BUILD')')
m4trace: -1- dnl
m4trace: -2- __buildnumber__ -> `esyscmd(`cat BUILD')'
m4trace: -2- esyscmd(`cat BUILD') -> `3'
m4trace: -1- define(`counter', `3')

Variant redirection to same file:

% m4 -dtaeq BUILD.m4 > BUILD
m4trace: -1- define(`__buildnumber__', `esyscmd(`cat BUILD')')
m4trace: -1- dnl
m4trace: -2- __buildnumber__ -> `esyscmd(`cat BUILD')'
m4trace: -2- esyscmd(`cat BUILD')
m4trace: -1- define(`counter', `')

Is there a way of doing it like this, or do I need to use some other means of capturing the output

bckmnn
  • 23
  • 3

1 Answers1

0

The shell will always first empty file BUILD whenever you use > BUILD in a command, before running m4, so this can never work.

What you can try is putting the write into BUILD within the m4 script. For example, replace the last line count dnl with

syscmd(`echo 'count` >BUILD')dnl
meuh
  • 49,672
  • 2
  • 52
  • 114
  • ok now I got it. so the redirection clears the `BUILD` file at the time of command invocation, so it is already empty when it's read by m4. – bckmnn Oct 07 '22 at 19:55