-/* $OpenBSD: bt_parse.y,v 1.22 2021/02/01 11:26:28 mpi Exp $ */
+/* $OpenBSD: bt_parse.y,v 1.23 2021/02/08 09:46:45 mpi Exp $ */
/*
* Copyright (c) 2019-2021 Martin Pieuchot <mpi@openbsd.org>
struct bt_rule *br_new(struct bt_probe *, struct bt_filter *, struct bt_stmt *,
enum bt_rtype);
-struct bt_filter *bf_new(enum bt_operand, enum bt_filtervar, int);
+struct bt_filter *bf_new(enum bt_argtype, enum bt_filtervar, int);
struct bt_probe *bp_new(const char *, const char *, const char *, int32_t);
struct bt_arg *ba_append(struct bt_arg *, struct bt_arg *);
struct bt_stmt *bs_new(enum bt_action, struct bt_arg *, struct bt_var *);
static int pflag;
%}
-%token ERROR OP_EQ OP_NEQ BEGIN END HZ
+%token ERROR OP_EQ OP_NE OP_LE OP_GE OP_LAND OP_LOR BEGIN END HZ
/* Builtins */
%token BUILTIN PID TID
/* Functions and Map operators */
%token <v.number> NUMBER
%type <v.string> gvar
-%type <v.i> filterval oper builtin
+%type <v.i> fval testop binop builtin
%type <v.i> BUILTIN F_DELETE F_PRINT FUNC0 FUNC1 FUNCN OP1 OP4
%type <v.i> MOP0 MOP1
%type <v.probe> probe probeval
;
-filterval : PID { $$ = B_FV_PID; }
+fval : PID { $$ = B_FV_PID; }
| TID { $$ = B_FV_TID; }
;
-oper : OP_EQ { $$ = B_OP_EQ; }
- | OP_NEQ { $$ = B_OP_NE; }
+testop : OP_EQ { $$ = B_AT_OP_EQ; }
+ | OP_NE { $$ = B_AT_OP_NE; }
+ | OP_LE { $$ = B_AT_OP_LE; }
+ | OP_GE { $$ = B_AT_OP_GE; }
+ | OP_LAND { $$ = B_AT_OP_LAND; }
+ | OP_LOR { $$ = B_AT_OP_LOR; }
+ ;
+
+binop : testop
+ | '+' { $$ = B_AT_OP_PLUS; }
+ | '-' { $$ = B_AT_OP_MINUS; }
+ | '*' { $$ = B_AT_OP_MULT; }
+ | '/' { $$ = B_AT_OP_DIVIDE; }
+ | '&' { $$ = B_AT_OP_BAND; }
+ | '|' { $$ = B_AT_OP_BOR; }
;
predicate : /* empty */ { $$ = NULL; }
- | '/' filterval oper NUMBER '/' { $$ = bf_new($3, $2, $4); }
- | '/' NUMBER oper filterval '/' { $$ = bf_new($3, $4, $2); }
+ | '/' fval testop NUMBER '/' { $$ = bf_new($3, $2, $4); }
+ | '/' NUMBER testop fval '/' { $$ = bf_new($3, $4, $2); }
| '/' condition '/' { $$ = bc_new($2); }
;
;
term : '(' term ')' { $$ = $2; }
- | term '+' term { $$ = ba_op('+', $1, $3); }
- | term '-' term { $$ = ba_op('-', $1, $3); }
- | term '/' term { $$ = ba_op('/', $1, $3); }
- | term '*' term { $$ = ba_op('*', $1, $3); }
- | term '&' term { $$ = ba_op('&', $1, $3); }
- | term '|' term { $$ = ba_op('|', $1, $3); }
+ | term binop term { $$ = ba_op($2, $1, $3); }
| NUMBER { $$ = ba_new($1, B_AT_LONG); }
| builtin { $$ = ba_new(NULL, $1); }
| gvar { $$ = bv_get($1); }
/* Create a new event filter */
struct bt_filter *
-bf_new(enum bt_operand op, enum bt_filtervar var, int val)
+bf_new(enum bt_argtype op, enum bt_filtervar var, int val)
{
struct bt_filter *bf;
/* Create an operator argument */
struct bt_arg *
-ba_op(const char op, struct bt_arg *da0, struct bt_arg *da1)
+ba_op(enum bt_argtype type, struct bt_arg *da0, struct bt_arg *da1)
{
- enum bt_argtype type;
-
- switch (op) {
- case '+':
- type = B_AT_OP_ADD;
- break;
- case '-':
- type = B_AT_OP_MINUS;
- break;
- case '*':
- type = B_AT_OP_MULT;
- break;
- case '/':
- type = B_AT_OP_DIVIDE;
- break;
- case '&':
- type = B_AT_OP_AND;
- break;
- case '|':
- type = B_AT_OP_OR;
- break;
- default:
- assert(0);
- }
-
return ba_new(ba_append(da0, da1), type);
}
lookup(char *s)
{
static const struct keyword kws[] = {
- { "!=", OP_NEQ, 0 },
- { "==", OP_EQ, 0 },
{ "BEGIN", BEGIN, 0 },
{ "END", END, 0 },
{ "arg0", BUILTIN, B_AT_BI_ARG0 },
}
switch (c) {
+ case '!':
case '=':
- if (peek() == '=')
- break;
+ if (peek() == '=') {
+ lgetc();
+ return (c == '=') ? OP_EQ : OP_NE;
+ }
+ case '&':
+ if (peek() == '&') {
+ lgetc();
+ return OP_LAND;
+ }
+ case '|':
+ if (peek() == '|') {
+ lgetc();
+ return OP_LOR;
+ }
case ',':
case '(':
case ')':
}
}
-#define allowed_in_string(x) (isalnum(c) || c == '!' || c == '=' || c == '_')
+#define allowed_in_string(x) (isalnum(c) || c == '_')
/* parsing next word */
if (allowed_in_string(c)) {
-/* $OpenBSD: btrace.c,v 1.28 2021/02/01 11:26:29 mpi Exp $ */
+/* $OpenBSD: btrace.c,v 1.29 2021/02/08 09:46:45 mpi Exp $ */
/*
* Copyright (c) 2019 - 2020 Martin Pieuchot <mpi@openbsd.org>
void debugx(const char *, ...);
const char *debug_rule_name(struct bt_rule *);
void debug_dump_filter(struct bt_rule *);
-void debug_dump_rule(struct bt_rule *);
struct dtioc_probe_info *dt_dtpis; /* array of available probes */
size_t dt_ndtpi; /* # of elements in the array */
}
static inline enum dt_operand
-dop2dt(enum bt_operand op)
+dop2dt(enum bt_argtype op)
{
switch (op) {
- case B_OP_EQ: return DT_OP_EQ;
- case B_OP_NE: return DT_OP_NE;
- case B_OP_NONE: return DT_OP_NONE;
+ case B_AT_OP_EQ: return DT_OP_EQ;
+ case B_AT_OP_NE: return DT_OP_NE;
default: break;
}
xabort("unknown operand %d", op);
int dokstack = 0, on = 1;
TAILQ_FOREACH(r, &g_rules, br_next) {
- debug_dump_rule(r);
+ debug("parsed probe '%s'", debug_rule_name(r));
+ debug_dump_filter(r);
if (r->br_type != B_RT_PROBE) {
if (r->br_type == B_RT_BEGIN)
if (rend)
rule_eval(rend, NULL);
else {
+ debug("eval default 'end' rule\n");
+
TAILQ_FOREACH(r, &g_rules, br_next)
rule_printmaps(r);
}
{
struct bt_stmt *bs;
- debug("eval rule '%s'\n", debug_rule_name(r));
+ debug("eval rule '%s'", debug_rule_name(r));
+ debug_dump_filter(r);
if (r->br_filter != NULL && r->br_filter->bf_condition != NULL) {
if (stmt_test(r->br_filter->bf_condition, dtev) == false)
bv_name(bv), ba2long(bval, dtev));
return;
}
- debug("hist=%p '%s' increment bucket=%s\n", bv->bv_value,
+ debug("hist=%p '%s' increment bucket '%s'\n", bv->bv_value,
bv_name(bv), bucket);
bv->bv_value = (struct bt_arg *)
case B_AT_BI_NSECS:
bv->bv_value = ba_new(builtin_nsecs(dtev), B_AT_LONG);
break;
- case B_AT_OP_ADD ... B_AT_OP_OR:
+ case B_AT_OP_PLUS ... B_AT_OP_LOR:
bv->bv_value = ba_new(ba2long(ba, dtev), B_AT_LONG);
break;
default:
second = ba2long(b, dtev);
switch (ba->ba_type) {
- case B_AT_OP_ADD:
+ case B_AT_OP_PLUS:
result = first + second;
break;
case B_AT_OP_MINUS:
case B_AT_OP_DIVIDE:
result = first / second;
break;
- case B_AT_OP_AND:
+ case B_AT_OP_BAND:
result = first & second;
break;
- case B_AT_OP_OR:
+ case B_AT_OP_BOR:
result = first | second;
break;
+ case B_AT_OP_EQ:
+ result = (first == second);
+ break;
+ case B_AT_OP_NE:
+ result = (first != second);
+ break;
+ case B_AT_OP_LE:
+ result = (first <= second);
+ break;
+ case B_AT_OP_GE:
+ result = (first >= second);
+ break;
+ case B_AT_OP_LAND:
+ result = (first && second);
+ break;
+ case B_AT_OP_LOR:
+ result = (first || second);
+ break;
default:
xabort("unsuported operation %d", ba->ba_type);
}
- debug("ba=%p (%ld op %ld) = %ld\n", ba, first, second, result);
+ debug("ba=%p '%ld %s %ld = %ld'\n", ba, first, ba_name(ba), second,
+ result);
--recursions;
return result;
}
+const char *
+ba_name(struct bt_arg *ba)
+{
+ switch (ba->ba_type) {
+ case B_AT_BI_PID:
+ return "pid";
+ case B_AT_BI_TID:
+ return "tid";
+ case B_AT_OP_PLUS:
+ return "+";
+ case B_AT_OP_MINUS:
+ return "-";
+ case B_AT_OP_MULT:
+ return "*";
+ case B_AT_OP_DIVIDE:
+ return "/";
+ case B_AT_OP_BAND:
+ return "&";
+ case B_AT_OP_BOR:
+ return "|";
+ case B_AT_OP_EQ:
+ return "==";
+ case B_AT_OP_NE:
+ return "!=";
+ case B_AT_OP_LE:
+ return "<=";
+ case B_AT_OP_GE:
+ return ">=";
+ case B_AT_OP_LAND:
+ return "&&";
+ case B_AT_OP_LOR:
+ return "||";
+ default:
+ break;
+ }
+
+ return ba2str(ba, NULL);
+}
+
/*
* Return the representation of `ba' as long.
*/
break;
case B_AT_MAP:
bv = ba->ba_value;
+ /* Unitialized map */
+ if (bv->bv_value == NULL)
+ return 0;
val = ba2long(map_get((struct map *)bv->bv_value,
ba2str(ba->ba_key, dtev)), dtev);
break;
case B_AT_BI_RETVAL:
val = dtev->dtev_sysretval[0];
break;
- case B_AT_OP_ADD ... B_AT_OP_OR:
+ case B_AT_OP_PLUS ... B_AT_OP_LOR:
val = baexpr2long(ba, dtev);
break;
default:
case B_AT_VAR:
str = ba2str(ba_read(ba), dtev);
break;
- case B_AT_OP_ADD ... B_AT_OP_OR:
+ case B_AT_OP_PLUS ... B_AT_OP_LOR:
snprintf(buf, sizeof(buf), "%ld", ba2long(ba, dtev));
str = buf;
break;
case B_AT_MF_MAX:
case B_AT_MF_MIN:
case B_AT_MF_SUM:
- case B_AT_OP_ADD ... B_AT_OP_OR:
+ case B_AT_OP_PLUS ... B_AT_OP_LOR:
break;
default:
xabort("invalid argument type %d", ba->ba_type);
debug_getfilterop(struct bt_evtfilter *df)
{
switch (df->bf_op) {
- case B_OP_EQ: return "==";
- case B_OP_NE: return "!=";
- case B_OP_NONE: return "";
+ case B_AT_OP_EQ: return "==";
+ case B_AT_OP_NE: return "!=";
default:
xabort("invalid operand %d", df->bf_op);
}
void
debug_dump_filter(struct bt_rule *r)
{
- if (r->br_filter != NULL && r->br_filter->bf_condition == NULL) {
- struct bt_evtfilter *df = &r->br_filter->bf_evtfilter;
+ if (r->br_filter != NULL) {
+ struct bt_stmt *bs = r->br_filter->bf_condition;
+
+ if (bs == NULL) {
+ struct bt_evtfilter *df = &r->br_filter->bf_evtfilter;
- debugx(" / %s %s %u /", debug_getfiltervar(df),
- debug_getfilterop(df), df->bf_val);
+ debugx(" / %s %s %u /", debug_getfiltervar(df),
+ debug_getfilterop(df), df->bf_val);
+ } else {
+ struct bt_arg *ba = SLIST_FIRST(&bs->bs_args);
+ struct bt_var *bv = ba->ba_value;
+
+ debugx(" / %s[%s] != 0 /.", bv_name(bv),
+ ba_name(ba->ba_key));
+ }
}
debugx("\n");
}
return buf;
}
-
-void
-debug_dump_rule(struct bt_rule *r)
-{
- debug("parsed probe '%s'", debug_rule_name(r));
- debug_dump_filter(r);
-}