autom4te and m4sh for the impatient

autom4te is the engine beneath autoconf, but you can use it to generate your own portable shell scripts for other purposes.  For example, create this test.m4sh:

# test.m4sh
m4_errprintn([before init])
AS_INIT
m4_errprintn([before copyright])
AS_COPYRIGHT([CC0])
AS_WARN([warning])
AS_ECHO([Hello!])

# draws a box on stdout
AS_BOX([Test foo])

# Puts a box in the output as a comment
m4_text_box([testing foo])

foo=1
AS_IF([test "x$foo" = 'x1'],[
echo Foo is 1
])
m4_errprintn([at end])

Run autom4te:

$ autom4te -l M4sh -Wall -o test.sh test.m4sh 
before init
before copyright
at end

(Note that the m4_errprintn calls print while autom4te is running.)

Now you have test.sh:

$ ./test.sh
test.sh: WARNING: warning
Hello!
## -------- ##
## Test foo ##
## -------- ##
Foo is 1

Stunning, right? 😉

The number one gotcha

If you forget AS_INIT, you will get no output and no error message.  You have been warned.

Commands used in this example

  • AS_INIT: required.  At the top of the input file.
  • AS_COPYRIGHT: puts the text you give it into the output as a comment at the top of the generated script file.
  • AS_WARN: prints a warning when the generated script runs
  • AS_ECHO: prints to stdout when the generated script runs
  • m4_errprintn: prints to stderr when autom4te runs.  No effect on the generated script.
  • AS_BOX: prints the “Test foo” box in the example output, when the generated script runs
  • m4_text_box: puts into the generated script file a comment like this one:
## ----------- ##
## testing foo ##
## ----------- ##
  • AS_IF: a shell conditional, but more portable.
  • test: the clunky, old-school (but very portable) way of checking conditionals.  For maximum portability, don’t let any argument to test be the empty string (hence the xs in the test command above)

Happy hacking!