APPROVE COMMIT
This is a rewrite of Stephen's complex option support for autoconf 2.5.  I
feel that the API is a now lot simpler with the declaration of --with-xft
being:
XE_COMPLEX_ARG_WITH([xft],
	[XE_COMPLEX_OPTION_HELP_STRING([--with-xft],
		[Xft client-side font rendering and anti-aliasing],
		[Xft],
		[`emacs' (buffers), `menubars', `tabs', and `gauges'],
		[X11, Xft, Xrender, freetype, and fontconfig],
		[`emacs,menubars,tabs,gauges'])],
	[],[],
	[XE_COMPLEX_OPTION([emacs],[yes]),
	XE_COMPLEX_OPTION([menubars],[yes]),
	XE_COMPLEX_OPTION([tabs],[yes]),
	XE_COMPLEX_OPTION([gauges],[yes])]
)
This patch also fixes all the bugs that I could find, adds
XE_COMPLEX_ARG_ENABLE for --enable- arguments and moves the runtime generation
of option lists to compile time.
ChangeLog addition:
2005-02-09  Malcolm Purvis  <malcolmp(a)xemacs.org>
	* configure.ac (XE_COMPLEX_OPTION):
	* configure.ac (XE_COMPLEX_OPTION_HELP_STRING):
	* configure.ac (XE_COMPLEX_ARG_WITH):
	* configure.ac (XE_COMPLEX_ARG_ENABLE):
	Rewritten complex option support with a simpler API and support
	for --enable as well a --with.
xemacs-xft-bugfixes source patch:
Diff command:   cvs -q diff -u
Files affected: configure.ac
Index: configure.ac
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/configure.ac,v
retrieving revision 1.1.14.2
diff -u -r1.1.14.2 configure.ac
--- configure.ac	2005/02/02 06:06:58	1.1.14.2
+++ configure.ac	2005/02/09 03:11:28
@@ -233,30 +233,19 @@
 dnl For example, we might use "--with-xft=all,nomenubars" for compatibility
 dnl with XFontSet i18n of menubars.  (Silly, Xft looks much better than XFS.)
 dnl Processing such an option requires a number of auxiliary variables.
-dnl Use the main variable name for a prefix, eg, "with_xft" for --with-xft.
-dnl Start by declaring it with XE_INIT_COMPLEX_OPTION (prefix), eg:
-dnl XE_INIT_COMPLEX_OPTION ([with_xft])
-dnl which also initializes auxiliary variables.  For each possible value,
-dnl declare and intialize it with
-dnl XE_APPEND_COMPLEX_OPTION_DEFAULT (prefix, component, yesno), eg:
-dnl XE_APPEND_COMPLEX_OPTION_DEFAULT ([with_xft], [emacs], [yes])
-dnl This will create a variable named ${prefix}_${component}.
-dnl Next, use XE_PARSE_COMPLEX_OPTION(prefix, cmdline-option) in AC_ARG_WITH
-dnl to parse the value.  After XE_PARSE_COMPLEX_OPTION is done, all the
-dnl component variables will have values.  The variable $prefix will contain
-dnl the complex value assigned on the command line.  Do any sanity-checking
-dnl now.  Finally, use XE_CLEANUP_COMPLEX_OPTION(prefix) to clear out the
-dnl namespace of the auxiliary variables.
 dnl
-dnl Probably a preferable API would look like
+dnl Complex options used an expanded forms of AC_ARG_[WITH|ENABLE] called
+dnl XE_COMPLEX_ARG_[WITH|ENABLE] both taking 5 parameters.  The first 4
+dnl parameters of these macros are the same as original macros with the
+dnl exception that all four paramaters are REQUIRED.  The ACTION-IF-TRUE code
+dnl is run after the argument list has been parsed.
 dnl
-dnl XE_INIT_COMPLEX_OPTION([--with-xft])
-dnl XE_APPEND_COMPLEX_OPTION_DEFAULT([--with-xft],[tabs],[yes])
-dnl XE_PARSE_COMPLEX_OPTION([--with-xft])
-dnl XE_CLEANUP_COMPLEX_OPTION([--with-xft])
+dnl The 5th parameter is a list of XE_COMPLEX_OPTION macros that define the
+dnl valid components and their default values.  The list must be quoted but
+dnl the individual macros should not.
 dnl
-dnl The reason for suggesting the command-line flag is that there is already
-dnl a facility for converting it to the variable name somewhere in autoconf.
+dnl Option values are stored in the variables with_<package>_<component> or
+dnl enable_<feature>_<component> (eg with_xft_menubars)
 dnl
 dnl There are two possible uses in XEmacs for this kind of facility.  One is
 dnl exemplified by sound: there are alternative protocols (native, ESD, NAS)
@@ -266,52 +255,66 @@
 dnl during development of a feature.  Perhaps specialized APIs should be
 dnl provided, see comment on XE_COMPLEX_OPTION_HELP_STRING below.
 
-dnl XE_INIT_COMPLEX_OPTION(prefix)
-define([XE_INIT_COMPLEX_OPTION],[[$1]_default="" [$1]_types=""])
-
-dnl XE_CLEANUP_COMPLEX_OPTION(prefix)
-define([XE_CLEANUP_COMPLEX_OPTION],
-[# cleanup
-unset [$1]_bogus [$1]_found [$1]_notfirst [$1]_types
-unset [$1]_default [$1]_all_default x y])
+dnl XE_COMPLEX_OPTION_DEFAULT(prefix, component, yesno)
+dnl ---------------------------------------------------
+dnl
+dnl Internal macro create the option's shell variable containing the default
+dnl value and to note the values in an option list.
+dnl
+define([XE_EXPAND_COMPLEX_OPTION],
+[[$1]_[$2]=[$3]
+m4_append([XE_COMPONENT_LIST],[$2],[ ])
+dnl Separate with a ':' instead of a ',' (see <prefix>_default below) to avoid
+dnl confusion with marco parameter lists.
+m4_append([XE_COMPONENT_DEFAULT],[m4_if([$3],no,no)[$2]],[:])
+])
 
-dnl #### This doesn't read so well for alternative libraries like sound.
-dnl #### Fucking autocrap.  AC_HELP_STRING does some weird internal shit,
-dnl so if you quote the second arg with [], you get really bizarre output
-dnl from ./configure --help.  Multiple quotes make it worse, and it matters
-dnl whether you define AC_HELP_STRING into XE_COMPLEX_OPTION_HELP_STRING, or
-dnl define XE_COMPLEX_OPTION_HELP_STRING to just do the string substitution
-dnl and invoke it inside of AC_HELP_STRING in the call to AC_ARG_WITH.  But
-dnl St. IGNUble himself won't be able to help you if you put a comma into the
-dnl second arg to AC_HELP_STRING without the quotes; autocrap will shit its
-dnl pants.  Yet it does fine if arguments to XE_COMPLEX_OPTION_HELP_STRING
-dnl contain commas!
+dnl XE_EXPAND_COMPLEX_OPTIONS(prefix, option_list)
+dnl ----------------------------------------------
 dnl
-dnl XE_COMPLEX_OPTION_HELP_STRING(flag, long, short, components, libraries)
-define([XE_COMPLEX_OPTION_HELP_STRING],
-[AC_HELP_STRING([$1],Compile with support for [$2]. Components that can use
-[$3] are [$4]. Prefix component with `no' to disable its use of [$3]. Requires
-[$5] support. Default is [$6].)])
+dnl Internal macro to recursively expand all the options in the option list.
+dnl
+define([XE_EXPAND_COMPLEX_OPTIONS],
+[m4_if([$2], [[]], [],
+       [XE_EXPAND_COMPLEX_OPTION([$1], m4_fst($2))[]dnl
+XE_EXPAND_COMPLEX_OPTIONS([$1], m4_cdr($2))])])
 
-dnl XE_APPEND_COMPLEX_OPTION_DEFAULT(prefix, component, yesno)
-define([XE_APPEND_COMPLEX_OPTION_DEFAULT],
-[[$1]_[$2]=[$3]
-test -n "${[$1]_default}" && [$1]_default="${[$1]_default},"
-test "${[$1]_[$2]}" != "yes" && [$1]_default="${[$1]_default}no"
-[$1]_default="${[$1]_default}[$2]"
-[$1]_notfirst=""
-test -n "${[$1]_types}" && [$1]_types="${[$1]_types} "
-[$1]_types="${[$1]_types}[$2]"])
+dnl XE_INIT_COMPLEX_OPTION(prefix, option_list)
+dnl -------------------------------------------
+dnl
+dnl Internal macro to initialise the complex option shell variables.
+dnl Variables of the form <prefix>_<option> contain the default value for that
+dnl option.  <prefix>_types contains a space-separated list of all the options
+dnl and <prefix>_default contains a comma-separated list of all the default
+dnl values.
+dnl
+define([XE_INIT_COMPLEX_OPTION],
+[[$1]_notfirst=""
+dnl
+XE_EXPAND_COMPLEX_OPTIONS($@)
+[$1]_types="XE_COMPONENT_LIST"
+[$1]_default="m4_translit(XE_COMPONENT_DEFAULT,[:],[,])"
+dnl Undefine these macros so that they can be reused by later complex
+dnl options.
+undefine([XE_COMPONENT_LIST])
+undefine([XE_COMPONENT_DEFAULT])
+])
 
 dnl XE_PARSE_COMPLEX_OPTION(prefix, cmdline-flag)
+dnl ---------------------------------------------
+dnl
+dnl Internal macro to parse the option values.  If an undeclared option is
+dnl found then an error is generated.
+dnl
 define([XE_PARSE_COMPLEX_OPTION],
-[for x in `echo "$withval" | sed -e 's/,/ /g'` ; do
+[for x in `echo "$[$1]" | sed -e 's/,/ /g'` ; do
     [$1]_all_default=""
     [$1]_found=""
     case "$x" in
         n | no | non | none ) [$1]_all_default=no ;;
         a | al | all | both ) [$1]_all_default=yes ;;
     esac
+
     if test -z "$[$1]_all_default"; then
         for y in $[$1]_types; do
             dnl echo "testing x='$x' against y='$y'"
@@ -319,29 +322,79 @@
 		dnl echo "$x" = "$y"
                 [$1]_found=yes
                 dnl echo eval `echo "[$1]_$y=yes"`
-                eval `echo "[$1]_$y=yes"`
+                eval "[$1]_$y=yes"
             elif test "$x" = "no$y"; then
                 dnl echo "$x" = "no$y"
                 [$1]_found=yes
                 dnl echo eval `echo "[$1]_$y=no"`
-                eval `echo "[$1]_$y=no"`
+                eval "[$1]_$y=no"
             fi
         done
-        test -z "[$1]_found" && [$1]_bogus=yes
+        test -z "$[$1]_found" && [$1]_bogus=yes
     fi
     if test "$[$1]_bogus" = "yes" -o \
          \( -n "$[$1]_all_default" -a -n "$[$1]_notfirst" \) ; then
-	USAGE_ERROR(["Valid values for the \`[$2]' option are:
+	USAGE_ERROR(["Valid values for the [$2] option are:
 $[$1]_types.  With prefix \"no\", switch it off.
 Defaults may be overridden with \`all' or \`none' first in the list.
-Hardcoded default is: \`$[$1]_default'."])
+Hardcoded default is: $[$1]_default."])
     elif test -n "$[$1]_all_default" ; then
-        for y in "$[$1]_types"; do
-	    eval `echo "[$1]_$y="'$[$1]_all_default'`
+        for y in $[$1]_types; do
+	    eval "[$1]_$y=$[$1]_all_default"
         done
     fi
     [$1]_notfirst=yes
 done
+unset [$1]_bogus [$1]_found [$1]_notfirst [$1]_types
+unset [$1]_default [$1]_all_default x y
+])
+
+dnl XE_COMPLEX_OPTION(option, yesno)
+dnl --------------------------------
+dnl
+dnl Declare a complex option and its default value.  The value MUST be either
+dnl yes or no.
+dnl
+define([XE_COMPLEX_OPTION],[[$1,$2]])
+
+dnl XE_COMPLEX_OPTION_HELP_STRING(flag, long, short, components, libraries)
+dnl -----------------------------------------------------------------------
+dnl Boilerplate help string for complex options.
+dnl #### This doesn't read so well for alternative libraries like sound.
+dnl
+define([XE_COMPLEX_OPTION_HELP_STRING],
+[AC_HELP_STRING([$1],[Compile with support for $2. Components that can use
+$3 are $4. Prefix component with `no' to disable its use of $3. Requires
+$5 support. Default is $6.])])
+
+dnl XE_COMPLEX_ARG_WITH(PACKAGE, HELP-STRING, ACTION-IF-TRUE, ACTION-IF-FALSE,
+dnl                     [XE_COMPLEX_OPTION(a,yes), ....])
+dnl --------------------------------------------------------------------------
+dnl
+dnl Expanded version of AC_ARG_WITH for complex options.  All the parameters
+dnl are required.
+dnl
+define([XE_COMPLEX_ARG_WITH],
+[XE_INIT_COMPLEX_OPTION([with_]patsubst([$1], -, _), m4_shiftn(4, $@))
+AC_ARG_WITH([$1],[$2],
+[XE_PARSE_COMPLEX_OPTION([with_]patsubst([$1], -, _), [--with-$1])
+$3
+],[$4])
+])
+
+dnl XE_COMPLEX_ARG_ENABLE(FEATURE, HELP-STRING, ACTION-IF-TRUE, ACTION-IF-FALSE,
+dnl                     [XE_COMPLEX_OPTION, ....])
+dnl --------------------------------------------------------------------------
+dnl
+dnl Expanded version of AC_ARG_ENABLE for complex options.  All the parameters
+dnl are required.
+dnl
+define([XE_COMPLEX_ARG_ENABLE],
+[XE_INIT_COMPLEX_OPTION([enable_]patsubst([$1], -, _), m4_shiftn(4, $@))
+AC_ARG_ENABLE([$1],[$2],
+[XE_PARSE_COMPLEX_OPTION([enable_]patsubst([$1], -, _), [--enable-$1])
+$3
+],[$4])
 ])
 
 dnl -------------------------------------------------------------------------
@@ -439,25 +492,20 @@
                         useful, for the same reason as JPEG images.]),
 	[], [])
 
-# Xft uses an option complex similar to sound and database
-XE_INIT_COMPLEX_OPTION([with_xft])
 dnl if you change defaults, make sure to fix arg 6 of the OPTION_HELP macro.
-dnl these should really be enable_xft_*, but COMPLEX_OPTION support doesn't
-dnl grok that mixed with AC_ARG_WITH.
-XE_APPEND_COMPLEX_OPTION_DEFAULT([with_xft],[emacs],[yes])
-XE_APPEND_COMPLEX_OPTION_DEFAULT([with_xft],[menubars],[yes])
-XE_APPEND_COMPLEX_OPTION_DEFAULT([with_xft],[tabs],[yes])
-XE_APPEND_COMPLEX_OPTION_DEFAULT([with_xft],[gauges],[yes])
-dnl handle arguments
-AC_ARG_WITH([xft],
+XE_COMPLEX_ARG_WITH([xft],
 	[XE_COMPLEX_OPTION_HELP_STRING([--with-xft],
 		[Xft client-side font rendering and anti-aliasing],
 		[Xft],
 		[`emacs' (buffers), `menubars', `tabs', and `gauges'],
 		[X11, Xft, Xrender, freetype, and fontconfig],
 		[`emacs,menubars,tabs,gauges'])],
-	[XE_PARSE_COMPLEX_OPTION([with_xft],[--with-xft])],
-	[])
+	[],[],
+	[XE_COMPLEX_OPTION([emacs],[yes]),
+	XE_COMPLEX_OPTION([menubars],[yes]),
+	XE_COMPLEX_OPTION([tabs],[yes]),
+	XE_COMPLEX_OPTION([gauges],[yes])]
+)
 dnl sanity checking
 dnl #### Maybe we should XE_DIE here instead?  Or fix the UI so that
 dnl emacs is always implicit?  (I worry that --without-xft would be weird.)
@@ -466,7 +514,6 @@
     AC_MSG_WARN([Forcing --with-xft=emacs because Xft is enabled])
     with_xft_emacs=yes
 fi
-XE_CLEANUP_COMPLEX_OPTION([with_xft])
 # end of Xft parsing
 AC_ARG_WITH([zlib],
 	AC_HELP_STRING([--with-zlib],[Support inflate (de)compression internally.]),
-- 
		     Malcolm Purvis <malcolmp(a)xemacs.org>