/***********************************************************************
* *
* 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 *
* (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>
/*
* exists predicate evaluation
*/
static int
{
register int c;
register int type;
char* pptoken;
long state;
switch (type)
{
case T_STRING:
case T_HEADER:
break;
default:
c = 0;
goto done;
}
{
if ((c = pplex()) == ',')
{
{
{
c = 1;
goto done;
}
if ((c = pplex()) != ',') break;
}
c = 0;
}
}
else
{
}
done:
while (pplex());
return c;
}
/*
*/
static int
{
register int c;
char* pptoken;
long state;
if (!pplex())
goto bad;
goto bad;
if (!match)
else if ((c = regcomp(&re, pp.token, REG_AUGMENTED|REG_LENIENT|REG_NULL)) || (c = regexec(&re, tmp, NiL, 0, 0)) && c != REG_NOMATCH)
else
{
c = !c;
}
goto bad;
return c;
bad:
while (pplex());
return 0;
}
/*
* #if predicate parse and evaluation
*/
static int
{
register char* args;
register struct pplist* p;
register int type;
int index;
/*
* first gather the args
*/
{
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:
return 0;
}
type = pppredargs();
switch (type)
{
case T_ID:
case T_STRING:
break;
default:
/*FALLTHROUGH*/
case 0:
return 0;
}
/*
* now evaluate
*/
{
case X_DEFINED:
case X_SIZEOF:
break;
default:
return 0;
}
switch (index)
{
case X_DEFINED:
{
{
}
}
break;
case X_EXISTS:
case X_INCLUDED:
case X_MATCH:
case X_STRCMP:
case X_NOTICED:
else if (((sym = pprefmac(args, REF_IF)) || (sym = ppsymref(pp.symtab, args))) && (sym->flags & SYM_NOTICED)) return 1;
break;
case X_OPTION:
case X_SIZEOF:
break;
default:
if (warn && !(pp.mode & HOSTED) && (sym = ppsymref(pp.symtab, pred)) && (sym->flags & SYM_PREDICATE))
{
if (!*args) return 1;
while (p)
{
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
{
register int c;
register long n;
register long x;
int un = 0;
int xn;
switch (lex(c))
{
case 0:
case '\n':
unlex(c);
return 0;
case '-':
break;
case '+':
break;
case '!':
break;
case '~':
break;
default:
unlex(c);
n = 0;
operand = 0;
break;
}
un <<= 1;
for (;;)
{
switch (lex(c))
{
case 0:
case '\n':
goto done;
case ')':
if (!precedence)
{
return 0;
}
goto done;
case '(':
if (lex(c) != ')')
{
unlex(c);
return 0;
}
if (operand)
{
return 0;
}
operand = 1;
un <<= 1;
continue;
case '?':
un = 0;
if (lex(c) == ':')
{
else
{
}
}
else
{
unlex(c);
if (lex(c) != ':')
{
unlex(c);
return 0;
}
if (n)
{
n = x;
}
}
break;
case ':':
goto done;
case T_ANDAND:
case T_OROR:
else
{
}
un = 0;
break;
case '|':
break;
case '^':
break;
case '&':
break;
case T_EQ:
case T_NE:
un = 0;
break;
case '<':
case T_LE:
case T_GE:
case '>':
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 (c == T_LSHIFT) n <<= x;
else n >>= x;
un >>= 1;
break;
case '+':
case '-':
if (c == '+') n += x;
else n -= x;
break;
case '*':
case '/':
case '%':
if (c == '*') n *= x;
else if (x == 0)
{
return 0;
}
else if (c == '/') n /= x;
else n %= x;
break;
case '#':
c = pplex();
if (c != T_ID)
{
return 0;
}
n = predicate(0);
goto gotoperand;
case T_ID:
n = predicate(1);
goto gotoperand;
case T_CHARCONST:
{
}
#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:
goto gotoperand;
case T_WCHARCONST:
goto gotoperand;
default:
return 0;
}
if (errmsg) return 0;
}
done:
unlex(c);
if (!operand)
{
return 0;
}
return n;
}
/*
* preprocessor expression evaluator using modified streval(3)
* *pun!=0 if result is unsigned
*/
long
{
long n;
int opeektoken;
long ppstate;
peektoken = -1;
*pun = 0;
if (errmsg)
{
errmsg = 0;
n = 0;
}
return n;
}
/*
* return non-zero if option s is set
*/
int
ppoption(char* s)
{
{
case X_ALLMULTIPLE:
case X_BUILTIN:
case X_CATLITERAL:
case X_COMPATIBILITY:
case X_DEBUG:
return -error_info.trace;
case X_ELSEIF:
case X_FINAL:
case X_HOSTDIR:
case X_HOSTED:
case X_INITIAL:
case X_KEYARGS:
case X_LINEBASE:
case X_LINEFILE:
case X_LINETYPE:
case X_PLUSCOMMENT:
case X_PLUSPLUS:
case X_PLUSSPLICE:
case X_PRAGMAEXPAND:
case X_PREDEFINED:
case X_PREFIX:
case X_PROTOTYPED:
case X_READONLY:
case X_REGUARD:
case X_SPACEOUT:
case X_SPLICECAT:
case X_SPLICESPACE:
case X_STRICT:
case X_STRINGSPAN:
case X_STRINGSPLIT:
case X_TEST:
case X_TEXT:
case X_TRANSITION:
case X_TRUNCATE:
case X_WARN:
default:
return 0;
}
}