+dnl SIMPLE_DECLS_EXPLAIN([arg], [arg...])
+dnl
+dnl Generate tests to validate correct parsing and output of each specification
+dnl argument. The arguments are quoted list of quoted items, with the first
+dnl item of each list being the C declaration or type name to be explained.
+dnl
+dnl The expected output is the fourth item of the list, or, if that is empty,
+dnl the second item in the list (this allows the same lists to be used for
+dnl both SIMPLE_DECLS_DECLARE and SIMPLE_DECLS_EXPLAIN even in case of
+dnl various equivalent syntactic forms)
+dnl
+dnl The items should be related to each other as the user-visible test group
+dnl name is determined only by the first argument.
+m4_define([SIMPLE_DECLS_EXPLAIN],
+[AT_SETUP([Explain "m4_car($1)"m4_ifnblank([$2], [ etc.])])
+AT_DATA([test.dat],
+[m4_map_args([explain m4_curry([_SIMPLE_DECL_ARG], [1])], $@)])
+AT_DATA([expout],
+[m4_map_args([m4_curry([_SIMPLE_DECL_ARG], [4 2])], $@)])
+AT_CHECK([cdecl99 -f test.dat], [0], [expout])
+AT_CLEANUP])
+
+dnl SIMPLE_DECLS_DECLARE([arg], [arg ...])
+dnl
+dnl Similar to SIMPLE_DECLS_EXPLAIN, except in the opposite direction. The
+dnl arguments are quoted lists of quoted items, with the second item of each
+dnl list being the input query.
+dnl
+dnl The expected output is the third item of the list, or, if that is empty,
+dnl the first item in the list (this allows the same lists to be used for
+dnl both SIMPLE_DECLS_DECLARE and SIMPLE_DECLS_EXPLAIN even in the case
+dnl of various equivalent syntactic forsm)
+dnl
+dnl The items should be related to each other as the user-visible test group
+dnl name is determined only by the first argument.
+m4_define([SIMPLE_DECLS_DECLARE],
+[AT_SETUP([Declare "m4_car($1)"m4_ifnblank([$2], [ etc.])])
+AT_DATA([test.dat],
+[m4_map_args([m4_curry([_SIMPLE_DECL_ARG], [2])], $@)])
+AT_DATA([expout],
+[m4_map_args([m4_curry([_SIMPLE_DECL_ARG], [3 1])], $@)])
+AT_CHECK([cdecl99 -f test.dat], [0], [expout])