* details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with these librararies and programs; if not, write
+ * License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
#include "ifparser.h"
#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.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) == '_')
+#define SKIPSPACE(ccc) while (isspace((int)*ccc)) ccc++
+#define isvarfirstletter(ccc) (isalpha((int)ccc) || (ccc) == '_')
static const char *
*varp = cp;
/* EMPTY */
- for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
+ for (cp++; isalnum((int)*cp) || *cp == '_'; cp++) ;
return cp;
}
const char *cp;
long *valp;
{
+ long base = 10;
SKIPSPACE (cp);
- if (!isdigit(*cp))
+ if (!isdigit((int)*cp))
return CALLFUNC(g, handle_error) (g, cp, "number");
- *valp = strtol(cp, &cp, 0);
- /* skip trailing qualifiers */
+ *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++;
-#if 0
- *valp = atoi (cp);
- /* EMPTY */
- for (cp++; isdigit(*cp); cp++) ;
-#endif
return cp;
}
const char *cp;
long *valp;
{
- const char *var;
+ const char *var, *varend;
*valp = 0;
*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));
+ *valp = ~(*valp);
+ return cp;
+
case '#':
DO (cp = parse_variable (g, cp + 1, &var));
SKIPSPACE (cp);
return cp + 1;
case 'd':
- if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
+ if (strncmp (cp, "defined", 7) == 0 && !isalnum((int)cp[7])) {
int paren = 0;
int len;
/* fall out */
}
- if (isdigit(*cp)) {
+ if (isdigit((int)*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));
- *valp = (*(g->funcs.eval_variable)) (g, var, 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;
case '/':
DO (cp = parse_product (g, cp + 1, &rightval));
- *valp = (*valp / rightval);
+ if (rightval)
+ *valp = (*valp / rightval);
+ else
+ *valp = LONG_MAX;
break;
case '%':
static const char *
-parse_bor (g, cp, valp)
+parse_bxor (g, cp, valp)
IfParser *g;
const char *cp;
long *valp;
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 (g, cp, valp)
+ IfParser *g;
+ const char *cp;
+ long *valp;
+{
+ long rightval;
+
+ DO (cp = parse_bxor (g, cp, valp));
+ SKIPSPACE (cp);
+
switch (*cp) {
case '|':
if (cp[1] != '|') {