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