summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2024-03-30 07:41:46 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2024-03-30 07:41:46 +0000
commitd75ffb62d682420b80696a36a3ef66b720266e66 (patch)
treea38d8c2632f7480b6bd3f1c0a4bc56d6a9ab7b4e
parentcb9a1aefad92d62b67d212884b980590840cef7f (diff)
Implement else branching logic including 'else if'.
Statement lists for if & else conditions are now wrapped in a new 'struct bt_cond'. Handling B_AC_TEST statements moved to stmt_eval() to handle nested conditional statements. From Christian Ludwig christian_ludwig at genua.de
-rw-r--r--regress/usr.sbin/btrace/if.bt29
-rw-r--r--regress/usr.sbin/btrace/if.ok4
-rw-r--r--usr.sbin/btrace/bt_parse.y20
-rw-r--r--usr.sbin/btrace/bt_parser.h10
-rw-r--r--usr.sbin/btrace/btrace.c34
5 files changed, 75 insertions, 22 deletions
diff --git a/regress/usr.sbin/btrace/if.bt b/regress/usr.sbin/btrace/if.bt
index 053801cac54..41f30815ba5 100644
--- a/regress/usr.sbin/btrace/if.bt
+++ b/regress/usr.sbin/btrace/if.bt
@@ -9,6 +9,20 @@ BEGIN {
if (1) {
printf("printed!\n");
}
+
+ if (0)
+ printf("simple if\n");
+ else
+ printf("simple else\n");
+
+ if (0) {
+ printf("disabled if\n");
+ } else if (1) {
+ printf("multiple statements in ");
+ printf("else-if branch\n");
+ } else {
+ printf("no else\n");
+ }
}
END {
@@ -18,4 +32,19 @@ END {
printf("(%d) ", @var);
printf("statements\n");
}
+
+ if (0) printf("single-line if\n"); else printf("single-line else\n");
+
+ if (0) {
+ printf("not printed\n");
+ } else {
+ if (0) {
+ printf("nested not printed\n");
+ } else {
+ printf("nested printed\n");
+ exit();
+ printf("nested not printed\n");
+ }
+ printf("also not printed\n");
+ }
}
diff --git a/regress/usr.sbin/btrace/if.ok b/regress/usr.sbin/btrace/if.ok
index c2d5a91bc90..cfac256dac6 100644
--- a/regress/usr.sbin/btrace/if.ok
+++ b/regress/usr.sbin/btrace/if.ok
@@ -1,2 +1,6 @@
printed!
+simple else
+multiple statements in else-if branch
multiple (4) statements
+single-line else
+nested printed
diff --git a/usr.sbin/btrace/bt_parse.y b/usr.sbin/btrace/bt_parse.y
index 075eaa5b7f8..2497ae4eadd 100644
--- a/usr.sbin/btrace/bt_parse.y
+++ b/usr.sbin/btrace/bt_parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: bt_parse.y,v 1.59 2024/02/12 15:11:06 mpi Exp $ */
+/* $OpenBSD: bt_parse.y,v 1.60 2024/03/30 07:41:45 mpi Exp $ */
/*
* Copyright (c) 2019-2023 Martin Pieuchot <mpi@openbsd.org>
@@ -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,15 +342,22 @@ 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_cond *bc;
bop = ba_op(B_AT_OP_NE, NULL, ba);
- return bs_new(B_AC_TEST, bop, (struct bt_var *)condbs);
+ bc = calloc(1, sizeof(*bc));
+ if (bc == NULL)
+ err(1, "bt_cond: calloc");
+ bc->bc_condbs = condbs;
+ bc->bc_elsebs = elsebs;
+ return bs_new(B_AC_TEST, bop, (struct bt_var *)bc);
}
+
/* Create a new probe */
struct bt_probe *
bp_new(const char *prov, const char *func, const char *name, int32_t rate)
@@ -714,6 +723,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/bt_parser.h b/usr.sbin/btrace/bt_parser.h
index 051bd72815d..081c0045c2f 100644
--- a/usr.sbin/btrace/bt_parser.h
+++ b/usr.sbin/btrace/bt_parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bt_parser.h,v 1.25 2023/10/12 15:16:44 cheloha Exp $ */
+/* $OpenBSD: bt_parser.h,v 1.26 2024/03/30 07:41:45 mpi Exp $ */
/*
* Copyright (c) 2019-2021 Martin Pieuchot <mpi@openbsd.org>
@@ -181,6 +181,14 @@ struct bt_arg {
#define BA_INITIALIZER(v, t) { { NULL }, (void *)(v), NULL, (t) }
/*
+ * Represents branches of an if-else statement.
+ */
+struct bt_cond {
+ struct bt_stmt *bc_condbs;
+ struct bt_stmt *bc_elsebs;
+};
+
+/*
* Each action associated with a given probe is made of at least one
* statement.
*
diff --git a/usr.sbin/btrace/btrace.c b/usr.sbin/btrace/btrace.c
index ce32989be91..b817d9c924b 100644
--- a/usr.sbin/btrace/btrace.c
+++ b/usr.sbin/btrace/btrace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: btrace.c,v 1.89 2024/02/27 12:38:12 mpi Exp $ */
+/* $OpenBSD: btrace.c,v 1.90 2024/03/30 07:41:45 mpi Exp $ */
/*
* Copyright (c) 2019 - 2023 Martin Pieuchot <mpi@openbsd.org>
@@ -460,6 +460,7 @@ static uint64_t
rules_action_scan(struct bt_stmt *bs)
{
struct bt_arg *ba;
+ struct bt_cond *bc;
uint64_t evtflags = 0;
while (bs != NULL) {
@@ -474,8 +475,9 @@ rules_action_scan(struct bt_stmt *bs)
evtflags |= ba2dtflags(ba);
break;
case B_AC_TEST:
- evtflags |= rules_action_scan(
- (struct bt_stmt *)bs->bs_var);
+ bc = (struct bt_cond *)bs->bs_var;
+ evtflags |= rules_action_scan(bc->bc_condbs);
+ evtflags |= rules_action_scan(bc->bc_elsebs);
break;
default:
break;
@@ -669,18 +671,6 @@ 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;
-
- while (bbs != NULL) {
- if (stmt_eval(bbs, dtev))
- return 1;
- bbs = SLIST_NEXT(bbs, bs_next);
- }
-
- continue;
- }
-
if (stmt_eval(bs, dtev))
return 1;
}
@@ -830,6 +820,8 @@ builtin_arg(struct dt_evt *dtev, enum bt_argtype dat)
int
stmt_eval(struct bt_stmt *bs, struct dt_evt *dtev)
{
+ struct bt_stmt *bbs;
+ struct bt_cond *bc;
int halt = 0;
switch (bs->bs_act) {
@@ -858,7 +850,17 @@ stmt_eval(struct bt_stmt *bs, struct dt_evt *dtev)
stmt_store(bs, dtev);
break;
case B_AC_TEST:
- /* done before */
+ bc = (struct bt_cond *)bs->bs_var;
+ if (stmt_test(bs, dtev) == true)
+ bbs = bc->bc_condbs;
+ else
+ bbs = bc->bc_elsebs;
+
+ while (bbs != NULL) {
+ if (stmt_eval(bbs, dtev))
+ return 1;
+ bbs = SLIST_NEXT(bbs, bs_next);
+ }
break;
case B_AC_TIME:
stmt_time(bs, dtev);