Test it.
* acgeneral.m4 (AC_OUTPUT_HEADERS): Renamed as...
(_AC_OUTPUT_HEADERS): this. All callers changed.
Don't mess with changequote, just quote properly.
Bug 1. Because of the `#' in `ac_dA', the quotes <<>> were not
removed, and therefore the sed script contained `<<define>>'
instead of `define'. Now that the block is properly quoted, there
is no need to quote `define'.
Bug 2. Once a `#define' substitution performed, we were branching
to the top of the sed script (`t top'). This resulted in an
endless substitution of `#define foo 1' to `#define foo 1'.
Branching is not enough: you also have to fetch the next input
line, i.e., use `t' instead of `t t' in ac_dD, and don't output
`: top' in `config.defines'.
Though it was correct for `#undef' templates, just apply the same
transformation to `ac_uD' and `config.undefs'.
Bug 3. Don't try to preserve what was behind the value in the
template, since on
#define NAME "bar baz"
it leads to
#define NAME 1 baz"
Now `ac_dB' catches everything behind the NAME (making sure there
is at least a space) and `ac_dC' only outputs a space.
* tests/torture.m4: Check that various forms of `#define' header
templates are properly handled.
+2000-02-10 Akim Demaille <akim@epita.fr>
+
+ Honor properly the `#define' config.h.in templates.
+ Test it.
+
+ * acgeneral.m4 (AC_OUTPUT_HEADERS): Renamed as...
+ (_AC_OUTPUT_HEADERS): this. All callers changed.
+ Don't mess with changequote, just quote properly.
+ Bug 1. Because of the `#' in `ac_dA', the quotes <<>> were not
+ removed, and therefore the sed script contained `<<define>>'
+ instead of `define'. Now that the block is properly quoted, there
+ is no need to quote `define'.
+ Bug 2. Once a `#define' substitution performed, we were branching
+ to the top of the sed script (`t top'). This resulted in an
+ endless substitution of `#define foo 1' to `#define foo 1'.
+ Branching is not enough: you also have to fetch the next input
+ line, i.e., use `t' instead of `t t' in ac_dD, and don't output
+ `: top' in `config.defines'.
+ Though it was correct for `#undef' templates, just apply the same
+ transformation to `ac_uD' and `config.undefs'.
+ Bug 3. Don't try to preserve what was behind the value in the
+ template, since on
+ #define NAME "bar baz"
+ it leads to
+ #define NAME 1 baz"
+ Now `ac_dB' catches everything behind the NAME (making sure there
+ is at least a space) and `ac_dC' only outputs a space.
+ * tests/torture.m4: Check that various forms of `#define' header
+ templates are properly handled.
+
2000-02-10 Akim Demaille <akim@epita.fr>
Avoid calling `rm' without arguments.
AC_OUTPUT_FILES()dnl
AC_DIVERT_POP()])dnl
ifset([AC_LIST_HEADERS],
- [AC_OUTPUT_HEADERS()])dnl
+ [_AC_OUTPUT_HEADERS()])dnl
ifset([AC_LIST_LINKS],
[AC_OUTPUT_LINKS()])dnl
ifset([AC_LIST_COMMANDS],
# Set the DEFS variable to the -D options determined earlier.
# This is a subroutine of AC_OUTPUT.
# It is called inside configure, outside of config.status.
-# FIXME: This has to be fixed the same way as in AC_OUTPUT_HEADERS.
+# FIXME: This has to be fixed the same way as in _AC_OUTPUT_HEADERS.
define(AC_OUTPUT_MAKE_DEFS,
[# Transform confdefs.h into DEFS.
dnl Using a here document instead of a string reduces the quoting nightmare.
])# AC_OUTPUT_FILES
-# AC_OUTPUT_HEADERS
-# -----------------
-# Create the config.h files from the config.h.in files.
-# This is a subroutine of AC_OUTPUT.
+# _AC_OUTPUT_HEADERS
+# ------------------
#
-# It has to send itself into $CONFIG_STATUS (eg, via here documents).
-# Upon exit, no here document shall be opened.
-define(AC_OUTPUT_HEADERS,
+# Output the code which instantiates the `config.h' files from their
+# `config.h.in'.
+#
+# This is a subroutine of _AC_OUTPUT_CONFIG_STATUS. It has to send
+# itself into $CONFIG_STATUS (eg, via here documents). Upon exit, no
+# here document shall be opened.
+#
+#
+# The code produced used to be extremely costly: there are was a
+# single sed script (n lines) handling both `#define' templates,
+# `#undef' templates with trailing space, and `#undef' templates
+# without trailing spaces. The full script was run on each of the m
+# lines of `config.h.in', i.e., about n x m.
+#
+# Now there are two scripts: `conftest.defines' for the `#define'
+# templates, and `conftest.undef' for the `#undef' templates.
+#
+# Optimization 1. It is incredibly costly to run two `#undef'
+# scripts, so just remove trailing spaces first. Removes about a
+# third of the cost.
+#
+# Optimization 2. Since `#define' are rare and obsoleted,
+# `conftest.defines' is built and run only if grep says there are
+# `#define'. Improves by at least a factor 2, since in addition we
+# avoid the cost of *producing* the sed script.
+#
+# Optimization 3. In each script, first check that the current input
+# line is a template. This avoids running the full sed script on
+# empty lines and comments (divides the cost by about 3 since each
+# template chunk is typically a comment, a template, an empty line).
+#
+# Optimization 4. Once a substitution performed, since there can be
+# only one per line, immediately restart the script on the next input
+# line (using the `t' sed instruction). Divides by about 2.
+# *Note:* In the case of the AC_SUBST sed script (AC_OUTPUT_FILES)
+# this optimization cannot be applied as is, because there can be
+# several substitutions per line.
+#
+#
+# The result is about, hm, ... times blah... plus.... Ahem. The
+# result is about much faster.
+define(_AC_OUTPUT_HEADERS,
[cat >>$CONFIG_STATUS <<\EOF
-changequote(<<, >>)dnl
#
# CONFIG_HEADER section.
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.
-ac_dA='s%^\([ ]*\)#\([ ]*<<define>>[ ][ ]*\)'
-ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
-ac_dC='\3'
-ac_dD='%;t t'
+dnl Double quote for the `[ ]' and `define'.
+[ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$%\1#\2'
+ac_dC=' '
+ac_dD='%;t'
# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
-ac_uB='<<$>>%\1#\2define\3'
+ac_uB='$%\1#\2define\3'
ac_uC=' '
-ac_uD='%;t t'
-changequote([, ])dnl
+ac_uD='%;t']
for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
changequote(, )dnl
# Write a limited-size here document to $ac_cs_root.frag.
echo ' cat >$ac_cs_root.frag <<CEOF' >>$CONFIG_STATUS
dnl Speed up: don't consider the non `#define' lines.
- echo ': t' >>$CONFIG_STATUS
echo '/^@BKL@ @BKR@*#@BKL@ @BKR@*define/!b' >>$CONFIG_STATUS
sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
echo 'CEOF
# Write a limited-size here document to $ac_cs_root.frag.
echo ' cat >$ac_cs_root.frag <<CEOF' >>$CONFIG_STATUS
dnl Speed up: don't consider the non `#undef'
- echo ': t' >>$CONFIG_STATUS
echo '/^@BKL@ @BKR@*#@BKL@ @BKR@*undef/!b' >>$CONFIG_STATUS
sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
echo 'CEOF
])dnl
fi; done
EOF
-])# AC_OUTPUT_HEADERS
+])# _AC_OUTPUT_HEADERS
# AC_OUTPUT_LINKS
AC_OUTPUT_FILES()dnl
AC_DIVERT_POP()])dnl
ifset([AC_LIST_HEADERS],
- [AC_OUTPUT_HEADERS()])dnl
+ [_AC_OUTPUT_HEADERS()])dnl
ifset([AC_LIST_LINKS],
[AC_OUTPUT_LINKS()])dnl
ifset([AC_LIST_COMMANDS],
# Set the DEFS variable to the -D options determined earlier.
# This is a subroutine of AC_OUTPUT.
# It is called inside configure, outside of config.status.
-# FIXME: This has to be fixed the same way as in AC_OUTPUT_HEADERS.
+# FIXME: This has to be fixed the same way as in _AC_OUTPUT_HEADERS.
define(AC_OUTPUT_MAKE_DEFS,
[# Transform confdefs.h into DEFS.
dnl Using a here document instead of a string reduces the quoting nightmare.
])# AC_OUTPUT_FILES
-# AC_OUTPUT_HEADERS
-# -----------------
-# Create the config.h files from the config.h.in files.
-# This is a subroutine of AC_OUTPUT.
+# _AC_OUTPUT_HEADERS
+# ------------------
#
-# It has to send itself into $CONFIG_STATUS (eg, via here documents).
-# Upon exit, no here document shall be opened.
-define(AC_OUTPUT_HEADERS,
+# Output the code which instantiates the `config.h' files from their
+# `config.h.in'.
+#
+# This is a subroutine of _AC_OUTPUT_CONFIG_STATUS. It has to send
+# itself into $CONFIG_STATUS (eg, via here documents). Upon exit, no
+# here document shall be opened.
+#
+#
+# The code produced used to be extremely costly: there are was a
+# single sed script (n lines) handling both `#define' templates,
+# `#undef' templates with trailing space, and `#undef' templates
+# without trailing spaces. The full script was run on each of the m
+# lines of `config.h.in', i.e., about n x m.
+#
+# Now there are two scripts: `conftest.defines' for the `#define'
+# templates, and `conftest.undef' for the `#undef' templates.
+#
+# Optimization 1. It is incredibly costly to run two `#undef'
+# scripts, so just remove trailing spaces first. Removes about a
+# third of the cost.
+#
+# Optimization 2. Since `#define' are rare and obsoleted,
+# `conftest.defines' is built and run only if grep says there are
+# `#define'. Improves by at least a factor 2, since in addition we
+# avoid the cost of *producing* the sed script.
+#
+# Optimization 3. In each script, first check that the current input
+# line is a template. This avoids running the full sed script on
+# empty lines and comments (divides the cost by about 3 since each
+# template chunk is typically a comment, a template, an empty line).
+#
+# Optimization 4. Once a substitution performed, since there can be
+# only one per line, immediately restart the script on the next input
+# line (using the `t' sed instruction). Divides by about 2.
+# *Note:* In the case of the AC_SUBST sed script (AC_OUTPUT_FILES)
+# this optimization cannot be applied as is, because there can be
+# several substitutions per line.
+#
+#
+# The result is about, hm, ... times blah... plus.... Ahem. The
+# result is about much faster.
+define(_AC_OUTPUT_HEADERS,
[cat >>$CONFIG_STATUS <<\EOF
-changequote(<<, >>)dnl
#
# CONFIG_HEADER section.
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.
-ac_dA='s%^\([ ]*\)#\([ ]*<<define>>[ ][ ]*\)'
-ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
-ac_dC='\3'
-ac_dD='%;t t'
+dnl Double quote for the `[ ]' and `define'.
+[ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$%\1#\2'
+ac_dC=' '
+ac_dD='%;t'
# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
-ac_uB='<<$>>%\1#\2define\3'
+ac_uB='$%\1#\2define\3'
ac_uC=' '
-ac_uD='%;t t'
-changequote([, ])dnl
+ac_uD='%;t']
for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
changequote(, )dnl
# Write a limited-size here document to $ac_cs_root.frag.
echo ' cat >$ac_cs_root.frag <<CEOF' >>$CONFIG_STATUS
dnl Speed up: don't consider the non `#define' lines.
- echo ': t' >>$CONFIG_STATUS
echo '/^@BKL@ @BKR@*#@BKL@ @BKR@*define/!b' >>$CONFIG_STATUS
sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
echo 'CEOF
# Write a limited-size here document to $ac_cs_root.frag.
echo ' cat >$ac_cs_root.frag <<CEOF' >>$CONFIG_STATUS
dnl Speed up: don't consider the non `#undef'
- echo ': t' >>$CONFIG_STATUS
echo '/^@BKL@ @BKR@*#@BKL@ @BKR@*undef/!b' >>$CONFIG_STATUS
sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
echo 'CEOF
])dnl
fi; done
EOF
-])# AC_OUTPUT_HEADERS
+])# _AC_OUTPUT_HEADERS
# AC_OUTPUT_LINKS
], ignore)
AT_CLEANUP(configure config.status config.log config.cache)
+
+
+
+## -------------------------------------------- ##
+## Check that `#define' templates are honored. ##
+## -------------------------------------------- ##
+
+# Use various forms of `#define' templates, and make sure there are no
+# problems when a symbol is prefix of another.
+
+AT_SETUP([#define header templates])
+
+AT_DATA(configure.in,
+[[AC_INIT
+AC_CONFIG_HEADERS(config.h:config.hin)
+# I18n of dummy variables: their French translations.
+AC_DEFINE(foo, toto)
+AC_DEFINE(bar, tata)
+AC_DEFINE(baz, titi)
+AC_DEFINE(fubar, tutu)
+# Symbols which are prefixes of another.
+AC_DEFINE(a, A)
+AC_DEFINE(aaa, AAA)
+AC_DEFINE(aa, AA)
+AC_OUTPUT
+]])
+
+AT_DATA(config.hin,
+[[#define foo 0
+# define bar bar
+# define baz "Archimedes was sinking in his baz"
+# define fubar tutu
+#define a B
+#define aa BB
+#define aaa BBB
+#undef a
+#undef aa
+#undef aaa
+]])
+
+AT_DATA(expout,
+[[/* config.h. Generated automatically by configure. */
+#define foo toto
+# define bar tata
+# define baz titi
+# define fubar tutu
+#define a A
+#define aa AA
+#define aaa AAA
+#define a A
+#define aa AA
+#define aaa AAA
+]])
+
+AT_CHECK([../autoconf -m .. -l $at_srcdir], 0)
+AT_CHECK([./configure], 0, ignore)
+AT_CHECK([cat config.h], 0, expout)
+
+AT_CLEANUP(configure config.status config.log config.cache config.h)