da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz* Copyright (c) 1986-2009 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * preprocessor expression evaluation support
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define lex(c) ((((c)=peektoken)>=0?(peektoken=(-1)):((c)=pplex())),(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * exists predicate evaluation
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s: \"...\" or <...> argument expected", pred);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c) error(1, "%s: \"...\" arguments expected", pred);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * strcmp/match predicate evaluation
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((c = regcomp(&re, pp.token, REG_AUGMENTED|REG_LENIENT|REG_NULL)) || (c = regexec(&re, tmp, NiL, 0, 0)) && c != REG_NOMATCH)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * #if predicate parse and evaluation
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct pplist* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * first gather the args
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * now evaluate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((pp.state & STRICT) && !(pp.mode & HOSTED)) switch (index)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s(%s): non-standard predicate test", pred, args);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (type != T_ID) error(1, "%s: identifier argument expected", pred);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((sym = pprefmac(args, REF_IF)) && sym->macro) return 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (args[0] == '_' && args[1] == '_' && !strncmp(args, "__STDPP__", 9))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return *(args + 9) ? (int)hashref(pp.strtab, args + 9) : 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (type != T_ID) error(1, "%s: identifier argument expected", pred);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (((sym = pprefmac(args, REF_IF)) || (sym = ppsymref(pp.symtab, args))) && (sym->flags & SYM_NOTICED)) return 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s invalid in #%s expressions", pred, dirname(IF));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (warn && !(pp.mode & HOSTED) && (sym = ppsymref(pp.symtab, pred)) && (sym->flags & SYM_PREDICATE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * evaluate a long integer subexpression with precedence
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * taken from the library routine streval()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * may be called recursively
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * NOTE: all operands are evaluated as both the parse
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * and evaluation are done on the fly
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic long
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register long n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register long x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (lex(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "more tokens expected";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (lex(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "too many )'s";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "closing ) expected";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operator expected";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = ": expected for ? operator";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n != 0) == (c == T_ANDAND)) n = subexpr(xn, &un) != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n < (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n < x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n < (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n < x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n <= (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n <= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n <= (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n <= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n >= (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n >= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n >= (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n >= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n > (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n > x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n > (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n > x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == T_LSHIFT) n <<= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n >>= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '+') n += x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n -= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '*') n *= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (x == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "divide by zero";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '/') n /= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n %= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "# must precede a predicate identifier";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "'%s': multi-character character constants are not portable", pp.token);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n = (char)n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid token";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (errmsg) return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operand expected";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * preprocessor expression evaluator using modified streval(3)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * *pun!=0 if result is unsigned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ppstate = (pp.state & (CONDITIONAL|DISABLE|NOSPACE|STRIP));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (peektoken == ':' && !errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid use of :";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return non-zero if option s is set