From: Akim Demaille Date: Thu, 10 Feb 2000 10:38:59 +0000 (+0000) Subject: Honor properly the `#define' config.h.in templates. X-Git-Tag: autoconf-2.50~1156 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=08de8c9f931365ac8a2dbcdf988dceee7c093753;p=thirdparty%2Fautoconf.git 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 `<>' 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. --- diff --git a/ChangeLog b/ChangeLog index af33e84c3..ac7cceb70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2000-02-10 Akim Demaille + + 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 `<>' + 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 Avoid calling `rm' without arguments. diff --git a/acgeneral.m4 b/acgeneral.m4 index d5744122f..4d698e503 100644 --- a/acgeneral.m4 +++ b/acgeneral.m4 @@ -3585,7 +3585,7 @@ ifset([AC_LIST_FILES], 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], @@ -3609,7 +3609,7 @@ chmod +x $CONFIG_STATUS # 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. @@ -3827,16 +3827,52 @@ EOF ])# 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. @@ -3846,16 +3882,16 @@ changequote(<<, >>)dnl # 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%^\([ ]*\)#\([ ]*<>[ ][ ]*\)' -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 @@ -3946,7 +3982,6 @@ do # Write a limited-size here document to $ac_cs_root.frag. echo ' cat >$ac_cs_root.frag <>$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 @@ -3971,7 +4006,6 @@ do # Write a limited-size here document to $ac_cs_root.frag. echo ' cat >$ac_cs_root.frag <>$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 @@ -4016,7 +4050,7 @@ AC_LIST_HEADERS_COMMANDS()dnl ])dnl fi; done EOF -])# AC_OUTPUT_HEADERS +])# _AC_OUTPUT_HEADERS # AC_OUTPUT_LINKS diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4 index d5744122f..4d698e503 100644 --- a/lib/autoconf/general.m4 +++ b/lib/autoconf/general.m4 @@ -3585,7 +3585,7 @@ ifset([AC_LIST_FILES], 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], @@ -3609,7 +3609,7 @@ chmod +x $CONFIG_STATUS # 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. @@ -3827,16 +3827,52 @@ EOF ])# 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. @@ -3846,16 +3882,16 @@ changequote(<<, >>)dnl # 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%^\([ ]*\)#\([ ]*<>[ ][ ]*\)' -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 @@ -3946,7 +3982,6 @@ do # Write a limited-size here document to $ac_cs_root.frag. echo ' cat >$ac_cs_root.frag <>$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 @@ -3971,7 +4006,6 @@ do # Write a limited-size here document to $ac_cs_root.frag. echo ' cat >$ac_cs_root.frag <>$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 @@ -4016,7 +4050,7 @@ AC_LIST_HEADERS_COMMANDS()dnl ])dnl fi; done EOF -])# AC_OUTPUT_HEADERS +])# _AC_OUTPUT_HEADERS # AC_OUTPUT_LINKS diff --git a/tests/torture.m4 b/tests/torture.m4 index 9d177aba5..9a6b88ffb 100644 --- a/tests/torture.m4 +++ b/tests/torture.m4 @@ -117,3 +117,62 @@ AT_CHECK([./config.status --recheck | sed -n -e 's/^result=//p'], 0, ], 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)