#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <fm/libtopo.h>
#include "alloc.h"
#include "out.h"
#include "stable.h"
#include "literals.h"
#include "lut.h"
#include "tree.h"
#include "ptree.h"
#include "itree.h"
#include "ipath.h"
#include "eval.h"
#include "config.h"
#include "platform.h"
#include "fme.h"
#include "stats.h"
static struct node *eval_dup(struct node *np, struct lut *ex,
struct node *events[]);
static int check_expr_args(struct evalue *lp, struct evalue *rp,
enum datatype dtype, struct node *np);
static struct node *eval_fru(struct node *np);
static struct node *eval_asru(struct node *np);
extern fmd_hdl_t *Hdl;
static int
begins_with(struct node *lhs, struct node *rhs, struct lut *ex)
{
int lnum;
int rnum;
struct iterinfo *iterinfop;
if (lhs == NULL)
return (1);
if (rhs == NULL)
return (0);
ASSERTeq(lhs->t, T_NAME, ptree_nodetype2str);
ASSERTeq(rhs->t, T_NAME, ptree_nodetype2str);
if (lhs->u.name.s != rhs->u.name.s)
return (0);
if (lhs->u.name.child && lhs->u.name.child->t == T_NUM) {
lnum = (int)lhs->u.name.child->u.ull;
} else if (lhs->u.name.child && lhs->u.name.child->t == T_NAME) {
iterinfop = lut_lookup(ex, (void *)lhs->u.name.child->u.name.s,
NULL);
if (iterinfop != NULL)
lnum = iterinfop->num;
else
out(O_DIE, "begins_with: unexpected lhs child");
} else {
out(O_DIE, "begins_with: unexpected lhs child");
}
if (rhs->u.name.child && rhs->u.name.child->t == T_NUM) {
rnum = (int)rhs->u.name.child->u.ull;
} else if (rhs->u.name.child && rhs->u.name.child->t == T_NAME) {
iterinfop = lut_lookup(ex, (void *)rhs->u.name.child->u.name.s,
NULL);
if (iterinfop != NULL)
rnum = iterinfop->num;
else
out(O_DIE, "begins_with: unexpected rhs child");
} else {
out(O_DIE, "begins_with: unexpected rhs child");
}
if (lnum != rnum)
return (0);
return (begins_with(lhs->u.name.next, rhs->u.name.next, ex));
}
static struct node *
eval_getname(struct node *funcnp, struct lut *ex, struct node *events[],
struct node *np, struct lut **globals,
struct config *croot, struct arrow *arrowp, int try, int *dupedp)
{
struct node *nodep;
const char *funcname = funcnp->u.func.s;
struct evalue val;
if (np->t == T_NAME)
nodep = np;
else if (np->t == T_FUNC && np->u.func.s == L_fru)
nodep = eval_fru(np->u.func.arglist);
else if (np->t == T_FUNC && np->u.func.s == L_asru)
nodep = eval_asru(np->u.func.arglist);
else if (np->t == T_FUNC) {
if (eval_expr(np, ex, events, globals, croot, arrowp, try,
&val) == 0)
return (NULL);
if (val.t == NODEPTR)
return ((struct node *)(uintptr_t)val.v);
else
return (np);
} else
out(O_DIE, "%s: unexpected type: %s",
funcname, ptree_nodetype2str(np->t));
if (try) {
if (eval_expr(nodep, ex, events, globals, croot,
arrowp, try, &val) && val.t == NODEPTR)
nodep = (struct node *)(uintptr_t)val.v;
else {
*dupedp = 1;
nodep = eval_dup(nodep, ex, events);
}
}
return (nodep);
}
static int
eval_cat(struct node *np, struct lut *ex, struct node *events[],
struct lut **globals, struct config *croot, struct arrow *arrowp,
int try, struct evalue *valuep)
{
if (np->t == T_LIST) {
struct evalue lval;
struct evalue rval;
int len;
char *s;
if (!eval_cat(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_cat(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
len = snprintf(NULL, 0, "%s%s", (char *)(uintptr_t)lval.v,
(char *)(uintptr_t)rval.v);
s = MALLOC(len + 1);
(void) snprintf(s, len + 1, "%s%s", (char *)(uintptr_t)lval.v,
(char *)(uintptr_t)rval.v);
outfl(O_ALTFP|O_VERB2, np->file, np->line,
"eval_cat: %s %s returns %s", (char *)(uintptr_t)lval.v,
(char *)(uintptr_t)rval.v, s);
valuep->t = STRING;
valuep->v = (uintptr_t)stable(s);
FREE(s);
} else {
if (!eval_expr(np, ex, events, globals, croot,
arrowp, try, valuep))
return (0);
if (check_expr_args(valuep, NULL, STRING, np))
return (0);
}
return (1);
}
static int
eval_func(struct node *funcnp, struct lut *ex, struct node *events[],
struct node *np, struct lut **globals,
struct config *croot, struct arrow *arrowp, int try, struct evalue *valuep)
{
const char *funcname = funcnp->u.func.s;
int duped_lhs = 0, duped_rhs = 0, duped = 0;
struct node *lhs;
struct node *rhs;
struct config *cp;
struct node *nodep;
char *path;
struct evalue val;
if (funcname == L_within) {
valuep->t = UINT64;
valuep->v = 1;
return (1);
} else if (funcname == L_is_under) {
lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
croot, arrowp, try, &duped_lhs);
rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
globals, croot, arrowp, try, &duped_rhs);
if (!rhs || !lhs)
return (0);
if (rhs->t != T_NAME || lhs->t != T_NAME) {
valuep->t = UNDEFINED;
return (1);
}
valuep->t = UINT64;
valuep->v = begins_with(lhs, rhs, ex);
out(O_ALTFP|O_VERB2|O_NONL, "eval_func:is_under(");
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, lhs);
out(O_ALTFP|O_VERB2|O_NONL, ",");
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, rhs);
out(O_ALTFP|O_VERB2|O_NONL, ") returned %d", (int)valuep->v);
if (duped_lhs)
tree_free(lhs);
if (duped_rhs)
tree_free(rhs);
return (1);
} else if (funcname == L_confprop || funcname == L_confprop_defined) {
const char *s;
ASSERT(np->u.expr.right->t == T_QUOTE);
nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
globals, croot, arrowp, try, &duped);
if (!nodep)
return (0);
if (nodep->t != T_NAME) {
valuep->t = UNDEFINED;
return (1);
}
if (nodep->u.name.last->u.name.cp != NULL) {
cp = nodep->u.name.last->u.name.cp;
} else {
path = ipath2str(NULL, ipath(nodep));
cp = config_lookup(croot, path, 0);
FREE((void *)path);
}
if (cp == NULL) {
if (funcname == L_confprop) {
out(O_ALTFP|O_VERB3, "%s: path ", funcname);
ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
out(O_ALTFP|O_VERB3, " not found");
valuep->v = (uintptr_t)stable("");
valuep->t = STRING;
if (duped)
tree_free(nodep);
return (1);
} else {
valuep->v = 0;
valuep->t = UINT64;
if (duped)
tree_free(nodep);
return (1);
}
}
s = config_getprop(cp, np->u.expr.right->u.quote.s);
if (s == NULL && strcmp(np->u.expr.right->u.quote.s,
"class-code") == 0)
s = config_getprop(cp, "CLASS-CODE");
if (s == NULL) {
if (funcname == L_confprop) {
out(O_ALTFP|O_VERB3|O_NONL,
"%s: \"%s\" not found for path ",
funcname, np->u.expr.right->u.quote.s);
ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
valuep->v = (uintptr_t)stable("");
valuep->t = STRING;
if (duped)
tree_free(nodep);
return (1);
} else {
valuep->v = 0;
valuep->t = UINT64;
if (duped)
tree_free(nodep);
return (1);
}
}
if (funcname == L_confprop) {
valuep->v = (uintptr_t)stable(s);
valuep->t = STRING;
out(O_ALTFP|O_VERB3|O_NONL, " %s(\"", funcname);
ptree_name_iter(O_ALTFP|O_VERB3|O_NONL, nodep);
out(O_ALTFP|O_VERB3|O_NONL,
"\", \"%s\") = \"%s\" ",
np->u.expr.right->u.quote.s,
(char *)(uintptr_t)valuep->v);
} else {
valuep->v = 1;
valuep->t = UINT64;
}
if (duped)
tree_free(nodep);
return (1);
} else if (funcname == L_is_connected) {
const char *connstrings[] = { "connected", "CONNECTED", NULL };
struct config *cp[2];
const char *matchthis[2], *s;
char *nameslist, *w;
int i, j;
lhs = eval_getname(funcnp, ex, events, np->u.expr.left, globals,
croot, arrowp, try, &duped_lhs);
rhs = eval_getname(funcnp, ex, events, np->u.expr.right,
globals, croot, arrowp, try, &duped_rhs);
if (!rhs || !lhs)
return (0);
if (rhs->t != T_NAME || lhs->t != T_NAME) {
valuep->t = UNDEFINED;
return (1);
}
path = ipath2str(NULL, ipath(lhs));
matchthis[1] = stable(path);
if (lhs->u.name.last->u.name.cp != NULL)
cp[0] = lhs->u.name.last->u.name.cp;
else
cp[0] = config_lookup(croot, path, 0);
FREE((void *)path);
path = ipath2str(NULL, ipath(rhs));
matchthis[0] = stable(path);
if (rhs->u.name.last->u.name.cp != NULL)
cp[1] = rhs->u.name.last->u.name.cp;
else
cp[1] = config_lookup(croot, path, 0);
FREE((void *)path);
if (duped_lhs)
tree_free(lhs);
if (duped_rhs)
tree_free(rhs);
valuep->t = UINT64;
valuep->v = 0;
if (cp[0] == NULL || cp[1] == NULL)
return (1);
if (cp[0] == cp[1]) {
valuep->v = 1;
return (1);
}
for (i = 0; i < 2 && valuep->v == 0; i++) {
for (j = 0; connstrings[j] != NULL && valuep->v == 0;
j++) {
s = config_getprop(cp[i],
stable(connstrings[j]));
if (s != NULL) {
nameslist = STRDUP(s);
w = strtok(nameslist, " ,");
while (w != NULL) {
if (stable(w) == matchthis[i]) {
valuep->v = 1;
break;
}
w = strtok(NULL, " ,");
}
FREE(nameslist);
}
}
}
return (1);
} else if (funcname == L_is_type) {
const char *typestrings[] = { "type", "TYPE", NULL };
const char *s;
int i;
nodep = eval_getname(funcnp, ex, events, np, globals,
croot, arrowp, try, &duped);
if (!nodep)
return (0);
if (nodep->t != T_NAME) {
valuep->t = UNDEFINED;
return (1);
}
if (nodep->u.name.last->u.name.cp != NULL) {
cp = nodep->u.name.last->u.name.cp;
} else {
path = ipath2str(NULL, ipath(nodep));
cp = config_lookup(croot, path, 0);
FREE((void *)path);
}
if (duped)
tree_free(nodep);
valuep->t = STRING;
valuep->v = (uintptr_t)stable("");
if (cp == NULL)
return (1);
for (i = 0; typestrings[i] != NULL; i++) {
s = config_getprop(cp, stable(typestrings[i]));
if (s != NULL) {
valuep->v = (uintptr_t)stable(s);
break;
}
}
return (1);
} else if (funcname == L_is_on) {
const char *onstrings[] = { "on", "ON", NULL };
const char *truestrings[] = { "yes", "YES", "y", "Y",
"true", "TRUE", "t", "T", "1", NULL };
const char *s;
int i, j;
nodep = eval_getname(funcnp, ex, events, np, globals,
croot, arrowp, try, &duped);
if (!nodep)
return (0);
if (nodep->t != T_NAME) {
valuep->t = UNDEFINED;
return (1);
}
if (nodep->u.name.last->u.name.cp != NULL) {
cp = nodep->u.name.last->u.name.cp;
} else {
path = ipath2str(NULL, ipath(nodep));
cp = config_lookup(croot, path, 0);
FREE((void *)path);
}
if (duped)
tree_free(nodep);
valuep->t = UINT64;
valuep->v = 0;
if (cp == NULL)
return (1);
for (i = 0; onstrings[i] != NULL; i++) {
s = config_getprop(cp, stable(onstrings[i]));
if (s != NULL) {
s = stable(s);
for (j = 0; truestrings[j] != NULL; j++) {
if (s == stable(truestrings[j])) {
valuep->v = 1;
return (1);
}
}
}
}
return (1);
} else if (funcname == L_is_present) {
nodep = eval_getname(funcnp, ex, events, np, globals,
croot, arrowp, try, &duped);
if (!nodep)
return (0);
if (nodep->t != T_NAME) {
valuep->t = UNDEFINED;
return (1);
}
if (nodep->u.name.last->u.name.cp != NULL) {
cp = nodep->u.name.last->u.name.cp;
} else {
path = ipath2str(NULL, ipath(nodep));
cp = config_lookup(croot, path, 0);
FREE((void *)path);
}
if (duped)
tree_free(nodep);
valuep->t = UINT64;
valuep->v = 0;
if (cp != NULL)
valuep->v = 1;
return (1);
} else if (funcname == L_has_fault) {
nvlist_t *rsrc = NULL;
nodep = eval_getname(funcnp, ex, events, np->u.expr.left,
globals, croot, arrowp, try, &duped);
if (!nodep)
return (0);
if (nodep->t != T_NAME) {
valuep->t = UNDEFINED;
return (1);
}
path = ipath2str(NULL, ipath(nodep));
platform_unit_translate(0, croot, TOPO_PROP_RESOURCE,
&rsrc, path);
outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line, "has_fault(");
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, nodep);
out(O_ALTFP|O_VERB2|O_NONL, "(%s), \"%s\") ", path,
np->u.expr.right->u.quote.s);
FREE((void *)path);
if (duped)
tree_free(nodep);
if (rsrc == NULL) {
valuep->v = 0;
out(O_ALTFP|O_VERB2, "no path");
} else {
valuep->v = fmd_nvl_fmri_has_fault(Hdl, rsrc,
FMD_HAS_FAULT_RESOURCE,
strcmp(np->u.expr.right->u.quote.s, "") == 0 ?
NULL : (char *)np->u.expr.right->u.quote.s);
out(O_ALTFP|O_VERB2, "returned %lld", valuep->v);
nvlist_free(rsrc);
}
valuep->t = UINT64;
return (1);
} else if (funcname == L_count) {
struct stats *statp;
struct istat_entry ent;
ASSERTinfo(np->t == T_EVENT, ptree_nodetype2str(np->t));
nodep = np->u.event.epname;
if (try) {
if (eval_expr(nodep, ex, events, globals,
croot, arrowp, try, &val) && val.t == NODEPTR)
nodep = (struct node *)(uintptr_t)val.v;
else {
duped = 1;
nodep = eval_dup(nodep, ex, events);
}
}
ent.ename = np->u.event.ename->u.name.s;
ent.ipath = ipath(nodep);
valuep->t = UINT64;
if ((statp = (struct stats *)
lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL)
valuep->v = 0;
else
valuep->v = stats_counter_value(statp);
if (duped)
tree_free(nodep);
return (1);
} else if (funcname == L_envprop) {
outfl(O_DIE, np->file, np->line,
"eval_func: %s not yet supported", funcname);
}
if (try)
return (0);
if (funcname == L_fru) {
valuep->t = NODEPTR;
valuep->v = (uintptr_t)eval_fru(np);
return (1);
} else if (funcname == L_asru) {
valuep->t = NODEPTR;
valuep->v = (uintptr_t)eval_asru(np);
return (1);
} else if (funcname == L_defined) {
ASSERTeq(np->t, T_GLOBID, ptree_nodetype2str);
valuep->t = UINT64;
valuep->v = (lut_lookup(*globals,
(void *)np->u.globid.s, NULL) != NULL);
return (1);
} else if (funcname == L_call) {
return (! platform_call(np, globals, croot, arrowp, valuep));
} else if (funcname == L_payloadprop) {
outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
"payloadprop(\"%s\") ", np->u.quote.s);
if (arrowp->head->myevent->count == 0) {
out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
return (0);
} else if (platform_payloadprop(np, valuep)) {
out(O_ALTFP|O_VERB, "not found.");
valuep->t = UNDEFINED;
return (1);
} else {
switch (valuep->t) {
case NODEPTR:
if (((struct node *)(uintptr_t)
(valuep->v))->t == T_NAME) {
char *s = ipath2str(NULL,
ipath((struct node *)
(uintptr_t)valuep->v));
out(O_ALTFP|O_VERB2,
"found: \"%s\"", s);
FREE(s);
} else
out(O_ALTFP|O_VERB2, "found: %llu",
valuep->v);
break;
case UINT64:
out(O_ALTFP|O_VERB2, "found: %llu", valuep->v);
break;
case STRING:
out(O_ALTFP|O_VERB2, "found: \"%s\"",
(char *)(uintptr_t)valuep->v);
break;
default:
out(O_ALTFP|O_VERB2, "found: undefined");
break;
}
return (1);
}
} else if (funcname == L_setpayloadprop) {
struct evalue *payloadvalp;
int alloced = 0;
ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
ASSERTinfo(np->u.expr.left->t == T_QUOTE,
ptree_nodetype2str(np->u.expr.left->t));
if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
return (0);
outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
"setpayloadprop: %s: %s=",
arrowp->tail->myevent->enode->u.event.ename->u.name.s,
np->u.expr.left->u.quote.s);
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
if ((payloadvalp = (struct evalue *)lut_lookup(
arrowp->tail->myevent->payloadprops,
(void *)np->u.expr.left->u.quote.s, NULL)) == NULL) {
payloadvalp = MALLOC(sizeof (*payloadvalp));
alloced = 1;
}
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, payloadvalp)) {
out(O_ALTFP|O_VERB2, " (cannot eval)");
if (alloced)
FREE(payloadvalp);
return (0);
} else {
if (payloadvalp->t == UNDEFINED) {
out(O_ALTFP|O_VERB2, " (undefined)");
valuep->t = UINT64;
valuep->v = 1;
return (1);
}
if (payloadvalp->t == UINT64)
out(O_ALTFP|O_VERB2,
" (%llu)", payloadvalp->v);
else
out(O_ALTFP|O_VERB2, " (\"%s\")",
(char *)(uintptr_t)payloadvalp->v);
}
arrowp->tail->myevent->payloadprops =
lut_add(arrowp->tail->myevent->payloadprops,
(void *)np->u.expr.left->u.quote.s,
(void *)payloadvalp, NULL);
valuep->t = UINT64;
valuep->v = 1;
return (1);
} else if (funcname == L_cat) {
int retval = eval_cat(np, ex, events, globals, croot,
arrowp, try, valuep);
outfl(O_ALTFP|O_VERB2, np->file, np->line,
"cat: returns %s", (char *)(uintptr_t)valuep->v);
return (retval);
} else if (funcname == L_setserdn || funcname == L_setserdt ||
funcname == L_setserdsuffix || funcname == L_setserdincrement) {
struct evalue *serdvalp;
int alloced = 0;
char *str;
struct event *flt = arrowp->tail->myevent;
if (!(arrowp->head->myevent->cached_state & REQMNTS_CREDIBLE))
return (0);
if (funcname == L_setserdn)
str = "n";
else if (funcname == L_setserdt)
str = "t";
else if (funcname == L_setserdsuffix)
str = "suffix";
else if (funcname == L_setserdincrement)
str = "increment";
if ((serdvalp = (struct evalue *)lut_lookup(flt->serdprops,
(void *)str, (lut_cmp)strcmp)) == NULL) {
serdvalp = MALLOC(sizeof (*serdvalp));
alloced = 1;
}
if (!eval_expr(np, ex, events, globals, croot, arrowp, try,
serdvalp)) {
outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
"setserd%s: %s: ", str,
flt->enode->u.event.ename->u.name.s);
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
out(O_ALTFP|O_VERB2, " (cannot eval)");
if (alloced)
FREE(serdvalp);
return (0);
} else if (serdvalp->t == UNDEFINED) {
outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
"setserd%s: %s: ", str,
flt->enode->u.event.ename->u.name.s);
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
out(O_ALTFP|O_VERB2, " (undefined)");
} else {
outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
"setserd%s: %s: ", str,
flt->enode->u.event.ename->u.name.s);
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np);
if ((funcname == L_setserdincrement ||
funcname == L_setserdn) && serdvalp->t == STRING) {
serdvalp->t = UINT64;
serdvalp->v = strtoull((char *)
(uintptr_t)serdvalp->v, NULL, 0);
}
if (funcname == L_setserdt && serdvalp->t == UINT64) {
int len = snprintf(NULL, 0, "%lldns",
serdvalp->v);
char *buf = MALLOC(len + 1);
(void) snprintf(buf, len + 1, "%lldns",
serdvalp->v);
serdvalp->t = STRING;
serdvalp->v = (uintptr_t)stable(buf);
FREE(buf);
}
if (funcname == L_setserdsuffix &&
serdvalp->t == UINT64) {
int len = snprintf(NULL, 0, "%lld",
serdvalp->v);
char *buf = MALLOC(len + 1);
(void) snprintf(buf, len + 1, "%lld",
serdvalp->v);
serdvalp->t = STRING;
serdvalp->v = (uintptr_t)stable(buf);
FREE(buf);
}
if (serdvalp->t == UINT64)
out(O_ALTFP|O_VERB2, " (%llu)", serdvalp->v);
else
out(O_ALTFP|O_VERB2, " (\"%s\")",
(char *)(uintptr_t)serdvalp->v);
flt->serdprops = lut_add(flt->serdprops, (void *)str,
(void *)serdvalp, (lut_cmp)strcmp);
}
valuep->t = UINT64;
valuep->v = 1;
return (1);
} else if (funcname == L_payloadprop_defined) {
outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
"payloadprop_defined(\"%s\") ", np->u.quote.s);
if (arrowp->head->myevent->count == 0) {
out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
return (0);
} else if (platform_payloadprop(np, NULL)) {
valuep->v = 0;
out(O_ALTFP|O_VERB2, "not found.");
} else {
valuep->v = 1;
out(O_ALTFP|O_VERB2, "found.");
}
valuep->t = UINT64;
return (1);
} else if (funcname == L_payloadprop_contains) {
int nvals;
struct evalue *vals;
struct evalue cmpval;
ASSERTinfo(np->t == T_LIST, ptree_nodetype2str(np->t));
ASSERTinfo(np->u.expr.left->t == T_QUOTE,
ptree_nodetype2str(np->u.expr.left->t));
outfl(O_ALTFP|O_VERB2|O_NONL, np->file, np->line,
"payloadprop_contains(\"%s\", ",
np->u.expr.left->u.quote.s);
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL, np->u.expr.right);
out(O_ALTFP|O_VERB2|O_NONL, ") ");
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &cmpval)) {
out(O_ALTFP|O_VERB2|O_NONL,
"(cannot eval) ");
return (0);
} else {
switch (cmpval.t) {
case UNDEFINED:
out(O_ALTFP|O_VERB2, "(undefined type)");
break;
case UINT64:
out(O_ALTFP|O_VERB2,
"(%llu) ", cmpval.v);
break;
case STRING:
out(O_ALTFP|O_VERB2,
"(\"%s\") ", (char *)(uintptr_t)cmpval.v);
break;
case NODEPTR:
out(O_ALTFP|O_VERB2|O_NONL, "(");
ptree_name_iter(O_ALTFP|O_VERB2|O_NONL,
(struct node *)(uintptr_t)(cmpval.v));
out(O_ALTFP|O_VERB2, ") ");
break;
}
}
vals = platform_payloadprop_values(np->u.expr.left->u.quote.s,
&nvals);
valuep->t = UINT64;
valuep->v = 0;
if (arrowp->head->myevent->count == 0) {
out(O_ALTFP|O_VERB2, "ereport not yet seen - defer.");
return (0);
} else if (nvals == 0) {
out(O_ALTFP|O_VERB2, "not found.");
return (1);
} else {
struct evalue preval;
int i;
out(O_ALTFP|O_VERB2|O_NONL, "found %d values ", nvals);
for (i = 0; i < nvals; i++) {
preval.t = vals[i].t;
preval.v = vals[i].v;
if (check_expr_args(&vals[i], &cmpval,
UNDEFINED, np))
continue;
if (preval.t == NODEPTR &&
((struct node *)(uintptr_t)(preval.v))->t ==
T_NAME) {
tree_free((struct node *)(uintptr_t)
preval.v);
}
if (vals[i].v == cmpval.v) {
valuep->v = 1;
break;
}
}
if (valuep->v)
out(O_ALTFP|O_VERB2, "match.");
else
out(O_ALTFP|O_VERB2, "no match.");
for (i = 0; i < nvals; i++) {
if (vals[i].t == NODEPTR) {
tree_free((struct node *)(uintptr_t)
vals[i].v);
break;
}
}
FREE(vals);
}
return (1);
} else if (funcname == L_confcall) {
return (!platform_confcall(np, globals, croot, arrowp, valuep));
} else
outfl(O_DIE, np->file, np->line,
"eval_func: unexpected func: %s", funcname);
return (0);
}
#define EXPR_TEMP_BOTH_UNK 0
#define EXPR_TEMP_LHS_UNK 1
#define EXPR_TEMP_RHS_UNK 2
static struct node *
eval_dup(struct node *np, struct lut *ex, struct node *events[])
{
struct node *newnp;
if (np == NULL)
return (NULL);
switch (np->t) {
case T_GLOBID:
return (tree_globid(np->u.globid.s, np->file, np->line));
case T_ASSIGN:
case T_CONDIF:
case T_CONDELSE:
case T_NE:
case T_EQ:
case T_LT:
case T_LE:
case T_GT:
case T_GE:
case T_BITAND:
case T_BITOR:
case T_BITXOR:
case T_BITNOT:
case T_LSHIFT:
case T_RSHIFT:
case T_NOT:
case T_ADD:
case T_SUB:
case T_MUL:
case T_DIV:
case T_MOD:
return (tree_expr(np->t,
eval_dup(np->u.expr.left, ex, events),
eval_dup(np->u.expr.right, ex, events)));
case T_LIST:
case T_AND:
switch (np->u.expr.temp) {
case EXPR_TEMP_LHS_UNK:
return (eval_dup(np->u.expr.left, ex, events));
case EXPR_TEMP_RHS_UNK:
return (eval_dup(np->u.expr.right, ex, events));
default:
return (tree_expr(np->t,
eval_dup(np->u.expr.left, ex, events),
eval_dup(np->u.expr.right, ex, events)));
}
case T_OR:
switch (np->u.expr.temp) {
case EXPR_TEMP_LHS_UNK:
return (eval_dup(np->u.expr.left, ex, events));
case EXPR_TEMP_RHS_UNK:
return (eval_dup(np->u.expr.right, ex, events));
default:
return (tree_expr(T_OR,
eval_dup(np->u.expr.left, ex, events),
eval_dup(np->u.expr.right, ex, events)));
}
case T_NAME: {
struct iterinfo *iterinfop;
int got_matchf = 0;
int got_matcht = 0;
struct evalue value;
struct node *np1f, *np2f, *np1t, *np2t, *retp = NULL;
struct node *npstart, *npcont, *npend, *npref, *newnp, *nprest;
for (np1f = np, np2f = events[0]->u.event.oldepname;
np1f != NULL && np2f != NULL;
np1f = np1f->u.name.next, np2f = np2f->u.name.next) {
if (strcmp(np1f->u.name.s, np2f->u.name.s) != 0)
break;
if (np1f->u.name.child->t != np2f->u.name.child->t)
break;
if (np1f->u.name.child->t == T_NUM &&
np1f->u.name.child->u.ull !=
np2f->u.name.child->u.ull)
break;
if (np1f->u.name.child->t == T_NAME &&
strcmp(np1f->u.name.child->u.name.s,
np2f->u.name.child->u.name.s) != 0)
break;
got_matchf++;
}
for (np1t = np, np2t = events[1]->u.event.oldepname;
np1t != NULL && np2t != NULL;
np1t = np1t->u.name.next, np2t = np2t->u.name.next) {
if (strcmp(np1t->u.name.s, np2t->u.name.s) != 0)
break;
if (np1t->u.name.child->t != np2t->u.name.child->t)
break;
if (np1t->u.name.child->t == T_NUM &&
np1t->u.name.child->u.ull !=
np2t->u.name.child->u.ull)
break;
if (np1t->u.name.child->t == T_NAME &&
strcmp(np1t->u.name.child->u.name.s,
np2t->u.name.child->u.name.s) != 0)
break;
got_matcht++;
}
nprest = np;
if (got_matchf || got_matcht) {
if (got_matchf > got_matcht) {
npstart = events[0]->u.event.ewname;
npcont = events[0]->u.event.oldepname;
npend = np2f;
nprest = np1f;
} else {
npstart = events[1]->u.event.ewname;
npcont = events[1]->u.event.oldepname;
npend = np2t;
nprest = np1t;
}
for (npref = npstart; npref != NULL;
npref = npref->u.name.next) {
newnp = newnode(T_NAME, np->file, np->line);
newnp->u.name.t = npref->u.name.t;
newnp->u.name.s = npref->u.name.s;
newnp->u.name.last = newnp;
newnp->u.name.it = npref->u.name.it;
newnp->u.name.cp = npref->u.name.cp;
newnp->u.name.child =
newnode(T_NUM, np->file, np->line);
if (eval_expr(npref->u.name.child, ex, events,
NULL, NULL, NULL, 1, &value) == 0 ||
value.t != UINT64) {
outfl(O_DIE, np->file, np->line,
"eval_dup: could not resolve "
"iterator of %s", np->u.name.s);
}
newnp->u.name.child->u.ull = value.v;
if (retp == NULL) {
retp = newnp;
} else {
retp->u.name.last->u.name.next = newnp;
retp->u.name.last = newnp;
}
}
for (npref = npcont; npref != NULL && npref != npend;
npref = npref->u.name.next) {
newnp = newnode(T_NAME, np->file, np->line);
newnp->u.name.t = npref->u.name.t;
newnp->u.name.s = npref->u.name.s;
newnp->u.name.last = newnp;
newnp->u.name.it = npref->u.name.it;
newnp->u.name.cp = npref->u.name.cp;
newnp->u.name.child =
newnode(T_NUM, np->file, np->line);
if (eval_expr(npref->u.name.child, ex, events,
NULL, NULL, NULL, 1, &value) == 0 ||
value.t != UINT64) {
outfl(O_DIE, np->file, np->line,
"eval_dup: could not resolve "
"iterator of %s", np->u.name.s);
}
newnp->u.name.child->u.ull = value.v;
if (retp == NULL) {
retp = newnp;
} else {
retp->u.name.last->u.name.next = newnp;
retp->u.name.last = newnp;
}
}
} else {
iterinfop = lut_lookup(ex, (void *)np->u.name.s, NULL);
if (iterinfop != NULL) {
newnp = newnode(T_NUM, np->file, np->line);
newnp->u.ull = iterinfop->num;
return (newnp);
}
}
for (npref = nprest; npref != NULL;
npref = npref->u.name.next) {
newnp = newnode(T_NAME, np->file, np->line);
newnp->u.name.t = npref->u.name.t;
newnp->u.name.s = npref->u.name.s;
newnp->u.name.last = newnp;
newnp->u.name.it = npref->u.name.it;
newnp->u.name.cp = npref->u.name.cp;
newnp->u.name.child =
newnode(T_NUM, np->file, np->line);
if (eval_expr(npref->u.name.child, ex, events,
NULL, NULL, NULL, 1, &value) == 0 ||
value.t != UINT64) {
outfl(O_DIE, np->file, np->line,
"eval_dup: could not resolve "
"iterator of %s", np->u.name.s);
}
newnp->u.name.child->u.ull = value.v;
if (retp == NULL) {
retp = newnp;
} else {
retp->u.name.last->u.name.next = newnp;
retp->u.name.last = newnp;
}
}
return (retp);
}
case T_EVENT:
newnp = newnode(T_NAME, np->file, np->line);
newnp->u.name.t = np->u.event.ename->u.name.t;
newnp->u.name.s = np->u.event.ename->u.name.s;
newnp->u.name.it = np->u.event.ename->u.name.it;
newnp->u.name.last = newnp;
return (tree_event(newnp,
eval_dup(np->u.event.epname, ex, events),
eval_dup(np->u.event.eexprlist, ex, events)));
case T_FUNC:
return (tree_func(np->u.func.s,
eval_dup(np->u.func.arglist, ex, events),
np->file, np->line));
case T_QUOTE:
newnp = newnode(T_QUOTE, np->file, np->line);
newnp->u.quote.s = np->u.quote.s;
return (newnp);
case T_NUM:
newnp = newnode(T_NUM, np->file, np->line);
newnp->u.ull = np->u.ull;
return (newnp);
case T_TIMEVAL:
newnp = newnode(T_TIMEVAL, np->file, np->line);
newnp->u.ull = np->u.ull;
return (newnp);
default:
outfl(O_DIE, np->file, np->line,
"eval_dup: unexpected node type: %s",
ptree_nodetype2str(np->t));
}
return (0);
}
int
eval_potential(struct node *np, struct lut *ex, struct node *events[],
struct node **newc, struct config *croot)
{
struct node *newnp;
struct evalue value;
if (eval_expr(np, ex, events, NULL, croot, NULL, 1, &value) == 0) {
newnp = eval_dup(np, ex, events);
if (*newc == NULL) {
*newc = newnp;
return (1);
} else {
*newc = tree_expr(T_AND, *newc, newnp);
return (1);
}
} else if (value.t == UNDEFINED) {
return (0);
} else if (value.t == UINT64 && value.v == 0) {
return (0);
} else {
return (1);
}
}
static int
check_expr_args(struct evalue *lp, struct evalue *rp, enum datatype dtype,
struct node *np)
{
if (lp->t == NODEPTR && ((struct node *)(uintptr_t)(lp->v))->t ==
T_NAME) {
char *s = ipath2str(NULL,
ipath((struct node *)(uintptr_t)lp->v));
lp->t = STRING;
lp->v = (uintptr_t)stable(s);
FREE(s);
out(O_ALTFP|O_VERB2, "convert lhs path to \"%s\"",
(char *)(uintptr_t)lp->v);
}
if (rp != NULL &&
rp->t == NODEPTR && ((struct node *)(uintptr_t)(rp->v))->t ==
T_NAME) {
char *s = ipath2str(NULL,
ipath((struct node *)(uintptr_t)rp->v));
rp->t = STRING;
rp->v = (uintptr_t)stable(s);
FREE(s);
out(O_ALTFP|O_VERB2, "convert rhs path to \"%s\"",
(char *)(uintptr_t)rp->v);
}
if (dtype == STRING) {
if (lp->t == UINT64) {
int len = snprintf(NULL, 0, "%llx", lp->v);
char *s = MALLOC(len + 1);
(void) snprintf(s, len + 1, "%llx", lp->v);
lp->t = STRING;
lp->v = (uintptr_t)stable(s);
FREE(s);
}
if (rp != NULL && rp->t == UINT64) {
int len = snprintf(NULL, 0, "%llx", rp->v);
char *s = MALLOC(len + 1);
(void) snprintf(s, len + 1, "%llx", rp->v);
rp->t = STRING;
rp->v = (uintptr_t)stable(s);
FREE(s);
}
}
if (dtype == UINT64) {
if (lp->t == STRING) {
lp->t = UINT64;
lp->v = strtoull((char *)(uintptr_t)lp->v, NULL, 0);
}
if (rp != NULL && rp->t == STRING) {
rp->t = UINT64;
rp->v = strtoull((char *)(uintptr_t)rp->v, NULL, 0);
}
}
if (dtype != UNDEFINED && lp->t != dtype) {
outfl(O_DIE, np->file, np->line,
"invalid datatype of argument for operation %s",
ptree_nodetype2str(np->t));
return (1);
}
if (rp != NULL && lp->t != rp->t) {
outfl(O_DIE, np->file, np->line,
"mismatch in datatype of arguments for operation %s",
ptree_nodetype2str(np->t));
return (1);
}
return (0);
}
int
eval_expr(struct node *np, struct lut *ex, struct node *events[],
struct lut **globals, struct config *croot, struct arrow *arrowp,
int try, struct evalue *valuep)
{
struct evalue *gval;
struct evalue lval;
struct evalue rval;
if (np == NULL) {
valuep->t = UINT64;
valuep->v = 1;
return (1);
}
valuep->t = UNDEFINED;
switch (np->t) {
case T_GLOBID:
if (try)
return (0);
gval = lut_lookup(*globals, (void *)np->u.globid.s, NULL);
if (gval == NULL) {
return (0);
} else {
valuep->t = gval->t;
valuep->v = gval->v;
return (1);
}
case T_ASSIGN:
if (try)
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
ASSERT(np->u.expr.left->t == T_GLOBID);
gval = lut_lookup(*globals,
(void *)np->u.expr.left->u.globid.s, NULL);
if (gval == NULL) {
gval = MALLOC(sizeof (*gval));
*globals = lut_add(*globals,
(void *) np->u.expr.left->u.globid.s, gval, NULL);
}
gval->t = rval.t;
gval->v = rval.v;
if (gval->t == UINT64) {
out(O_ALTFP|O_VERB2,
"assign $%s=%llu",
np->u.expr.left->u.globid.s, gval->v);
} else {
out(O_ALTFP|O_VERB2,
"assign $%s=\"%s\"",
np->u.expr.left->u.globid.s,
(char *)(uintptr_t)gval->v);
}
valuep->t = UINT64;
valuep->v = 1;
return (1);
case T_EQ:
#define IMPLICIT_ASSIGN_IN_EQ
#ifdef IMPLICIT_ASSIGN_IN_EQ
if (try == 0 &&
np->u.expr.left->t == T_GLOBID &&
(gval = lut_lookup(*globals,
(void *)np->u.expr.left->u.globid.s, NULL)) == NULL) {
if (!eval_expr(np->u.expr.right, ex, events, globals,
croot, arrowp, try, &rval))
return (0);
gval = MALLOC(sizeof (*gval));
*globals = lut_add(*globals,
(void *) np->u.expr.left->u.globid.s,
gval, NULL);
gval->t = rval.t;
gval->v = rval.v;
valuep->t = rval.t;
valuep->v = rval.v;
return (1);
}
#endif
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (rval.t == UINT64 || lval.t == UINT64) {
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
} else {
if (check_expr_args(&lval, &rval, UNDEFINED, np))
return (0);
}
valuep->t = UINT64;
valuep->v = (lval.v == rval.v);
return (1);
case T_LT:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = UINT64;
valuep->v = (lval.v < rval.v);
return (1);
case T_LE:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = UINT64;
valuep->v = (lval.v <= rval.v);
return (1);
case T_GT:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = UINT64;
valuep->v = (lval.v > rval.v);
return (1);
case T_GE:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = UINT64;
valuep->v = (lval.v >= rval.v);
return (1);
case T_BITAND:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = lval.t;
valuep->v = (lval.v & rval.v);
return (1);
case T_BITOR:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = lval.t;
valuep->v = (lval.v | rval.v);
return (1);
case T_BITXOR:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = lval.t;
valuep->v = (lval.v ^ rval.v);
return (1);
case T_BITNOT:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
ASSERT(np->u.expr.right == NULL);
if (check_expr_args(&lval, NULL, UINT64, np))
return (0);
valuep->t = UINT64;
valuep->v = ~ lval.v;
return (1);
case T_LSHIFT:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = UINT64;
valuep->v = (lval.v << rval.v);
return (1);
case T_RSHIFT:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = UINT64;
valuep->v = (lval.v >> rval.v);
return (1);
case T_CONDIF: {
struct node *retnp;
int dotrue = 0;
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (lval.t != UNDEFINED && lval.v != 0)
dotrue = 1;
ASSERT(np->u.expr.right != NULL);
if (np->u.expr.right->t == T_CONDELSE) {
if (dotrue)
retnp = np->u.expr.right->u.expr.left;
else
retnp = np->u.expr.right->u.expr.right;
} else {
if (dotrue)
retnp = np->u.expr.right;
else {
outfl(O_DIE, np->file, np->line,
"eval_expr: missing condelse");
}
}
if (!eval_expr(retnp, ex, events, globals, croot,
arrowp, try, valuep))
return (0);
return (1);
}
case T_CONDELSE:
out(O_ALTFP|O_DIE, "eval_expr: wrong context for operation %s",
ptree_nodetype2str(np->t));
break;
case T_NE:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (rval.t == UINT64 || lval.t == UINT64) {
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
} else {
if (check_expr_args(&lval, &rval, UNDEFINED, np))
return (0);
}
valuep->t = UINT64;
valuep->v = (lval.v != rval.v);
return (1);
case T_LIST:
case T_AND:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, valuep)) {
if (!try) {
np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
return (0);
}
if (!eval_expr(np->u.expr.right, ex, events, globals,
croot, arrowp, try, valuep)) {
np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
return (0);
}
if (valuep->v != 0) {
np->u.expr.temp = EXPR_TEMP_LHS_UNK;
return (0);
}
}
if (valuep->v == 0) {
valuep->t = UINT64;
return (1);
}
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, valuep)) {
np->u.expr.temp = EXPR_TEMP_RHS_UNK;
return (0);
}
valuep->t = UINT64;
valuep->v = valuep->v == 0 ? 0 : 1;
return (1);
case T_OR:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, valuep)) {
if (!try) {
np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
return (0);
}
if (!eval_expr(np->u.expr.right, ex, events, globals,
croot, arrowp, try, valuep)) {
np->u.expr.temp = EXPR_TEMP_BOTH_UNK;
return (0);
}
if (valuep->v == 0) {
np->u.expr.temp = EXPR_TEMP_LHS_UNK;
return (0);
}
}
if (valuep->v != 0) {
valuep->t = UINT64;
valuep->v = 1;
return (1);
}
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, valuep)) {
np->u.expr.temp = EXPR_TEMP_RHS_UNK;
return (0);
}
valuep->t = UINT64;
valuep->v = valuep->v == 0 ? 0 : 1;
return (1);
case T_NOT:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, valuep))
return (0);
valuep->t = UINT64;
valuep->v = ! valuep->v;
return (1);
case T_ADD:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = lval.t;
valuep->v = lval.v + rval.v;
return (1);
case T_SUB:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
if (lval.v < rval.v) {
outfl(O_DIE, np->file, np->line,
"eval_expr: T_SUB result is out of range");
}
valuep->t = lval.t;
valuep->v = lval.v - rval.v;
return (1);
case T_MUL:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
valuep->t = lval.t;
valuep->v = lval.v * rval.v;
return (1);
case T_DIV:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
if (rval.v == 0) {
outfl(O_DIE, np->file, np->line,
"eval_expr: T_DIV division by zero");
}
valuep->t = lval.t;
valuep->v = lval.v / rval.v;
return (1);
case T_MOD:
if (!eval_expr(np->u.expr.left, ex, events, globals, croot,
arrowp, try, &lval))
return (0);
if (!eval_expr(np->u.expr.right, ex, events, globals, croot,
arrowp, try, &rval))
return (0);
if (check_expr_args(&lval, &rval, UINT64, np))
return (0);
if (rval.v == 0) {
outfl(O_DIE, np->file, np->line,
"eval_expr: T_MOD division by zero");
}
valuep->t = lval.t;
valuep->v = lval.v % rval.v;
return (1);
case T_NAME:
if (try) {
struct iterinfo *iterinfop;
struct node *np1, *np2;
int i, gotmatch = 0;
for (i = 0; i < 1; i++) {
for (np1 = np,
np2 = events[i]->u.event.oldepname;
np1 != NULL && np2 != NULL;
np1 = np1->u.name.next,
np2 = np2->u.name.next) {
if (strcmp(np1->u.name.s,
np2->u.name.s) != 0)
break;
if (np1->u.name.child->t !=
np2->u.name.child->t)
break;
if (np1->u.name.child->t == T_NUM &&
np1->u.name.child->u.ull !=
np2->u.name.child->u.ull)
break;
if (np1->u.name.child->t == T_NAME &&
strcmp(np1->u.name.child->u.name.s,
np2->u.name.child->u.name.s) != 0)
break;
gotmatch++;
}
if (np1 == NULL && np2 == NULL) {
valuep->t = NODEPTR;
valuep->v = (uintptr_t)
events[i]->u.event.epname;
return (1);
}
}
if (!gotmatch) {
iterinfop = lut_lookup(ex, (void *)np->u.name.s,
NULL);
if (iterinfop != NULL) {
valuep->t = UINT64;
valuep->v =
(unsigned long long)iterinfop->num;
return (1);
}
}
return (0);
}
valuep->t = NODEPTR;
valuep->v = (uintptr_t)np;
return (1);
case T_QUOTE:
valuep->t = STRING;
valuep->v = (uintptr_t)np->u.quote.s;
return (1);
case T_FUNC:
return (eval_func(np, ex, events, np->u.func.arglist,
globals, croot, arrowp, try, valuep));
case T_NUM:
case T_TIMEVAL:
valuep->t = UINT64;
valuep->v = np->u.ull;
return (1);
default:
outfl(O_DIE, np->file, np->line,
"eval_expr: unexpected node type: %s",
ptree_nodetype2str(np->t));
}
return (0);
}
static struct node *
eval_fru(struct node *np)
{
ASSERT(np->t == T_NAME);
return (np);
}
static struct node *
eval_asru(struct node *np)
{
ASSERT(np->t == T_NAME);
return (np);
}