Merge branch 'vendor/FILE'
[dragonfly.git] / sys / ddb / db_expr.c
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  * $FreeBSD: src/sys/ddb/db_expr.c,v 1.13 1999/08/28 00:41:07 peter Exp $
27  * $DragonFly: src/sys/ddb/db_expr.c,v 1.4 2005/12/23 21:35:44 swildner Exp $
28  */
29
30 /*
31  *      Author: David B. Golub, Carnegie Mellon University
32  *      Date:   7/90
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 boolean_t        db_add_expr (db_expr_t *valuep);
42 static boolean_t        db_mult_expr (db_expr_t *valuep);
43 static boolean_t        db_shift_expr (db_expr_t *valuep);
44 static boolean_t        db_term (db_expr_t *valuep);
45 static boolean_t        db_unary (db_expr_t *valuep);
46
47 static boolean_t
48 db_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_error("Symbol not found\n");
56                 /*NOTREACHED*/
57             }
58             return (TRUE);
59         }
60         if (t == tNUMBER) {
61             *valuep = (db_expr_t)db_tok_number;
62             return (TRUE);
63         }
64         if (t == tDOT) {
65             *valuep = (db_expr_t)db_dot;
66             return (TRUE);
67         }
68         if (t == tDOTDOT) {
69             *valuep = (db_expr_t)db_prev;
70             return (TRUE);
71         }
72         if (t == tPLUS) {
73             *valuep = (db_expr_t) db_next;
74             return (TRUE);
75         }
76         if (t == tDITTO) {
77             *valuep = (db_expr_t)db_last_addr;
78             return (TRUE);
79         }
80         if (t == tDOLLAR) {
81             if (!db_get_variable(valuep))
82                 return (FALSE);
83             return (TRUE);
84         }
85         if (t == tLPAREN) {
86             if (!db_expression(valuep)) {
87                 db_error("Syntax error\n");
88                 /*NOTREACHED*/
89             }
90             t = db_read_token();
91             if (t != tRPAREN) {
92                 db_error("Syntax error\n");
93                 /*NOTREACHED*/
94             }
95             return (TRUE);
96         }
97         db_unread_token(t);
98         return (FALSE);
99 }
100
101 static boolean_t
102 db_unary(db_expr_t *valuep)
103 {
104         int     t;
105
106         t = db_read_token();
107         if (t == tMINUS) {
108             if (!db_unary(valuep)) {
109                 db_error("Syntax error\n");
110                 /*NOTREACHED*/
111             }
112             *valuep = -*valuep;
113             return (TRUE);
114         }
115         if (t == tSTAR) {
116             /* indirection */
117             if (!db_unary(valuep)) {
118                 db_error("Syntax error\n");
119                 /*NOTREACHED*/
120             }
121             *valuep = db_get_value((db_addr_t)*valuep, sizeof(int), FALSE);
122             return (TRUE);
123         }
124         db_unread_token(t);
125         return (db_term(valuep));
126 }
127
128 static boolean_t
129 db_mult_expr(db_expr_t *valuep)
130 {
131         db_expr_t       lhs, rhs;
132         int             t;
133
134         *valuep = 0;    /* silence gcc */
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
166 static boolean_t
167 db_add_expr(db_expr_t *valuep)
168 {
169         db_expr_t       lhs, rhs;
170         int             t;
171
172         *valuep = 0;    /* silence gcc */
173
174         if (!db_mult_expr(&lhs))
175             return (FALSE);
176
177         t = db_read_token();
178         while (t == tPLUS || t == tMINUS) {
179             if (!db_mult_expr(&rhs)) {
180                 db_error("Syntax error\n");
181                 /*NOTREACHED*/
182             }
183             if (t == tPLUS)
184                 lhs += rhs;
185             else
186                 lhs -= rhs;
187             t = db_read_token();
188         }
189         db_unread_token(t);
190         *valuep = lhs;
191         return (TRUE);
192 }
193
194 static boolean_t
195 db_shift_expr(db_expr_t *valuep)
196 {
197         db_expr_t       lhs, rhs;
198         int             t;
199
200         if (!db_add_expr(&lhs))
201             return (FALSE);
202
203         t = db_read_token();
204         while (t == tSHIFT_L || t == tSHIFT_R) {
205             if (!db_add_expr(&rhs)) {
206                 db_error("Syntax error\n");
207                 /*NOTREACHED*/
208             }
209             if (rhs < 0) {
210                 db_error("Negative shift amount\n");
211                 /*NOTREACHED*/
212             }
213             if (t == tSHIFT_L)
214                 lhs <<= rhs;
215             else {
216                 /* Shift right is unsigned */
217                 lhs = (unsigned) lhs >> rhs;
218             }
219             t = db_read_token();
220         }
221         db_unread_token(t);
222         *valuep = lhs;
223         return (TRUE);
224 }
225
226 int
227 db_expression(db_expr_t *valuep)
228 {
229         return (db_shift_expr(valuep));
230 }