### 11.7 Formatting strings (printf-like) ¶

Formatted output can be made with `format`:

Builtin: format (format-string, …) ¶

  Works much like the C function `printf`. The first argument format-string can contain ‘`%`’ specifications which are satisfied by additional arguments, and the expansion of `format` is the formatted string.

  The macro `format` is recognized only with parameters.

Its use is best described by a few examples:

    define(`foo', `The brown fox jumped over the lazy dog')
    ⇒
    format(`The string "%s" uses %d characters', foo, len(foo))
    ⇒The string "The brown fox jumped over the lazy dog" uses 38 characters
    format(`%*.*d', `-1', `-1', `1')
    ⇒1
    format(`%.0f', `56789.9876')
    ⇒56790
    len(format(`%-*X', `5000', `1'))
    ⇒5000
    ifelse(format(`%010F', `infinity'), `       INF', `success',
           format(`%010F', `infinity'), `  INFINITY', `success',
           format(`%010F', `infinity'))
    ⇒success
    ifelse(format(`%.1A', `1.999'), `0X1.0P+1', `success',
           format(`%.1A', `1.999'), `0X2.0P+0', `success',
           format(`%.1A', `1.999'))
    ⇒success
    format(`%g', `0xa.P+1')
    ⇒20

Using the `forloop` macro defined earlier (see Iteration by counting), this example shows how `format` can be used to produce tabular output.

    $ m4 -I examples
    include(`forloop.m4')
    ⇒
    forloop(`i', `1', `10', `format(`%6d squared is %10d
    ', i, eval(i**2))')
    ⇒     1 squared is          1
    ⇒     2 squared is          4
    ⇒     3 squared is          9
    ⇒     4 squared is         16
    ⇒     5 squared is         25
    ⇒     6 squared is         36
    ⇒     7 squared is         49
    ⇒     8 squared is         64
    ⇒     9 squared is         81
    ⇒    10 squared is        100
    ⇒

The builtin `format` is modeled after the ANSI C ‘`printf`’ function, and supports these ‘`%`’ specifiers: ‘`c`’, ‘`s`’, ‘`d`’, ‘`o`’, ‘`x`’, ‘`X`’, ‘`u`’, ‘`a`’, ‘`A`’, ‘`e`’, ‘`E`’, ‘`f`’, ‘`F`’, ‘`g`’, ‘`G`’, and ‘`%`’; it supports field widths and precisions, and the flags ‘`+`’, ‘`-`’, ‘`` ’, ‘`0`’, ‘`#`’, and ‘`'`’. For integer specifiers, the width modifiers ‘`hh`’, ‘`h`’, and ‘`l`’ are recognized, and for floating point specifiers, the width modifier ‘`l`’ is recognized. Items not yet supported include positional arguments, the ‘`n`’, ‘`p`’, ‘`S`’, and ‘`C`’ specifiers, the ‘`z`’, ‘`t`’, ‘`j`’, ‘`L`’ and ‘`ll`’ modifiers, and any platform extensions available in the native `printf`. For more details on the functioning of `printf`, see the C Library Manual, or the POSIX specification (for example, ‘`%a`’ is supported even on platforms that haven’t yet implemented C99 hexadecimal floating point output natively).

Unrecognized specifiers result in a warning. It is anticipated that a future release of GNU `m4` will support more specifiers, and give better warnings when various problems such as overflow are encountered. Likewise, escape sequences are not yet recognized.

    format(`%p', `0')
    error→m4:stdin:1: Warning: unrecognized specifier in `%p'
    ⇒