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 #include <sys/param.h> 35 #include <sys/systm.h> 36 37 #include <ddb/ddb.h> 38 #include <ddb/db_lex.h> 39 #include <ddb/db_access.h> 40 #include <ddb/db_command.h> 41 42 static bool db_add_expr(db_expr_t *valuep); 43 static bool db_mult_expr(db_expr_t *valuep); 44 static bool db_shift_expr(db_expr_t *valuep); 45 static bool db_term(db_expr_t *valuep); 46 static bool db_unary(db_expr_t *valuep); 47 static bool db_logical_or_expr(db_expr_t *valuep); 48 static bool db_logical_and_expr(db_expr_t *valuep); 49 static bool db_logical_relation_expr(db_expr_t *valuep); 50 51 static bool 52 db_term(db_expr_t *valuep) 53 { 54 int t; 55 56 t = db_read_token(); 57 if (t == tIDENT) { 58 if (!db_value_of_name(db_tok_string, valuep) && 59 !db_value_of_name_pcpu(db_tok_string, valuep) && 60 !db_value_of_name_vnet(db_tok_string, valuep)) { 61 db_printf("Symbol '%s' not found\n", db_tok_string); 62 db_error(NULL); 63 /*NOTREACHED*/ 64 } 65 return (true); 66 } 67 if (t == tNUMBER) { 68 *valuep = (db_expr_t)db_tok_number; 69 return (true); 70 } 71 if (t == tDOT) { 72 *valuep = (db_expr_t)db_dot; 73 return (true); 74 } 75 if (t == tDOTDOT) { 76 *valuep = (db_expr_t)db_prev; 77 return (true); 78 } 79 if (t == tPLUS) { 80 *valuep = (db_expr_t) db_next; 81 return (true); 82 } 83 if (t == tDITTO) { 84 *valuep = (db_expr_t)db_last_addr; 85 return (true); 86 } 87 if (t == tDOLLAR) { 88 if (!db_get_variable(valuep)) 89 return (false); 90 return (true); 91 } 92 if (t == tLPAREN) { 93 if (!db_expression(valuep)) { 94 db_printf("Expression syntax error after '%c'\n", '('); 95 db_error(NULL); 96 /*NOTREACHED*/ 97 } 98 t = db_read_token(); 99 if (t != tRPAREN) { 100 db_printf("Expression syntax error -- expected '%c'\n", ')'); 101 db_error(NULL); 102 /*NOTREACHED*/ 103 } 104 return (true); 105 } 106 db_unread_token(t); 107 return (false); 108 } 109 110 static bool 111 db_unary(db_expr_t *valuep) 112 { 113 int t; 114 115 t = db_read_token(); 116 if (t == tMINUS) { 117 if (!db_unary(valuep)) { 118 db_printf("Expression syntax error after '%c'\n", '-'); 119 db_error(NULL); 120 /*NOTREACHED*/ 121 } 122 *valuep = -*valuep; 123 return (true); 124 } 125 if (t == tEXCL) { 126 if (!db_unary(valuep)) { 127 db_printf("Expression syntax error after '%c'\n", '!'); 128 db_error(NULL); 129 /* NOTREACHED */ 130 } 131 *valuep = (!(*valuep)); 132 return (true); 133 } 134 if (t == tBIT_NOT) { 135 if (!db_unary(valuep)) { 136 db_printf("Expression syntax error after '%c'\n", '~'); 137 db_error(NULL); 138 /* NOTREACHED */ 139 } 140 *valuep = (~(*valuep)); 141 return (true); 142 } 143 if (t == tSTAR) { 144 /* indirection */ 145 if (!db_unary(valuep)) { 146 db_printf("Expression syntax error after '%c'\n", '*'); 147 db_error(NULL); 148 /*NOTREACHED*/ 149 } 150 *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *), 151 false); 152 return (true); 153 } 154 db_unread_token(t); 155 return (db_term(valuep)); 156 } 157 158 static bool 159 db_mult_expr(db_expr_t *valuep) 160 { 161 db_expr_t lhs, rhs; 162 int t; 163 164 if (!db_unary(&lhs)) 165 return (false); 166 167 t = db_read_token(); 168 while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH || 169 t == tBIT_AND ) { 170 if (!db_term(&rhs)) { 171 db_printf("Expression syntax error after '%c'\n", 172 t == tSTAR ? '*' : t == tSLASH ? '/' : t == tPCT ? '%' : 173 t == tHASH ? '#' : '&'); 174 db_error(NULL); 175 /*NOTREACHED*/ 176 } 177 switch(t) { 178 case tSTAR: 179 lhs *= rhs; 180 break; 181 case tBIT_AND: 182 lhs &= rhs; 183 break; 184 default: 185 if (rhs == 0) { 186 db_error("Division by 0\n"); 187 /*NOTREACHED*/ 188 } 189 if (t == tSLASH) 190 lhs /= rhs; 191 else if (t == tPCT) 192 lhs %= rhs; 193 else 194 lhs = roundup(lhs, rhs); 195 } 196 t = db_read_token(); 197 } 198 db_unread_token(t); 199 *valuep = lhs; 200 return (true); 201 } 202 203 static bool 204 db_add_expr(db_expr_t *valuep) 205 { 206 db_expr_t lhs, rhs; 207 int t; 208 209 if (!db_mult_expr(&lhs)) 210 return (false); 211 212 t = db_read_token(); 213 while (t == tPLUS || t == tMINUS || t == tBIT_OR) { 214 if (!db_mult_expr(&rhs)) { 215 db_printf("Expression syntax error after '%c'\n", 216 t == tPLUS ? '+' : t == tMINUS ? '-' : '|'); 217 db_error(NULL); 218 /*NOTREACHED*/ 219 } 220 switch (t) { 221 case tPLUS: 222 lhs += rhs; 223 break; 224 case tMINUS: 225 lhs -= rhs; 226 break; 227 case tBIT_OR: 228 lhs |= rhs; 229 break; 230 default: 231 __assert_unreachable(); 232 } 233 t = db_read_token(); 234 } 235 db_unread_token(t); 236 *valuep = lhs; 237 return (true); 238 } 239 240 static bool 241 db_shift_expr(db_expr_t *valuep) 242 { 243 db_expr_t lhs, rhs; 244 int t; 245 246 if (!db_add_expr(&lhs)) 247 return (false); 248 t = db_read_token(); 249 while (t == tSHIFT_L || t == tSHIFT_R) { 250 if (!db_add_expr(&rhs)) { 251 db_printf("Expression syntax error after '%s'\n", 252 t == tSHIFT_L ? "<<" : ">>"); 253 db_error(NULL); 254 /*NOTREACHED*/ 255 } 256 if (rhs < 0) { 257 db_printf("Negative shift amount %jd\n", (intmax_t)rhs); 258 db_error(NULL); 259 /*NOTREACHED*/ 260 } 261 if (t == tSHIFT_L) 262 lhs <<= rhs; 263 else { 264 /* Shift right is unsigned */ 265 lhs = (db_addr_t)lhs >> rhs; 266 } 267 t = db_read_token(); 268 } 269 db_unread_token(t); 270 *valuep = lhs; 271 return (true); 272 } 273 274 static bool 275 db_logical_relation_expr( 276 db_expr_t *valuep) 277 { 278 db_expr_t lhs, rhs; 279 int t; 280 281 if (!db_shift_expr(&lhs)) 282 return (false); 283 284 t = db_read_token(); 285 while (t == tLOG_EQ || t == tLOG_NOT_EQ || t == tGREATER || 286 t == tGREATER_EQ || t == tLESS || t == tLESS_EQ) { 287 if (!db_shift_expr(&rhs)) { 288 db_printf("Expression syntax error after '%s'\n", 289 t == tLOG_EQ ? "==" : t == tLOG_NOT_EQ ? "!=" : 290 t == tGREATER ? ">" : t == tGREATER_EQ ? ">=" : 291 t == tLESS ? "<" : "<="); 292 db_error(NULL); 293 /*NOTREACHED*/ 294 } 295 switch(t) { 296 case tLOG_EQ: 297 lhs = (lhs == rhs); 298 break; 299 case tLOG_NOT_EQ: 300 lhs = (lhs != rhs); 301 break; 302 case tGREATER: 303 lhs = (lhs > rhs); 304 break; 305 case tGREATER_EQ: 306 lhs = (lhs >= rhs); 307 break; 308 case tLESS: 309 lhs = (lhs < rhs); 310 break; 311 case tLESS_EQ: 312 lhs = (lhs <= rhs); 313 break; 314 default: 315 __assert_unreachable(); 316 } 317 t = db_read_token(); 318 } 319 db_unread_token(t); 320 *valuep = lhs; 321 return (true); 322 } 323 324 static bool 325 db_logical_and_expr( 326 db_expr_t *valuep) 327 { 328 db_expr_t lhs, rhs; 329 int t; 330 331 if (!db_logical_relation_expr(&lhs)) 332 return (false); 333 334 t = db_read_token(); 335 while (t == tLOG_AND) { 336 if (!db_logical_relation_expr(&rhs)) { 337 db_printf("Expression syntax error after '%s'\n", "&&"); 338 db_error(NULL); 339 /*NOTREACHED*/ 340 } 341 lhs = (lhs && rhs); 342 t = db_read_token(); 343 } 344 db_unread_token(t); 345 *valuep = lhs; 346 return (true); 347 } 348 349 static bool 350 db_logical_or_expr( 351 db_expr_t *valuep) 352 { 353 db_expr_t lhs, rhs; 354 int t; 355 356 if (!db_logical_and_expr(&lhs)) 357 return(false); 358 359 t = db_read_token(); 360 while (t == tLOG_OR) { 361 if (!db_logical_and_expr(&rhs)) { 362 db_printf("Expression syntax error after '%s'\n", "||"); 363 db_error(NULL); 364 /*NOTREACHED*/ 365 } 366 lhs = (lhs || rhs); 367 t = db_read_token(); 368 } 369 db_unread_token(t); 370 *valuep = lhs; 371 return (true); 372 } 373 374 int 375 db_expression(db_expr_t *valuep) 376 { 377 return (db_logical_or_expr(valuep)); 378 } 379