summaryrefslogtreecommitdiff
path: root/usr/src/lib/libpp/common/ppexpr.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/libpp/common/ppexpr.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/libpp/common/ppexpr.c')
-rw-r--r--usr/src/lib/libpp/common/ppexpr.c697
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;
- }
-}