Commit | Line | Data |
---|---|---|
bd5635a1 | 1 | /* Print in infix form a struct expression. |
28de880c | 2 | Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc. |
bd5635a1 RP |
3 | |
4 | This file is part of GDB. | |
5 | ||
10147c02 | 6 | This program is free software; you can redistribute it and/or modify |
bd5635a1 | 7 | it under the terms of the GNU General Public License as published by |
10147c02 JG |
8 | the Free Software Foundation; either version 2 of the License, or |
9 | (at your option) any later version. | |
bd5635a1 | 10 | |
10147c02 | 11 | This program is distributed in the hope that it will be useful, |
bd5635a1 RP |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
10147c02 JG |
17 | along with this program; if not, write to the Free Software |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
bd5635a1 | 19 | |
bd5635a1 RP |
20 | #include "defs.h" |
21 | #include "symtab.h" | |
28de880c | 22 | #include "gdbtypes.h" |
bd5635a1 RP |
23 | #include "expression.h" |
24 | #include "value.h" | |
28de880c JG |
25 | #include "language.h" |
26 | #include "parser-defs.h" | |
bd5635a1 | 27 | |
28de880c JG |
28 | /* Prototypes for local functions */ |
29 | ||
30 | static void | |
31 | print_subexp PARAMS ((struct expression *, int *, FILE *, enum precedence)); | |
32 | ||
33 | static void | |
34 | print_simple_m2_func PARAMS ((char *, struct expression *, int *, FILE *)); | |
bd5635a1 RP |
35 | |
36 | void | |
37 | print_expression (exp, stream) | |
38 | struct expression *exp; | |
39 | FILE *stream; | |
40 | { | |
41 | int pc = 0; | |
42 | print_subexp (exp, &pc, stream, PREC_NULL); | |
43 | } | |
44 | ||
45 | /* Print the subexpression of EXP that starts in position POS, on STREAM. | |
46 | PREC is the precedence of the surrounding operator; | |
47 | if the precedence of the main operator of this subexpression is less, | |
48 | parentheses are needed here. */ | |
49 | ||
50 | static void | |
51 | print_subexp (exp, pos, stream, prec) | |
52 | register struct expression *exp; | |
53 | register int *pos; | |
54 | FILE *stream; | |
55 | enum precedence prec; | |
56 | { | |
57 | register unsigned tem; | |
28de880c | 58 | register const struct op_print *op_print_tab; |
bd5635a1 RP |
59 | register int pc; |
60 | unsigned nargs; | |
61 | register char *op_str; | |
62 | int assign_modify = 0; | |
63 | enum exp_opcode opcode; | |
64 | enum precedence myprec; | |
65 | /* Set to 1 for a right-associative operator. */ | |
66 | int assoc; | |
28de880c | 67 | value val; |
bd5635a1 | 68 | |
28de880c | 69 | op_print_tab = exp->language_defn->la_op_print_tab; |
bd5635a1 RP |
70 | pc = (*pos)++; |
71 | opcode = exp->elts[pc].opcode; | |
72 | switch (opcode) | |
73 | { | |
28de880c JG |
74 | /* Common ops */ |
75 | ||
bd5635a1 | 76 | case OP_SCOPE: |
5d074aa9 FF |
77 | myprec = PREC_PREFIX; |
78 | assoc = 0; | |
a8a69e63 | 79 | (*pos) += 3; |
5d074aa9 FF |
80 | print_subexp (exp, pos, stream, |
81 | (enum precedence) ((int) myprec + assoc)); | |
82 | fputs_filtered (" :: ", stream); | |
a8a69e63 FF |
83 | nargs = longest_to_int (exp->elts[pc + 2].longconst); |
84 | (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element); | |
bd5635a1 | 85 | |
a8a69e63 | 86 | fputs_filtered (&exp->elts[pc + 3].string, stream); |
bd5635a1 RP |
87 | return; |
88 | ||
89 | case OP_LONG: | |
90 | (*pos) += 3; | |
28de880c | 91 | value_print (value_from_longest (exp->elts[pc + 1].type, |
a8a69e63 | 92 | exp->elts[pc + 2].longconst), |
bd5635a1 RP |
93 | stream, 0, Val_no_prettyprint); |
94 | return; | |
95 | ||
96 | case OP_DOUBLE: | |
97 | (*pos) += 3; | |
98 | value_print (value_from_double (exp->elts[pc + 1].type, | |
99 | exp->elts[pc + 2].doubleconst), | |
100 | stream, 0, Val_no_prettyprint); | |
101 | return; | |
102 | ||
103 | case OP_VAR_VALUE: | |
104 | (*pos) += 2; | |
10147c02 | 105 | fputs_filtered (SYMBOL_NAME (exp->elts[pc + 1].symbol), stream); |
bd5635a1 RP |
106 | return; |
107 | ||
108 | case OP_LAST: | |
109 | (*pos) += 2; | |
10147c02 JG |
110 | fprintf_filtered (stream, "$%d", |
111 | longest_to_int (exp->elts[pc + 1].longconst)); | |
bd5635a1 RP |
112 | return; |
113 | ||
114 | case OP_REGISTER: | |
115 | (*pos) += 2; | |
10147c02 | 116 | fprintf_filtered (stream, "$%s", |
35fcebce | 117 | reg_names[longest_to_int (exp->elts[pc + 1].longconst)]); |
bd5635a1 RP |
118 | return; |
119 | ||
5d074aa9 FF |
120 | case OP_BOOL: |
121 | (*pos) += 2; | |
122 | fprintf_filtered (stream, "%s", | |
123 | longest_to_int (exp->elts[pc + 1].longconst) | |
124 | ? "TRUE" : "FALSE"); | |
125 | return; | |
126 | ||
bd5635a1 RP |
127 | case OP_INTERNALVAR: |
128 | (*pos) += 2; | |
10147c02 | 129 | fprintf_filtered (stream, "$%s", |
bd5635a1 RP |
130 | internalvar_name (exp->elts[pc + 1].internalvar)); |
131 | return; | |
132 | ||
133 | case OP_FUNCALL: | |
134 | (*pos) += 2; | |
10147c02 | 135 | nargs = longest_to_int (exp->elts[pc + 1].longconst); |
bd5635a1 | 136 | print_subexp (exp, pos, stream, PREC_SUFFIX); |
10147c02 | 137 | fputs_filtered (" (", stream); |
bd5635a1 RP |
138 | for (tem = 0; tem < nargs; tem++) |
139 | { | |
140 | if (tem != 0) | |
10147c02 | 141 | fputs_filtered (", ", stream); |
bd5635a1 RP |
142 | print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); |
143 | } | |
10147c02 | 144 | fputs_filtered (")", stream); |
bd5635a1 RP |
145 | return; |
146 | ||
147 | case OP_STRING: | |
a8a69e63 FF |
148 | nargs = longest_to_int (exp -> elts[pc + 1].longconst); |
149 | (*pos) += 3 + (nargs + sizeof (union exp_element)) | |
150 | / sizeof (union exp_element); | |
151 | /* LA_PRINT_STRING will print using the current repeat count threshold. | |
5d074aa9 | 152 | If necessary, we can temporarily set it to zero, or pass it as an |
a8a69e63 FF |
153 | additional parameter to LA_PRINT_STRING. -fnf */ |
154 | LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 0); | |
bd5635a1 RP |
155 | return; |
156 | ||
157 | case TERNOP_COND: | |
158 | if ((int) prec > (int) PREC_COMMA) | |
10147c02 | 159 | fputs_filtered ("(", stream); |
bd5635a1 RP |
160 | /* Print the subexpressions, forcing parentheses |
161 | around any binary operations within them. | |
162 | This is more parentheses than are strictly necessary, | |
163 | but it looks clearer. */ | |
164 | print_subexp (exp, pos, stream, PREC_HYPER); | |
10147c02 | 165 | fputs_filtered (" ? ", stream); |
bd5635a1 | 166 | print_subexp (exp, pos, stream, PREC_HYPER); |
10147c02 | 167 | fputs_filtered (" : ", stream); |
bd5635a1 RP |
168 | print_subexp (exp, pos, stream, PREC_HYPER); |
169 | if ((int) prec > (int) PREC_COMMA) | |
10147c02 | 170 | fputs_filtered (")", stream); |
bd5635a1 RP |
171 | return; |
172 | ||
173 | case STRUCTOP_STRUCT: | |
a8a69e63 FF |
174 | tem = longest_to_int (exp->elts[pc + 1].longconst); |
175 | (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); | |
bd5635a1 | 176 | print_subexp (exp, pos, stream, PREC_SUFFIX); |
10147c02 | 177 | fputs_filtered (".", stream); |
a8a69e63 | 178 | fputs_filtered (&exp->elts[pc + 2].string, stream); |
bd5635a1 RP |
179 | return; |
180 | ||
28de880c | 181 | /* Will not occur for Modula-2 */ |
bd5635a1 | 182 | case STRUCTOP_PTR: |
a8a69e63 FF |
183 | tem = longest_to_int (exp->elts[pc + 1].longconst); |
184 | (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); | |
bd5635a1 | 185 | print_subexp (exp, pos, stream, PREC_SUFFIX); |
10147c02 | 186 | fputs_filtered ("->", stream); |
a8a69e63 | 187 | fputs_filtered (&exp->elts[pc + 2].string, stream); |
bd5635a1 RP |
188 | return; |
189 | ||
190 | case BINOP_SUBSCRIPT: | |
191 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
10147c02 | 192 | fputs_filtered ("[", stream); |
bd5635a1 | 193 | print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); |
10147c02 | 194 | fputs_filtered ("]", stream); |
bd5635a1 RP |
195 | return; |
196 | ||
197 | case UNOP_POSTINCREMENT: | |
198 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
10147c02 | 199 | fputs_filtered ("++", stream); |
bd5635a1 RP |
200 | return; |
201 | ||
202 | case UNOP_POSTDECREMENT: | |
203 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
10147c02 | 204 | fputs_filtered ("--", stream); |
bd5635a1 RP |
205 | return; |
206 | ||
207 | case UNOP_CAST: | |
208 | (*pos) += 2; | |
209 | if ((int) prec > (int) PREC_PREFIX) | |
10147c02 JG |
210 | fputs_filtered ("(", stream); |
211 | fputs_filtered ("(", stream); | |
bd5635a1 | 212 | type_print (exp->elts[pc + 1].type, "", stream, 0); |
10147c02 | 213 | fputs_filtered (") ", stream); |
bd5635a1 RP |
214 | print_subexp (exp, pos, stream, PREC_PREFIX); |
215 | if ((int) prec > (int) PREC_PREFIX) | |
10147c02 | 216 | fputs_filtered (")", stream); |
bd5635a1 RP |
217 | return; |
218 | ||
219 | case UNOP_MEMVAL: | |
220 | (*pos) += 2; | |
221 | if ((int) prec > (int) PREC_PREFIX) | |
10147c02 | 222 | fputs_filtered ("(", stream); |
28de880c JG |
223 | if (exp->elts[pc + 1].type->code == TYPE_CODE_FUNC && |
224 | exp->elts[pc + 3].opcode == OP_LONG) { | |
225 | /* We have a minimal symbol fn, probably. It's encoded | |
226 | as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address). | |
227 | Swallow the OP_LONG (including both its opcodes); ignore | |
228 | its type; print the value in the type of the MEMVAL. */ | |
229 | (*pos) += 4; | |
230 | val = value_at_lazy (exp->elts[pc + 1].type, | |
231 | (CORE_ADDR) exp->elts[pc + 5].longconst); | |
232 | value_print (val, stream, 0, Val_no_prettyprint); | |
233 | } else { | |
234 | fputs_filtered ("{", stream); | |
235 | type_print (exp->elts[pc + 1].type, "", stream, 0); | |
236 | fputs_filtered ("} ", stream); | |
237 | print_subexp (exp, pos, stream, PREC_PREFIX); | |
238 | } | |
bd5635a1 | 239 | if ((int) prec > (int) PREC_PREFIX) |
10147c02 | 240 | fputs_filtered (")", stream); |
bd5635a1 RP |
241 | return; |
242 | ||
243 | case BINOP_ASSIGN_MODIFY: | |
244 | opcode = exp->elts[pc + 1].opcode; | |
245 | (*pos) += 2; | |
246 | myprec = PREC_ASSIGN; | |
247 | assoc = 1; | |
248 | assign_modify = 1; | |
28de880c JG |
249 | op_str = "???"; |
250 | for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++) | |
bd5635a1 RP |
251 | if (op_print_tab[tem].opcode == opcode) |
252 | { | |
253 | op_str = op_print_tab[tem].string; | |
254 | break; | |
255 | } | |
81919cc8 | 256 | break; |
bd5635a1 | 257 | |
28de880c JG |
258 | /* C++ ops */ |
259 | ||
bd5635a1 RP |
260 | case OP_THIS: |
261 | ++(*pos); | |
10147c02 | 262 | fputs_filtered ("this", stream); |
bd5635a1 RP |
263 | return; |
264 | ||
28de880c JG |
265 | /* Modula-2 ops */ |
266 | ||
267 | case BINOP_MULTI_SUBSCRIPT: | |
268 | (*pos) += 2; | |
269 | nargs = longest_to_int (exp->elts[pc + 1].longconst); | |
270 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
271 | fprintf (stream, " ["); | |
272 | for (tem = 0; tem < nargs; tem++) | |
273 | { | |
274 | if (tem != 0) | |
275 | fprintf (stream, ", "); | |
276 | print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); | |
277 | } | |
278 | fprintf (stream, "]"); | |
279 | return; | |
280 | ||
281 | case BINOP_VAL: | |
282 | (*pos)+=2; | |
283 | fprintf(stream,"VAL("); | |
284 | type_print(exp->elts[pc+1].type,"",stream,0); | |
285 | fprintf(stream,","); | |
286 | print_subexp(exp,pos,stream,PREC_PREFIX); | |
287 | fprintf(stream,")"); | |
288 | return; | |
289 | ||
290 | case UNOP_CAP: | |
291 | print_simple_m2_func("CAP",exp,pos,stream); | |
292 | return; | |
293 | ||
294 | case UNOP_CHR: | |
295 | print_simple_m2_func("CHR",exp,pos,stream); | |
296 | return; | |
297 | ||
298 | case UNOP_ORD: | |
299 | print_simple_m2_func("ORD",exp,pos,stream); | |
300 | return; | |
301 | ||
302 | case UNOP_ABS: | |
303 | print_simple_m2_func("ABS",exp,pos,stream); | |
304 | return; | |
305 | ||
306 | case UNOP_FLOAT: | |
307 | print_simple_m2_func("FLOAT",exp,pos,stream); | |
308 | return; | |
309 | ||
310 | case UNOP_HIGH: | |
311 | print_simple_m2_func("HIGH",exp,pos,stream); | |
312 | return; | |
313 | ||
314 | case UNOP_MAX: | |
315 | print_simple_m2_func("MAX",exp,pos,stream); | |
316 | return; | |
317 | ||
318 | case UNOP_MIN: | |
319 | print_simple_m2_func("MIN",exp,pos,stream); | |
320 | return; | |
321 | ||
322 | case UNOP_ODD: | |
323 | print_simple_m2_func("ODD",exp,pos,stream); | |
324 | return; | |
325 | ||
326 | case UNOP_TRUNC: | |
327 | print_simple_m2_func("TRUNC",exp,pos,stream); | |
328 | return; | |
329 | ||
330 | case BINOP_INCL: | |
331 | case BINOP_EXCL: | |
332 | error("print_subexp: Not implemented."); | |
333 | ||
334 | /* Default ops */ | |
335 | ||
bd5635a1 | 336 | default: |
28de880c JG |
337 | op_str = "???"; |
338 | for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++) | |
bd5635a1 RP |
339 | if (op_print_tab[tem].opcode == opcode) |
340 | { | |
341 | op_str = op_print_tab[tem].string; | |
342 | myprec = op_print_tab[tem].precedence; | |
343 | assoc = op_print_tab[tem].right_assoc; | |
344 | break; | |
345 | } | |
28de880c | 346 | } |
bd5635a1 RP |
347 | |
348 | if ((int) myprec < (int) prec) | |
10147c02 | 349 | fputs_filtered ("(", stream); |
bd5635a1 RP |
350 | if ((int) opcode > (int) BINOP_END) |
351 | { | |
352 | /* Unary prefix operator. */ | |
10147c02 | 353 | fputs_filtered (op_str, stream); |
bd5635a1 RP |
354 | print_subexp (exp, pos, stream, PREC_PREFIX); |
355 | } | |
356 | else | |
357 | { | |
358 | /* Binary operator. */ | |
359 | /* Print left operand. | |
360 | If operator is right-associative, | |
361 | increment precedence for this operand. */ | |
10147c02 JG |
362 | print_subexp (exp, pos, stream, |
363 | (enum precedence) ((int) myprec + assoc)); | |
bd5635a1 RP |
364 | /* Print the operator itself. */ |
365 | if (assign_modify) | |
10147c02 | 366 | fprintf_filtered (stream, " %s= ", op_str); |
bd5635a1 | 367 | else if (op_str[0] == ',') |
10147c02 | 368 | fprintf_filtered (stream, "%s ", op_str); |
bd5635a1 | 369 | else |
10147c02 | 370 | fprintf_filtered (stream, " %s ", op_str); |
bd5635a1 RP |
371 | /* Print right operand. |
372 | If operator is left-associative, | |
373 | increment precedence for this operand. */ | |
10147c02 JG |
374 | print_subexp (exp, pos, stream, |
375 | (enum precedence) ((int) myprec + !assoc)); | |
bd5635a1 | 376 | } |
28de880c | 377 | |
bd5635a1 | 378 | if ((int) myprec < (int) prec) |
10147c02 | 379 | fputs_filtered (")", stream); |
bd5635a1 | 380 | } |
28de880c JG |
381 | |
382 | /* Print out something of the form <s>(<arg>). | |
383 | This is used to print out some builtin Modula-2 | |
384 | functions. | |
385 | FIXME: There is probably some way to get the precedence | |
386 | rules to do this (print a unary operand with parens around it). */ | |
387 | static void | |
388 | print_simple_m2_func(s,exp,pos,stream) | |
389 | char *s; | |
390 | register struct expression *exp; | |
391 | register int *pos; | |
392 | FILE *stream; | |
393 | { | |
394 | fprintf(stream,"%s(",s); | |
395 | print_subexp(exp,pos,stream,PREC_PREFIX); | |
396 | fprintf(stream,")"); | |
397 | } | |
398 | ||
399 | /* Return the operator corresponding to opcode OP as | |
400 | a string. NULL indicates that the opcode was not found in the | |
401 | current language table. */ | |
402 | char * | |
403 | op_string(op) | |
404 | enum exp_opcode op; | |
405 | { | |
406 | int tem; | |
407 | register const struct op_print *op_print_tab; | |
408 | ||
409 | op_print_tab = current_language->la_op_print_tab; | |
410 | for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++) | |
411 | if (op_print_tab[tem].opcode == op) | |
412 | return op_print_tab[tem].string; | |
413 | return NULL; | |
414 | } |