summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcmd/common/expr.c
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2020-12-27 17:47:37 +0000
committerAndy Fiddaman <omnios@citrus-it.co.uk>2021-01-30 17:13:33 +0000
commitb30d193948be5a7794d7ae3ba0ed9c2f72c88e0f (patch)
tree6a37e590faffb9bb9af66887de645c546445036c /usr/src/lib/libcmd/common/expr.c
parentdf36e06d12cbf655ddf22339ef8c39fa2b83ebf8 (diff)
downloadillumos-gate-b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f.tar.gz
13405 ksh93 update to 2012-08-01
13434 sh: mishandles backslash as last character of a block of input 11750 ksh mkdir builtin doesn't honor special file permissions 9199 ksh93 builtin *grep -v mishandles blank lines, blows up libgcrypt-config 6756 sh (and ksh) have issues with ${1+"$@"} 6520 ksh: sleep could wait forever 4860 ksh93: core in printf 3791 /bin/sh's builtin 'rm' busted: 'rm -f' without arguments returns error 1047 ksh overwrites child core files 880 ksh93 coredumps on 'unset' 499 "interrupted system call" when using "tee" builtin in ksh Reviewed by: Robert Mustacchi <rm@fingolfin.org> Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> Reviewed by: Dominik Hassler <hadfl@omnios.org> Approved by: Rich Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib/libcmd/common/expr.c')
-rw-r--r--usr/src/lib/libcmd/common/expr.c535
1 files changed, 0 insertions, 535 deletions
diff --git a/usr/src/lib/libcmd/common/expr.c b/usr/src/lib/libcmd/common/expr.c
deleted file mode 100644
index 537408e507..0000000000
--- a/usr/src/lib/libcmd/common/expr.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/***********************************************************************
-* *
-* This software is part of the ast package *
-* Copyright (c) 1992-2010 AT&T Intellectual Property *
-* and is licensed under the *
-* Common Public License, Version 1.0 *
-* by AT&T Intellectual Property *
-* *
-* A copy of the License is available at *
-* http://www.opensource.org/licenses/cpl1.0.txt *
-* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
-* *
-* 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) 2008-01-30 $\n]"
-USAGE_LICENSE
-"[+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
-
-#define OP_EQ (T_CMP|0)
-#define OP_GT (T_CMP|1)
-#define OP_LT (T_CMP|2)
-#define OP_GE (T_CMP|3)
-#define OP_LE (T_CMP|4)
-#define OP_NE (T_CMP|5)
-#define OP_PLUS (T_ADD|0)
-#define OP_MINUS (T_ADD|1)
-#define OP_MULT (T_MULT|0)
-#define OP_DIV (T_MULT|1)
-#define OP_MOD (T_MULT|2)
-#define OP_INDEX (T_FUN|0)
-#define OP_LENGTH (T_FUN|1)
-#define OP_MATCH (T_FUN|2)
-#define OP_QUOTE (T_FUN|3)
-#define OP_SUBSTR (T_FUN|4)
-
-#define numeric(np) ((np)->type&T_NUM)
-
-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;
-
-static int expr_or(State_t*, Node_t*);
-
-static int getnode(State_t* state, Node_t *np)
-{
- register char* sp;
- register char* cp;
- register int i;
- register int j;
- register int k;
- register int tok;
- char* ep;
-
- if (!(cp = *state->arglist++))
- error(ERROR_exit(2), "argument expected");
- if (!state->standard)
- switch (cp[0])
- {
- case 'i':
- if (cp[1] == 'n' && !strcmp(cp, "index"))
- {
- if (!(cp = *state->arglist++))
- error(ERROR_exit(2), "string argument expected");
- if (!(ep = *state->arglist++))
- error(ERROR_exit(2), "chars argument expected");
- np->num = (ep = strpbrk(cp, ep)) ? (ep - cp + 1) : 0;
- np->type = T_NUM;
- goto next;
- }
- break;
- case 'l':
- if (cp[1] == 'e' && !strcmp(cp, "length"))
- {
- if (!(cp = *state->arglist++))
- error(ERROR_exit(2), "string argument expected");
- np->num = strlen(cp);
- np->type = T_NUM;
- goto next;
- }
- break;
- case 'm':
- if (cp[1] == 'a' && !strcmp(cp, "match"))
- {
- if (!(np->str = *state->arglist++))
- error(ERROR_exit(2), "pattern argument expected");
- np->type = T_STR;
- return ':';
- }
- break;
- case 'q':
- if (cp[1] == 'u' && !strcmp(cp, "quote") && !(cp = *state->arglist++))
- error(ERROR_exit(2), "string argument expected");
- break;
- case 's':
- if (cp[1] == 'u' && !strcmp(cp, "substr"))
- {
- if (!(sp = *state->arglist++))
- error(ERROR_exit(2), "string argument expected");
- if (!(cp = *state->arglist++))
- error(ERROR_exit(2), "position argument expected");
- i = strtol(cp, &ep, 10);
- if (*ep || --i < 0)
- i = -1;
- if (!(cp = *state->arglist++))
- error(ERROR_exit(2), "length argument expected");
- j = strtol(cp, &ep, 10);
- if (*ep)
- j = -1;
- k = strlen(sp);
- if (i < 0 || i >= k || j < 0)
- sp = "";
- else
- {
- sp += i;
- k -= i;
- if (j < k)
- sp[j] = 0;
- }
- np->type = T_STR;
- np->str = sp;
- goto next;
- }
- break;
- }
- if (*cp=='(' && cp[1]==0)
- {
- tok = expr_or(state, np);
- if (tok != ')')
- error(ERROR_exit(2),"closing parenthesis missing");
- }
- else
- {
- np->type = T_STR;
- np->str = cp;
- if (*cp)
- {
- np->num = strtol(np->str,&ep,10);
- if (!*ep)
- np->type |= T_NUM;
- }
- }
- next:
- if (!(cp = *state->arglist))
- return 0;
- state->arglist++;
- for (i=0; i < sizeof(optable)/sizeof(*optable); i++)
- if (*cp==optable[i].opname[0] && cp[1]==optable[i].opname[1])
- return optable[i].op;
- error(ERROR_exit(2),"%s: unknown operator argument",cp);
- return 0;
-}
-
-static int expr_cond(State_t* state, Node_t *np)
-{
- register int tok = getnode(state, np);
-
- while (tok==':')
- {
- regex_t re;
- regmatch_t match[2];
- int n;
- Node_t rp;
- char *cp;
- tok = getnode(state, &rp);
- if (np->type&T_STR)
- cp = np->str;
- else
- sfsprintf(cp=state->buf,sizeof(state->buf),"%d",np->num);
- np->num = 0;
- np->type = T_NUM;
- if (n = regcomp(&re, rp.str, REG_LEFT|REG_LENIENT))
- regfatal(&re, ERROR_exit(2), n);
- if (!(n = regexec(&re, cp, elementsof(match), match, 0)))
- {
- if (re.re_nsub > 0)
- {
- np->type = T_STR;
- if (match[1].rm_so >= 0)
- {
- np->str = cp + match[1].rm_so;
- np->str[match[1].rm_eo - match[1].rm_so] = 0;
- np->num = strtol(np->str,&cp,10);
- if (cp!=np->str && *cp==0)
- np->type |= T_NUM;
- }
- else
- np->str = "";
- }
- else
- np->num = match[0].rm_eo - match[0].rm_so;
- }
- else if (n != REG_NOMATCH)
- regfatal(&re, ERROR_exit(2), n);
- else if (re.re_nsub)
- {
- np->str = "";
- np->type = T_STR;
- }
- regfree(&re);
- }
- return tok;
-}
-
-static int expr_mult(State_t* state, Node_t *np)
-{
- register int tok = expr_cond(state, np);
-
- while ((tok&~T_OP)==T_MULT)
- {
- Node_t rp;
- int op = (tok&T_OP);
- tok = expr_cond(state, &rp);
- if (!numeric(np) || !numeric(&rp))
- error(ERROR_exit(2),"non-numeric argument");
- if (op && rp.num==0)
- error(ERROR_exit(2),"division by zero");
- switch(op)
- {
- case 0:
- np->num *= rp.num;
- break;
- case 1:
- np->num /= rp.num;
- break;
- case 2:
- np->num %= rp.num;
- }
- np->type = T_NUM;
- }
- return tok;
-}
-
-static int expr_add(State_t* state, Node_t *np)
-{
- register int tok = expr_mult(state, np);
-
- while ((tok&~T_OP)==T_ADD)
- {
- Node_t rp;
- int op = (tok&T_OP);
- tok = expr_mult(state, &rp);
- if (!numeric(np) || !numeric(&rp))
- error(ERROR_exit(2),"non-numeric argument");
- if (op)
- np->num -= rp.num;
- else
- np->num += rp.num;
- np->type = T_NUM;
- }
- return tok;
-}
-
-static int expr_cmp(State_t* state, Node_t *np)
-{
- register int tok = expr_add(state, np);
-
- while ((tok&~T_OP)==T_CMP)
- {
- Node_t rp;
- register char *left,*right;
- char buff1[36],buff2[36];
- int op = (tok&T_OP);
- tok = expr_add(state, &rp);
- if (numeric(&rp) && numeric(np))
- op |= 010;
- else
- {
- if (np->type&T_STR)
- left = np->str;
- else
- sfsprintf(left=buff1,sizeof(buff1),"%d",np->num);
- if (rp.type&T_STR)
- right = rp.str;
- else
- sfsprintf(right=buff2,sizeof(buff2),"%d",rp.num);
- }
- switch(op)
- {
- case 0:
- np->num = streq(left,right);
- break;
- case 1:
- np->num = (strcoll(left,right)>0);
- break;
- case 2:
- np->num = (strcoll(left,right)<0);
- break;
- case 3:
- np->num = (strcoll(left,right)>=0);
- break;
- case 4:
- np->num = (strcoll(left,right)<=0);
- break;
- case 5:
- np->num = !streq(left,right);
- break;
- case 010:
- np->num = (np->num==rp.num);
- break;
- case 011:
- np->num = (np->num>rp.num);
- break;
- case 012:
- np->num = (np->num<rp.num);
- break;
- case 013:
- np->num = (np->num>=rp.num);
- break;
- case 014:
- np->num = (np->num<=rp.num);
- break;
- case 015:
- np->num = (np->num!=rp.num);
- break;
- }
- np->type = T_NUM;
- }
- return tok;
-}
-
-static int expr_and(State_t* state, Node_t *np)
-{
- register int tok = expr_cmp(state, np);
- while (tok=='&')
- {
- Node_t rp;
- tok = expr_cmp(state, &rp);
- if ((numeric(&rp) && rp.num==0) || *rp.str==0)
- {
- np->num = 0;
- np->type=T_NUM;
- }
- }
- return tok;
-}
-
-static int expr_or(State_t* state, Node_t *np)
-{
- register int tok = expr_and(state, np);
- while (tok=='|')
- {
- Node_t rp;
- tok = expr_and(state, &rp);
- if ((numeric(np) && np->num==0) || *np->str==0)
- *np = rp;
- }
- return tok;
-}
-
-int
-b_expr(int argc, char *argv[], void *context)
-{
- State_t state;
- Node_t node;
- int n;
-
- cmdinit(argc, argv,context, ERROR_CATALOG, 0);
- state.standard = !strcmp(astconf("CONFORMANCE", NiL, NiL), "standard");
-#if 0
- if (state.standard)
- state.arglist = argv+1;
- else
-#endif
- {
- while (n=optget(argv, usage))
- {
- /*
- * 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=='?')
- error(ERROR_usage(2), "%s", opt_info.arg);
- if (opt_info.option[1] != '?')
- break;
- error(ERROR_usage(2), "%s", opt_info.arg);
- }
- if (error_info.errors)
- error(ERROR_usage(2),"%s",optusage((char*)0));
- state.arglist = argv+opt_info.index;
- }
- if (expr_or(&state, &node))
- error(ERROR_exit(2),"syntax error");
- if (node.type&T_STR)
- {
- if (*node.str)
- sfprintf(sfstdout,"%s\n",node.str);
- }
- else
- sfprintf(sfstdout,"%d\n",node.num);
- return numeric(&node)?node.num==0:*node.str==0;
-}