Re: multiline output variables.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Tue, 8 Feb 2005, Stepan Kasal wrote:

> Proof: Let's have an occurence of `@foo@'. If its left `@' wasn't in the
> original input, then it has to be followed by |#_!!_#|, so it's not `@foo',
> contradiction.  So the left `@' had to be inthe original line.
> If some characters of this occurence `@foo@' were inserted by a previous
> substitution, then there would have to be the |#_!!_#| from the beginning
> of the substituted value.
> Thus the whole `@foo@' had to be in the original line, q.e.d.
	Indeedy.

>
> > Note that I changed the deleted string to
> > be a palendrome, since that allows it to be inserted at its own center.
>
> What?  IIRC, the previous suggestion was |#_!_#|, which is also a
> palendrome.  No big deal, of course.
	I have misspoken; I meant that I made it symetric around an empty
string, rather than a central character, so that it has the form abccba,
so that self-escaping it is done in a symetric way: abcabccbacba.  Compare
abcba, which must be escaped as ababcbacba, which is lop-sided.  This
isn't functionally important in the least, but I think the symetry looks
better.  This is probably just a consequence of being OCD enough to write
autoconf code in the first place.

>
> One more comment:
>
> I notice that your patch contains
>
> m4_define([_AC_SED_CMDS],m4_defn([_AC_SED_CMDS])[| sed 's/|#_!!_#|//g' ])
>
> As I have admitted before, I don't (yet) fully understand your patch,
> but this seems a bit suspicious to me.  Does this mean that you use one
> more `sed' call in the pipe to remove these tokens?
	I'm afraid that you have missed something.  I only add this as a
new separate sed command if the previous sed command that does the last of
the substitutions is full.  Think of it not as an "extra" sed command, but
as a simplification of the unusual case of the last fragment being:
	/@word@/!b end
	:end
	s/empty//g

>
> It's clear that you cannot put s/|#_!!_#|//g at the end of each fragment,
> But I think you can put it as the very last command of the last fragment.
> Oh yes, you have to change the last fragment to:
>
> 	/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
> 	...
> 	:end
> 	s/|#_!!_#|//g
	I do do this.  There's some rigamarole to notice when it's
necessary and to append the 'end' label to the 'b' command at the top and
then insert the last two commands.  I even check for the case that there's
room for only one more command, in which case the special-case last sed
fragment described above is used anyway.

>
> but I think it's worth it.  (Perhaps it would help to put the label `:end'
> at the end of each fragment, so that the first command of each fragment
> will be the same.  You can decrease the number of commands for each segment
> by 2 (the label plus possibly s/|#_!!_#|//g).  All this is still better
> than having one more process in the pipe.
	I've changed the label to actually be `end', rather than the `n'
that it was.  I hope this makes the admittedly obscure code faintly more
obvious.  I've made design decision to make the m4 code more complicated
in order to make the sh code more efficient.  I hope others think this is
a good trade-off.

And in your other email you suggested
  for f in 1 2 3; do ...
Which I complicated (rather than simplified) to
  for ac_last_try in false false :; do ...
so that the break-out step avoids one more call to test.

> > My thanks go to Stepan for all the help he's given with this.
>
> I'm glad to generate hints.  But I have stated several times that I cannot
> keep pace with you and I actually don't understand your code.  ;-)
	Then you've been faking it wonderfully so far.  *Grin.*

By the way, I generated the last patch and this one via `cvs diff -u',
which certainly captures all the needed information but I tried actually
applying the patch to a new cvs working copy and couldn't figure out how
to do it, and eventually cut the patch up by hand and applied it manually
to each affected file.  Is there something better I should be doing, or am
I just having a brain fart wrt the use of patch?

-Dan
? multi.diff
? multi2.diff
Index: doc/autoconf.texi
===================================================================
RCS file: /cvsroot/autoconf/autoconf/doc/autoconf.texi,v
retrieving revision 1.877
diff -u -r1.877 autoconf.texi
--- doc/autoconf.texi	8 Feb 2005 17:27:04 -0000	1.877
+++ doc/autoconf.texi	8 Feb 2005 18:53:02 -0000
@@ -4873,6 +4873,39 @@
 # define __bool_true_false_are_defined 1
 #endif
 @end verbatim
+
+However, since output variables can now contain newlines, it is possible
+to construct an output variable that includes only those headers and
+definitions needed, such as:
+
+@verbatim
+AC_HEADER_STDBOOL
+AC_SUBST(stdbool)
+if test "x$ac_cv_header_stdbool_h" = xyes; then
+  stdbool='
+#include <stdbool.h>
+'
+else
+  if test "x$ac_cv_type__Bool" != xyes; then
+    stdbool='
+#ifdef __cplusplus
+typedef bool _Bool;
+#else
+typedef unsigned char _Bool;
+#endif
+'
+  else
+    stdbool='
+'
+  fi
+  stdbool=$stdbool'dnl
+# define bool _Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+'
+fi
+@end verbatim
 @end defmac
 
 
@@ -7297,9 +7330,13 @@
 or more @file{Makefile}s).  This means that @code{AC_OUTPUT} will
 replace instances of @samp{@@@var{variable}@@} in input files with the
 value that the shell variable @var{variable} has when @code{AC_OUTPUT}
-is called.  This value of @var{variable} should not contain literal
-newlines.  (There is currently no portable way to escape literal
-newlines.)
+is called.  It is now permissible for the value to contain newlines.
+The substituted value is not rescanned for more output variables;
+occurences of @samp{@@@var{variable}@@} in the value are inserted
+literally into the output file.  (Actually, the surrounding @code{@@}s
+are surrounded by @code{|#_!!_#|}, and all occurences of @code{|#_!!_#|}
+are ultimately removed.  If by some misfortune, you need a literal
+@code{|#_!!_#|} in your output file, use @code{|#_!|#_!!_#|!_#|}.)
 
 If @var{value} is given, in addition assign it to @var{variable}.
 
@@ -7316,7 +7353,10 @@
 @samp{@@@var{variable}@@} in output files (such as @file{Makefile.in})
 with the contents of the file that the shell variable @var{variable}
 names when @code{AC_OUTPUT} is called.  Set the variable to
-@file{/dev/null} for cases that do not have a file to insert.
+@file{/dev/null} for cases that do not have a file to insert.  This
+substitution only occurs when the @samp{@@@var{variable}@@} is on a line
+by itself, optionally surrounded by spaces and tabs.  The whole line,
+including the spaces, tabs, and the terminating newline, is replaced.
 
 This macro is useful for inserting @file{Makefile} fragments containing
 special dependencies or other @code{make} directives for particular host
Index: lib/autoconf/status.m4
===================================================================
RCS file: /cvsroot/autoconf/autoconf/lib/autoconf/status.m4,v
retrieving revision 1.49
diff -u -r1.49 status.m4
--- lib/autoconf/status.m4	2 Feb 2005 23:31:17 -0000	1.49
+++ lib/autoconf/status.m4	8 Feb 2005 18:53:02 -0000
@@ -850,7 +850,15 @@
 m4_define([AC_LIST_FILES])
 m4_define([AC_LIST_FILES_COMMANDS])
 
-
+# _AC_SED_CMD_LIMIT
+# -----------------
+# Evaluate to an m4 number equal to the maximum number of commands to put
+# in any single sed program.
+#
+# Some seds have small command number limits, like on Digital OSF/1 and HP-UX.
+m4_define([_AC_SED_CMD_LIMIT],
+dnl One cannot portably go further than 100 commands because of HP-UX.
+[100])
 
 # _AC_OUTPUT_FILES
 # ----------------
@@ -860,80 +868,142 @@
 # It has to send itself into $CONFIG_STATUS (eg, via here documents).
 # Upon exit, no here document shall be opened.
 m4_define([_AC_OUTPUT_FILES],
-[cat >>$CONFIG_STATUS <<_ACEOF
-
+[cat >>$CONFIG_STATUS <<\_ACEOF
 #
 # CONFIG_FILES section.
 #
 
 # No need to generate the scripts if there are no CONFIG_FILES.
 # This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
-  # Protect against being on the right side of a sed subst in config.status.
-dnl Please, pay attention that this sed code depends a lot on the shape
-dnl of the sed commands issued by AC_SUBST.  So if you change one, change
-dnl the other too.
-[  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
-   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >"\$tmp/subs.sed" <<\\CEOF]
-dnl These here document variables are unquoted when configure runs
-dnl but quoted when config.status runs, so variables are expanded once.
-dnl Insert the sed substitutions of variables.
-m4_ifdef([_AC_SUBST_VARS],
-	 [AC_FOREACH([AC_Var], m4_defn([_AC_SUBST_VARS]),
-[s,@AC_Var@,$AC_Var,;t t
-])])dnl
-m4_ifdef([_AC_SUBST_FILES],
-	 [AC_FOREACH([AC_Var], m4_defn([_AC_SUBST_FILES]),
-[/@AC_Var@/r $AC_Var
-s,@AC_Var@,,;t t
-])])dnl
-CEOF
+if test -n "$CONFIG_FILES"; then
 
 _ACEOF
 
-  cat >>$CONFIG_STATUS <<\_ACEOF
-  # Split the substitutions into bite-sized pieces for seds with
-  # small command number limits, like on Digital OSF/1 and HP-UX.
-dnl One cannot portably go further than 100 commands because of HP-UX.
-dnl Here, there are 2 cmd per line, and two cmd are added later.
-  ac_max_sed_lines=48
-  ac_sed_frag=1 # Number of current file.
-  ac_beg=1 # First line for current file.
-  ac_end=$ac_max_sed_lines # Line after last line for current file.
-  ac_more_lines=:
-  ac_sed_cmds=
-  while $ac_more_lines; do
-    if test $ac_beg -gt 1; then
-      sed "1,${ac_beg}d; ${ac_end}q" "$tmp/subs.sed" >"$tmp/subs.frag"
-    else
-      sed "${ac_end}q" "$tmp/subs.sed" >"$tmp/subs.frag"
-    fi
-    if test ! -s "$tmp/subs.frag"; then
-      ac_more_lines=false
-    else
-      # The purpose of the label and of the branching condition is to
-      # speed up the sed processing (if there are no `@' at all, there
-      # is no need to browse any of the substitutions).
-      # These are the two extra sed commands mentioned above.
-      (echo [':t
-  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b'] && cat "$tmp/subs.frag") >"$tmp/subs-$ac_sed_frag.sed"
-      if test -z "$ac_sed_cmds"; then
-	ac_sed_cmds="sed -f '$tmp/subs-$ac_sed_frag.sed'"
-      else
-	ac_sed_cmds="$ac_sed_cmds | sed -f '$tmp/subs-$ac_sed_frag.sed'"
-      fi
-      ac_sed_frag=`expr $ac_sed_frag + 1`
-      ac_beg=$ac_end
-      ac_end=`expr $ac_end + $ac_max_sed_lines`
-    fi
-  done
-  if test -z "$ac_sed_cmds"; then
-    ac_sed_cmds=cat
+m4_pushdef([_AC_SED_CMDS], [])dnl Part of pipeline that does substitutions.
+dnl
+m4_pushdef([_AC_SED_FRAG_NUM], 0)dnl Fragment number.
+m4_pushdef([_AC_SED_CMD_NUM], 1)dnl Num of commands in current frag so far.
+m4_pushdef([_AC_SED_DELIM_NUM], 0)dnl Expected number of delimiters in file.
+m4_pushdef([_AC_SED_FRAG], [])dnl The constant part of the current fragment.
+dnl
+m4_ifdef([_AC_SUBST_FILES],
+[# Create sed commands to just substitute file output variables.
+
+AC_FOREACH([_AC_Var], m4_defn([_AC_SUBST_FILES]),
+[dnl End fragments at beginning of loop so that last fragment is not ended.
+m4_if(1,m4_eval(_AC_SED_CMD_NUM+4>_AC_SED_CMD_LIMIT),
+[dnl Fragment is full and not the last one, so no need for the final un-escape.
+dnl Increment fragment number.
+m4_define([_AC_SED_FRAG_NUM],m4_eval(_AC_SED_FRAG_NUM+1))dnl
+dnl Record that this fragment will need to be used.
+m4_define([_AC_SED_CMDS],
+m4_defn([_AC_SED_CMDS])[| sed -f "$tmp/subs-]_AC_SED_FRAG_NUM[.sed" ])dnl
+[cat >>$CONFIG_STATUS <<_ACEOF
+cat >"$tmp/subs-]_AC_SED_FRAG_NUM[.sed" <\CEOF
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+]m4_defn(_AC_SED_FRAG)dnl
+[CEOF
+
+_ACEOF
+]m4_define([_AC_SED_CMD_NUM], 1)m4_define([_AC_SED_FRAG])dnl
+])dnl Last fragment ended.
+m4_define([_AC_SED_CMD_NUM], m4_eval(_AC_SED_CMD_NUM+4))dnl
+m4_define([_AC_SED_FRAG],
+m4_defn([_AC_SED_FRAG])dnl
+[/^[ 	]*@]_AC_Var[@[ 	]*$/{ r $]_AC_Var[
+d; }
+])dnl
+])dnl
+# Remaining file output variables are in a fragment that also has non-file
+# output varibles.
+
+])
+dnl
+m4_define([_AC_SED_FRAG],[
+]m4_defn([_AC_SED_FRAG]))dnl
+AC_FOREACH([_AC_Var],
+m4_ifdef([_AC_SUBST_VARS],[m4_defn([_AC_SUBST_VARS]) ])[@END@],
+[m4_if(_AC_SED_DELIM_NUM,0,
+[m4_if(_AC_Var,[@END@],
+[dnl The whole of the last fragment would be the final deletion of `|#_!!_#|'.
+m4_define([_AC_SED_CMDS],m4_defn([_AC_SED_CMDS])[| sed 's/|#_!!_#|//g' ])],
+[
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+])])dnl
+m4_if(_AC_Var,[ac_delim],
+[dnl Just to be on the safe side, claim that $ac_delim is the empty string.
+m4_define([_AC_SED_FRAG],
+m4_defn([_AC_SED_FRAG])dnl
+[s,ac_delim,|#_!!_#|,g
+])dnl
+m4_define([_AC_SED_CMD_NUM], m4_eval(_AC_SED_CMD_NUM+1))],
+      _AC_Var,[@END@],
+      [m4_if(1,m4_eval(_AC_SED_CMD_NUM+2<=_AC_SED_CMD_LIMIT),
+             [m4_define([_AC_SED_FRAG], [ end]m4_defn([_AC_SED_FRAG]))])],
+[m4_define([_AC_SED_CMD_NUM], m4_eval(_AC_SED_CMD_NUM+1))dnl
+m4_define([_AC_SED_DELIM_NUM], m4_eval(_AC_SED_DELIM_NUM+1))dnl
+_AC_Var!$_AC_Var$ac_delim
+])dnl
+m4_if(_AC_SED_CMD_LIMIT,
+      m4_if(_AC_Var,[@END@],_AC_SED_CMD_LIMIT,_AC_SED_CMD_NUM),
+[_ACEOF
+
+  if test `grep -c "$ac_delim\$" conf$$subs.sed` = _AC_SED_DELIM_NUM; then
+    break
+  elif $ac_last_try; then
+    AC_MSG_ERROR([could not make $CONFIG_STATUS])
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
   fi
-fi # test -n "$CONFIG_FILES"
+done
 
+ac_eof=
+while grep -q "^CEOF$ac_eof\$" conf$$subs.sed; do
+  ac_eof=`expr $ac_eof + 1`
+done
+
+dnl Increment fragment number.
+m4_define([_AC_SED_FRAG_NUM],m4_eval(_AC_SED_FRAG_NUM+1))dnl
+dnl Record that this fragment will need to be used.
+m4_define([_AC_SED_CMDS],
+m4_defn([_AC_SED_CMDS])[| sed -f "$tmp/subs-]_AC_SED_FRAG_NUM[.sed" ])dnl
+[cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-]_AC_SED_FRAG_NUM[.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b]m4_defn([_AC_SED_FRAG])dnl
+[_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^[^\n]*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+]m4_if(_AC_Var,[@END@],
+[m4_if(1,m4_eval(_AC_SED_CMD_NUM+2>_AC_SED_CMD_LIMIT),
+[m4_define([_AC_SED_CMDS],m4_defn([_AC_SED_CMDS])[| sed 's/|#_!!_#|//g' ])],
+[[:end
+s/|#_!!_#|//g
+]])])dnl
+CEOF$ac_eof
 _ACEOF
+m4_define([_AC_SED_FRAG], [
+])m4_define([_AC_SED_DELIM_NUM], 0)m4_define([_AC_SED_CMD_NUM], 1)dnl
+
+])])dnl
+dnl
+m4_popdef([_AC_SED_FRAG_NUM])dnl
+m4_popdef([_AC_SED_CMD_NUM])dnl
+m4_popdef([_AC_SED_DELIM_NUM])dnl
+m4_popdef([_AC_SED_FRAG])dnl
+dnl
 cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
 for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
   # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
   case $ac_file in
@@ -1018,8 +1088,8 @@
 s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
 AC_PROVIDE_IFELSE([AC_PROG_INSTALL], [s,@INSTALL@,$ac_INSTALL,;t t
 ])dnl
-dnl The parens around the eval prevent an "illegal io" in Ultrix sh.
-" $ac_file_inputs | (eval "$ac_sed_cmds") >"$tmp/out"
+" $ac_file_inputs m4_defn([_AC_SED_CMDS])>$tmp/out
+m4_popdef([_AC_SED_CMDS])dnl
   rm -f "$tmp/stdin"
 dnl This would break Makefile dependencies.
 dnl  if diff $ac_file "$tmp/out" >/dev/null 2>&1; then
Index: tests/torture.at
===================================================================
RCS file: /cvsroot/autoconf/autoconf/tests/torture.at,v
retrieving revision 1.50
diff -u -r1.50 torture.at
--- tests/torture.at	5 Feb 2005 07:34:54 -0000	1.50
+++ tests/torture.at	8 Feb 2005 18:53:02 -0000
@@ -556,7 +556,6 @@
 ## ---------------------- ##
 
 AT_SETUP([Substitute a newline])
-AT_XFAIL_IF(:)
 
 AT_DATA([Foo.in],
 [@foo@
_______________________________________________
Autoconf mailing list
Autoconf@xxxxxxx
http://lists.gnu.org/mailman/listinfo/autoconf

[Index of Archives]     [GCC Help]     [Kernel Discussion]     [RPM Discussion]     [Red Hat Development]     [Yosemite News]     [Linux USB]     [Samba]

  Powered by Linux