-/* $OpenBSD: bt_parse.y,v 1.36 2021/08/31 08:39:26 mpi Exp $ */
+/* $OpenBSD: bt_parse.y,v 1.37 2021/08/31 12:51:24 mpi Exp $ */
/*
* Copyright (c) 2019-2021 Martin Pieuchot <mpi@openbsd.org>
%token <v.i> ERROR ENDFILT
%token <v.i> OP_EQ OP_NE OP_LE OP_LT OP_GE OP_GT OP_LAND OP_LOR
/* Builtins */
-%token <v.i> BUILTIN BEGIN END HZ
+%token <v.i> BUILTIN BEGIN END HZ IF
/* Functions and Map operators */
%token <v.i> F_DELETE F_PRINT FUNC0 FUNC1 FUNCN OP1 OP4 MOP0 MOP1
%token <v.string> STRING CSTRING
%type <v.i> beginend
%type <v.probe> probe pname
%type <v.filter> filter
-%type <v.stmt> action stmt stmtlist
+%type <v.stmt> action stmt stmtblck stmtlist block
%type <v.arg> pat vargs mentry mpat pargs
%type <v.arg> expr term fterm factor
%%
| gvar '=' OP4 '(' pat ',' vargs ')' { $$ = bh_inc($1, $5, $7); }
;
-stmtlist: stmt
+stmtblck: IF '(' expr ')' block { $$ = bt_new($3, $5); }
+ ;
+
+stmtlist: stmtlist stmtblck { $$ = bs_append($1, $2); }
| stmtlist stmt { $$ = bs_append($1, $2); }
+ | stmtblck
+ | stmt
+ ;
+
+block : '{' stmt ';' '}' { $$ = $2; }
+ | stmt ';'
;
action : '{' stmtlist '}' { $$ = $2; }
return bf;
}
+/* Create a new if/else test */
+struct bt_stmt *
+bt_new(struct bt_arg *ba, struct bt_stmt *condbs)
+{
+ struct bt_arg *bop;
+
+ bop = ba_op(B_AT_OP_NE, NULL, ba);
+
+ return bs_new(B_AC_TEST, bop, (struct bt_var *)condbs);
+
+}
/* Create a new probe */
struct bt_probe *
bp_new(const char *prov, const char *func, const char *name, int32_t rate)
{ "exit", FUNC0, B_AC_EXIT },
{ "hist", OP1, 0 },
{ "hz", HZ, 0 },
+ { "if", IF, 0 },
{ "kstack", BUILTIN, B_AT_BI_KSTACK },
{ "lhist", OP4, 0 },
{ "max", MOP1, B_AT_MF_MAX },
-/* $OpenBSD: btrace.c,v 1.41 2021/08/31 11:30:21 mpi Exp $ */
+/* $OpenBSD: btrace.c,v 1.42 2021/08/31 12:51:24 mpi Exp $ */
/*
* Copyright (c) 2019 - 2020 Martin Pieuchot <mpi@openbsd.org>
uint64_t builtin_nsecs(struct dt_evt *);
const char *builtin_kstack(struct dt_evt *);
const char *builtin_arg(struct dt_evt *, enum bt_argtype);
+void stmt_eval(struct bt_stmt *, struct dt_evt *);
void stmt_bucketize(struct bt_stmt *, struct dt_evt *);
void stmt_clear(struct bt_stmt *);
void stmt_delete(struct bt_stmt *, struct dt_evt *);
}
SLIST_FOREACH(bs, &r->br_action, bs_next) {
- switch (bs->bs_act) {
- case B_AC_BUCKETIZE:
- stmt_bucketize(bs, dtev);
- break;
- case B_AC_CLEAR:
- stmt_clear(bs);
- break;
- case B_AC_DELETE:
- stmt_delete(bs, dtev);
- break;
- case B_AC_EXIT:
- exit(0);
- break;
- case B_AC_INSERT:
- stmt_insert(bs, dtev);
- break;
- case B_AC_PRINT:
- stmt_print(bs, dtev);
- break;
- case B_AC_PRINTF:
- stmt_printf(bs, dtev);
- break;
- case B_AC_STORE:
- stmt_store(bs, dtev);
- break;
- case B_AC_TIME:
- stmt_time(bs, dtev);
- break;
- case B_AC_ZERO:
- stmt_zero(bs);
- break;
- default:
- xabort("no handler for action type %d", bs->bs_act);
- }
+ if ((bs->bs_act == B_AC_TEST) && stmt_test(bs, dtev) == true)
+ stmt_eval((struct bt_stmt *)bs->bs_var, dtev);
+
+ stmt_eval(bs, dtev);
}
}
return buf;
}
+void
+stmt_eval(struct bt_stmt *bs, struct dt_evt *dtev)
+{
+ switch (bs->bs_act) {
+ case B_AC_BUCKETIZE:
+ stmt_bucketize(bs, dtev);
+ break;
+ case B_AC_CLEAR:
+ stmt_clear(bs);
+ break;
+ case B_AC_DELETE:
+ stmt_delete(bs, dtev);
+ break;
+ case B_AC_EXIT:
+ exit(0);
+ break;
+ case B_AC_INSERT:
+ stmt_insert(bs, dtev);
+ break;
+ case B_AC_PRINT:
+ stmt_print(bs, dtev);
+ break;
+ case B_AC_PRINTF:
+ stmt_printf(bs, dtev);
+ break;
+ case B_AC_STORE:
+ stmt_store(bs, dtev);
+ break;
+ case B_AC_TEST:
+ /* done before */
+ break;
+ case B_AC_TIME:
+ stmt_time(bs, dtev);
+ break;
+ case B_AC_ZERO:
+ stmt_zero(bs);
+ break;
+ default:
+ xabort("no handler for action type %d", bs->bs_act);
+ }
+}
+
/*
* Increment a bucket: { @h = hist(v); } or { @h = lhist(v, min, max, step); }
*
if (bs == NULL)
return true;
- assert(bs->bs_var == NULL);
ba = SLIST_FIRST(&bs->bs_args);
return baexpr2long(ba, dtev) != 0;