1 /*- 2 * SPDX-License-Identifier: MIT-CMU 3 * 4 * Mach Operating System 5 * Copyright (c) 1991,1990 Carnegie Mellon University 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify and distribute this software and its 9 * documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie the 26 * rights to redistribute these changes. 27 */ 28 /* 29 * Author: David B. Golub, Carnegie Mellon University 30 * Date: 7/90 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 39 #include <ddb/ddb.h> 40 #include <ddb/db_lex.h> 41 #include <ddb/db_access.h> 42 #include <ddb/db_command.h> 43 44 static bool db_add_expr(db_expr_t *valuep); 45 static bool db_mult_expr(db_expr_t *valuep); 46 static bool db_shift_expr(db_expr_t *valuep); 47 static bool db_term(db_expr_t *valuep); 48 static bool db_unary(db_expr_t *valuep); 49 static bool db_logical_or_expr(db_expr_t *valuep); 50 static bool db_logical_and_expr(db_expr_t *valuep); 51 static bool db_logical_relation_expr(db_expr_t *valuep); 52 53 static bool 54 db_term(db_expr_t *valuep) 55 { 56 int t; 57 58 t = db_read_token(); 59 if (t == tIDENT) { 60 if (!db_value_of_name(db_tok_string, valuep) && 61 !db_value_of_name_pcpu(db_tok_string, valuep) && 62 !db_value_of_name_vnet(db_tok_string, valuep)) { 63 db_printf("Symbol '%s' not found\n", db_tok_string); 64 db_error(NULL); 65 /*NOTREACHED*/ 66 } 67 return (true); 68 } 69 if (t == tNUMBER) { 70 *valuep = (db_expr_t)db_tok_number; 71 return (true); 72 } 73 if (t == tDOT) { 74 *valuep = (db_expr_t)db_dot; 75 return (true); 76 } 77 if (t == tDOTDOT) { 78 *valuep = (db_expr_t)db_prev; 79 return (true); 80 } 81 if (t == tPLUS) { 82 *valuep = (db_expr_t) db_next; 83 return (true); 84 } 85 if (t == tDITTO) { 86 *valuep = (db_expr_t)db_last_addr; 87 return (true); 88 } 89 if (t == tDOLLAR) { 90 if (!db_get_variable(valuep)) 91 return (false); 92 return (true); 93 } 94 if (t == tLPAREN) { 95 if (!db_expression(valuep)) { 96 db_printf("Expression syntax error after '%c'\n", '('); 97 db_error(NULL); 98 /*NOTREACHED*/ 99 } 100 t = db_read_token(); 101 if (t != tRPAREN) { 102 db_printf("Expression syntax error -- expected '%c'\n", ')'); 103 db_error(NULL); 104 /*NOTREACHED*/ 105 } 106 return (true); 107 } 108 db_unread_token(t); 109 return (false); 110 } 111 112 static bool 113 db_unary(db_expr_t *valuep) 114 { 115 int t; 116 117 t = db_read_token(); 118 if (t == tMINUS) { 119 if (!db_unary(valuep)) { 120 db_printf("Expression syntax error after '%c'\n", '-'); 121 db_error(NULL); 122 /*NOTREACHED*/ 123 } 124 *valuep = -*valuep; 125 return (true); 126 } 127 if (t == tEXCL) { 128 if (!db_unary(valuep)) { 129 db_printf("Expression syntax error after '%c'\n", '!'); 130 db_error(NULL); 131 /* NOTREACHED */ 132 } 133 *valuep = (!(*valuep)); 134 return (true); 135 } 136 if (t == tBIT_NOT) { 137 if (!db_unary(valuep)) { 138 db_printf("Expression syntax error after '%c'\n", '~'); 139 db_error(NULL); 140 /* NOTREACHED */ 141 } 142 *valuep = (~(*valuep)); 143 return (true); 144 } 145 if (t == tSTAR) { 146 /* indirection */ 147 if (!db_unary(valuep)) { 148 db_printf("Expression syntax error after '%c'\n", '*'); 149 db_error(NULL); 150 /*NOTREACHED*/ 151 } 152 *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *), 153 false); 154 return (true); 155 } 156 db_unread_token(t); 157 return (db_term(valuep)); 158 } 159 160 static bool 161 db_mult_expr(db_expr_t *valuep) 162 { 163 db_expr_t lhs, rhs; 164 int t; 165 166 if (!db_unary(&lhs)) 167 return (false); 168 169 t = db_read_token(); 170 while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH || 171 t == tBIT_AND ) { 172 if (!db_term(&rhs)) { 173 db_printf("Expression syntax error after '%c'\n", 174 t == tSTAR ? '*' : t == tSLASH ? '/' : t == tPCT ? '%' : 175 t == tHASH ? '#' : '&'); 176 db_error(NULL); 177 /*NOTREACHED*/ 178 } 179 switch(t) { 180 case tSTAR: 181 lhs *= rhs; 182 break; 183 case tBIT_AND: 184 lhs &= rhs; 185 break; 186 default: 187 if (rhs == 0) { 188 db_error("Division by 0\n"); 189 /*NOTREACHED*/ 190 } 191 if (t == tSLASH) 192 lhs /= rhs; 193 else if (t == tPCT) 194 lhs %= rhs; 195 else 196 lhs = roundup(lhs, rhs); 197 } 198 t = db_read_token(); 199 } 200 db_unread_token(t); 201 *valuep = lhs; 202 return (true); 203 } 204 205 static bool 206 db_add_expr(db_expr_t *valuep) 207 { 208 db_expr_t lhs, rhs; 209 int t; 210 211 if (!db_mult_expr(&lhs)) 212 return (false); 213 214 t = db_read_token(); 215 while (t == tPLUS || t == tMINUS || t == tBIT_OR) { 216 if (!db_mult_expr(&rhs)) { 217 db_printf("Expression syntax error after '%c'\n", 218 t == tPLUS ? '+' : t == tMINUS ? '-' : '|'); 219 db_error(NULL); 220 /*NOTREACHED*/ 221 } 222 switch (t) { 223 case tPLUS: 224 lhs += rhs; 225 break; 226 case tMINUS: 227 lhs -= rhs; 228 break; 229 case tBIT_OR: 230 lhs |= rhs; 231 break; 232 default: 233 __assert_unreachable(); 234 } 235 t = db_read_token(); 236 } 237 db_unread_token(t); 238 *valuep = lhs; 239 return (true); 240 } 241 242 static bool 243 db_shift_expr(db_expr_t *valuep) 244 { 245 db_expr_t lhs, rhs; 246 int t; 247 248 if (!db_add_expr(&lhs)) 249 return (false); 250 t = db_read_token(); 251 while (t == tSHIFT_L || t == tSHIFT_R) { 252 if (!db_add_expr(&rhs)) { 253 db_printf("Expression syntax error after '%s'\n", 254 t == tSHIFT_L ? "<<" : ">>"); 255 db_error(NULL); 256 /*NOTREACHED*/ 257 } 258 if (rhs < 0) { 259 db_printf("Negative shift amount %jd\n", (intmax_t)rhs); 260 db_error(NULL); 261 /*NOTREACHED*/ 262 } 263 if (t == tSHIFT_L) 264 lhs <<= rhs; 265 else { 266 /* Shift right is unsigned */ 267 lhs = (db_addr_t)lhs >> rhs; 268 } 269 t = db_read_token(); 270 } 271 db_unread_token(t); 272 *valuep = lhs; 273 return (true); 274 } 275 276 static bool 277 db_logical_relation_expr( 278 db_expr_t *valuep) 279 { 280 db_expr_t lhs, rhs; 281 int t; 282 283 if (!db_shift_expr(&lhs)) 284 return (false); 285 286 t = db_read_token(); 287 while (t == tLOG_EQ || t == tLOG_NOT_EQ || t == tGREATER || 288 t == tGREATER_EQ || t == tLESS || t == tLESS_EQ) { 289 if (!db_shift_expr(&rhs)) { 290 db_printf("Expression syntax error after '%s'\n", 291 t == tLOG_EQ ? "==" : t == tLOG_NOT_EQ ? "!=" : 292 t == tGREATER ? ">" : t == tGREATER_EQ ? ">=" : 293 t == tLESS ? "<" : "<="); 294 db_error(NULL); 295 /*NOTREACHED*/ 296 } 297 switch(t) { 298 case tLOG_EQ: 299 lhs = (lhs == rhs); 300 break; 301 case tLOG_NOT_EQ: 302 lhs = (lhs != rhs); 303 break; 304 case tGREATER: 305 lhs = (lhs > rhs); 306 break; 307 case tGREATER_EQ: 308 lhs = (lhs >= rhs); 309 break; 310 case tLESS: 311 lhs = (lhs < rhs); 312 break; 313 case tLESS_EQ: 314 lhs = (lhs <= rhs); 315 break; 316 default: 317 __assert_unreachable(); 318 } 319 t = db_read_token(); 320 } 321 db_unread_token(t); 322 *valuep = lhs; 323 return (true); 324 } 325 326 static bool 327 db_logical_and_expr( 328 db_expr_t *valuep) 329 { 330 db_expr_t lhs, rhs; 331 int t; 332 333 if (!db_logical_relation_expr(&lhs)) 334 return (false); 335 336 t = db_read_token(); 337 while (t == tLOG_AND) { 338 if (!db_logical_relation_expr(&rhs)) { 339 db_printf("Expression syntax error after '%s'\n", "&&"); 340 db_error(NULL); 341 /*NOTREACHED*/ 342 } 343 lhs = (lhs && rhs); 344 t = db_read_token(); 345 } 346 db_unread_token(t); 347 *valuep = lhs; 348 return (true); 349 } 350 351 static bool 352 db_logical_or_expr( 353 db_expr_t *valuep) 354 { 355 db_expr_t lhs, rhs; 356 int t; 357 358 if (!db_logical_and_expr(&lhs)) 359 return(false); 360 361 t = db_read_token(); 362 while (t == tLOG_OR) { 363 if (!db_logical_and_expr(&rhs)) { 364 db_printf("Expression syntax error after '%s'\n", "||"); 365 db_error(NULL); 366 /*NOTREACHED*/ 367 } 368 lhs = (lhs || rhs); 369 t = db_read_token(); 370 } 371 db_unread_token(t); 372 *valuep = lhs; 373 return (true); 374 } 375 376 int 377 db_expression(db_expr_t *valuep) 378 { 379 return (db_logical_or_expr(valuep)); 380 } 381