mpers: add support of conditionally compiled printers

We used to declare and define all printers marked with
MPERS_PRINTER_DECL, including ifdef'ed ones.  That approach left us
no way to conditionally compile mpersified printers, which was not
a problem until btrfs ioctls appeared on the horizon.

With this change, those mpersified printers that are not going
to be compiled are also won't be declared and won't be added to
struct_printers.

This is implemented by filtering all source files containing
MPERS_PRINTER_DECL markers through CPP.  As a nice side effect, this
also lifts an ugly requirement of writing all MPERS_PRINTER_DECL
declarations in a single line.

* README-mpers: Update description of MPERS_PRINTER_DECL syntax.
* defs.h [IN_MPERS_BOOTSTRAP] (MPERS_PRINTER_DECL): Turn into
a recursive variadic macro.
[!IN_MPERS_BOOTSTRAP] (MPERS_PRINTER_DECL): Turn into a variadic macro.
All callers changed.
* Makefile.am (mpers_preproc_files, mpers_printer_decl_pattern):
New variables.
(CLEANFILES): Add $(mpers_preproc_files).
(%.c.mpers.i): New rule.
(printers.h, %_printer_decls.h, %_printer_defs.h): Use
mpers_preproc_files instead of srcdir_mpers_source_files,
use mpers_printer_decl_pattern.
* .gitignore: Add /*.mpers.i.
diff --git a/.gitignore b/.gitignore
index f360940..122e197 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,3 +67,4 @@
 /native_printer_decls.h
 /native_printer_defs.h
 /printers.h
+/*.mpers.i
diff --git a/Makefile.am b/Makefile.am
index 4b66b04..1585a7c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -718,13 +718,14 @@
 
 BUILT_SOURCES = $(ioctl_redefs_h) $(ioctlent_h) \
 		native_printer_decls.h native_printer_defs.h printers.h sen.h sys_func.h .version
-CLEANFILES    = $(ioctl_redefs_h) $(ioctlent_h) \
+CLEANFILES    = $(ioctl_redefs_h) $(ioctlent_h) $(mpers_preproc_files) \
 		native_printer_decls.h native_printer_defs.h printers.h sen.h sys_func.h
 DISTCLEANFILES = gnu/stubs-32.h gnu/stubs-x32.h
 
 # defines mpers_source_files
 include mpers.am
 srcdir_mpers_source_files = $(patsubst %,$(srcdir)/%,$(mpers_source_files))
+mpers_preproc_files = $(mpers_source_files:.c=.c.mpers.i)
 
 mpers_NAME =
 mpers_PREFIX = $(mpers_NAME)_
@@ -764,28 +765,36 @@
 
 # printers
 
-printers.h: $(srcdir_mpers_source_files)
+%.c.mpers.i: $(srcdir)/%.c
+	$(CPP) -P $(mpers_sh_opts) -DIN_MPERS_BOOTSTRAP $< -o $@
+
+mpers_printer_decl_pattern = ^MPERS_PRINTER_DECL(\([^,)]\+\),[[:space:]]*\([^,)]\+\),[[:space:]]*\([^)]\+\))$$
+
+printers.h: $(mpers_preproc_files)
 	echo '/* Generated by Makefile from $^; do not edit. */' > $@-t
 	echo 'typedef struct {' >> $@-t
 	for f in $^; do \
-		sed -n 's/^MPERS_PRINTER_DECL(\([^,]\+\),[[:space:]]*\([^)]\+\))\(.*\)/ \1 (*\2) \3;\n#define \2 MPERS_PRINTER_NAME(\2)\n/p' $$f || exit; \
+		sed -n 's/$(mpers_printer_decl_pattern)/ \1 (*\2)(\3);\n#define \2 MPERS_PRINTER_NAME(\2)\n/p' $$f \
+		|| exit; \
 	done >> $@-t
 	echo '} struct_printers;' >> $@-t
 	echo 'extern const struct_printers *printers;' >> $@-t
 	echo '#define MPERS_PRINTER_NAME(printer_name) printers->printer_name' >> $@-t
 	mv $@-t $@
 
-%_printer_decls.h: $(srcdir_mpers_source_files)
+%_printer_decls.h: $(mpers_preproc_files)
 	echo '/* Generated by Makefile from $^; do not edit. */' > $@-t
 	for f in $^; do \
-		sed -n 's/^MPERS_PRINTER_DECL(\([^,]\+\),[[:space:]]*\([^)]\+\))\(.*\)/extern \1 $(mpers_PREFIX)\2\3;/p' $$f || exit; \
+		sed -n 's/$(mpers_printer_decl_pattern)/extern \1 $(mpers_PREFIX)\2(\3);/p' $$f \
+		|| exit; \
 	done >> $@-t
 	mv $@-t $@
 
-%_printer_defs.h: $(srcdir_mpers_source_files)
+%_printer_defs.h: $(mpers_preproc_files)
 	echo '/* Generated by Makefile from $^; do not edit. */' > $@-t
 	for f in $^; do \
-		sed -n 's/^MPERS_PRINTER_DECL(\([^,]\+\),[[:space:]]*\([^)]\+\))\(.*\)/\.\2 = $(mpers_PREFIX)\2,/p' $$f || exit; \
+		sed -n 's/$(mpers_printer_decl_pattern)/\.\2 = $(mpers_PREFIX)\2,/p' $$f \
+		|| exit; \
 	done >> $@-t
 	mv $@-t $@
 
diff --git a/README-mpers b/README-mpers
index 8ae418d..ad1ca18 100644
--- a/README-mpers
+++ b/README-mpers
@@ -8,7 +8,7 @@
 (containing definitions of these types or other behaviour-affecting
 defines);
 * printers should be defined
-as MPERS_PRINTER_DECL(return_type, function_name)(args),
+as MPERS_PRINTER_DECL(return_type, function_name, args),
 inside files that include MPERS_DEFS these printers should be called
 as MPERS_FUNC_NAME(function_name)(args), in other files
 they should be called just as function_name(args).
diff --git a/defs.h b/defs.h
index f693da1..3cde145 100644
--- a/defs.h
+++ b/defs.h
@@ -795,11 +795,17 @@
 extern unsigned nioctlents;
 extern unsigned num_quals;
 
-#if SUPPORTED_PERSONALITIES > 1
-# include "printers.h"
-#else
-# include "native_printer_decls.h"
-#endif
+#ifdef IN_MPERS_BOOTSTRAP
+/* Transform multi-line MPERS_PRINTER_DECL statements to one-liners.  */
+# define MPERS_PRINTER_DECL(type, name, ...) MPERS_PRINTER_DECL(type, name, __VA_ARGS__)
+#else /* !IN_MPERS_BOOTSTRAP */
+# if SUPPORTED_PERSONALITIES > 1
+#  include "printers.h"
+# else
+#  include "native_printer_decls.h"
+# endif
+# define MPERS_PRINTER_DECL(type, name, ...) type MPERS_FUNC_NAME(name)(__VA_ARGS__)
+#endif /* !IN_MPERS_BOOTSTRAP */
 
 /*
  * If you need non-NULL sysent[scno].sys_func and sysent[scno].sys_name
@@ -819,8 +825,6 @@
 
 #define SYS_FUNC(syscall_name) int SYS_FUNC_NAME(sys_ ## syscall_name)(struct tcb *tcp)
 
-#define MPERS_PRINTER_DECL(type, name) type MPERS_FUNC_NAME(name)
-
 /*
  * The kernel used to define 64-bit types on 64-bit systems on a per-arch
  * basis.  Some architectures would use unsigned long and others would use
diff --git a/fetch_seccomp_fprog.c b/fetch_seccomp_fprog.c
index dbaf83a..d54b979 100644
--- a/fetch_seccomp_fprog.c
+++ b/fetch_seccomp_fprog.c
@@ -34,7 +34,8 @@
 
 #include MPERS_DEFS
 
-MPERS_PRINTER_DECL(bool, fetch_seccomp_fprog)(struct tcb *tcp, const long addr, void *p)
+MPERS_PRINTER_DECL(bool, fetch_seccomp_fprog,
+		   struct tcb *tcp, const long addr, void *p)
 {
 	struct seccomp_fprog *pfp = p;
 	seccomp_fprog_t mfp;
diff --git a/fetch_struct_flock.c b/fetch_struct_flock.c
index cd195e2..b5713f4 100644
--- a/fetch_struct_flock.c
+++ b/fetch_struct_flock.c
@@ -51,7 +51,8 @@
 	 && FLOCK_MEMBERS_EQ(type, l_len) \
 	 && FLOCK_MEMBERS_EQ(type, l_pid))
 
-MPERS_PRINTER_DECL(bool, fetch_struct_flock)(struct tcb *tcp, const long addr, void *p)
+MPERS_PRINTER_DECL(bool, fetch_struct_flock,
+		   struct tcb *tcp, const long addr, void *p)
 {
 	struct_kernel_flock64 *pfl = p;
 	struct_flock mfl;
@@ -70,7 +71,8 @@
 	return true;
 }
 
-MPERS_PRINTER_DECL(bool, fetch_struct_flock64)(struct tcb *tcp, const long addr, void *p)
+MPERS_PRINTER_DECL(bool, fetch_struct_flock64,
+		   struct tcb *tcp, const long addr, void *p)
 {
 	struct_kernel_flock64 *pfl = p;
 	struct_flock64 mfl;
diff --git a/fetch_struct_statfs.c b/fetch_struct_statfs.c
index 7c8b088..0717e4b 100644
--- a/fetch_struct_statfs.c
+++ b/fetch_struct_statfs.c
@@ -47,7 +47,8 @@
 	else						\
 		dst = (unsigned long long) (src)
 
-MPERS_PRINTER_DECL(bool, fetch_struct_statfs)(struct tcb *tcp, const long addr, struct strace_statfs *p)
+MPERS_PRINTER_DECL(bool, fetch_struct_statfs,
+		   struct tcb *tcp, const long addr, struct strace_statfs *p)
 {
 	struct_statfs b;
 
@@ -84,7 +85,9 @@
 # define COMPAT_STATFS64_PADDED_SIZE (sizeof(struct_statfs64) + 4)
 #endif
 
-MPERS_PRINTER_DECL(bool, fetch_struct_statfs64)(struct tcb *tcp, const long addr, const unsigned long size, struct strace_statfs *p)
+MPERS_PRINTER_DECL(bool, fetch_struct_statfs64,
+		   struct tcb *tcp, const long addr, const unsigned long size,
+		   struct strace_statfs *p)
 {
 	struct_statfs64 b;
 
diff --git a/mpers_type.h b/mpers_type.h
index adbefd5..4ce569b 100644
--- a/mpers_type.h
+++ b/mpers_type.h
@@ -39,5 +39,9 @@
 #else
 # define MPERS_PREFIX
 # define DEF_MPERS_TYPE(args) "empty.h"
-# define MPERS_DEFS "native_defs.h"
+# if IN_MPERS_BOOTSTRAP
+#  define MPERS_DEFS "empty.h"
+# else
+#  define MPERS_DEFS "native_defs.h"
+# endif
 #endif
diff --git a/print_mq_attr.c b/print_mq_attr.c
index a43d437..1807834 100644
--- a/print_mq_attr.c
+++ b/print_mq_attr.c
@@ -41,7 +41,7 @@
 
 #include MPERS_DEFS
 
-MPERS_PRINTER_DECL(void, printmqattr)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(void, printmqattr, struct tcb *tcp, const long addr)
 {
 #if defined HAVE_MQUEUE_H || defined HAVE_LINUX_MQUEUE_H
 	mq_attr_t attr;
diff --git a/print_msgbuf.c b/print_msgbuf.c
index c7e87e4..68d8741 100644
--- a/print_msgbuf.c
+++ b/print_msgbuf.c
@@ -38,7 +38,8 @@
 typedef struct msgbuf msgbuf_t;
 #include MPERS_DEFS
 
-MPERS_PRINTER_DECL(void, tprint_msgbuf)(struct tcb *tcp, const long addr, const unsigned long count)
+MPERS_PRINTER_DECL(void, tprint_msgbuf,
+		   struct tcb *tcp, const long addr, const unsigned long count)
 {
 	msgbuf_t msg;
 
diff --git a/print_sigevent.c b/print_sigevent.c
index f8eb8a0..1c2b174 100644
--- a/print_sigevent.c
+++ b/print_sigevent.c
@@ -35,7 +35,7 @@
 #include <signal.h>
 #include "xlat/sigev_value.h"
 
-MPERS_PRINTER_DECL(void, print_sigevent)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(void, print_sigevent, struct tcb *tcp, const long addr)
 {
 	struct_sigevent sev;
 
diff --git a/print_time.c b/print_time.c
index dddb3f1..500ce8e 100644
--- a/print_time.c
+++ b/print_time.c
@@ -73,7 +73,8 @@
 	tprintf(time_fmt, (intmax_t) t->tv_sec, (intmax_t) t->tv_usec);
 }
 
-MPERS_PRINTER_DECL(void, print_timespec)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(void, print_timespec,
+		   struct tcb *tcp, const long addr)
 {
 	timespec_t t;
 
@@ -83,7 +84,8 @@
 	print_timespec_t(&t);
 }
 
-MPERS_PRINTER_DECL(const char *, sprint_timespec)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(const char *, sprint_timespec,
+		   struct tcb *tcp, const long addr)
 {
 	timespec_t t;
 	static char buf[sizeof(time_fmt) + 3 * sizeof(t)];
@@ -101,7 +103,8 @@
 	return buf;
 }
 
-MPERS_PRINTER_DECL(void, print_timespec_utime_pair)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(void, print_timespec_utime_pair,
+		   struct tcb *tcp, const long addr)
 {
 	timespec_t t[2];
 
@@ -115,7 +118,8 @@
 	tprints("]");
 }
 
-MPERS_PRINTER_DECL(void, print_itimerspec)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(void, print_itimerspec,
+		   struct tcb *tcp, const long addr)
 {
 	timespec_t t[2];
 
@@ -129,7 +133,8 @@
 	tprints("}");
 }
 
-MPERS_PRINTER_DECL(void, print_timeval)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(void, print_timeval,
+		   struct tcb *tcp, const long addr)
 {
 	timeval_t t;
 
@@ -139,7 +144,8 @@
 	print_timeval_t(&t);
 }
 
-MPERS_PRINTER_DECL(void, print_timeval_pair)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(void, print_timeval_pair,
+		   struct tcb *tcp, const long addr)
 {
 	timeval_t t[2];
 
@@ -153,7 +159,8 @@
 	tprints("]");
 }
 
-MPERS_PRINTER_DECL(const char *, sprint_timeval)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(const char *, sprint_timeval,
+		   struct tcb *tcp, const long addr)
 {
 	timeval_t t;
 	static char buf[sizeof(time_fmt) + 3 * sizeof(t)];
@@ -171,7 +178,8 @@
 	return buf;
 }
 
-MPERS_PRINTER_DECL(void, print_itimerval)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(void, print_itimerval,
+		   struct tcb *tcp, const long addr)
 {
 	timeval_t t[2];
 
diff --git a/print_timex.c b/print_timex.c
index 4eac54d..ad6a711 100644
--- a/print_timex.c
+++ b/print_timex.c
@@ -40,7 +40,7 @@
 #include "xlat/adjtimex_modes.h"
 #include "xlat/adjtimex_status.h"
 
-MPERS_PRINTER_DECL(int, print_timex)(struct tcb *tcp, const long addr)
+MPERS_PRINTER_DECL(int, print_timex, struct tcb *tcp, const long addr)
 {
 	struct_timex tx;
 
diff --git a/printrusage.c b/printrusage.c
index be56e66..0375f8f 100644
--- a/printrusage.c
+++ b/printrusage.c
@@ -37,7 +37,7 @@
 
 #include MPERS_DEFS
 
-MPERS_PRINTER_DECL(void, printrusage)(struct tcb *tcp, long addr)
+MPERS_PRINTER_DECL(void, printrusage, struct tcb *tcp, long addr)
 {
 	rusage_t ru;
 
diff --git a/printsiginfo.c b/printsiginfo.c
index 78508df..a14ebb4 100644
--- a/printsiginfo.c
+++ b/printsiginfo.c
@@ -228,7 +228,8 @@
 	tprints("}");
 }
 
-MPERS_PRINTER_DECL(void, printsiginfo_at)(struct tcb *tcp, long addr)
+MPERS_PRINTER_DECL(void, printsiginfo_at,
+		   struct tcb *tcp, long addr)
 {
 	siginfo_t si;
 
@@ -243,7 +244,8 @@
 	return true;
 }
 
-MPERS_PRINTER_DECL(void, print_siginfo_array)(struct tcb *tcp, unsigned long addr, unsigned long len)
+MPERS_PRINTER_DECL(void, print_siginfo_array,
+		   struct tcb *tcp, unsigned long addr, unsigned long len)
 {
 	siginfo_t si;
 
diff --git a/v4l2.c b/v4l2.c
index ab9a69c..c0cda21 100644
--- a/v4l2.c
+++ b/v4l2.c
@@ -846,7 +846,8 @@
 }
 #endif /* VIDIOC_CREATE_BUFS */
 
-MPERS_PRINTER_DECL(int, v4l2_ioctl)(struct tcb *tcp, const unsigned int code, const long arg)
+MPERS_PRINTER_DECL(int, v4l2_ioctl,
+		   struct tcb *tcp, const unsigned int code, const long arg)
 {
 	if (!verbose(tcp))
 		return RVAL_DECODED;