From: mpi Date: Sat, 30 Mar 2024 07:41:45 +0000 (+0000) Subject: Implement else branching logic including 'else if'. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=ca41b7499da326730839ef3d139e7af7af229460;p=openbsd 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 --- 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 @@ -119,7 +119,7 @@ static int beflag = 0; /* BEGIN/END parsing context flag */ %token ERROR ENDFILT %token OP_EQ OP_NE OP_LE OP_LT OP_GE OP_GT OP_LAND OP_LOR /* Builtins */ -%token BUILTIN BEGIN END HZ IF STR +%token BUILTIN BEGIN ELSE END HZ IF STR /* Functions and Map operators */ %token F_DELETE F_PRINT %token 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 @@ -180,6 +180,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 @@ -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);