Download raw body.
btrace: Implement else-branch for if-statements in bt(5)
Hi,
btrace has support for if-statements already implemented, but it lacks
support for an else-branch. This diff implements that, including
'else if'.
Although it has a regress test attached, it certainly needs more
testing.
Is the abuse of a struct bt_arg as container for the two statement
lists acceptable, or do we want a proper type?
So long,
- Christian
---
regress/usr.sbin/btrace/if.bt | 8 ++++++++
regress/usr.sbin/btrace/if.ok | 1 +
usr.sbin/btrace/bt_parse.y | 15 ++++++++++-----
usr.sbin/btrace/btrace.c | 14 +++++++++++---
4 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/regress/usr.sbin/btrace/if.bt b/regress/usr.sbin/btrace/if.bt
index 053801cac54..89cdc3f9f47 100644
--- a/regress/usr.sbin/btrace/if.bt
+++ b/regress/usr.sbin/btrace/if.bt
@@ -1,6 +1,8 @@
BEGIN {
if (0)
printf("nothing");
+ else
+ printf("printed!\n");
@var = 0;
if (@var)
@@ -8,10 +10,16 @@ BEGIN {
if (1) {
printf("printed!\n");
+ } else if (1) {
+ printf("not printed\n");
+ } else {
+ printf("not printed\n");
}
}
END {
+ if (1) { ; } else printf("not printed\n");
+
if (42) {
printf("multiple ");
@var = 4;
diff --git a/regress/usr.sbin/btrace/if.ok b/regress/usr.sbin/btrace/if.ok
index c2d5a91bc90..7b26ae9cd7c 100644
--- a/regress/usr.sbin/btrace/if.ok
+++ b/regress/usr.sbin/btrace/if.ok
@@ -1,2 +1,3 @@
printed!
+printed!
multiple (4) statements
diff --git a/usr.sbin/btrace/bt_parse.y b/usr.sbin/btrace/bt_parse.y
index 075eaa5b7f8..19b3e5029c6 100644
--- a/usr.sbin/btrace/bt_parse.y
+++ b/usr.sbin/btrace/bt_parse.y
@@ -119,7 +119,7 @@ static int beflag = 0; /* BEGIN/END parsing context flag */
%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 IF STR
+%token <v.i> BUILTIN BEGIN ELSE END HZ IF STR
/* Functions and Map operators */
%token <v.i> F_DELETE F_PRINT
%token <v.i> MFUNC FUNC0 FUNC1 FUNCN OP1 OP2 OP4 MOP0 MOP1
@@ -248,7 +248,9 @@ stmt : ';' NL { $$ = NULL; }
| GVAR '=' OP4 '(' expr ',' vargs ')' { $$ = bh_inc($1, $5, $7); }
;
-stmtblck: IF '(' expr ')' block { $$ = bt_new($3, $5); }
+stmtblck: IF '(' expr ')' block { $$ = bt_new($3, $5, NULL); }
+ | IF '(' expr ')' block ELSE block { $$ = bt_new($3, $5, $7); }
+ | IF '(' expr ')' block ELSE stmtblck { $$ = bt_new($3, $5, $7); }
;
stmtlist: stmtlist stmtblck { $$ = bs_append($1, $2); }
@@ -340,13 +342,15 @@ bc_new(struct bt_arg *term, enum bt_argtype op, struct bt_arg *ba)
/* Create a new if/else test */
struct bt_stmt *
-bt_new(struct bt_arg *ba, struct bt_stmt *condbs)
+bt_new(struct bt_arg *ba, struct bt_stmt *condbs, struct bt_stmt *elsebs)
{
- struct bt_arg *bop;
+ struct bt_arg *bop, *lnk;
bop = ba_op(B_AT_OP_NE, NULL, ba);
+ lnk = ba_new(condbs, 0);
+ lnk->ba_key = (struct bt_arg *)elsebs;
- return bs_new(B_AC_TEST, bop, (struct bt_var *)condbs);
+ return bs_new(B_AC_TEST, bop, (struct bt_var *)lnk);
}
/* Create a new probe */
@@ -714,6 +718,7 @@ lookup(char *s)
{ "count", MOP0, B_AT_MF_COUNT },
{ "cpu", BUILTIN, B_AT_BI_CPU },
{ "delete", F_DELETE, B_AC_DELETE },
+ { "else", ELSE, 0 },
{ "exit", FUNC0, B_AC_EXIT },
{ "hist", OP1, 0 },
{ "hz", HZ, 0 },
diff --git a/usr.sbin/btrace/btrace.c b/usr.sbin/btrace/btrace.c
index ce32989be91..ba3efb2983a 100644
--- a/usr.sbin/btrace/btrace.c
+++ b/usr.sbin/btrace/btrace.c
@@ -474,8 +474,11 @@ rules_action_scan(struct bt_stmt *bs)
evtflags |= ba2dtflags(ba);
break;
case B_AC_TEST:
+ ba = (struct bt_arg *)bs->bs_var;
evtflags |= rules_action_scan(
- (struct bt_stmt *)bs->bs_var);
+ (struct bt_stmt *)ba->ba_value);
+ evtflags |= rules_action_scan(
+ (struct bt_stmt *)ba->ba_key);
break;
default:
break;
@@ -669,8 +672,13 @@ rule_eval(struct bt_rule *r, struct dt_evt *dtev)
}
SLIST_FOREACH(bs, &r->br_action, bs_next) {
- if ((bs->bs_act == B_AC_TEST) && stmt_test(bs, dtev) == true) {
- struct bt_stmt *bbs = (struct bt_stmt *)bs->bs_var;
+ if (bs->bs_act == B_AC_TEST) {
+ struct bt_arg *lnk = (struct bt_arg *)bs->bs_var;
+ struct bt_stmt *bbs;
+ if (stmt_test(bs, dtev) == true)
+ bbs = (struct bt_stmt *)lnk->ba_value;
+ else
+ bbs = (struct bt_stmt *)lnk->ba_key;
while (bbs != NULL) {
if (stmt_eval(bbs, dtev))
--
2.34.1
btrace: Implement else-branch for if-statements in bt(5)