7b4ac7e1 |
1 | /* Perform arithmetic and other operations on values, for GDB. |
2 | Copyright (C) 1986 Free Software Foundation, Inc. |
3 | |
4 | GDB is distributed in the hope that it will be useful, but WITHOUT ANY |
5 | WARRANTY. No author or distributor accepts responsibility to anyone |
6 | for the consequences of using it or for whether it serves any |
7 | particular purpose or works at all, unless he says so in writing. |
8 | Refer to the GDB General Public License for full details. |
9 | |
10 | Everyone is granted permission to copy, modify and redistribute GDB, |
11 | but only under the conditions described in the GDB General Public |
12 | License. A copy of this license is supposed to have been given to you |
13 | along with GDB so you can know your rights and responsibilities. It |
14 | should be in a file named COPYING. Among other things, the copyright |
15 | notice and this notice must be preserved on all copies. |
16 | |
17 | In other words, go ahead and share GDB, but don't try to stop |
18 | anyone else from sharing it farther. Help stamp out software hoarding! |
19 | */ |
20 | |
21 | #include "defs.h" |
22 | #include "initialize.h" |
23 | #include "param.h" |
24 | #include "symtab.h" |
25 | #include "value.h" |
26 | #include "expression.h" |
27 | |
28 | START_FILE |
29 | \f |
30 | value |
31 | value_add (arg1, arg2) |
32 | value arg1, arg2; |
33 | { |
34 | register value val, valint, valptr; |
35 | register int len; |
36 | |
37 | COERCE_ARRAY (arg1); |
38 | COERCE_ARRAY (arg2); |
39 | |
40 | if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR |
41 | || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR) |
42 | && |
43 | (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT |
44 | || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)) |
45 | /* Exactly one argument is a pointer, and one is an integer. */ |
46 | { |
47 | if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) |
48 | { |
49 | valptr = arg1; |
50 | valint = arg2; |
51 | } |
52 | else |
53 | { |
54 | valptr = arg2; |
55 | valint = arg1; |
56 | } |
57 | len = TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (valptr))); |
58 | if (len == 0) len = 1; /* For (void *) */ |
59 | val = value_from_long (builtin_type_long, |
60 | value_as_long (valptr) |
61 | + (len * value_as_long (valint))); |
62 | VALUE_TYPE (val) = VALUE_TYPE (valptr); |
63 | return val; |
64 | } |
65 | |
7c75bab3 |
66 | return value_binop (arg1, arg2, BINOP_ADD); |
7b4ac7e1 |
67 | } |
68 | |
69 | value |
70 | value_sub (arg1, arg2) |
71 | value arg1, arg2; |
72 | { |
73 | register value val; |
74 | |
75 | COERCE_ARRAY (arg1); |
76 | COERCE_ARRAY (arg2); |
77 | |
78 | if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR |
79 | && |
80 | TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT) |
81 | { |
82 | val = value_from_long (builtin_type_long, |
83 | value_as_long (arg1) |
84 | - TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) * value_as_long (arg2)); |
85 | VALUE_TYPE (val) = VALUE_TYPE (arg1); |
86 | return val; |
87 | } |
88 | |
89 | if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR |
90 | && |
91 | VALUE_TYPE (arg1) == VALUE_TYPE (arg2)) |
92 | { |
93 | val = value_from_long (builtin_type_long, |
94 | (value_as_long (arg1) - value_as_long (arg2)) |
95 | / TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)))); |
96 | return val; |
97 | } |
98 | |
7c75bab3 |
99 | return value_binop (arg1, arg2, BINOP_SUB); |
7b4ac7e1 |
100 | } |
101 | |
102 | /* Return the value of ARRAY[IDX]. */ |
103 | |
104 | value |
105 | value_subscript (array, idx) |
106 | value array, idx; |
107 | { |
108 | return value_ind (value_add (array, idx)); |
109 | } |
7c75bab3 |
110 | |
7b4ac7e1 |
111 | /* Perform a binary operation on two integers or two floats. |
112 | Does not support addition and subtraction on pointers; |
113 | use value_add or value_sub if you want to handle those possibilities. */ |
114 | |
115 | value |
116 | value_binop (arg1, arg2, op) |
117 | value arg1, arg2; |
118 | int op; |
119 | { |
120 | register value val; |
121 | |
122 | COERCE_ENUM (arg1); |
123 | COERCE_ENUM (arg2); |
124 | |
125 | if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT |
126 | && |
127 | TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT) |
128 | || |
129 | (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT |
130 | && |
131 | TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT)) |
132 | error ("Argument to arithmetic operation not a number."); |
133 | |
134 | if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT |
135 | || |
136 | TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT) |
137 | { |
138 | double v1, v2, v; |
139 | v1 = value_as_double (arg1); |
140 | v2 = value_as_double (arg2); |
141 | switch (op) |
142 | { |
143 | case BINOP_ADD: |
144 | v = v1 + v2; |
145 | break; |
146 | |
147 | case BINOP_SUB: |
148 | v = v1 - v2; |
149 | break; |
150 | |
151 | case BINOP_MUL: |
152 | v = v1 * v2; |
153 | break; |
154 | |
155 | case BINOP_DIV: |
156 | v = v1 / v2; |
157 | break; |
158 | |
159 | default: |
160 | error ("Integer-only operation on floating point number."); |
161 | } |
162 | |
163 | val = allocate_value (builtin_type_double); |
164 | *(double *) VALUE_CONTENTS (val) = v; |
165 | } |
166 | else |
167 | { |
168 | long v1, v2, v; |
169 | v1 = value_as_long (arg1); |
170 | v2 = value_as_long (arg2); |
171 | |
172 | switch (op) |
173 | { |
174 | case BINOP_ADD: |
175 | v = v1 + v2; |
176 | break; |
177 | |
178 | case BINOP_SUB: |
179 | v = v1 - v2; |
180 | break; |
181 | |
182 | case BINOP_MUL: |
183 | v = v1 * v2; |
184 | break; |
185 | |
186 | case BINOP_DIV: |
187 | v = v1 / v2; |
188 | break; |
189 | |
190 | case BINOP_REM: |
191 | v = v1 % v2; |
192 | break; |
193 | |
194 | case BINOP_LSH: |
195 | v = v1 << v2; |
196 | break; |
197 | |
198 | case BINOP_RSH: |
199 | v = v1 >> v2; |
200 | break; |
201 | |
202 | case BINOP_LOGAND: |
203 | v = v1 & v2; |
204 | break; |
205 | |
206 | case BINOP_LOGIOR: |
207 | v = v1 | v2; |
208 | break; |
209 | |
210 | case BINOP_LOGXOR: |
211 | v = v1 ^ v2; |
212 | break; |
213 | |
214 | case BINOP_AND: |
215 | v = v1 && v2; |
216 | break; |
217 | |
218 | case BINOP_OR: |
219 | v = v1 || v2; |
220 | break; |
221 | |
222 | default: |
223 | error ("Invalid binary operation on numbers."); |
224 | } |
225 | |
226 | val = allocate_value (builtin_type_long); |
227 | *(long *) VALUE_CONTENTS (val) = v; |
228 | } |
229 | |
230 | return val; |
231 | } |
232 | \f |
233 | /* Simulate the C operator ! -- return 1 if ARG1 contains zeros. */ |
234 | |
235 | int |
236 | value_zerop (arg1) |
237 | value arg1; |
238 | { |
239 | register int len; |
240 | register char *p; |
241 | |
242 | COERCE_ARRAY (arg1); |
243 | |
244 | len = TYPE_LENGTH (VALUE_TYPE (arg1)); |
245 | p = VALUE_CONTENTS (arg1); |
246 | |
247 | while (--len >= 0) |
248 | { |
249 | if (*p++) |
250 | break; |
251 | } |
252 | |
253 | return len < 0; |
254 | } |
255 | |
256 | /* Simulate the C operator == by returning a 1 |
257 | iff ARG1 and ARG2 have equal contents. */ |
258 | |
259 | int |
260 | value_equal (arg1, arg2) |
261 | register value arg1, arg2; |
262 | |
263 | { |
264 | register int len; |
265 | register char *p1, *p2; |
266 | enum type_code code1; |
267 | enum type_code code2; |
268 | |
269 | COERCE_ARRAY (arg1); |
270 | COERCE_ARRAY (arg2); |
271 | |
272 | code1 = TYPE_CODE (VALUE_TYPE (arg1)); |
273 | code2 = TYPE_CODE (VALUE_TYPE (arg2)); |
274 | |
275 | if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT) |
276 | return value_as_long (arg1) == value_as_long (arg2); |
277 | else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT) |
278 | && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT)) |
279 | return value_as_double (arg1) == value_as_double (arg2); |
280 | else if ((code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT) |
281 | || (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT)) |
282 | return value_as_long (arg1) == value_as_long (arg2); |
283 | else if (code1 == code2 |
284 | && ((len = TYPE_LENGTH (VALUE_TYPE (arg1))) |
285 | == TYPE_LENGTH (VALUE_TYPE (arg2)))) |
286 | { |
287 | p1 = VALUE_CONTENTS (arg1); |
288 | p2 = VALUE_CONTENTS (arg2); |
289 | while (--len >= 0) |
290 | { |
291 | if (*p1++ != *p2++) |
292 | break; |
293 | } |
294 | return len < 0; |
295 | } |
296 | else |
297 | error ("Invalid type combination in equality test."); |
298 | } |
299 | |
300 | /* Simulate the C operator < by returning 1 |
301 | iff ARG1's contents are less than ARG2's. */ |
302 | |
303 | int |
304 | value_less (arg1, arg2) |
305 | register value arg1, arg2; |
306 | { |
307 | register enum type_code code1; |
308 | register enum type_code code2; |
309 | |
310 | COERCE_ARRAY (arg1); |
311 | COERCE_ARRAY (arg2); |
312 | |
313 | code1 = TYPE_CODE (VALUE_TYPE (arg1)); |
314 | code2 = TYPE_CODE (VALUE_TYPE (arg2)); |
315 | |
316 | if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT) |
317 | return value_as_long (arg1) < value_as_long (arg2); |
318 | else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT) |
319 | && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT)) |
320 | return value_as_double (arg1) < value_as_double (arg2); |
321 | else if ((code1 == TYPE_CODE_PTR || code1 == TYPE_CODE_INT) |
322 | && (code2 == TYPE_CODE_PTR || code2 == TYPE_CODE_INT)) |
323 | return value_as_long (arg1) < value_as_long (arg2); |
324 | else |
325 | error ("Invalid type combination in ordering comparison."); |
326 | } |
327 | \f |
328 | /* The unary operators - and ~. Both free the argument ARG1. */ |
329 | |
330 | value |
331 | value_neg (arg1) |
332 | register value arg1; |
333 | { |
334 | register struct type *type; |
335 | |
336 | COERCE_ENUM (arg1); |
337 | |
338 | type = VALUE_TYPE (arg1); |
339 | |
340 | if (TYPE_CODE (type) == TYPE_CODE_FLT) |
341 | return value_from_double (type, - value_as_double (arg1)); |
342 | else if (TYPE_CODE (type) == TYPE_CODE_INT) |
343 | return value_from_long (type, - value_as_long (arg1)); |
344 | else |
345 | error ("Argument to negate operation not a number."); |
346 | } |
347 | |
348 | value |
349 | value_lognot (arg1) |
350 | register value arg1; |
351 | { |
352 | COERCE_ENUM (arg1); |
353 | |
354 | if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT) |
355 | error ("Argument to complement operation not an integer."); |
356 | |
357 | return value_from_long (VALUE_TYPE (arg1), ~ value_as_long (arg1)); |
358 | } |
359 | \f |
360 | static |
361 | initialize () |
362 | { |
363 | } |
364 | |
365 | END_FILE |