GNU Make user-defined functions, part 2

[article]

string into the output buffer o of a GNU Make function.   The first argument should be the output buffer, the second the string to copy and the last the amount of the string to copy.

func_findstring either copies all of its first argument (if the strstr was successful) or leaves [tt ]o[/tt] untouched (and, hence, empty since it is initialized to an empty string before func_findstring is called).

With that we have enough information to start making our own GNU Make function.

Reverse a string

There's no easy wasy to reverse a string in GNU Make, but it's easy to write a C function that does that and insert it into GNU Make.

First, we'll add the definition of reverse to the list of functions that GNU Make knows about.  reverse will have a single argument that must be expanded and will call a C function
named func_reverse .

Here's the entry to add to the function_table_init[]:

~  { STRING_SIZE_TUPLE("reverse"),   
1,  1,  1,  func_reverse},

[/tt]

And now we can define
[tt]func_reverse[/tt] which reverses the string in

[tt]argv[0][/tt] by
swapping characters and then updates the output

buffer
[tt]o[/tt].:

[tt]

static char*

func_reverse (char *o, char **argv,
const char *funcname UNUSED)

{

~  int len = strlen(argv[0]);

~  if (
len > 0 ) {

~    char * p = argv[0];

~    int left = 0;

~    int
right = len - 1;

~    while ( left < right ) {

~      char temp = *(p +
left);

~      *(p + left) = *(p + right);

~      *(p + right) =
temp;

~      left++;

~      right--;

~    }

~    o =
variable_buffer_output (o, p, len);

~  }

~  return
o;

}

This function works by walking from the start of the string and from the end of the string at the same time and swapping characters as they go until they meet in the middle.

To test it out we can write a little Makefile that tries three possibilities: an empty string, a string with even length and a string with odd length calling the new built-in function reverse:

EMPTY :=

$(info Empty string:
[$(reverse $(EMPTY))]);

EVEN := 1234

$(info Even length string:
[$(reverse $(EVEN))]);

ODD := ABCDE

$(info Odd length string:
[$(reverse $(ODD))]);

[/tt]

And the output shows that it works
correctly:

[tt]

$ ./make

Empty string: []

Even length string:
[4321]

Odd length string: [EDCBA]

Since writing in C gives you access to the full range of C library functions, the GNU Make built-in functions you create are only limited by your imagination and your needs.

Conclusion

Creating GNU Make built-in functions is easy, but it does create a maintenance problem: the next time GNU Make is updated we'll need to port our changes to the new version.

If we can do what we need with GNU Make built-ins without resorting to modiying the source then Makefiles will be more portable.   One helping hand is the GNU Make Standard Library project that provides lots of additional functionality without modifying the GNU Make source.

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!

Upcoming Events

Sep 22
Sep 24
Oct 12
Nov 09