expr.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1992-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* expr.c
* Written by David Korn
* Tue Oct 31 08:48:11 EST 1995
*/
static const char usage[] =
"[-?\n@(#)$Id: expr (AT&T Research) 2010-08-11 $\n]"
"[+NAME?expr - evaluate arguments as an expression]"
"[+DESCRIPTION?\bexpr\b evaluates an expression given as arguments and writes "
"the result to standard output. The character \b0\b will be written "
"to indicate a zero value and nothing will be written to indicate an "
"empty string.]"
"[+?Most of the functionality of \bexpr\b is provided in a more natural "
"way by the shell, \bsh\b(1), and \bexpr\b is provided primarily "
"for backward compatibility.]"
"[+?Terms of the expression must be separate arguments. A string argument is "
"one that can not be identified as an integer. Integer-valued "
"arguments may be preceded by a unary plus or minus sign. Because "
"many of the operators use characters that have special meaning to "
"the shell, they must be quoted when entered from the shell.]"
"[+?Expressions are formed from the operators listed below in order "
"of increasing precedence within groups. All of the operators are "
"left associative. The symbols \aexpr1\a and \aexpr2\a represent "
"expressions formed from strings and integers and the following "
"operators:]{"
"[+\aexpr1\a \b|\b \aexpr2\a?Returns the evaluation of \aexpr1\a if "
"it is neither null nor 0, otherwise returns the evaluation of expr2.]"
"[+\aexpr1\a \b&\b \aexpr2\a?Returns the evaluation of \aexpr1\a if "
"neither expression evaluates to null or 0, otherwise returns 0.]"
"[+\aexpr1\a \aop\a \aexpr2\a?Returns the result of a decimal integer "
"comparison if both arguments are integers; otherwise, returns the "
"result of a string comparison using the locale-specific collation "
"sequence. The result of each comparison will be 1 if the specified "
"relationship is true, or 0 if the relationship is false. \aop\a "
"can be one of the following:]{"
"[+=?Equal.]"
"[+==?Equal.]"
"[+>?Greater than.]"
"[+>=?Greater than or equal to.]"
"[+<?Less than.]"
"[+<=?Less than or equal to.]"
"[+!=?Not equal to.]"
"}"
"[+\aexpr1\a \aop\a \aexpr2\a?Where \aop\a is \b+\b or \b-\b; "
"addition or subtraction of decimal integer-valued arguments.]"
"[+\aexpr1\a \aop\a \aexpr2\a?Where \aop\a is \b*\b, \b/\b or \b%\b; "
"multiplication, division, or remainder of the decimal "
"integer-valued arguments.]"
"[+\aexpr1\a \b::\b \aexpr2\a?The matching operator : compares "
"\aexpr1\a with \aexpr2\a, which must be a BRE. Normally, "
"the matching operator returns the number of bytes matched "
"and 0 on failure. However, if the pattern contains at "
"least one sub-expression [\\( . . .\\)]], the string "
"corresponding to \\1 will be returned.]"
"[+( \aexpr1\a )?Grouping symbols. An expression can "
"be placed within parenthesis to change precedence.]"
"[+match\b \astring\a \aexpr\a?Equivalent to \astring\a \b:\b "
"\aexpr\a.]"
"[+substr\b \astring\a \apos\a \alength\a?\alength\a character "
"substring of \astring\a starting at \apos\a "
"(counting from 1).]"
"[+index\b \astring\a \achars\a?The position in \astring\a "
"(counting from 1) of the leftmost occurrence of any "
"character in \achars\a.]"
"[+length\b \astring\a?The number of characters in \astring\a.]"
"[+quote\b \atoken\a?Treat \atoken\a as a string operand.]"
"}"
"[+?For backwards compatibility, unrecognized options beginning with "
"a \b-\b will be treated as operands. Portable applications "
"should use \b--\b to indicate end of options.]"
"\n"
"\n operand ...\n"
"\n"
"[+EXIT STATUS?]{"
"[+0?The expression is neither null nor 0.]"
"[+1?The expression is null or 0.]"
"[+2?Invalid expressions.]"
"[+>2?An error occurred.]"
"}"
"[+SEE ALSO?\bregcomp\b(5), \bgrep\b(1), \bsh\b(1)]"
;
#include <cmd.h>
#include <regex.h>
#define T_ADD 0x100
#define T_MULT 0x200
#define T_CMP 0x400
#define T_FUN 0x800
#define T_OP 7
#define T_NUM 1
#define T_STR 2
static const struct Optable_s
{
const char opname[3];
int op;
}
optable[] =
{
"|", '|',
"&", '&',
"=", OP_EQ,
"==", OP_EQ,
">", OP_GT,
"<", OP_LT,
">=", OP_GE,
"<=", OP_LE,
"!=", OP_NE,
"+", OP_PLUS,
"-", OP_MINUS,
"*", OP_MULT,
"/", OP_DIV,
"%", OP_MOD,
":", ':',
"(", '(',
")", ')'
};
typedef struct Node_s
{
int type;
long num;
char *str;
} Node_t;
typedef struct State_s
{
int standard;
char** arglist;
char buf[36];
} State_t;
{
register char* sp;
register char* cp;
register int i;
register int j;
register int k;
register int tok;
char* ep;
switch (cp[0])
{
case 'i':
{
goto next;
}
break;
case 'l':
{
goto next;
}
break;
case 'm':
{
return ':';
}
break;
case 'q':
break;
case 's':
{
if (*ep || --i < 0)
i = -1;
if (*ep)
j = -1;
if (i < 0 || i >= k || j < 0)
sp = "";
else
{
sp += i;
k -= i;
if (j < k)
sp[j] = 0;
}
goto next;
}
break;
}
{
if (tok != ')')
}
else
{
if (*cp)
{
if (!*ep)
}
}
next:
return 0;
return 0;
}
{
while (tok==':')
{
int n;
char *cp;
else
{
{
{
}
else
}
else
}
else if (n != REG_NOMATCH)
{
}
}
return tok;
}
{
{
switch(op)
{
case 0:
break;
case 1:
break;
case 2:
}
}
return tok;
}
{
{
if (op)
else
}
return tok;
}
{
{
op |= 010;
else
{
else
else
}
switch(op)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 010:
break;
case 011:
break;
case 012:
break;
case 013:
break;
case 014:
break;
case 015:
break;
}
}
return tok;
}
{
while (tok=='&')
{
{
}
}
return tok;
}
{
while (tok=='|')
{
}
return tok;
}
int
{
int n;
#if 0
else
#endif
{
{
/*
* NOTE: this loop ignores all but literal -- and -?
* out of kindness for obsolescent usage
* (and is ok with the standard) but strict
* getopt conformance would give usage for all
* unknown - options
*/
if(n=='?')
break;
}
if (error_info.errors)
}
{
}
else
}