/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1989-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
* expression library evaluator
*/
#include "exlib.h"
#include "exop.h"
#include <tm.h>
static char*
{
register char* b;
static int n;
if (++n >= TOTNAME)
n = 0;
b = buf[n];
if (op == '=')
{
else
}
else if (subop < 0)
else
return b;
}
/*
* return dynamic (associative array) variable value
* assoc will point to the associative array bucket
*/
static Extype_t
{
Exassoc_t* b;
Extype_t v;
{
{
}
{
exnospace();
}
*assoc = b;
if (b)
{
return b->value;
}
return v;
}
*assoc = 0;
}
typedef struct
{
void* env;
} Fmt_t;
/*
* printf %! extension function
*/
static int
{
register char* s;
register char* txt;
int n;
int from;
int to;
{
else
}
exerror("printf: not enough arguments");
else
{
{
case 'f':
case 'g':
break;
case 's':
case '[':
break;
default:
switch (from)
{
case INTEGER:
case UNSIGNED:
break;
default:
break;
}
break;
}
else
{
{
{
if (s = fmtbuf(n + 1))
}
}
}
}
switch (to)
{
case STRING:
break;
case FLOATING:
break;
default:
break;
}
{
else
{
}
}
else
txt = 0;
{
case 'q':
case 'Q':
s = *((char**)vp);
break;
case 'S':
s = *((char**)vp);
if (txt)
{
{
if (*s && !isalpha(*s))
*s++ = '_';
for (; *s; s++)
if (!isalnum(*s))
*s = '_';
}
{
for (; *s; s++)
if (isupper(*s))
*s = tolower(*s);
else if (islower(*s))
*s = toupper(*s);
}
{
for (; *s; s++)
if (isupper(*s))
*s = tolower(*s);
}
{
for (; *s; s++)
if (islower(*s))
*s = toupper(*s);
}
{
for (; *s; s++)
if (!isalnum(*s) && *s != '_')
*s = '.';
}
}
break;
case 't':
case 'T':
break;
}
return 0;
}
/*
* do printf
*/
static int
{
register Print_t* x;
Extype_t v;
if (!sp)
{
if (v.integer < 0 || v.integer >= elementsof(ex->file) || !(sp = ex->file[v.integer]) && !(sp = ex->file[v.integer] = sfnew(NiL, NiL, SF_UNBOUND, v.integer, SF_READ|SF_WRITE)))
{
return 0;
}
}
if (x->format)
do
{
if (x->arg)
{
}
else
} while (x = x->next);
else
{
}
return 1;
}
/*
* scanf %! extension function
*/
static int
{
{
exerror("scanf: not enough arguments");
return -1;
}
{
case 'f':
case 'g':
{
exerror("scanf: %s: floating variable address argument expected", node->data.variable.symbol->name);
return -1;
}
break;
case 's':
{
return -1;
}
*((void**)vp) = node->data.variable.symbol->value->data.constant.value.string = vmnewof(fmt->expr->vm, node->data.variable.symbol->value->data.constant.value.string, char, fmt->fmt.size, 0);
break;
default:
{
return -1;
}
break;
}
return 0;
}
/*
* do scanf
*/
static int
{
Extype_t v;
Extype_t u;
int n;
if (!sp)
{
{
goto get;
}
else
v.integer = 0;
if (v.integer < 0 || v.integer >= elementsof(ex->file) || !(sp = ex->file[v.integer]) && !(sp = ex->file[v.integer] = sfnew(NiL, NiL, SF_UNBOUND, v.integer, SF_READ|SF_WRITE)))
{
return 0;
}
}
get:
exerror("scanf: %s: too many arguments", fmt.actuals->data.operand.left->data.variable.symbol->name);
return n;
}
/*
* string add
*/
static char*
{
}
/*
* string ior
*/
static char*
{
register int c;
register char* s = l;
while (c = *s++)
if (!strchr(s, c))
while (c = *r++)
}
/*
* string and
*/
static char*
{
register int c;
while (c = *l++)
}
/*
* string xor
*/
static char*
{
register int c;
register char* s = l;
while (c = *s++)
while (c = *r++)
}
/*
* string mod
*/
static char*
{
register int c;
while (c = *l++)
}
/*
* string mpy
*/
static char*
{
register int lc;
register int rc;
}
/*
* internal exeval
*/
static Extype_t
{
register Exnode_t* x;
register Exnode_t* a;
register Extype_t** t;
register int n;
Extype_t v;
Extype_t r;
Extype_t i;
char* e;
{
v.integer = 1;
return v;
}
{
case BREAK:
case CONTINUE:
return v;
case CONSTANT:
case DEC:
n = -1;
add:
else
{
else
r = (*ex->disc->getf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)i.integer, ex->disc);
}
v = r;
switch (x->type)
{
case FLOATING:
v.floating += n;
break;
case INTEGER:
case UNSIGNED:
v.integer += n;
break;
default:
goto huh;
}
set:
{
{
}
if (assoc)
else
}
else
{
else
if ((*ex->disc->setf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)i.integer, v, ex->disc) < 0)
}
r = v;
return r;
case DYNAMIC:
case EXIT:
/*NOTREACHED*/
v.integer = -1;
return v;
case IF:
if (v.integer)
else
v.integer = 1;
return v;
case FOR:
case WHILE:
for (;;)
{
if (!r.integer)
{
v.integer = 1;
return v;
}
{
{
v.integer = 0;
return v;
}
}
}
/*NOTREACHED*/
case SWITCH:
r.integer = 0;
n = 0;
{
n = 1;
else
for (; *t; t++)
{
switch ((int)i.integer)
{
case INTEGER:
case UNSIGNED:
break;
continue;
case STRING:
if ((ex->disc->version >= 19981111L && ex->disc->matchf) ? (*ex->disc->matchf)(ex, x, (*t)->string, expr->data.operand.left, v.string, env, ex->disc) : strmatch((*t)->string, v.string))
break;
continue;
case FLOATING:
break;
continue;
}
n = 1;
break;
}
if (n)
{
{
r.integer = 1;
break;
}
{
break;
}
}
}
if (!n && a)
{
}
return r;
case ITERATE:
v.integer = 0;
{
for (assoc = (Exassoc_t*)dtfirst((Dt_t*)expr->data.generate.array->data.variable.symbol->local.pointer); assoc; assoc = (Exassoc_t*)dtnext((Dt_t*)expr->data.generate.array->data.variable.symbol->local.pointer, assoc))
{
v.integer++;
if (n)
else
{
v.integer = 0;
break;
}
}
}
else
{
r = (*ex->disc->getf)(ex, expr, expr->data.generate.array->data.variable.symbol, expr->data.generate.array->data.variable.reference, env, 0, ex->disc);
{
{
v.integer = 0;
break;
}
}
}
return v;
case CALL:
for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && x; a = a->data.operand.right)
{
if (n < elementsof(args))
{
}
else
a->data.operand.left->data.variable.symbol->value->data.constant.value = eval(ex, x->data.operand.left, env);
}
for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && n < elementsof(save); a = a->data.operand.right)
if (x)
exerror("too many actual args");
else if (a)
exerror("not enough actual args");
for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && n < elementsof(save); a = a->data.operand.right)
return v;
case FUNCTION:
n = 0;
return (*ex->disc->getf)(ex, expr->data.operand.left, expr->data.operand.left->data.variable.symbol, expr->data.operand.left->data.variable.reference, args+1, EX_CALL, ex->disc);
case ID:
else
return (*ex->disc->getf)(ex, expr, expr->data.variable.symbol, expr->data.variable.reference, env, (int)i.integer, ex->disc);
case INC:
n = 1;
goto add;
case PRINTF:
return v;
case QUERY:
return v;
case RETURN:
case SCANF:
case SSCANF:
return v;
case SPRINTF:
return v;
case '=':
{
r = v;
else
{
else
v = (*ex->disc->getf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)v.integer, ex->disc);
}
switch (x->type)
{
case FLOATING:
{
case '+':
break;
case '-':
break;
case '*':
break;
case '/':
if (r.floating == 0.0)
exerror("floating divide by 0");
else
break;
case '%':
exerror("floating 0 modulus");
else
break;
case '&':
break;
case '|':
break;
case '^':
break;
case LS:
break;
case RS:
#if _WIN32
#else
#endif
break;
default:
goto huh;
}
break;
case INTEGER:
case UNSIGNED:
{
case '+':
break;
case '-':
break;
case '*':
break;
case '/':
if (r.integer == 0)
exerror("integer divide by 0");
else
break;
case '%':
if (r.integer == 0)
exerror("integer 0 modulus");
else
break;
case '&':
break;
case '|':
break;
case '^':
break;
case LS:
break;
case RS:
break;
default:
goto huh;
}
break;
case STRING:
{
case '+':
break;
case '|':
break;
case '&':
break;
case '^':
break;
case '%':
break;
case '*':
break;
default:
goto huh;
}
break;
default:
goto huh;
}
}
else
assoc = 0;
r = v;
goto set;
case ';':
case ',':
{
return v;
}
case '?':
return v.integer ? eval(ex, expr->data.operand.right->data.operand.left, env) : eval(ex, expr->data.operand.right->data.operand.right, env);
case AND:
case OR:
}
{
case FLOATING:
{
case F2I:
return v;
case F2S:
{
}
else if ((*ex->disc->convertf)(ex, &tmp, STRING, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
case F2X:
if ((*ex->disc->convertf)(ex, &tmp, expr->type, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
case '!':
return v;
case '~':
return v;
case '-':
if (x)
else
return v;
case '+':
return v;
case '&':
return v;
case '|':
return v;
case '^':
return v;
case '*':
return v;
case '/':
if (r.floating == 0.0)
exerror("floating divide by 0");
else
return v;
case '%':
exerror("floating 0 modulus");
else
return v;
case '<':
return v;
case LE:
return v;
case EQ:
return v;
case NE:
return v;
case GE:
return v;
case '>':
return v;
case LS:
return v;
case RS:
return v;
}
break;
default:
{
case X2F:
if ((*ex->disc->convertf)(ex, &tmp, FLOATING, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
exerror("%s: cannot convert value to floating", expr->data.operand.left->data.variable.symbol->name);
case X2I:
if ((*ex->disc->convertf)(ex, &tmp, INTEGER, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
exerror("%s: cannot convert value to integer", expr->data.operand.left->data.variable.symbol->name);
case X2S:
if ((*ex->disc->convertf)(ex, &tmp, STRING, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
}
goto integer;
case UNSIGNED:
{
case '<':
return v;
case LE:
return v;
case GE:
return v;
case '>':
return v;
}
/*FALLTHROUGH*/
case INTEGER:
{
case I2F:
#if _WIN32
#else
else
#endif
return v;
case I2S:
{
else
}
else if ((*ex->disc->convertf)(ex, &tmp, STRING, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
case I2X:
if ((*ex->disc->convertf)(ex, &tmp, expr->type, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
case '!':
return v;
case '~':
return v;
case '-':
if (x)
else
return v;
case '+':
return v;
case '&':
return v;
case '|':
return v;
case '^':
return v;
case '*':
return v;
case '/':
if (r.integer == 0)
exerror("integer divide by 0");
else
return v;
case '%':
if (r.integer == 0)
exerror("integer 0 modulus");
else
return v;
case EQ:
return v;
case NE:
return v;
case LS:
return v;
case RS:
return v;
case '<':
return v;
case LE:
return v;
case GE:
return v;
case '>':
return v;
}
break;
case STRING:
{
case S2B:
return v;
case S2F:
if ((*ex->disc->convertf)(ex, &tmp, FLOATING, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
{
if (*e)
}
case S2I:
if ((*ex->disc->convertf)(ex, &tmp, INTEGER, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
{
if (*e)
}
case S2X:
if ((*ex->disc->convertf)(ex, &tmp, expr->type, expr->data.operand.right ? expr->data.operand.right->data.variable.symbol : (Exid_t*)0, 0, ex->disc))
case EQ:
case NE:
v.integer = ((v.string && r.string) ? ((ex->disc->version >= 19981111L && ex->disc->matchf) ? (*ex->disc->matchf)(ex, expr->data.operand.left, v.string, expr->data.operand.right, r.string, env, ex->disc) : strmatch(v.string, r.string)) : (v.string == r.string)) == (expr->op == EQ);
return v;
case '+':
return v;
case '|':
return v;
case '&':
return v;
case '^':
return v;
case '%':
return v;
case '*':
return v;
}
{
case '<':
return v;
case LE:
return v;
case GE:
return v;
case '>':
return v;
}
goto huh;
}
huh:
exerror("operator %s %s %s not implemented", lexname(expr->data.operand.left->type, -1), lexname(expr->op, expr->subop), expr->data.operand.right ? lexname(expr->data.operand.right->type, -1) : "UNARY");
else
exerror("operator %s %s not implemented", lexname(expr->op, expr->subop), lexname(expr->data.operand.left->type, -1));
}
/*
* evaluate expression expr
*/
{
Extype_t v;
{
{
case FLOATING:
break;
case STRING:
break;
default:
break;
}
}
else
{
{
}
}
return v;
}