autoconf-patches
[Top][All Lists]
Advanced

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

Re: proposed Autoconf patch so that "configure" need not use Awk


From: Paul Eggert
Subject: Re: proposed Autoconf patch so that "configure" need not use Awk
Date: Wed, 31 Oct 2001 11:43:29 -0800 (PST)

> From: Akim Demaille <address@hidden>
> Date: 31 Oct 2001 15:28:53 +0100

> | 1.  The GNU Coding Standards suggest that we not use Awk.
> 
> IMHO this is wrong from the portability point of view.

I tend to agree with you.  I will try to convince RMS to add Awk to
the list; that would remove this objection (but not the other two).

> I never played with multiline pattern spaces.  I trust you about the
> portability of s/.*\n//

That stuff has been in 'sed' ever since the early days, so it should
be portable.  (One never knows till one tries, of course.)

We're peering into the origin of Unix here.  I knew people at Bell
Labs though I never worked there myself.  The late Lee E. McMahon, the
original author of 'sed', was a fellow student at Rice University in
the early 1970s before he went off to Bell Labs to write 'sed'.
McMahon and the late Joe Ossanna (who wrote 'troff') were the two guys
who convinced management to buy a new PDP-11 computer for word
processing, an important milestone in the original development of Unix.

> it is not clear to me who ^ and $ are: the usual ones, or they refer
> to the beginning and end of the pattern space.

The latter.  I've never run into the former (incorrect) behavior in
practice.

> In any case, I'm surprised by s/ $//;s/.*\n//.  I would be less
> surprised, I guess, with s/ $//g;s/.*\n//.

You don't want the 'g', because that would remove trailing white space
from the input script.  For each line, there is a single s/$/ / at the
start, and this needs to be undone by a single s/ $// at the end.  We
need to insert the trailing ' ' so that trailing '$LINENO' is handled
correctly.  (Any trailing character will do, so long as it's not
alphanumeric or _.)  This is all a bit tricky, admittedly -- but it is
just as tricky with Awk, since the same problem occurs if we use an
Awk prepass instead of Sed.

> | Both commands work, but the Sed version is shorter and easier to follow,
> | assuming you know both Awk and Sed.
> 
> OK, I'm convinced.

Great!  I installed it, along with some commentary and minor changes
suggested by the above discussion.  Here's the patch I installed:

2001-10-31  Paul Eggert  <address@hidden>

        * lib/m4sugar/m4sh.m4 (_AS_LINENO_PREPARE): Use Sed rather than
        Awk.  Fix the sed prepass to work even if there are multiple
        instances of $LINENO on the same line.  Do not substitute for
        other variables like $LINENOT.  Do not check file dates; such a
        check is unreliable on sufficiently fast machines, and removing
        the check makes the code simpler and more reliable.  Check for
        output and chmod failures.

        * doc/autoconf.texi (Special Shell Variables): Document
        the above.

Index: lib/m4sugar/m4sh.m4
===================================================================
RCS file: /cvsroot/autoconf/autoconf/lib/m4sugar/m4sh.m4,v
retrieving revision 1.67
diff -p -u -r1.67 m4sh.m4
--- lib/m4sugar/m4sh.m4 2001/10/26 19:52:43     1.67
+++ lib/m4sugar/m4sh.m4 2001/10/31 19:20:01
@@ -474,15 +474,11 @@ m4_define([_AS_LINENO_WORKS],
 # _AS_LINENO_PREPARE
 # ------------------
 # If LINENO is not supported by the shell, produce a version of this
-# script where LINENO is hard coded.  Rewrite if not up to date only.
+# script where LINENO is hard coded.
 # Comparing LINENO against _oline_ is not a good solution, since in
 # the case of embedded executables (such as config.status within
 # configure) you'd compare LINENO wrt config.status vs. _oline_ vs
-# configure.  Hence a useless rewrite (not to mention the risk of
-# ``infinite'' rewrites.  Merely check that LINENO is incremented
-# between two lines, which is a property guaranteed for _oline_, hence
-# it protects us from repetitive rewrites.  Be sure to have a test
-# that does detect non LINENO support...
+# configure.
 m4_define([_AS_LINENO_PREPARE],
 [_AS_LINENO_WORKS || {
   # Find who we are.  Look in the path if we contain no path at all
@@ -515,19 +511,27 @@ m4_define([_AS_LINENO_PREPARE],
         esac
        done]);;
   esac
-  if test ! -f "$as_me.lineno" ||
-     test x`ls -1dt "$as_me.lineno" "$as_myself" 2>/dev/null | sed 1q` \
-                != x"$as_me.lineno"; then
-     # Be sure to write the pattern so that it doesn't replace itself:
-     # it must not match itself.
-     awk <$as_myself '
-           /[[$]]LINENO/ { printf "%d:", NR }
-                         { print }
-         ' |
-       sed ['/[$]LINENO/s/^\([0-9][0-9]*\):\(.*\)[$]LINENO/\2\1/'] \
-         >$as_me.lineno
-    chmod +x $as_me.lineno
-  fi
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\([[0-9]]*\)\(.*\)[[$]]LINENO\([[^a-zA-Z0-9_]]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^[[0-9]]*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    AS_ERROR([cannot create $as_me.lineno; rerun with a POSIX shell])
 
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
Index: doc/autoconf.texi
===================================================================
RCS file: /cvsroot/autoconf/autoconf/doc/autoconf.texi,v
retrieving revision 1.555
diff -p -u -r1.555 autoconf.texi
--- doc/autoconf.texi   2001/10/26 19:52:07     1.555
+++ doc/autoconf.texi   2001/10/31 19:21:37
@@ -8190,16 +8190,17 @@ Most modern shells provide the current l
 Its value is the line number of the beginning of the current command.
 Autoconf attempts to execute @command{configure} with a modern shell.
 If no such shell is available, it attempts to implement @code{LINENO}
-with a simple Awk+Sed prepass that replaces the first instance of the
-string @code{$LINENO} in each line with the line's number.
+with a Sed prepass that replaces the each instance of the string
address@hidden (not followed by an alphanumeric character) with the
+line's number.
 
 You should not rely on @code{LINENO} within @command{eval}, as the
-behavior differs in practice.  Also, the possibility of the Awk+Sed
+behavior differs in practice.  Also, the possibility of the Sed
 prepass means that you should not rely on @code{$LINENO} when quoted,
 when in here-documents, or when in long commands that cross line
-boundaries or that have multiple instances of $LINENO.  Subshells
-should be OK, though.  In the following example, lines 1, 6, and 10
-are portable, but the other instances of @code{LINENO} are not:
+boundaries.  Subshells should be OK, though.  In the following
+example, lines 1, 6, and 9 are portable, but the other instances of
address@hidden are not:
 
 @example
 @group
@@ -8211,10 +8212,9 @@ cat <<EOF
 EOF
 ( echo 6. $LINENO )
 eval 'echo 7. $LINENO'
-echo 8. $LINENO $LINENO
-echo 9. '$LINENO'
-echo 10. $LINENO '
-11.' $LINENO
+echo 8. '$LINENO'
+echo 9. $LINENO '
+10.' $LINENO
 @end group
 @group
 $ @kbd{bash-2.05 lineno}
@@ -8223,10 +8223,9 @@ $ @kbd{bash-2.05 lineno}
 4. 2
 6. 6
 7. 1
-8. 8 8
-9. $LINENO
-10. 10 
-11. 10
+8. $LINENO
+9. 9
+10. 9
 @end group
 @group
 $ @kbd{zsh-3.0.6 lineno}
@@ -8235,10 +8234,9 @@ $ @kbd{zsh-3.0.6 lineno}
 4. 2
 6. 6
 7. 7
-8. 8 8
-9. $LINENO
-10. 10 
-11. 10
+8. $LINENO
+9. 9
+10. 9
 @end group
 @group
 $ @kbd{pdksh-5.2.14 lineno}
@@ -8247,15 +8245,22 @@ $ @kbd{pdksh-5.2.14 lineno}
 4. 2
 6. 6
 7. 0
-8. 8 8
-9. $LINENO
-10. 10 
-11. 10
+8. $LINENO
+9. 9
+10. 9
 @end group
 @group
-$ @kbd{awk '/\$LINENO/@{printf "%d:", address@hidden; @address@hidden' lineno 
|}
-> @kbd{sed '/\$LINENO/s/^\([^:]*\):\(.*\)\$LINENO/\2\1/' |}
-> @kbd{sh}
+$ @kbd{sed '=' <lineno |}
+> @kbd{  sed '}
+> @kbd{    N}
+> @kbd{    s,$,-,}
+> @kbd{    : loop}
+> @kbd{    s,^\([0-9]*\)\(.*\)[$]LINENO\([^a-zA-Z0-9_]\),\1\2\1\3,}
+> @kbd{    t loop}
+> @kbd{    s,-$,,}
+> @kbd{    s,^[0-9]*\n,,}
+> @kbd{  ' |}
+> @kbd{  sh}
 1. 1
 3. 3
 4. 4
@@ -8264,7 +8269,6 @@ $ @kbd{awk '/\$LINENO/@{printf "%d:", NR
 8. 8
 9. 9
 10. 10 
-11. 11
 @end group
 @end example
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]