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