diff --git a/bin/expr/expr.1 b/bin/expr/expr.1 new file mode 100644 index 000000000000..e4d3c0648289 --- /dev/null +++ b/bin/expr/expr.1 @@ -0,0 +1,131 @@ +.\" Copyright (c) 1993 Winning Strategies, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Winning Strategies, Inc. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software withough specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Header: /b/source/CVS/src/bin/expr/expr.1,v 1.1 1993/07/20 20:16:26 jtc Exp $ +.\" +.Dd July 3, 1993 +.Dt EXPR 1 +.Os +.Sh NAME +.Nm expr +.Nd evaluate expression +.Sh SYNOPSIS +.Nm expr +.Ar expression +.Sh DESCRIPTION +The +.Nm expr +utility evaluates +.Ar expression +and writes the result on standard output. +.Pp +All operators are separate arguments to the +.Nm expr +utility. +Characters special to the command interpreter must be escaped. +.Pp +Operators are listed below in order of increasing precidence. +Operators with equal precidence are grouped within { } symbols. +.Bl -tag -width indent +.It Ar expr1 Li | Ar expr2 +Returns the evaluation of +.Ar expr1 +if it is neither an empty string nor zero; +otherwise, returns the evaluation of +.Ar expr2 . +.It Ar expr1 Li & Ar expr2 +Returns the evaluation of +.Ar expr1 +if neither expression evaluates to an empty string or zero; +otherwise, returns zero. +.It Ar expr1 Li "{=, >, >=, <, <=, !=}" Ar expr2 +Returns the results of integer comparision if both arguments are integers; +otherwise, returns the results of lexical comparison. +The result of each comparison is 1 if the specified relation is true, +or 0 if the relation is false. +.It Ar expr1 Li "{+, -}" Ar expr2 +Returns the results of addition or subtraction of integer-valued arguments. +.It Ar expr1 Li "{*, /, %}" Ar expr2 +Returns the results of multiplication, integer division, or remainder of integer-valued arguments. +.It Ar expr1 Li : Ar expr2 +The +.Dq \: +operator matches +.Ar expr1 +against +.Ar expr2 , +which must be a regular expression. The regular expression is anchored +to the begining of the string with an invisible +.Dq ^ , +therefore +.Dq ^ +is not a special character. +.Pp +If the pattern contains at lest one regular expression +subexpression +.Dq "\e(...\e)" , +the string corresponding to +.Dq "\e1" +is returned; +otherwise the matching operator returns the number of characters matched. +.El +.Pp +Parentheses are used for grouping in the usual manner. +.Sh EXAMPLES +.Bl -enum +.It +The following example adds one to the variable a. +.Dl a=`expr $a + 1` +.It +The following example returns the filename portion of a pathname stored +in variable a. The // characters act to eliminate ambiguity with the +division operator. +.Dl expr "//$a" Li : '.*/\e(.*\e)' +.It +The following example returns the number of characters in variable a. +.Dl expr $a Li : '.*' +.El +.Sh DIAGNOSTICS +The +.Nm expr +utility exits with one of the following values: +.Bl -tag -width Ds +.It 0 +the expression is neither an empty string nor 0. +.It 1 +the expression is an empty string or 0. +.It 2 +the expression is invalid. +.El +.Sh STANDARDS +The +.Nm expr +utility +is expected to be +.St -p1003.2 +compatible. diff --git a/bin/expr/expr.y b/bin/expr/expr.y index d267094c5c74..0789483fdba2 100644 --- a/bin/expr/expr.y +++ b/bin/expr/expr.y @@ -2,7 +2,7 @@ /* Written by Pace Willisson (pace@blitz.com) * and placed in the public domain * - * /b/source/CVS/src/bin/expr/expr.y,v 1.6 1993/06/14 19:59:07 jtc Exp + * $Header: /b/source/CVS/src/bin/expr/expr.y,v 1.9 1993/07/20 01:10:55 jtc Exp $ */ #include #include @@ -219,13 +219,10 @@ int is_zero_or_null (vp) struct val *vp; { - /* Like most other versions of expr, this version will return - false for a string value of multiple zeros.*/ - if (vp->type == integer) { return (vp->u.i == 0); } else { - return (*vp->u.s == 0 || strcmp (vp->u.s, "0") == 0); + return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); } /* NOTREACHED */ } @@ -292,12 +289,6 @@ struct val *a, *b; { struct val *r; - /* attempt to coerce both arguments to integers */ - (void) to_integer (a); - (void) to_integer (b); - - /* But if either one of them really is a string, do - a string comparison */ if (isstring (a) || isstring (b)) { to_string (a); to_string (b); @@ -317,12 +308,6 @@ struct val *a, *b; { struct val *r; - /* attempt to coerce both arguments to integers */ - (void) to_integer (a); - (void) to_integer (b); - - /* But if either one of them really is a string, do - a string comparison */ if (isstring (a) || isstring (b)) { to_string (a); to_string (b); @@ -342,12 +327,6 @@ struct val *a, *b; { struct val *r; - /* attempt to coerce both arguments to integers */ - (void) to_integer (a); - (void) to_integer (b); - - /* But if either one of them really is a string, do - a string comparison */ if (isstring (a) || isstring (b)) { to_string (a); to_string (b); @@ -367,12 +346,6 @@ struct val *a, *b; { struct val *r; - /* attempt to coerce both arguments to integers */ - (void) to_integer (a); - (void) to_integer (b); - - /* But if either one of them really is a string, do - a string comparison */ if (isstring (a) || isstring (b)) { to_string (a); to_string (b); @@ -392,12 +365,6 @@ struct val *a, *b; { struct val *r; - /* attempt to coerce both arguments to integers */ - (void) to_integer (a); - (void) to_integer (b); - - /* But if either one of them really is a string, do - a string comparison */ if (isstring (a) || isstring (b)) { to_string (a); to_string (b); @@ -417,12 +384,6 @@ struct val *a, *b; { struct val *r; - /* attempt to coerce both arguments to integers */ - (void) to_integer (a); - (void) to_integer (b); - - /* But if either one of them really is a string, do - a string comparison */ if (isstring (a) || isstring (b)) { to_string (a); to_string (b); @@ -542,8 +503,12 @@ struct val *a, *b; regmatch_t rm[SE_MAX]; char errbuf[256]; int eval; - char *newpat; struct val *v; + char *newpat; + + /* coerce to both arguments to strings */ + to_string(a); + to_string(b); /* patterns are anchored to the beginning of the line */ newpat = malloc (strlen (b->u.s) + 2);