1/* $NetBSD: db_expr.c,v 1.15 2007/02/22 06:41:01 thorpej Exp $ */ 2 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 "AS IS" 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 * Author: David B. Golub, Carnegie Mellon University 29 * Date: 7/90 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: db_expr.c,v 1.15 2007/02/22 06:41:01 thorpej Exp $"); 34 35#include <sys/param.h> 36#include <sys/proc.h> 37 38#include <ddb/ddb.h> 39 40static bool db_term(db_expr_t *); 41static bool db_unary(db_expr_t *); 42static bool db_mult_expr(db_expr_t *); 43static bool db_add_expr(db_expr_t *); 44static bool db_shift_expr(db_expr_t *); 45 46static bool 47db_term(db_expr_t *valuep) 48{ 49 int t; 50 51 t = db_read_token(); 52 if (t == tIDENT) { 53 if (!db_value_of_name(db_tok_string, valuep)) { 54 db_expr_t v = 0; 55 int i, c, byte; 56 57 /* See if we can make a number out of all of it */ 58 for (i = 0; (c = db_tok_string[i]) != '\0'; i++) { 59 byte = 0; 60 if (c >= '0' && c <= '9') 61 byte = c - '0'; 62 else if (db_radix == 16 && c >= 'a' && c <= 'f') 63 byte = c - 'a' + 10; 64 else if (db_radix == 16 && c >= 'A' && c <= 'F') 65 byte = c - 'A' + 10; 66 else 67 db_error("Symbol not found\n"); 68 /*NOTREACHED*/ 69 v = v * db_radix + byte; 70 } 71 *valuep = (db_expr_t)v; 72 } 73 return (true); 74 } 75 if (t == tNUMBER) { 76 *valuep = (db_expr_t)db_tok_number; 77 return (true); 78 } 79 if (t == tDOT) { 80 *valuep = (db_expr_t)db_dot; 81 return (true); 82 } 83 if (t == tDOTDOT) { 84 *valuep = (db_expr_t)db_prev; 85 return (true); 86 } 87 if (t == tPLUS) { 88 *valuep = (db_expr_t) db_next; 89 return (true); 90 } 91 if (t == tDITTO) { 92 *valuep = (db_expr_t)db_last_addr; 93 return (true); 94 } 95 if (t == tDOLLAR) { 96 if (!db_get_variable(valuep)) 97 return (false); 98 return (true); 99 } 100 if (t == tLPAREN) { 101 if (!db_expression(valuep)) { 102 db_error("Syntax error\n"); 103 /*NOTREACHED*/ 104 } 105 t = db_read_token(); 106 if (t != tRPAREN) { 107 db_error("Syntax error\n"); 108 /*NOTREACHED*/ 109 } 110 return (true); 111 } 112 db_unread_token(t); 113 return (false); 114} 115 116static bool 117db_unary(db_expr_t *valuep) 118{ 119 int t; 120 121 t = db_read_token(); 122 if (t == tMINUS) { 123 if (!db_unary(valuep)) { 124 db_error("Syntax error\n"); 125 /*NOTREACHED*/ 126 } 127 *valuep = -*valuep; 128 return (true); 129 } 130 if (t == tSTAR) { 131 /* indirection */ 132 if (!db_unary(valuep)) { 133 db_error("Syntax error\n"); 134 /*NOTREACHED*/ 135 } 136 *valuep = db_get_value((db_addr_t)*valuep, sizeof(db_expr_t), 137 false); 138 return (true); 139 } 140 db_unread_token(t); 141 return (db_term(valuep)); 142} 143 144static bool 145db_mult_expr(db_expr_t *valuep) 146{ 147 db_expr_t lhs, rhs; 148 int t; 149 150 if (!db_unary(&lhs)) 151 return (false); 152 153 t = db_read_token(); 154 while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) { 155 if (!db_term(&rhs)) { 156 db_error("Syntax error\n"); 157 /*NOTREACHED*/ 158 } 159 if (t == tSTAR) 160 lhs *= rhs; 161 else { 162 if (rhs == 0) { 163 db_error("Divide by 0\n"); 164 /*NOTREACHED*/ 165 } 166 if (t == tSLASH) 167 lhs /= rhs; 168 else if (t == tPCT) 169 lhs %= rhs; 170 else 171 lhs = ((lhs+rhs-1)/rhs)*rhs; 172 } 173 t = db_read_token(); 174 } 175 db_unread_token(t); 176 *valuep = lhs; 177 return (true); 178} 179 180static bool 181db_add_expr(db_expr_t *valuep) 182{ 183 db_expr_t lhs, rhs; 184 int t; 185 186 if (!db_mult_expr(&lhs)) 187 return (false); 188 189 t = db_read_token(); 190 while (t == tPLUS || t == tMINUS) { 191 if (!db_mult_expr(&rhs)) { 192 db_error("Syntax error\n"); 193 /*NOTREACHED*/ 194 } 195 if (t == tPLUS) 196 lhs += rhs; 197 else 198 lhs -= rhs; 199 t = db_read_token(); 200 } 201 db_unread_token(t); 202 *valuep = lhs; 203 return (true); 204} 205 206static bool 207db_shift_expr(db_expr_t *valuep) 208{ 209 db_expr_t lhs, rhs; 210 int t; 211 212 if (!db_add_expr(&lhs)) 213 return (false); 214 215 t = db_read_token(); 216 while (t == tSHIFT_L || t == tSHIFT_R) { 217 if (!db_add_expr(&rhs)) { 218 db_error("Syntax error\n"); 219 /*NOTREACHED*/ 220 } 221 if (rhs < 0) { 222 db_error("Negative shift amount\n"); 223 /*NOTREACHED*/ 224 } 225 if (t == tSHIFT_L) 226 lhs <<= rhs; 227 else { 228 /* Shift right is unsigned */ 229 lhs = (unsigned long) lhs >> rhs; 230 } 231 t = db_read_token(); 232 } 233 db_unread_token(t); 234 *valuep = lhs; 235 return (true); 236} 237 238int 239db_expression(db_expr_t *valuep) 240{ 241 242 return (db_shift_expr(valuep)); 243} 244