Learning GNU Make Functions with Arithmetic


We can avoid recursion in the special case of division by 2; we define the halve function to be the opposite of double:

    halve = $(subst xx,x,            \
$(filter-out xy x y, \
$(join $1,$(foreach a,$1,y x))))

By now you've seen all the functions used as part of halve; work through an example, say $(call halve,$(five)) to see how it works.

So, the only tricky thing to do is turn a number entered by the user into a string of x's. The encode function does this by chopping out a substring of x's from a predefined list of x's:

    16 := x x x x x x x x x x x x x x x
input_int := $(foreach a,$(16), \
$(foreach b,$(16), \
$(foreach c,$(16),$(16)))))

encode = $(wordlist 1,$1,$(input_int))

Here we are limited to being able to enter numbers up to 65536. Once we've got the number in the encoding, only available memory limits the size of integers we can work with.

To really show off this library here's an implementation of a reverse polish notation calculator written entirely in GNU Make functions:

    stack := 

push = $(eval stack := $$1 $(stack))
pop = $(word 1,$(stack))$(eval stack := $(wordlist 2,$(words \
pope = $(call encode,$(call pop))
pushd = $(call push,$(call decode,$1))
comma := ,
calculate = $(foreach t,$(subst $(comma), ,$1),$(call \
seq = $(filter $1,$2)
handle = $(call pushd, \
$(if $(call seq,+,$1), \
$(call plus,$(call pope),$(call pope)), \
$(if $(call seq,-,$1), \
$(call subtract,$(call pope),$(call pope)), \
$(if $(call seq,*,$1), \

$(call multiply,$(call pope),$(call pope)), \
$(if $(call seq,/,$1), \
$(call divide,$(call pope),$(call pope)), \
$(call encode,$1))))))

.PHONY: calc
calc: ; @echo $(call calculate,$(calc))

You'll need to be using GNU Make 3.80 or later for this to work. The operators and numbers are passed into GNU Make in the calc variable separated by commas. For example,

    make calc="1,3,-,3,21,5,*,+,/"

Will output 54. Clearly, that's not what GNU Make was designed for, and I don't have space here to explain how the calculator transforms its input into calls to our plus, minus,multiply and divide functions, but I hope I've shown you the power of GNU Make functions.

Now go read chapter eight of the GNU Make manual to learn about the other functions that I have not touched on here.

Here's the complete commented Makefile:

# input_int consists of 65536 x's built from the 16 x's in 16

16 := x x x x x x x x x x x x x x x
input_int := $(foreach a,$(16),$(foreach b,$(16),$(foreach c,$(16),$(16)))))

# decode turns a number in x's representation into a integer for human
# consumption

decode = $(words $1)

# encode takes an integer and returns the appropriate x's
# representation of the number by chopping $1 x's from the start of
# input_int

encode = $(wordlist 1,$1,$(input_int))

# plus adds its two arguments, subtract subtracts its second argument
# from its first iff this would not result in a negative result.

plus = $1 $2
subtract = $(if $(call gte,$1,$2), \
$(filter-out xx,$(join $1,$2)), \
$(warning Subtraction underflow))

# multiply multiplies its two arguments and divide divides it first
# argument by its second

multiply = $(foreach a,$1,$2)
divide = $(if $(call gte,$1,$2), \
x $(call divide,$(call subtract,$1,$2),$2),)

# max returns the maximum of its arguments and min the minimum

max = $(subst xx,x,$(join $1,$2))
min = $(subst xx,x,$(filter xx,$(join $1,$2)))

About the author

John Graham-Cumming's picture John Graham-Cumming

John Graham-Cumming is Co-Founder at Electric Cloud, Inc . Prior to joining Electric Cloud, John was a Venture Consultant with Accel Partners, VP of Internet Technology at Interwoven, Inc. (IWOV), VP of Engineering at Scriptics Corporation (acquired by Interwoven), and Chief Architect at Optimal Networks, Inc. John holds BA and MA degrees in Mathematics and Computation and a Doctorate in Computer Security from Oxford University. John is the creator of the highly acclaimed open source POPFile project. He also holds two patents in network analysis and has others pending.

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!