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