# sum.m4 -- summary of m4(1) macro processor # # $Id$ # Carlos Duarte , 981012 . the fundamental principle of m4 operation, is _expansion_ - almost builtins and user-defined macros, are expanded, which means: what is textually occupied by them, gets replaced by its result: incr(3) -> 4 the textual representation "incr(3)", is replaced by "4" . as a general rule, if there is no argument, it is seen as an empty one - ifdef(a, b) == ifdef(a, b, `') . white space _before_ arguments, is ignored - define(a, b) == define(a,b) . in this text (not in M4!), it is used the following syntax: - a==b ? c : d, means if `a' equals `b', then `c', else `d' . and can be extended: a==b ? c : d==e ? f ... . m4 interprets and tries to expand tokens _only_, _recursively_! - tokens are: [A-Za-z_][A-Za-z_0-9]* - that is: alphanumeric strings, started by letters only (being `_' a letter) . each m4 interpretation strips one level of quotes - quoted stuff is not expanded . tricks: - null string: `' (left and right default character quotes) - force a token interpretation adding `': divert`'dnl - produce no output: divert(-1) ... divert - quote to stop recursive expansion: `incr(1)' -> incr(1) . on unix, `unix' is defined . on vms, `vms' is defined Defining macros --------------- define(macro, expansion) `macro' gets replaced per `expansion' each time it is seen unquoted. if `expansion' contains $1 .. $9, those are replaced by arguments `macro' arguments. macro(a,b,c) -> `expansion' sees $1,$2,$3 as a,b,c $0 is seen as the macro name. undefine(macro) undefines `macro': it will be no longer expanded into anything. Advanced definitions -------------------- defn(`builtin') expands to the definition of the quoted argument. if argument is a macro (user defined), expands into its literal text definition. if argument is a builtin, returns an internal code, only meaningful to `define' and `pushdef'. pushdef(name, expansion) pushes the current expansion of `name' to stack and make `expansion' the new one popdef(name) pops the last pushdef'ed expansion, into `name' Conditionals ------------ ifdef(a, b) `a' is defined? yes: `b' ifdef(a, b, c) `a' is defined? yes: `b', no: `c' ifelse(a,b,c) a=b ? c : `' ifelse(a,b,c,d) a=b ? c : d ifelse(a,b,c,d,e,f) a=b ? c : d=e ? f : `' ifelse(a,b,c,d,e,f,g) a=b ? c : d=e ? f : g Arithmetic ---------- incr(n) -> n+1 decr(n) -> n-1 eval(expr) evaluates `expr'. expr is composed by (priority decreases down): . unary + and - . ** or ^ (exponentiation) . * / % (modulus) . + - . == != < <= > >= . ! (not) . & or && (logical and) . | or || (logical or) parenteses may be used for grouping Strings ------- substr(s, i, n) s[i..i+n-1]: sub-string of `s', started at `i'th position (zero based), length `n'. substr(s, i) sub-string of `s', started at `i't position, until end of `s'. index(s1, s2) where `s2' occurs in `s1', zero based. -1 if not present. len(s) length of `s' in characters. translit(s, from, to) expands into `s', with characters listed in `from' replaced by characters in `to'. if `to' is smaller than `from', extra chars on `from' are removed (translated into void). translit(s, from) expands into `s', with chars present in `from' removed Diversions ---------- divert(n) n: 0..9; output is redirected into diversion `n'. diversion 0, is normal output; others may be seen as 9 temporary files, that hold otherwise normal output divert same as divert(0) undivert(i,j,k,l,...) output all diverted stuff, starting with diversion `i' then diversion `j', `k', `l', ... undivert same as: undivert(1,2,3,4,5,6,7,8,9). NOTE: at the end, an `undivert' is automatically done. NOTE: stuff output per `undivert', is not rescanned again (no search for macros, no further expansion) divnum number of current active diversion (normally 0) File inclusion -------------- include(file) expands into `file' contents; output is rescanned as usual. sinclude(file) same as `include', but do not complains, on failing to include `file': `s' stands for `silent' System interaction ------------------ syscmd(cmd) execute `cmd' as an external shell command, and gets replaced by its output, that it is NOT rescanned. sysval exit status of last done `syscmd' maketemp(templ) expands into a nonexistent filename. if `templ' contains XXXXXX, they get replaced by current process id. Miscelandeous ------------- changequote(L, R) change Left and Right quote characters. L/R are composed by one or more NON alphanumeric char. changequote restore default `' as LR quote chars, respectively. changecom(L, R) change L/R comment characters. changecom disable quote mechanism. NOTE: commented text, is outputed, but not scanned for macros. NOTE: default L R comment chars: # ... \n shift(a, b, c, d, ...) -> b,c,d,... expands to all arguments quoted, except first. dnl eats (i.e. does not output) text up to next newline, inclusive errprint(s1, s2, ...) outputs `s1, s2, ...' to stderr dumpdef dumps all macro definitions dumpdef(m1, m2, ...) dumps only specified macros m4wrap(args,...) pushes `args' into a stack, which gets poped and expanded at end of input, automatically. m4exit(code) exits immediately (without reading more input) with exit code `code'. m4exit same as m4exit(0)