mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-26 18:31:29 +00:00
36000fce8e
--HG-- rename : security/coreconf/AIX.mk => security/nss/coreconf/AIX.mk rename : security/coreconf/Android.mk => security/nss/coreconf/Android.mk rename : security/coreconf/BSD_OS.mk => security/nss/coreconf/BSD_OS.mk rename : security/coreconf/BeOS.mk => security/nss/coreconf/BeOS.mk rename : security/coreconf/Darwin.mk => security/nss/coreconf/Darwin.mk rename : security/coreconf/FreeBSD.mk => security/nss/coreconf/FreeBSD.mk rename : security/coreconf/HP-UX.mk => security/nss/coreconf/HP-UX.mk rename : security/coreconf/HP-UXA.09.03.mk => security/nss/coreconf/HP-UXA.09.03.mk rename : security/coreconf/HP-UXA.09.07.mk => security/nss/coreconf/HP-UXA.09.07.mk rename : security/coreconf/HP-UXA.09.mk => security/nss/coreconf/HP-UXA.09.mk rename : security/coreconf/HP-UXB.10.01.mk => security/nss/coreconf/HP-UXB.10.01.mk rename : security/coreconf/HP-UXB.10.10.mk => security/nss/coreconf/HP-UXB.10.10.mk rename : security/coreconf/HP-UXB.10.20.mk => security/nss/coreconf/HP-UXB.10.20.mk rename : security/coreconf/HP-UXB.10.30.mk => security/nss/coreconf/HP-UXB.10.30.mk rename : security/coreconf/HP-UXB.10.mk => security/nss/coreconf/HP-UXB.10.mk rename : security/coreconf/HP-UXB.11.00.mk => security/nss/coreconf/HP-UXB.11.00.mk rename : security/coreconf/HP-UXB.11.11.mk => security/nss/coreconf/HP-UXB.11.11.mk rename : security/coreconf/HP-UXB.11.20.mk => security/nss/coreconf/HP-UXB.11.20.mk rename : security/coreconf/HP-UXB.11.22.mk => security/nss/coreconf/HP-UXB.11.22.mk rename : security/coreconf/HP-UXB.11.23.mk => security/nss/coreconf/HP-UXB.11.23.mk rename : security/coreconf/HP-UXB.11.mk => security/nss/coreconf/HP-UXB.11.mk rename : security/coreconf/IRIX.mk => security/nss/coreconf/IRIX.mk rename : security/coreconf/IRIX5.2.mk => security/nss/coreconf/IRIX5.2.mk rename : security/coreconf/IRIX5.3.mk => security/nss/coreconf/IRIX5.3.mk rename : security/coreconf/IRIX5.mk => security/nss/coreconf/IRIX5.mk rename : security/coreconf/IRIX6.2.mk => security/nss/coreconf/IRIX6.2.mk rename : security/coreconf/IRIX6.3.mk => security/nss/coreconf/IRIX6.3.mk rename : security/coreconf/IRIX6.5.mk => security/nss/coreconf/IRIX6.5.mk rename : security/coreconf/IRIX6.mk => security/nss/coreconf/IRIX6.mk rename : security/coreconf/Linux.mk => security/nss/coreconf/Linux.mk rename : security/coreconf/Makefile => security/nss/coreconf/Makefile rename : security/coreconf/NCR3.0.mk => security/nss/coreconf/NCR3.0.mk rename : security/coreconf/NEC4.2.mk => security/nss/coreconf/NEC4.2.mk rename : security/coreconf/NetBSD.mk => security/nss/coreconf/NetBSD.mk rename : security/coreconf/OS2.mk => security/nss/coreconf/OS2.mk rename : security/coreconf/OSF1.mk => security/nss/coreconf/OSF1.mk rename : security/coreconf/OSF1V3.0.mk => security/nss/coreconf/OSF1V2.0.mk rename : security/coreconf/OSF1V3.0.mk => security/nss/coreconf/OSF1V3.0.mk rename : security/coreconf/OSF1V3.2.mk => security/nss/coreconf/OSF1V3.2.mk rename : security/coreconf/OSF1V4.0.mk => security/nss/coreconf/OSF1V4.0.mk rename : security/coreconf/OSF1V4.0B.mk => security/nss/coreconf/OSF1V4.0B.mk rename : security/coreconf/OSF1V4.0D.mk => security/nss/coreconf/OSF1V4.0D.mk rename : security/coreconf/OSF1V5.0.mk => security/nss/coreconf/OSF1V5.0.mk rename : security/coreconf/OSF1V5.1.mk => security/nss/coreconf/OSF1V5.1.mk rename : security/coreconf/OpenBSD.mk => security/nss/coreconf/OpenBSD.mk rename : security/coreconf/OpenUNIX.mk => security/nss/coreconf/OpenUNIX.mk rename : security/coreconf/QNX.mk => security/nss/coreconf/QNX.mk rename : security/coreconf/README => security/nss/coreconf/README rename : security/coreconf/RISCOS.mk => security/nss/coreconf/RISCOS.mk rename : security/coreconf/ReliantUNIX.mk => security/nss/coreconf/ReliantUNIX.mk rename : security/coreconf/ReliantUNIX5.4.mk => security/nss/coreconf/ReliantUNIX5.4.mk rename : security/coreconf/SCOOS5.0.mk => security/nss/coreconf/SCOOS5.0.mk rename : security/coreconf/SCO_SV3.2.mk => security/nss/coreconf/SCO_SV3.2.mk rename : security/coreconf/SunOS4.1.3_U1.mk => security/nss/coreconf/SunOS4.1.3_U1.mk rename : security/coreconf/UNIX.mk => security/nss/coreconf/UNIX.mk rename : security/coreconf/UNIXWARE2.1.mk => security/nss/coreconf/UNIXWARE2.1.mk rename : security/coreconf/WIN95.mk => security/nss/coreconf/WIN95.mk rename : security/coreconf/WINNT.mk => security/nss/coreconf/WINNT.mk rename : security/coreconf/arch.mk => security/nss/coreconf/arch.mk rename : security/coreconf/command.mk => security/nss/coreconf/command.mk rename : security/coreconf/coreconf.pl => security/nss/coreconf/coreconf.pl rename : security/coreconf/cpdist.pl => security/nss/coreconf/cpdist.pl rename : security/coreconf/headers.mk => security/nss/coreconf/headers.mk rename : security/coreconf/import.pl => security/nss/coreconf/import.pl rename : security/coreconf/jdk.mk => security/nss/coreconf/jdk.mk rename : security/coreconf/jniregen.pl => security/nss/coreconf/jniregen.pl rename : security/coreconf/location.mk => security/nss/coreconf/location.mk rename : security/coreconf/mkdepend/Makefile => security/nss/coreconf/mkdepend/Makefile rename : security/coreconf/mkdepend/cppsetup.c => security/nss/coreconf/mkdepend/cppsetup.c rename : security/coreconf/mkdepend/def.h => security/nss/coreconf/mkdepend/def.h rename : security/coreconf/mkdepend/ifparser.c => security/nss/coreconf/mkdepend/ifparser.c rename : security/coreconf/mkdepend/ifparser.h => security/nss/coreconf/mkdepend/ifparser.h rename : security/coreconf/mkdepend/imakemdep.h => security/nss/coreconf/mkdepend/imakemdep.h rename : security/coreconf/mkdepend/include.c => security/nss/coreconf/mkdepend/include.c rename : security/coreconf/mkdepend/main.c => security/nss/coreconf/mkdepend/main.c rename : security/coreconf/mkdepend/mkdepend.man => security/nss/coreconf/mkdepend/mkdepend.man rename : security/coreconf/mkdepend/parse.c => security/nss/coreconf/mkdepend/parse.c rename : security/coreconf/mkdepend/pr.c => security/nss/coreconf/mkdepend/pr.c rename : security/coreconf/module.mk => security/nss/coreconf/module.mk rename : security/coreconf/nsinstall/Makefile => security/nss/coreconf/nsinstall/Makefile rename : security/coreconf/nsinstall/nsinstall.c => security/nss/coreconf/nsinstall/nsinstall.c rename : security/coreconf/nsinstall/pathsub.c => security/nss/coreconf/nsinstall/pathsub.c rename : security/coreconf/nsinstall/pathsub.h => security/nss/coreconf/nsinstall/pathsub.h rename : security/coreconf/nsinstall/sunos4.h => security/nss/coreconf/nsinstall/sunos4.h rename : security/coreconf/outofdate.pl => security/nss/coreconf/outofdate.pl rename : security/coreconf/prefix.mk => security/nss/coreconf/prefix.mk rename : security/coreconf/release.pl => security/nss/coreconf/release.pl rename : security/coreconf/rules.mk => security/nss/coreconf/rules.mk rename : security/coreconf/ruleset.mk => security/nss/coreconf/ruleset.mk rename : security/coreconf/source.mk => security/nss/coreconf/source.mk rename : security/coreconf/suffix.mk => security/nss/coreconf/suffix.mk rename : security/coreconf/tree.mk => security/nss/coreconf/tree.mk rename : security/coreconf/version.mk => security/nss/coreconf/version.mk rename : security/coreconf/version.pl => security/nss/coreconf/version.pl rename : security/dbm/config/config.mk => security/nss/lib/dbm/config/config.mk rename : dbm/include/cdefs.h => security/nss/lib/dbm/include/cdefs.h rename : dbm/include/extern.h => security/nss/lib/dbm/include/extern.h rename : dbm/include/hash.h => security/nss/lib/dbm/include/hash.h rename : dbm/include/search.h => security/nss/lib/dbm/include/hsearch.h rename : dbm/include/mcom_db.h => security/nss/lib/dbm/include/mcom_db.h rename : dbm/include/mpool.h => security/nss/lib/dbm/include/mpool.h rename : dbm/include/ncompat.h => security/nss/lib/dbm/include/ncompat.h rename : dbm/include/page.h => security/nss/lib/dbm/include/page.h rename : dbm/include/queue.h => security/nss/lib/dbm/include/queue.h rename : dbm/include/search.h => security/nss/lib/dbm/include/search.h rename : dbm/include/winfile.h => security/nss/lib/dbm/include/winfile.h rename : dbm/src/db.c => security/nss/lib/dbm/src/db.c rename : security/dbm/src/dirent.c => security/nss/lib/dbm/src/dirent.c rename : security/dbm/src/dirent.h => security/nss/lib/dbm/src/dirent.h rename : dbm/src/h_bigkey.c => security/nss/lib/dbm/src/h_bigkey.c rename : dbm/src/h_func.c => security/nss/lib/dbm/src/h_func.c rename : dbm/src/h_log2.c => security/nss/lib/dbm/src/h_log2.c rename : dbm/src/h_page.c => security/nss/lib/dbm/src/h_page.c rename : dbm/src/hash.c => security/nss/lib/dbm/src/hash.c rename : dbm/src/hash_buf.c => security/nss/lib/dbm/src/hash_buf.c rename : dbm/src/memmove.c => security/nss/lib/dbm/src/memmove.c rename : dbm/src/mktemp.c => security/nss/lib/dbm/src/mktemp.c rename : dbm/src/snprintf.c => security/nss/lib/dbm/src/snprintf.c rename : dbm/src/strerror.c => security/nss/lib/dbm/src/strerror.c rename : dbm/tests/dbmtest.pkg => security/nss/lib/dbm/tests/dbmtest.pkg rename : dbm/tests/lots.c => security/nss/lib/dbm/tests/lots.c extra : rebase_source : 119dad5f824e8e760182047fd32e2a0d0f944172 extra : amend_source : 98e24aa51f9044d9091a26f013b643925e8f9dcf
552 lines
12 KiB
C
552 lines
12 KiB
C
/*
|
|
* $Xorg: ifparser.c,v 1.3 2000/08/17 19:41:50 cpqbld Exp $
|
|
*
|
|
* Copyright 1992 Network Computing Devices, Inc.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
* documentation for any purpose and without fee is hereby granted, provided
|
|
* that the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Network Computing Devices may not be
|
|
* used in advertising or publicity pertaining to distribution of the software
|
|
* without specific, written prior permission. Network Computing Devices makes
|
|
* no representations about the suitability of this software for any purpose.
|
|
* It is provided ``as is'' without express or implied warranty.
|
|
*
|
|
* NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
|
|
* IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
|
|
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Author: Jim Fulton
|
|
* Network Computing Devices, Inc.
|
|
*
|
|
* Simple if statement processor
|
|
*
|
|
* This module can be used to evaluate string representations of C language
|
|
* if constructs. It accepts the following grammar:
|
|
*
|
|
* EXPRESSION := VALUE
|
|
* | VALUE BINOP EXPRESSION
|
|
* | VALUE '?' EXPRESSION ':' EXPRESSION
|
|
*
|
|
* VALUE := '(' EXPRESSION ')'
|
|
* | '!' VALUE
|
|
* | '-' VALUE
|
|
* | '+' VALUE
|
|
* | '~' VALUE
|
|
* | 'defined' '(' variable ')'
|
|
* | 'defined' variable
|
|
* | # variable '(' variable-list ')'
|
|
* | variable
|
|
* | number
|
|
*
|
|
* BINOP := '*' | '/' | '%'
|
|
* | '+' | '-'
|
|
* | '<<' | '>>'
|
|
* | '<' | '>' | '<=' | '>='
|
|
* | '==' | '!='
|
|
* | '&' | '^' | '|'
|
|
* | '&&' | '||'
|
|
*
|
|
* The normal C order of precedence is supported.
|
|
*
|
|
*
|
|
* External Entry Points:
|
|
*
|
|
* ParseIfExpression parse a string for #if
|
|
*/
|
|
/* $XFree86: xc/config/makedepend/ifparser.c,v 3.11 2002/09/23 01:48:08 tsi Exp $ */
|
|
|
|
#include "ifparser.h"
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/****************************************************************************
|
|
Internal Macros and Utilities for Parser
|
|
****************************************************************************/
|
|
|
|
#define DO(val) if (!(val)) return NULL
|
|
#define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
|
|
#define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
|
|
#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
|
|
|
|
|
|
static const char *
|
|
parse_variable (IfParser *g, const char *cp, const char **varp)
|
|
{
|
|
SKIPSPACE (cp);
|
|
|
|
if (!isvarfirstletter (*cp))
|
|
return CALLFUNC(g, handle_error) (g, cp, "variable name");
|
|
|
|
*varp = cp;
|
|
/* EMPTY */
|
|
for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_number (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long base = 10;
|
|
SKIPSPACE (cp);
|
|
|
|
if (!isdigit(*cp))
|
|
return CALLFUNC(g, handle_error) (g, cp, "number");
|
|
|
|
*valp = 0;
|
|
|
|
if (*cp == '0') {
|
|
cp++;
|
|
if ((*cp == 'x') || (*cp == 'X')) {
|
|
base = 16;
|
|
cp++;
|
|
} else {
|
|
base = 8;
|
|
}
|
|
}
|
|
|
|
/* Ignore overflows and assume ASCII, what source is usually written in */
|
|
while (1) {
|
|
int increment = -1;
|
|
if (base == 8) {
|
|
if ((*cp >= '0') && (*cp <= '7'))
|
|
increment = *cp++ - '0';
|
|
} else if (base == 16) {
|
|
if ((*cp >= '0') && (*cp <= '9'))
|
|
increment = *cp++ - '0';
|
|
else if ((*cp >= 'A') && (*cp <= 'F'))
|
|
increment = *cp++ - ('A' - 10);
|
|
else if ((*cp >= 'a') && (*cp <= 'f'))
|
|
increment = *cp++ - ('a' - 10);
|
|
} else { /* Decimal */
|
|
if ((*cp >= '0') && (*cp <= '9'))
|
|
increment = *cp++ - '0';
|
|
}
|
|
if (increment < 0)
|
|
break;
|
|
*valp = (*valp * base) + increment;
|
|
}
|
|
|
|
/* Skip trailing qualifiers */
|
|
while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
|
|
return cp;
|
|
}
|
|
|
|
static const char *
|
|
parse_character (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
char val;
|
|
|
|
SKIPSPACE (cp);
|
|
if (*cp == '\\')
|
|
switch (cp[1]) {
|
|
case 'n': val = '\n'; break;
|
|
case 't': val = '\t'; break;
|
|
case 'v': val = '\v'; break;
|
|
case 'b': val = '\b'; break;
|
|
case 'r': val = '\r'; break;
|
|
case 'f': val = '\f'; break;
|
|
case 'a': val = '\a'; break;
|
|
case '\\': val = '\\'; break;
|
|
case '?': val = '\?'; break;
|
|
case '\'': val = '\''; break;
|
|
case '\"': val = '\"'; break;
|
|
case 'x': val = (char) strtol (cp + 2, NULL, 16); break;
|
|
default: val = (char) strtol (cp + 1, NULL, 8); break;
|
|
}
|
|
else
|
|
val = *cp;
|
|
while (*cp != '\'') cp++;
|
|
*valp = (long) val;
|
|
return cp;
|
|
}
|
|
|
|
static const char *
|
|
parse_value (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
const char *var, *varend;
|
|
|
|
*valp = 0;
|
|
|
|
SKIPSPACE (cp);
|
|
if (!*cp)
|
|
return cp;
|
|
|
|
switch (*cp) {
|
|
case '(':
|
|
DO (cp = ParseIfExpression (g, cp + 1, valp));
|
|
SKIPSPACE (cp);
|
|
if (*cp != ')')
|
|
return CALLFUNC(g, handle_error) (g, cp, ")");
|
|
|
|
return cp + 1; /* skip the right paren */
|
|
|
|
case '!':
|
|
DO (cp = parse_value (g, cp + 1, valp));
|
|
*valp = !(*valp);
|
|
return cp;
|
|
|
|
case '-':
|
|
DO (cp = parse_value (g, cp + 1, valp));
|
|
*valp = -(*valp);
|
|
return cp;
|
|
|
|
case '+':
|
|
DO (cp = parse_value (g, cp + 1, valp));
|
|
return cp;
|
|
|
|
case '~':
|
|
DO (cp = parse_value (g, cp + 1, valp));
|
|
*valp = ~(*valp);
|
|
return cp;
|
|
|
|
case '#':
|
|
DO (cp = parse_variable (g, cp + 1, &var));
|
|
SKIPSPACE (cp);
|
|
if (*cp != '(')
|
|
return CALLFUNC(g, handle_error) (g, cp, "(");
|
|
do {
|
|
DO (cp = parse_variable (g, cp + 1, &var));
|
|
SKIPSPACE (cp);
|
|
} while (*cp && *cp != ')');
|
|
if (*cp != ')')
|
|
return CALLFUNC(g, handle_error) (g, cp, ")");
|
|
*valp = 1; /* XXX */
|
|
return cp + 1;
|
|
|
|
case '\'':
|
|
DO (cp = parse_character (g, cp + 1, valp));
|
|
if (*cp != '\'')
|
|
return CALLFUNC(g, handle_error) (g, cp, "'");
|
|
return cp + 1;
|
|
|
|
case 'd':
|
|
if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
|
|
int paren = 0;
|
|
int len;
|
|
|
|
cp += 7;
|
|
SKIPSPACE (cp);
|
|
if (*cp == '(') {
|
|
paren = 1;
|
|
cp++;
|
|
}
|
|
DO (cp = parse_variable (g, cp, &var));
|
|
len = cp - var;
|
|
SKIPSPACE (cp);
|
|
if (paren && *cp != ')')
|
|
return CALLFUNC(g, handle_error) (g, cp, ")");
|
|
*valp = (*(g->funcs.eval_defined)) (g, var, len);
|
|
return cp + paren; /* skip the right paren */
|
|
}
|
|
/* fall out */
|
|
}
|
|
|
|
if (isdigit(*cp)) {
|
|
DO (cp = parse_number (g, cp, valp));
|
|
} else if (!isvarfirstletter(*cp))
|
|
return CALLFUNC(g, handle_error) (g, cp, "variable or number");
|
|
else {
|
|
DO (cp = parse_variable (g, cp, &var));
|
|
varend = cp;
|
|
SKIPSPACE(cp);
|
|
if (*cp != '(') {
|
|
*valp = (*(g->funcs.eval_variable)) (g, var, varend - var);
|
|
} else {
|
|
do {
|
|
long dummy;
|
|
DO (cp = ParseIfExpression (g, cp + 1, &dummy));
|
|
SKIPSPACE(cp);
|
|
if (*cp == ')')
|
|
break;
|
|
if (*cp != ',')
|
|
return CALLFUNC(g, handle_error) (g, cp, ",");
|
|
} while (1);
|
|
|
|
*valp = 1; /* XXX */
|
|
cp++;
|
|
}
|
|
}
|
|
|
|
return cp;
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
parse_product (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_value (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '*':
|
|
DO (cp = parse_product (g, cp + 1, &rightval));
|
|
*valp = (*valp * rightval);
|
|
break;
|
|
|
|
case '/':
|
|
DO (cp = parse_product (g, cp + 1, &rightval));
|
|
if (rightval == 0)
|
|
return CALLFUNC(g, handle_error) (g, cp, "0");
|
|
*valp = (*valp / rightval);
|
|
break;
|
|
|
|
case '%':
|
|
DO (cp = parse_product (g, cp + 1, &rightval));
|
|
*valp = (*valp % rightval);
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_sum (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_product (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '+':
|
|
DO (cp = parse_sum (g, cp + 1, &rightval));
|
|
*valp = (*valp + rightval);
|
|
break;
|
|
|
|
case '-':
|
|
DO (cp = parse_sum (g, cp + 1, &rightval));
|
|
*valp = (*valp - rightval);
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_shift (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_sum (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '<':
|
|
if (cp[1] == '<') {
|
|
DO (cp = parse_shift (g, cp + 2, &rightval));
|
|
*valp = (*valp << rightval);
|
|
}
|
|
break;
|
|
|
|
case '>':
|
|
if (cp[1] == '>') {
|
|
DO (cp = parse_shift (g, cp + 2, &rightval));
|
|
*valp = (*valp >> rightval);
|
|
}
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_inequality (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_shift (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '<':
|
|
if (cp[1] == '=') {
|
|
DO (cp = parse_inequality (g, cp + 2, &rightval));
|
|
*valp = (*valp <= rightval);
|
|
} else {
|
|
DO (cp = parse_inequality (g, cp + 1, &rightval));
|
|
*valp = (*valp < rightval);
|
|
}
|
|
break;
|
|
|
|
case '>':
|
|
if (cp[1] == '=') {
|
|
DO (cp = parse_inequality (g, cp + 2, &rightval));
|
|
*valp = (*valp >= rightval);
|
|
} else {
|
|
DO (cp = parse_inequality (g, cp + 1, &rightval));
|
|
*valp = (*valp > rightval);
|
|
}
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_equality (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_inequality (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '=':
|
|
if (cp[1] == '=')
|
|
cp++;
|
|
DO (cp = parse_equality (g, cp + 1, &rightval));
|
|
*valp = (*valp == rightval);
|
|
break;
|
|
|
|
case '!':
|
|
if (cp[1] != '=')
|
|
break;
|
|
DO (cp = parse_equality (g, cp + 2, &rightval));
|
|
*valp = (*valp != rightval);
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_band (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_equality (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '&':
|
|
if (cp[1] != '&') {
|
|
DO (cp = parse_band (g, cp + 1, &rightval));
|
|
*valp = (*valp & rightval);
|
|
}
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_bxor (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_band (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '^':
|
|
DO (cp = parse_bxor (g, cp + 1, &rightval));
|
|
*valp = (*valp ^ rightval);
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_bor (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_bxor (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '|':
|
|
if (cp[1] != '|') {
|
|
DO (cp = parse_bor (g, cp + 1, &rightval));
|
|
*valp = (*valp | rightval);
|
|
}
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_land (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_bor (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '&':
|
|
if (cp[1] != '&')
|
|
return CALLFUNC(g, handle_error) (g, cp, "&&");
|
|
DO (cp = parse_land (g, cp + 2, &rightval));
|
|
*valp = (*valp && rightval);
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_lor (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long rightval;
|
|
|
|
DO (cp = parse_land (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '|':
|
|
if (cp[1] != '|')
|
|
return CALLFUNC(g, handle_error) (g, cp, "||");
|
|
DO (cp = parse_lor (g, cp + 2, &rightval));
|
|
*valp = (*valp || rightval);
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
static const char *
|
|
parse_cond(IfParser *g, const char *cp, long *valp)
|
|
{
|
|
long trueval, falseval;
|
|
|
|
DO (cp = parse_lor (g, cp, valp));
|
|
SKIPSPACE (cp);
|
|
|
|
switch (*cp) {
|
|
case '?':
|
|
DO (cp = parse_cond (g, cp + 1, &trueval));
|
|
SKIPSPACE (cp);
|
|
if (*cp != ':')
|
|
return CALLFUNC(g, handle_error) (g, cp, ":");
|
|
DO (cp = parse_cond (g, cp + 1, &falseval));
|
|
*valp = (*valp ? trueval : falseval);
|
|
break;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
External Entry Points
|
|
****************************************************************************/
|
|
|
|
const char *
|
|
ParseIfExpression (IfParser *g, const char *cp, long *valp)
|
|
{
|
|
return parse_cond (g, cp, valp);
|
|
}
|