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
41static boolean_t	db_add_expr(db_expr_t *valuep);
42static boolean_t	db_mult_expr(db_expr_t *valuep);
43static boolean_t	db_shift_expr(db_expr_t *valuep);
44static boolean_t	db_term(db_expr_t *valuep);
45static boolean_t	db_unary(db_expr_t *valuep);
46
47static boolean_t
48db_term(db_expr_t *valuep)
49{
50	int	t;
51
52	t = db_read_token();
53	if (t == tIDENT) {
54	    if (!db_value_of_name(db_tok_string, valuep) &&
55		!db_value_of_name_pcpu(db_tok_string, valuep) &&
56		!db_value_of_name_vnet(db_tok_string, valuep)) {
57		db_error("Symbol not found\n");
58		/*NOTREACHED*/
59	    }
60	    return (TRUE);
61	}
62	if (t == tNUMBER) {
63	    *valuep = (db_expr_t)db_tok_number;
64	    return (TRUE);
65	}
66	if (t == tDOT) {
67	    *valuep = (db_expr_t)db_dot;
68	    return (TRUE);
69	}
70	if (t == tDOTDOT) {
71	    *valuep = (db_expr_t)db_prev;
72	    return (TRUE);
73	}
74	if (t == tPLUS) {
75	    *valuep = (db_expr_t) db_next;
76	    return (TRUE);
77	}
78	if (t == tDITTO) {
79	    *valuep = (db_expr_t)db_last_addr;
80	    return (TRUE);
81	}
82	if (t == tDOLLAR) {
83	    if (!db_get_variable(valuep))
84		return (FALSE);
85	    return (TRUE);
86	}
87	if (t == tLPAREN) {
88	    if (!db_expression(valuep)) {
89		db_error("Syntax error\n");
90		/*NOTREACHED*/
91	    }
92	    t = db_read_token();
93	    if (t != tRPAREN) {
94		db_error("Syntax error\n");
95		/*NOTREACHED*/
96	    }
97	    return (TRUE);
98	}
99	db_unread_token(t);
100	return (FALSE);
101}
102
103static boolean_t
104db_unary(db_expr_t *valuep)
105{
106	int	t;
107
108	t = db_read_token();
109	if (t == tMINUS) {
110	    if (!db_unary(valuep)) {
111		db_error("Syntax error\n");
112		/*NOTREACHED*/
113	    }
114	    *valuep = -*valuep;
115	    return (TRUE);
116	}
117	if (t == tSTAR) {
118	    /* indirection */
119	    if (!db_unary(valuep)) {
120		db_error("Syntax error\n");
121		/*NOTREACHED*/
122	    }
123	    *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *), FALSE);
124	    return (TRUE);
125	}
126	db_unread_token(t);
127	return (db_term(valuep));
128}
129
130static boolean_t
131db_mult_expr(db_expr_t *valuep)
132{
133	db_expr_t	lhs, rhs;
134	int		t;
135
136	if (!db_unary(&lhs))
137	    return (FALSE);
138
139	t = db_read_token();
140	while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) {
141	    if (!db_term(&rhs)) {
142		db_error("Syntax error\n");
143		/*NOTREACHED*/
144	    }
145	    if (t == tSTAR)
146		lhs *= rhs;
147	    else {
148		if (rhs == 0) {
149		    db_error("Divide by 0\n");
150		    /*NOTREACHED*/
151		}
152		if (t == tSLASH)
153		    lhs /= rhs;
154		else if (t == tPCT)
155		    lhs %= rhs;
156		else
157		    lhs = ((lhs+rhs-1)/rhs)*rhs;
158	    }
159	    t = db_read_token();
160	}
161	db_unread_token(t);
162	*valuep = lhs;
163	return (TRUE);
164}
165
166static boolean_t
167db_add_expr(db_expr_t *valuep)
168{
169	db_expr_t	lhs, rhs;
170	int		t;
171
172	if (!db_mult_expr(&lhs))
173	    return (FALSE);
174
175	t = db_read_token();
176	while (t == tPLUS || t == tMINUS) {
177	    if (!db_mult_expr(&rhs)) {
178		db_error("Syntax error\n");
179		/*NOTREACHED*/
180	    }
181	    if (t == tPLUS)
182		lhs += rhs;
183	    else
184		lhs -= rhs;
185	    t = db_read_token();
186	}
187	db_unread_token(t);
188	*valuep = lhs;
189	return (TRUE);
190}
191
192static boolean_t
193db_shift_expr(db_expr_t *valuep)
194{
195	db_expr_t	lhs, rhs;
196	int		t;
197
198	if (!db_add_expr(&lhs))
199	    return (FALSE);
200
201	t = db_read_token();
202	while (t == tSHIFT_L || t == tSHIFT_R) {
203	    if (!db_add_expr(&rhs)) {
204		db_error("Syntax error\n");
205		/*NOTREACHED*/
206	    }
207	    if (rhs < 0) {
208		db_error("Negative shift amount\n");
209		/*NOTREACHED*/
210	    }
211	    if (t == tSHIFT_L)
212		lhs <<= rhs;
213	    else {
214		/* Shift right is unsigned */
215		lhs = (unsigned) lhs >> rhs;
216	    }
217	    t = db_read_token();
218	}
219	db_unread_token(t);
220	*valuep = lhs;
221	return (TRUE);
222}
223
224int
225db_expression(db_expr_t *valuep)
226{
227	return (db_shift_expr(valuep));
228}
229