diff options
author | Andy Fiddaman <omnios@citrus-it.co.uk> | 2020-12-27 17:47:37 +0000 |
---|---|---|
committer | Andy Fiddaman <omnios@citrus-it.co.uk> | 2021-01-30 17:13:33 +0000 |
commit | b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f (patch) | |
tree | 6a37e590faffb9bb9af66887de645c546445036c /usr/src/lib/libpp/common/ppexpr.c | |
parent | df36e06d12cbf655ddf22339ef8c39fa2b83ebf8 (diff) | |
download | illumos-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/libpp/common/ppexpr.c')
-rw-r--r-- | usr/src/lib/libpp/common/ppexpr.c | 697 |
1 files changed, 0 insertions, 697 deletions
diff --git a/usr/src/lib/libpp/common/ppexpr.c b/usr/src/lib/libpp/common/ppexpr.c deleted file mode 100644 index 225034b97d..0000000000 --- a/usr/src/lib/libpp/common/ppexpr.c +++ /dev/null @@ -1,697 +0,0 @@ -/*********************************************************************** -* * -* This software is part of the ast package * -* Copyright (c) 1986-2009 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> * -* * -***********************************************************************/ -#pragma prototyped -/* - * Glenn Fowler - * AT&T Research - * - * preprocessor expression evaluation support - */ - -#include "pplib.h" - -#include <regex.h> - -#define lex(c) ((((c)=peektoken)>=0?(peektoken=(-1)):((c)=pplex())),(c)) -#define unlex(c) (peektoken=(c)) - -static int peektoken; /* expression lookahead token */ -static char* errmsg; /* subexpr() error message */ - -/* - * exists predicate evaluation - */ - -static int -exists(int op, char* pred, register char* args) -{ - register int c; - register int type; - char* pptoken; - long state; - char file[MAXTOKEN + 1]; - - state = (pp.state & ~DISABLE); - PUSH_STRING(args); - pptoken = pp.token; - pp.token = file; - pp.state |= HEADER|PASSEOF; - type = pplex(); - pp.state &= ~HEADER; - pp.token = pptoken; - switch (type) - { - case T_STRING: - case T_HEADER: - break; - default: - error(1, "%s: \"...\" or <...> argument expected", pred); - c = 0; - goto done; - } - if (op == X_EXISTS) - { - if ((c = pplex()) == ',') - { - while ((c = pplex()) == T_STRING) - { - if (pathaccess(pp.path, pp.token, file, NiL, 0)) - { - pathcanon(pp.path, 0); - message((-2, "%s: %s found", pred, pp.path)); - c = 1; - goto done; - } - if ((c = pplex()) != ',') break; - } - if (c) error(1, "%s: \"...\" arguments expected", pred); - strcpy(pp.path, file); - message((-2, "%s: %s not found", pred, file)); - c = 0; - } - else c = ppsearch(file, type, SEARCH_EXISTS) >= 0; - } - else - { - register struct ppfile* fp; - - fp = ppsetfile(file); - c = fp->flags || fp->guard == INC_IGNORE; - } - done: - while (pplex()); - pp.state = state; - return c; -} - -/* - * strcmp/match predicate evaluation - */ - -static int -compare(char* pred, char* args, int match) -{ - register int c; - char* pptoken; - long state; - regex_t re; - char tmp[MAXTOKEN + 1]; - - state = (pp.state & ~DISABLE); - PUSH_STRING(args); - pp.state |= PASSEOF; - pptoken = pp.token; - pp.token = tmp; - if (!pplex()) - goto bad; - pp.token = pptoken; - if (pplex() != ',' || !pplex()) - goto bad; - if (!match) - c = strcmp(tmp, pp.token); - else if ((c = regcomp(&re, pp.token, REG_AUGMENTED|REG_LENIENT|REG_NULL)) || (c = regexec(&re, tmp, NiL, 0, 0)) && c != REG_NOMATCH) - regfatal(&re, 3, c); - else - { - c = !c; - regfree(&re); - } - if ((pp.state & PASSEOF) && pplex()) - goto bad; - pp.state = state; - return c; - bad: - pp.token = pptoken; - error(2, "%s: 2 arguments expected", pred); - while (pplex()); - pp.state = state; - return 0; -} - -/* - * #if predicate parse and evaluation - */ - -static int -predicate(int warn) -{ - register char* args; - register struct pplist* p; - register struct ppsymbol* sym; - register int type; - int index; - - static char pred[MAXID + 1]; - - /* - * first gather the args - */ - - index = (int)hashref(pp.strtab, pp.token); - if (warn && peekchr() != '(') switch (index) - { - case X_DEFINED: - case X_EXISTS: - case X_INCLUDED: - case X_MATCH: - case X_NOTICED: - case X_OPTION: - case X_SIZEOF: - case X_STRCMP: - break; - default: - if (pp.macref) pprefmac(pp.token, REF_IF); - return 0; - } - strcpy(pred, pp.token); - pp.state |= DISABLE; - type = pppredargs(); - pp.state &= ~DISABLE; - switch (type) - { - case T_ID: - case T_STRING: - break; - default: - unlex(type); - /*FALLTHROUGH*/ - case 0: - if (index && !(pp.state & STRICT)) - error(1, "%s: predicate argument expected", pred); - if (pp.macref) pprefmac(pred, REF_IF); - return 0; - } - args = pp.args; - - /* - * now evaluate - */ - - debug((-6, "pred=%s args=%s", pred, args)); - if ((pp.state & STRICT) && !(pp.mode & HOSTED)) switch (index) - { - case X_DEFINED: - case X_SIZEOF: - break; - default: - error(1, "%s(%s): non-standard predicate test", pred, args); - return 0; - } - switch (index) - { - case X_DEFINED: - if (type != T_ID) error(1, "%s: identifier argument expected", pred); - else if ((sym = pprefmac(args, REF_IF)) && sym->macro) return 1; - else if (args[0] == '_' && args[1] == '_' && !strncmp(args, "__STDPP__", 9)) - { - if (pp.hosted == 1 && pp.in->prev->type == IN_FILE) - { - pp.mode |= HOSTED; - pp.flags |= PP_hosted; - } - return *(args + 9) ? (int)hashref(pp.strtab, args + 9) : 1; - } - break; - case X_EXISTS: - case X_INCLUDED: - return exists(index, pred, args); - case X_MATCH: - case X_STRCMP: - return compare(pred, args, index == X_MATCH); - case X_NOTICED: - if (type != T_ID) error(1, "%s: identifier argument expected", pred); - else if (((sym = pprefmac(args, REF_IF)) || (sym = ppsymref(pp.symtab, args))) && (sym->flags & SYM_NOTICED)) return 1; - break; - case X_OPTION: - return ppoption(args); - case X_SIZEOF: - error(2, "%s invalid in #%s expressions", pred, dirname(IF)); - break; - default: - if (warn && !(pp.mode & HOSTED) && (sym = ppsymref(pp.symtab, pred)) && (sym->flags & SYM_PREDICATE)) - error(1, "use #%s(%s) to disambiguate", pred, args); - if (p = (struct pplist*)hashget(pp.prdtab, pred)) - { - if (!*args) return 1; - while (p) - { - if (streq(p->value, args)) return 1; - p = p->next; - } - } - break; - } - return 0; -} - -/* - * evaluate a long integer subexpression with precedence - * taken from the library routine streval() - * may be called recursively - * - * NOTE: all operands are evaluated as both the parse - * and evaluation are done on the fly - */ - -static long -subexpr(register int precedence, int* pun) -{ - register int c; - register long n; - register long x; - register int operand = 1; - int un = 0; - int xn; - - switch (lex(c)) - { - case 0: - case '\n': - unlex(c); - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "more tokens expected"; - return 0; - case '-': - n = -subexpr(13, &un); - break; - case '+': - n = subexpr(13, &un); - break; - case '!': - n = !subexpr(13, &un); - break; - case '~': - n = ~subexpr(13, &un); - break; - default: - unlex(c); - n = 0; - operand = 0; - break; - } - un <<= 1; - for (;;) - { - switch (lex(c)) - { - case 0: - case '\n': - goto done; - case ')': - if (!precedence) - { - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "too many )'s"; - return 0; - } - goto done; - case '(': - n = subexpr(1, &un); - if (lex(c) != ')') - { - unlex(c); - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "closing ) expected"; - return 0; - } - gotoperand: - if (operand) - { - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operator expected"; - return 0; - } - operand = 1; - un <<= 1; - continue; - case '?': - if (precedence > 1) goto done; - un = 0; - if (lex(c) == ':') - { - if (!n) n = subexpr(2, &un); - else - { - x = pp.mode; - pp.mode |= INACTIVE; - subexpr(2, &xn); - pp.mode = x; - } - } - else - { - unlex(c); - x = subexpr(2, &xn); - if (lex(c) != ':') - { - unlex(c); - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = ": expected for ? operator"; - return 0; - } - if (n) - { - n = x; - un = xn; - subexpr(2, &xn); - } - else n = subexpr(2, &un); - } - break; - case ':': - goto done; - case T_ANDAND: - case T_OROR: - xn = (c == T_ANDAND) ? 4 : 3; - if (precedence >= xn) goto done; - if ((n != 0) == (c == T_ANDAND)) n = subexpr(xn, &un) != 0; - else - { - x = pp.mode; - pp.mode |= INACTIVE; - subexpr(xn, &un); - pp.mode = x; - } - un = 0; - break; - case '|': - if (precedence > 4) goto done; - n |= subexpr(5, &un); - break; - case '^': - if (precedence > 5) goto done; - n ^= subexpr(6, &un); - break; - case '&': - if (precedence > 6) goto done; - n &= subexpr(7, &un); - break; - case T_EQ: - case T_NE: - if (precedence > 7) goto done; - n = (n == subexpr(8, &un)) == (c == T_EQ); - un = 0; - break; - case '<': - case T_LE: - case T_GE: - case '>': - if (precedence > 8) goto done; - x = subexpr(9, &un); - switch (c) - { - case '<': - switch (un) - { - case 01: - n = n < (unsigned long)x; - break; - case 02: - n = (unsigned long)n < x; - break; - case 03: - n = (unsigned long)n < (unsigned long)x; - break; - default: - n = n < x; - break; - } - break; - case T_LE: - switch (un) - { - case 01: - n = n <= (unsigned long)x; - break; - case 02: - n = (unsigned long)n <= x; - break; - case 03: - n = (unsigned long)n <= (unsigned long)x; - break; - default: - n = n <= x; - break; - } - break; - case T_GE: - switch (un) - { - case 01: - n = n >= (unsigned long)x; - break; - case 02: - n = (unsigned long)n >= x; - break; - case 03: - n = (unsigned long)n >= (unsigned long)x; - break; - default: - n = n >= x; - break; - } - break; - case '>': - switch (un) - { - case 01: - n = n > (unsigned long)x; - break; - case 02: - n = (unsigned long)n > x; - break; - case 03: - n = (unsigned long)n > (unsigned long)x; - break; - default: - n = n > x; - break; - } - break; - } - un = 0; - break; - case T_LSHIFT: - case T_RSHIFT: - if (precedence > 9) goto done; - x = subexpr(10, &un); - if (c == T_LSHIFT) n <<= x; - else n >>= x; - un >>= 1; - break; - case '+': - case '-': - if (precedence > 10) goto done; - x = subexpr(11, &un); - if (c == '+') n += x; - else n -= x; - break; - case '*': - case '/': - case '%': - if (precedence > 11) goto done; - x = subexpr(12, &un); - if (c == '*') n *= x; - else if (x == 0) - { - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "divide by zero"; - return 0; - } - else if (c == '/') n /= x; - else n %= x; - break; - case '#': - pp.state |= DISABLE; - c = pplex(); - pp.state &= ~DISABLE; - if (c != T_ID) - { - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "# must precede a predicate identifier"; - return 0; - } - n = predicate(0); - goto gotoperand; - case T_ID: - n = predicate(1); - goto gotoperand; - case T_CHARCONST: - c = *(pp.toknxt - 1); - *(pp.toknxt - 1) = 0; - n = chrtoi(pp.token + 1); - *(pp.toknxt - 1) = c; - if (n & ~((1<<CHAR_BIT)-1)) - { - if (!(pp.mode & HOSTED)) - error(1, "'%s': multi-character character constants are not portable", pp.token); - } -#if CHAR_MIN < 0 - else n = (char)n; -#endif - goto gotoperand; - case T_DECIMAL_U: - case T_DECIMAL_UL: - case T_OCTAL_U: - case T_OCTAL_UL: - case T_HEXADECIMAL_U: - case T_HEXADECIMAL_UL: - un |= 01; - /*FALLTHROUGH*/ - case T_DECIMAL: - case T_DECIMAL_L: - case T_OCTAL: - case T_OCTAL_L: - case T_HEXADECIMAL: - case T_HEXADECIMAL_L: - n = strtoul(pp.token, NiL, 0); - if ((unsigned long)n > LONG_MAX) un |= 01; - goto gotoperand; - case T_WCHARCONST: - n = chrtoi(pp.token); - goto gotoperand; - default: - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid token"; - return 0; - } - if (errmsg) return 0; - if (!operand) goto nooperand; - } - done: - unlex(c); - if (!operand) - { - nooperand: - if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operand expected"; - return 0; - } - if (un) *pun |= 01; - return n; -} - -/* - * preprocessor expression evaluator using modified streval(3) - * *pun!=0 if result is unsigned - */ - -long -ppexpr(int* pun) -{ - long n; - int opeektoken; - long ppstate; - - ppstate = (pp.state & (CONDITIONAL|DISABLE|NOSPACE|STRIP)); - pp.state &= ~(DISABLE|STRIP); - pp.state |= CONDITIONAL|NOSPACE; - opeektoken = peektoken; - peektoken = -1; - *pun = 0; - n = subexpr(0, pun); - if (peektoken == ':' && !errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid use of :"; - if (errmsg) - { - error(2, "%s in expression", errmsg); - errmsg = 0; - n = 0; - } - peektoken = opeektoken; - pp.state &= ~(CONDITIONAL|NOSPACE); - pp.state |= ppstate; - if (*pun) debug((-4, "ppexpr() = %luU", n)); - else debug((-4, "ppexpr() = %ld", n)); - return n; -} - -/* - * return non-zero if option s is set - */ - -int -ppoption(char* s) -{ - switch ((int)hashget(pp.strtab, s)) - { - case X_ALLMULTIPLE: - return pp.mode & ALLMULTIPLE; - case X_BUILTIN: - return pp.mode & BUILTIN; - case X_CATLITERAL: - return pp.mode & CATLITERAL; - case X_COMPATIBILITY: - return pp.state & COMPATIBILITY; - case X_DEBUG: - return -error_info.trace; - case X_ELSEIF: - return pp.option & ELSEIF; - case X_FINAL: - return pp.option & FINAL; - case X_HOSTDIR: - return pp.mode & HOSTED; - case X_HOSTED: - return pp.flags & PP_hosted; - case X_INITIAL: - return pp.option & INITIAL; - case X_KEYARGS: - return pp.option & KEYARGS; - case X_LINEBASE: - return pp.flags & PP_linebase; - case X_LINEFILE: - return pp.flags & PP_linefile; - case X_LINETYPE: - return pp.flags & PP_linetype; - case X_PLUSCOMMENT: - return pp.option & PLUSCOMMENT; - case X_PLUSPLUS: - return pp.option & PLUSPLUS; - case X_PLUSSPLICE: - return pp.option & PLUSSPLICE; - case X_PRAGMAEXPAND: - return pp.option & PRAGMAEXPAND; - case X_PREDEFINED: - return pp.option & PREDEFINED; - case X_PREFIX: - return pp.option & PREFIX; - case X_PROTOTYPED: - return pp.option & PROTOTYPED; - case X_READONLY: - return pp.mode & READONLY; - case X_REGUARD: - return pp.option & REGUARD; - case X_SPACEOUT: - return pp.state & SPACEOUT; - case X_SPLICECAT: - return pp.option & SPLICECAT; - case X_SPLICESPACE: - return pp.option & SPLICESPACE; - case X_STRICT: - return pp.state & STRICT; - case X_STRINGSPAN: - return pp.option & STRINGSPAN; - case X_STRINGSPLIT: - return pp.option & STRINGSPLIT; - case X_TEST: - return pp.test; - case X_TEXT: - return !(pp.state & NOTEXT); - case X_TRANSITION: - return pp.state & TRANSITION; - case X_TRUNCATE: - return pp.truncate; - case X_WARN: - return pp.state & WARN; - default: - if (pp.state & WARN) error(1, "%s: unknown option name", s); - return 0; - } -} |