da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
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* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * preprocessor expression evaluation support
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "pplib.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <regex.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define lex(c) ((((c)=peektoken)>=0?(peektoken=(-1)):((c)=pplex())),(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define unlex(c) (peektoken=(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int peektoken; /* expression lookahead token */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char* errmsg; /* subexpr() error message */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * exists predicate evaluation
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinexists(int op, char* pred, register char* args)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* pptoken;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char file[MAXTOKEN + 1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state = (pp.state & ~DISABLE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin PUSH_STRING(args);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pptoken = pp.token;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.token = file;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state |= HEADER|PASSEOF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin type = pplex();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state &= ~HEADER;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.token = pptoken;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_STRING:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_HEADER:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s: \"...\" or <...> argument expected", pred);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (op == X_EXISTS)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c = pplex()) == ',')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((c = pplex()) == T_STRING)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pathaccess(pp.path, pp.token, file, NiL, 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pathcanon(pp.path, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin message((-2, "%s: %s found", pred, pp.path));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c = pplex()) != ',') break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c) error(1, "%s: \"...\" arguments expected", pred);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strcpy(pp.path, file);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin message((-2, "%s: %s not found", pred, file));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else c = ppsearch(file, type, SEARCH_EXISTS) >= 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct ppfile* fp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp = ppsetfile(file);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = fp->flags || fp->guard == INC_IGNORE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin done:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (pplex());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state = state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * strcmp/match predicate evaluation
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chincompare(char* pred, char* args, int match)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* pptoken;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin regex_t re;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char tmp[MAXTOKEN + 1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state = (pp.state & ~DISABLE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin PUSH_STRING(args);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state |= PASSEOF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pptoken = pp.token;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.token = tmp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!pplex())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.token = pptoken;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pplex() != ',' || !pplex())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!match)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = strcmp(tmp, pp.token);
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 regfatal(&re, 3, c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = !c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin regfree(&re);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((pp.state & PASSEOF) && pplex())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state = state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bad:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.token = pptoken;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: 2 arguments expected", pred);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (pplex());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state = state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * #if predicate parse and evaluation
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinpredicate(int warn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* args;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct pplist* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct ppsymbol* sym;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int index;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static char pred[MAXID + 1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * first gather the args
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin index = (int)hashref(pp.strtab, pp.token);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (warn && peekchr() != '(') switch (index)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_DEFINED:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_EXISTS:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_INCLUDED:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_MATCH:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_NOTICED:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_OPTION:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_SIZEOF:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_STRCMP:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.macref) pprefmac(pp.token, REF_IF);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strcpy(pred, pp.token);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state |= DISABLE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin type = pppredargs();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state &= ~DISABLE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_ID:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_STRING:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unlex(type);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (index && !(pp.state & STRICT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s: predicate argument expected", pred);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.macref) pprefmac(pred, REF_IF);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin args = pp.args;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * now evaluate
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin debug((-6, "pred=%s args=%s", pred, args));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((pp.state & STRICT) && !(pp.mode & HOSTED)) switch (index)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_DEFINED:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_SIZEOF:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s(%s): non-standard predicate test", pred, args);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (index)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_DEFINED:
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 {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.hosted == 1 && pp.in->prev->type == IN_FILE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.mode |= HOSTED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.flags |= PP_hosted;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return *(args + 9) ? (int)hashref(pp.strtab, args + 9) : 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_EXISTS:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_INCLUDED:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return exists(index, pred, args);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_MATCH:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_STRCMP:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return compare(pred, args, index == X_MATCH);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_NOTICED:
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 break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_OPTION:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return ppoption(args);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_SIZEOF:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s invalid in #%s expressions", pred, dirname(IF));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (warn && !(pp.mode & HOSTED) && (sym = ppsymref(pp.symtab, pred)) && (sym->flags & SYM_PREDICATE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "use #%s(%s) to disambiguate", pred, args);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (p = (struct pplist*)hashget(pp.prdtab, pred))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!*args) return 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (streq(p->value, args)) return 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = p->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * evaluate a long integer subexpression with precedence
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * taken from the library routine streval()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * may be called recursively
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * NOTE: all operands are evaluated as both the parse
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * and evaluation are done on the fly
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic long
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsubexpr(register int precedence, int* pun)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register long n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register long x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int operand = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int un = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int xn;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (lex(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unlex(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "more tokens expected";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '-':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = -subexpr(13, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '+':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = subexpr(13, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '!':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = !subexpr(13, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '~':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = ~subexpr(13, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unlex(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin operand = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un <<= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (lex(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ')':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!precedence)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "too many )'s";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '(':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = subexpr(1, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (lex(c) != ')')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unlex(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "closing ) expected";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gotoperand:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (operand)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operator expected";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin operand = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un <<= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '?':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 1) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (lex(c) == ':')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!n) n = subexpr(2, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = pp.mode;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.mode |= INACTIVE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subexpr(2, &xn);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.mode = x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unlex(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = subexpr(2, &xn);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (lex(c) != ':')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unlex(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = ": expected for ? operator";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un = xn;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subexpr(2, &xn);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n = subexpr(2, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ':':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_ANDAND:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_OROR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin xn = (c == T_ANDAND) ? 4 : 3;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence >= xn) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n != 0) == (c == T_ANDAND)) n = subexpr(xn, &un) != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = pp.mode;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.mode |= INACTIVE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin subexpr(xn, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.mode = x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '|':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 4) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n |= subexpr(5, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '^':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 5) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n ^= subexpr(6, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '&':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 6) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n &= subexpr(7, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_EQ:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_NE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 7) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (n == subexpr(8, &un)) == (c == T_EQ);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '<':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_LE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_GE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '>':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 8) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = subexpr(9, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '<':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (un)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 01:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n < (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 02:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n < x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 03:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n < (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n < x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_LE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (un)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 01:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n <= (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 02:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n <= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 03:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n <= (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n <= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_GE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (un)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 01:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n >= (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 02:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n >= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 03:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n >= (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n >= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '>':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (un)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 01:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n > (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 02:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n > x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 03:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = (unsigned long)n > (unsigned long)x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n > x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_LSHIFT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_RSHIFT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 9) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = subexpr(10, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == T_LSHIFT) n <<= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n >>= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un >>= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '+':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '-':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 10) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = subexpr(11, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '+') n += x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n -= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '*':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '/':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '%':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (precedence > 11) goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = subexpr(12, &un);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '*') n *= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (x == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "divide by zero";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '/') n /= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n %= x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '#':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state |= DISABLE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = pplex();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state &= ~DISABLE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c != T_ID)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "# must precede a predicate identifier";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = predicate(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto gotoperand;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_ID:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = predicate(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto gotoperand;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_CHARCONST:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = *(pp.toknxt - 1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *(pp.toknxt - 1) = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = chrtoi(pp.token + 1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *(pp.toknxt - 1) = c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n & ~((1<<CHAR_BIT)-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(pp.mode & HOSTED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "'%s': multi-character character constants are not portable", pp.token);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if CHAR_MIN < 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else n = (char)n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto gotoperand;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_DECIMAL_U:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_DECIMAL_UL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_OCTAL_U:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_OCTAL_UL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_HEXADECIMAL_U:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_HEXADECIMAL_UL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin un |= 01;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_DECIMAL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_DECIMAL_L:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_OCTAL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_OCTAL_L:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_HEXADECIMAL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_HEXADECIMAL_L:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = strtoul(pp.token, NiL, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((unsigned long)n > LONG_MAX) un |= 01;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto gotoperand;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case T_WCHARCONST:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = chrtoi(pp.token);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto gotoperand;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid token";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (errmsg) return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!operand) goto nooperand;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin done:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unlex(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!operand)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nooperand:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operand expected";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (un) *pun |= 01;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * preprocessor expression evaluator using modified streval(3)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * *pun!=0 if result is unsigned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinlong
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinppexpr(int* pun)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int opeektoken;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long ppstate;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ppstate = (pp.state & (CONDITIONAL|DISABLE|NOSPACE|STRIP));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state &= ~(DISABLE|STRIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state |= CONDITIONAL|NOSPACE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin opeektoken = peektoken;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin peektoken = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *pun = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = subexpr(0, pun);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (peektoken == ':' && !errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid use of :";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (errmsg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s in expression", errmsg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errmsg = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin peektoken = opeektoken;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state &= ~(CONDITIONAL|NOSPACE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.state |= ppstate;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*pun) debug((-4, "ppexpr() = %luU", n));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else debug((-4, "ppexpr() = %ld", n));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return non-zero if option s is set
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinppoption(char* s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch ((int)hashget(pp.strtab, s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_ALLMULTIPLE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.mode & ALLMULTIPLE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_BUILTIN:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.mode & BUILTIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_CATLITERAL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.mode & CATLITERAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_COMPATIBILITY:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.state & COMPATIBILITY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_DEBUG:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -error_info.trace;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_ELSEIF:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & ELSEIF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_FINAL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & FINAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_HOSTDIR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.mode & HOSTED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_HOSTED:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.flags & PP_hosted;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_INITIAL:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & INITIAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_KEYARGS:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & KEYARGS;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_LINEBASE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.flags & PP_linebase;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_LINEFILE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.flags & PP_linefile;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_LINETYPE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.flags & PP_linetype;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_PLUSCOMMENT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & PLUSCOMMENT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_PLUSPLUS:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & PLUSPLUS;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_PLUSSPLICE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & PLUSSPLICE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_PRAGMAEXPAND:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & PRAGMAEXPAND;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_PREDEFINED:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & PREDEFINED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_PREFIX:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & PREFIX;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_PROTOTYPED:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & PROTOTYPED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_READONLY:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.mode & READONLY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_REGUARD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & REGUARD;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_SPACEOUT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.state & SPACEOUT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_SPLICECAT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & SPLICECAT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_SPLICESPACE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & SPLICESPACE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_STRICT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.state & STRICT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_STRINGSPAN:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & STRINGSPAN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_STRINGSPLIT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.option & STRINGSPLIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_TEST:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.test;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_TEXT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return !(pp.state & NOTEXT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_TRANSITION:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.state & TRANSITION;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_TRUNCATE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.truncate;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case X_WARN:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return pp.state & WARN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.state & WARN) error(1, "%s: unknown option name", s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}