[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: AS_DIRNAME and expr
From: |
Akim Demaille |
Subject: |
Re: AS_DIRNAME and expr |
Date: |
29 Nov 2000 16:53:01 +0100 |
User-agent: |
Gnus/5.0807 (Gnus v5.8.7) XEmacs/21.1 (Channel Islands) |
Here is my proposal for fixing and documenting our expr problems. I'm
applying it now so that David may run the test suite and check the
issue is indeed fixed, but of course any request for modification will
be honored.
I'm happy to (hopefully) close this thread, it was getting obscure :)
Index: ChangeLog
from Akim Demaille <address@hidden>
QNX 4.2.5's expr always exits 1 when `:' is used with parens.
* doc/autoconf.texi (Limitations of Usual Tools) <expr>: More
information, thanks to Paul Berrevoets, Paul Eggert and David
Morgan.
* sh.m4 (_AS_EXPR_PREPARE): New.
(AS_DIRNAME): Use it.
Index: THANKS
===================================================================
RCS file: /cvs/autoconf/THANKS,v
retrieving revision 1.44
diff -u -u -r1.44 THANKS
--- THANKS 2000/11/10 12:10:13 1.44
+++ THANKS 2000/11/29 15:45:10
@@ -28,6 +28,7 @@
Cort Dougan address@hidden
Dave Adams address@hidden
Dave Love address@hidden
+David Morgan address@hidden
Didier Desseaux address@hidden
Didier Verna address@hidden
Dietmar P. Schindler address@hidden
@@ -98,6 +99,7 @@
Noah Friedman address@hidden
Ossama Othman address@hidden
Patrick Tullmann address@hidden
+Paul Berrevoets address@hidden
Paul Eggert address@hidden
Paul Gampe address@hidden
Paul Martinolich address@hidden
Index: m4sh.m4
===================================================================
RCS file: /cvs/autoconf/m4sh.m4,v
retrieving revision 1.12
diff -u -u -r1.12 m4sh.m4
--- m4sh.m4 2000/11/29 10:09:44 1.12
+++ m4sh.m4 2000/11/29 15:45:16
@@ -66,6 +66,7 @@
set -o posix
fi
+_AS_EXPR_PREPARE
_AS_UNSET_PREPARE
# NLS nuisances.
@@ -242,29 +245,13 @@
-## ------------------------------------------- ##
-## 4. Portable versions of common file utils. ##
-## ------------------------------------------- ##
+## -------------------------------------- ##
+## 4. Portable versions of common tools. ##
+## -------------------------------------- ##
# This section is lexicographically sorted.
# AS_DIRNAME(PATHNAME)
# --------------------
# Simulate running `dirname(1)' on PATHNAME, not all systems have it.
@@ -276,14 +263,20 @@
# a silly length limit that causes expr to fail if the matched
# substring is longer than 120 bytes. So fall back on echo|sed if
# expr fails.
-m4_define([AS_DIRNAME_EXPR],
-[expr X[]$1 : 'X\(.*[[^/]]\)//*[[^/][^/]]*/*$' \| \
- X[]$1 : 'X\(//\)[[^/]]' \| \
- X[]$1 : 'X\(//\)$' \| \
- X[]$1 : 'X\(/\)' \| \
- . : '\(.\)'])
+#
+# FIXME: Please note the following m4_require is quite wrong: if the first
+# occurrence of AS_DIRNAME_EXPR is in a backquoted expression, the
+# shell will be lost. We might have to introduce diversions for
+# setting up an M4sh script: required macros will them be expanded there.
+m4_defun([AS_DIRNAME_EXPR],
+[m4_require([_AS_EXPR_PREPARE])dnl
+$as_expr X[]$1 : 'X\(.*[[^/]]\)//*[[^/][^/]]*/*$' \| \
+ X[]$1 : 'X\(//\)[[^/]]' \| \
+ X[]$1 : 'X\(//\)$' \| \
+ X[]$1 : 'X\(/\)' \| \
+ . : '\(.\)'])
-m4_define([AS_DIRNAME_SED],
+m4_defun([AS_DIRNAME_SED],
[echo X[]$1 |
sed ['/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
/^X\(\/\/\)[^/].*/{ s//\1/; q; }
@@ -291,9 +284,39 @@
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q']])
-m4_define([AS_DIRNAME],
+m4_defun([AS_DIRNAME],
[AS_DIRNAME_EXPR([$1]) 2>/dev/null ||
AS_DIRNAME_SED([$1])])
+
+
+# _AS_EXPR_PREPARE
+# ----------------
+# Some expr work properly (i.e. compute and issue the right result),
+# but exit with failure. When a fall back to expr (as in AS_DIRNAME)
+# is provided, you get twice the result. Prevent this.
+m4_defun([_AS_EXPR_PREPARE],
+[as_expr=`expr a : '\(a\)'`
+case $as_expr,$? in
+ a,0) as_expr=expr;;
+ *) as_expr=false;;
+esac[]dnl
+])# _AS_EXPR_PREPARE
+
Index: doc/autoconf.texi
===================================================================
RCS file: /cvs/autoconf/doc/autoconf.texi,v
retrieving revision 1.394
diff -u -u -r1.394 autoconf.texi
--- doc/autoconf.texi 2000/11/28 18:58:16 1.394
+++ doc/autoconf.texi 2000/11/29 15:46:17
@@ -5825,42 +5825,95 @@
@item @command{expr}
@cindex @command{expr}
No @command{expr} keyword starts with @samp{x}, so use @samp{expr
-x"@var{word}" : '@var{regex}'} to keep @command{expr} from
+x"@var{word}" : 'address@hidden'} to keep @command{expr} from
misinterpreting @var{word}.
-You can use @samp{|}. There is one portability problem occuring when
-you @samp{|} together the empty string (or zero) with the empty string.
-For example:
+Don't use @code{length}, @code{substr}, @code{match} and @code{index}.
+
address@hidden @command{expr} (@samp{|})
address@hidden @command{expr} (@samp{|})
+You can use @samp{|}. Although @sc{posix} does require that @samp{expr
+''} return the empty string, it does not specify the result when you
address@hidden|} together the empty string (or zero) with the empty string. For
+example:
@example
expr '' \| ''
@end example
address@hidden/Linux and @sc{posix.2} return the empty string for this case,
-but traditional Unix returns @samp{0}. In the latest @sc{posix} draft,
-the specification has been changed to match traditional Unix's behavior
-(which is bizarre, but it's too late to fix this).
address@hidden/Linux and @sc{posix.2-1992} return the empty string for this
+case, but traditional Unix returns @samp{0} (Solaris is one such
+example). In the latest @sc{posix} draft, the specification has been
+changed to match traditional Unix's behavior (which is bizarre, but it's
+too late to fix this). Please note that the same problem does arise
+when the empty string results from a computation, as in:
-Avoid this portability problem by avoiding the empty string.
address@hidden
+expr bar : foo \| foo : bar
address@hidden example
-Don't use @code{length}, @code{substr}, @code{match} and @code{index}.
address@hidden
+Avoid this portability problem by avoiding the empty string.
@item @command{expr} (@samp{:})
@cindex @command{expr}
Don't use @samp{\?}, @samp{\+} and @samp{\|} in patterns, they are
not supported on Solaris.
+
+The @sc{posix.2-1992} standard is ambiguous as to whether @samp{expr a :
+b} (and @samp{expr 'a' : '\(b\)'}) output @samp{0} or the empty string.
+In practice, it outputs the empty string on most platforms, but portable
+scripts should not assume this. For instance, the @sc{qnx} 4.2.5 native
address@hidden returns @samp{0}.
+
+You may believe that one means to get a uniform behavior would be to use
+the empty string as a default value:
+
address@hidden
+expr a : b \| ''
address@hidden example
-The @sc{posix}.2-1996 standard is ambiguous as to whether @samp{expr 'a'
-: '\(b\)'} outputs @samp{0} or the empty string. In practice, it
-outputs the empty string on most platforms, but portable scripts should
-not assume this. For instance, the @sc{qnx} 4.2.5 native @command{expr}
-returns @samp{0}.
address@hidden
+unfortunately this behaves exactly as the original expression, see the
address@hidden@command{expr} (@samp{:})} entry for more information.
Older @command{expr} implementations (e.g. SunOS 4 @command{expr} and
Solaris 8 @command{/usr/ucb/expr}) have a silly length limit that causes
@command{expr} to fail if the matched substring is longer than 120
bytes. In this case, you might want to fall back on @samp{echo|sed} if
@command{expr} fails.
+
+Don't leave, there is some more!
+
+The @sc{qnx} 4.2.5 @command{expr}, in addition of preferring @samp{0} to
+the empty string, has a funny behavior wrt exit status: it's always 1
+when the parenthesis are used!
+
address@hidden
+$ val=`expr 'a' : 'a'`; echo "$?: $val"
+0: 1
+$ val=`expr 'a' : 'b'`; echo "$?: $val"
+1: 0
+
+$ val=`expr 'a' : '\(a\)'`; echo "?: $val"
+1: a
+$ val=`expr 'a' : '\(b\)'`; echo "?: $val"
+1: 0
address@hidden example
+
address@hidden
+In practice this can be a big problem if you are ready to catch failures
+of @command{expr} programs with some other method (such as using
address@hidden), since you may get twice the result. For instance
+
address@hidden
+$ expr 'a' : '\(a\)' || echo 'a' | sed 's/^\(a\)$/\1/'
address@hidden example
+
address@hidden
+will output @samp{a} on most hosts, but @samp{aa} on @sc{qnx} 4.2.5. A
+simple work around consists in testing @command{expr} and use a variable
+set to @command{expr} or to @command{false} according to the result.
@item @command{grep}
Index: tests/m4sh.at
===================================================================
RCS file: /cvs/autoconf/tests/m4sh.at,v
retrieving revision 1.9
diff -u -u -r1.9 m4sh.at
--- tests/m4sh.at 2000/11/29 10:12:05 1.9
+++ tests/m4sh.at 2000/11/29 15:46:17
@@ -12,7 +12,9 @@
AT_SETUP([[AS_DIRNAME & AS_DIRNAME_SED]])
AT_DATA(configure.in,
-[[define([AS_DIRNAME_TEST],
+[[_AS_EXPR_PREPARE
+
+define([AS_DIRNAME_TEST],
[dir=`AS_DIRNAME([$1])`
test "$dir" = "$2" ||
echo "dirname($1) = $dir instead of $2" >&2
- Re: AS_DIRNAME and expr,
Akim Demaille <=