From c69cee69f9886806e57d9b08337d565b2bdf8298 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Mon, 16 May 2016 19:42:38 +0000 Subject: [PATCH] Add a small set of logical operators to DDB command language. This are based on Mach3. Documentation is pending but has been promised. Submitted by: Dan Partelly Reviewed by: adrian, jhb (older version) Differential Revision: https://reviews.freebsd.org/D4230 RelNotes: yes --- sys/ddb/db_examine.c | 4 + sys/ddb/db_expr.c | 193 +++++++++++++++++++++++++++++++++++++------ sys/ddb/db_lex.c | 33 +++++++- sys/ddb/db_lex.h | 13 +++ 4 files changed, 216 insertions(+), 27 deletions(-) diff --git a/sys/ddb/db_examine.c b/sys/ddb/db_examine.c index a41fcb5dae69..de2bbe4e7735 100644 --- a/sys/ddb/db_examine.c +++ b/sys/ddb/db_examine.c @@ -225,6 +225,10 @@ db_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif) else db_printf("\\%03o", (int)value); break; + default: + db_print_format = 'x'; + db_error("Syntax error: unsupported print modifier\n"); + /*NOTREACHED*/ } db_printf("\n"); } diff --git a/sys/ddb/db_expr.c b/sys/ddb/db_expr.c index 85886762f37c..db17f3698572 100644 --- a/sys/ddb/db_expr.c +++ b/sys/ddb/db_expr.c @@ -43,6 +43,9 @@ static bool db_mult_expr(db_expr_t *valuep); static bool db_shift_expr(db_expr_t *valuep); static bool db_term(db_expr_t *valuep); static bool db_unary(db_expr_t *valuep); +static bool db_logical_or_expr(db_expr_t *valuep); +static bool db_logical_and_expr(db_expr_t *valuep); +static bool db_logical_relation_expr(db_expr_t *valuep); static bool db_term(db_expr_t *valuep) @@ -108,19 +111,40 @@ db_unary(db_expr_t *valuep) t = db_read_token(); if (t == tMINUS) { if (!db_unary(valuep)) { - db_error("Syntax error\n"); + db_printf("Expression syntax error after '%c'\n", '-'); + db_error(NULL); /*NOTREACHED*/ } *valuep = -*valuep; return (true); } + if (t == tEXCL) { + if(!db_unary(valuep)) { + db_printf("Expression syntax error after '%c'\n", '!'); + db_error(NULL); + /* NOTREACHED */ + } + *valuep = (!(*valuep)); + return (true); + } + if (t == tBIT_NOT) { + if(!db_unary(valuep)) { + db_printf("Expression syntax error after '%c'\n", '~'); + db_error(NULL); + /* NOTREACHED */ + } + *valuep = (~(*valuep)); + return (true); + } if (t == tSTAR) { /* indirection */ if (!db_unary(valuep)) { - db_error("Syntax error\n"); + db_printf("Expression syntax error after '%c'\n", '*'); + db_error(NULL); /*NOTREACHED*/ } - *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *), false); + *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *), + false); return (true); } db_unread_token(t); @@ -137,24 +161,31 @@ db_mult_expr(db_expr_t *valuep) return (false); t = db_read_token(); - while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) { + while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH || + t == tBIT_AND ) { if (!db_term(&rhs)) { - db_error("Syntax error\n"); + db_printf("Expression syntax error after '%c'\n", '!'); + db_error(NULL); /*NOTREACHED*/ } - if (t == tSTAR) - lhs *= rhs; - else { - if (rhs == 0) { - db_error("Divide by 0\n"); - /*NOTREACHED*/ - } - if (t == tSLASH) - lhs /= rhs; - else if (t == tPCT) - lhs %= rhs; - else - lhs = roundup(lhs, rhs); + switch(t) { + case tSTAR: + lhs *= rhs; + break; + case tBIT_AND: + lhs &= rhs; + break; + default: + if (rhs == 0) { + db_error("Divide by 0\n"); + /*NOTREACHED*/ + } + if (t == tSLASH) + lhs /= rhs; + else if (t == tPCT) + lhs %= rhs; + else + lhs = roundup(lhs, rhs); } t = db_read_token(); } @@ -168,20 +199,32 @@ db_add_expr(db_expr_t *valuep) { db_expr_t lhs, rhs; int t; + char c; if (!db_mult_expr(&lhs)) return (false); t = db_read_token(); - while (t == tPLUS || t == tMINUS) { + while (t == tPLUS || t == tMINUS || t == tBIT_OR) { if (!db_mult_expr(&rhs)) { - db_error("Syntax error\n"); + c = db_tok_string[0]; + db_printf("Expression syntax error after '%c'\n", c); + db_error(NULL); /*NOTREACHED*/ } - if (t == tPLUS) + switch (t) { + case tPLUS: lhs += rhs; - else + break; + case tMINUS: lhs -= rhs; + break; + case tBIT_OR: + lhs |= rhs; + break; + default: + __unreachable(); + } t = db_read_token(); } db_unread_token(t); @@ -196,8 +239,7 @@ db_shift_expr(db_expr_t *valuep) int t; if (!db_add_expr(&lhs)) - return (false); - + return (false); t = db_read_token(); while (t == tSHIFT_L || t == tSHIFT_R) { if (!db_add_expr(&rhs)) { @@ -221,8 +263,109 @@ db_shift_expr(db_expr_t *valuep) return (true); } +static bool +db_logical_relation_expr( + db_expr_t *valuep) +{ + db_expr_t lhs, rhs; + int t; + char op[3]; + + if (!db_shift_expr(&lhs)) + return (false); + + t = db_read_token(); + while (t == tLOG_EQ || t == tLOG_NOT_EQ || t == tGREATER || + t == tGREATER_EQ || t == tLESS || t == tLESS_EQ) { + op[0] = db_tok_string[0]; + op[1] = db_tok_string[1]; + op[2] = 0; + if (!db_shift_expr(&rhs)) { + db_printf("Expression syntax error after \"%s\"\n", op); + db_error(NULL); + /*NOTREACHED*/ + } + switch(t) { + case tLOG_EQ: + lhs = (lhs == rhs); + break; + case tLOG_NOT_EQ: + lhs = (lhs != rhs); + break; + case tGREATER: + lhs = (lhs > rhs); + break; + case tGREATER_EQ: + lhs = (lhs >= rhs); + break; + case tLESS: + lhs = (lhs < rhs); + break; + case tLESS_EQ: + lhs = (lhs <= rhs); + break; + default: + __unreachable(); + } + t = db_read_token(); + } + db_unread_token(t); + *valuep = lhs; + return (true); +} + +static bool +db_logical_and_expr( + db_expr_t *valuep) +{ + db_expr_t lhs, rhs; + int t; + + if (!db_logical_relation_expr(&lhs)) + return (false); + + t = db_read_token(); + while (t == tLOG_AND) { + if (!db_logical_relation_expr(&rhs)) { + db_printf("Expression syntax error after '%s'\n", "&&"); + db_error(NULL); + /*NOTREACHED*/ + } + lhs = (lhs && rhs); + t = db_read_token(); + } + db_unread_token(t); + *valuep = lhs; + return (true); +} + +static bool +db_logical_or_expr( + db_expr_t *valuep) +{ + db_expr_t lhs, rhs; + int t; + + if (!db_logical_and_expr(&lhs)) + return(false); + + t = db_read_token(); + while (t == tLOG_OR) { + if (!db_logical_and_expr(&rhs)) { + db_printf("Expression syntax error after '%s'\n", "||"); + db_error(NULL); + /*NOTREACHED*/ + } + lhs = (lhs || rhs); + t = db_read_token(); + } + db_unread_token(t); + *valuep = lhs; + return (true); +} + int db_expression(db_expr_t *valuep) { - return (db_shift_expr(valuep)); + return (db_logical_or_expr(valuep)); } diff --git a/sys/ddb/db_lex.c b/sys/ddb/db_lex.c index 8a81046579a3..4fdfa317c6e4 100644 --- a/sys/ddb/db_lex.c +++ b/sys/ddb/db_lex.c @@ -274,6 +274,10 @@ db_lex(void) case '/': return (tSLASH); case '=': + c = db_read_char(); + if (c == '=') + return (tLOG_EQ); + db_unread_char(c); return (tEQ); case '%': return (tPCT); @@ -290,21 +294,46 @@ db_lex(void) case '$': return (tDOLLAR); case '!': + c = db_read_char(); + if (c == '='){ + return (tLOG_NOT_EQ); + } + db_unread_char(c); return (tEXCL); case ';': return (tSEMI); + case '&': + c = db_read_char(); + if (c == '&') + return (tLOG_AND); + db_unread_char(c); + return (tBIT_AND); + case '|': + c = db_read_char(); + if (c == '|') + return (tLOG_OR); + db_unread_char(c); + return (tBIT_OR); case '<': c = db_read_char(); if (c == '<') return (tSHIFT_L); + if (c == '=') + return (tLESS_EQ); db_unread_char(c); - break; + return (tLESS); case '>': c = db_read_char(); if (c == '>') return (tSHIFT_R); + if (c == '=') + return (tGREATER_EQ); db_unread_char(c); - break; + return (tGREATER); + case '?': + return (tQUESTION); + case '~': + return (tBIT_NOT); case -1: return (tEOF); } diff --git a/sys/ddb/db_lex.h b/sys/ddb/db_lex.h index 8713a27055f1..e20907db8420 100644 --- a/sys/ddb/db_lex.h +++ b/sys/ddb/db_lex.h @@ -69,5 +69,18 @@ extern char db_tok_string[TOK_STRING_SIZE]; #define tSHIFT_R 19 #define tDOTDOT 20 #define tSEMI 21 +#define tLOG_EQ 22 +#define tLOG_NOT_EQ 23 +#define tLESS 24 +#define tLESS_EQ 25 +#define tGREATER 26 +#define tGREATER_EQ 27 +#define tBIT_AND 28 +#define tBIT_OR 29 +#define tLOG_AND 30 +#define tLOG_OR 31 +#define tSTRING 32 +#define tQUESTION 33 +#define tBIT_NOT 34 #endif /* !_DDB_DB_LEX_H_ */