]>
Commit | Line | Data |
---|---|---|
bd5635a1 RP |
1 | /* Print in infix form a struct expression. |
2 | Copyright (C) 1986, 1989 Free Software Foundation, Inc. | |
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 RP |
19 | |
20 | #include <stdio.h> | |
21 | #include "defs.h" | |
22 | #include "symtab.h" | |
23 | #include "param.h" | |
24 | #include "expression.h" | |
25 | #include "value.h" | |
26 | ||
27 | \f | |
28 | /* These codes indicate operator precedences, least tightly binding first. */ | |
29 | /* Adding 1 to a precedence value is done for binary operators, | |
30 | on the operand which is more tightly bound, so that operators | |
31 | of equal precedence within that operand will get parentheses. */ | |
32 | /* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator; | |
33 | they are used as the "surrounding precedence" to force | |
34 | various kinds of things to be parenthesized. */ | |
35 | enum precedence | |
36 | { PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND, | |
37 | PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER, | |
38 | PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT, | |
39 | PREC_HYPER, PREC_PREFIX, PREC_SUFFIX }; | |
40 | ||
41 | /* Table mapping opcodes into strings for printing operators | |
42 | and precedences of the operators. */ | |
43 | ||
44 | struct op_print | |
45 | { | |
46 | char *string; | |
47 | enum exp_opcode opcode; | |
48 | /* Precedence of operator. These values are used only by comparisons. */ | |
49 | enum precedence precedence; | |
50 | int right_assoc; | |
51 | }; | |
52 | ||
81919cc8 | 53 | const static struct op_print op_print_tab[] = |
bd5635a1 RP |
54 | { |
55 | {",", BINOP_COMMA, PREC_COMMA, 0}, | |
56 | {"=", BINOP_ASSIGN, PREC_ASSIGN, 1}, | |
57 | {"||", BINOP_OR, PREC_OR, 0}, | |
58 | {"&&", BINOP_AND, PREC_AND, 0}, | |
59 | {"|", BINOP_LOGIOR, PREC_LOGIOR, 0}, | |
60 | {"&", BINOP_LOGAND, PREC_LOGAND, 0}, | |
61 | {"^", BINOP_LOGXOR, PREC_LOGXOR, 0}, | |
62 | {"==", BINOP_EQUAL, PREC_EQUAL, 0}, | |
63 | {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0}, | |
64 | {"<=", BINOP_LEQ, PREC_ORDER, 0}, | |
65 | {">=", BINOP_GEQ, PREC_ORDER, 0}, | |
66 | {">", BINOP_GTR, PREC_ORDER, 0}, | |
67 | {"<", BINOP_LESS, PREC_ORDER, 0}, | |
68 | {">>", BINOP_RSH, PREC_SHIFT, 0}, | |
69 | {"<<", BINOP_LSH, PREC_SHIFT, 0}, | |
70 | {"+", BINOP_ADD, PREC_ADD, 0}, | |
71 | {"-", BINOP_SUB, PREC_ADD, 0}, | |
72 | {"*", BINOP_MUL, PREC_MUL, 0}, | |
73 | {"/", BINOP_DIV, PREC_MUL, 0}, | |
74 | {"%", BINOP_REM, PREC_MUL, 0}, | |
75 | {"@", BINOP_REPEAT, PREC_REPEAT, 0}, | |
76 | {"-", UNOP_NEG, PREC_PREFIX, 0}, | |
77 | {"!", UNOP_ZEROP, PREC_PREFIX, 0}, | |
78 | {"~", UNOP_LOGNOT, PREC_PREFIX, 0}, | |
79 | {"*", UNOP_IND, PREC_PREFIX, 0}, | |
80 | {"&", UNOP_ADDR, PREC_PREFIX, 0}, | |
81 | {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0}, | |
82 | {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0}, | |
83 | {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}, | |
84 | /* C++ */ | |
85 | {"::", BINOP_SCOPE, PREC_PREFIX, 0}, | |
86 | }; | |
87 | \f | |
88 | static void print_subexp (); | |
89 | ||
90 | void | |
91 | print_expression (exp, stream) | |
92 | struct expression *exp; | |
93 | FILE *stream; | |
94 | { | |
95 | int pc = 0; | |
96 | print_subexp (exp, &pc, stream, PREC_NULL); | |
97 | } | |
98 | ||
99 | /* Print the subexpression of EXP that starts in position POS, on STREAM. | |
100 | PREC is the precedence of the surrounding operator; | |
101 | if the precedence of the main operator of this subexpression is less, | |
102 | parentheses are needed here. */ | |
103 | ||
104 | static void | |
105 | print_subexp (exp, pos, stream, prec) | |
106 | register struct expression *exp; | |
107 | register int *pos; | |
108 | FILE *stream; | |
109 | enum precedence prec; | |
110 | { | |
111 | register unsigned tem; | |
112 | register int pc; | |
113 | unsigned nargs; | |
114 | register char *op_str; | |
115 | int assign_modify = 0; | |
116 | enum exp_opcode opcode; | |
117 | enum precedence myprec; | |
118 | /* Set to 1 for a right-associative operator. */ | |
119 | int assoc; | |
120 | ||
121 | pc = (*pos)++; | |
122 | opcode = exp->elts[pc].opcode; | |
123 | switch (opcode) | |
124 | { | |
125 | case OP_SCOPE: | |
126 | myprec = PREC_PREFIX; | |
127 | assoc = 0; | |
128 | (*pos) += 2; | |
10147c02 JG |
129 | print_subexp (exp, pos, stream, |
130 | (enum precedence) ((int) myprec + assoc)); | |
131 | fputs_filtered (" :: ", stream); | |
bd5635a1 RP |
132 | nargs = strlen (&exp->elts[pc + 2].string); |
133 | (*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element); | |
134 | ||
10147c02 | 135 | fputs_filtered (&exp->elts[pc + 2].string, stream); |
bd5635a1 RP |
136 | return; |
137 | ||
138 | case OP_LONG: | |
139 | (*pos) += 3; | |
140 | value_print (value_from_long (exp->elts[pc + 1].type, | |
141 | exp->elts[pc + 2].longconst), | |
142 | stream, 0, Val_no_prettyprint); | |
143 | return; | |
144 | ||
145 | case OP_DOUBLE: | |
146 | (*pos) += 3; | |
147 | value_print (value_from_double (exp->elts[pc + 1].type, | |
148 | exp->elts[pc + 2].doubleconst), | |
149 | stream, 0, Val_no_prettyprint); | |
150 | return; | |
151 | ||
152 | case OP_VAR_VALUE: | |
153 | (*pos) += 2; | |
10147c02 | 154 | fputs_filtered (SYMBOL_NAME (exp->elts[pc + 1].symbol), stream); |
bd5635a1 RP |
155 | return; |
156 | ||
157 | case OP_LAST: | |
158 | (*pos) += 2; | |
10147c02 JG |
159 | fprintf_filtered (stream, "$%d", |
160 | longest_to_int (exp->elts[pc + 1].longconst)); | |
bd5635a1 RP |
161 | return; |
162 | ||
163 | case OP_REGISTER: | |
164 | (*pos) += 2; | |
10147c02 JG |
165 | fprintf_filtered (stream, "$%s", |
166 | longest_to_int (reg_names[exp->elts[pc + 1].longconst])); | |
bd5635a1 RP |
167 | return; |
168 | ||
169 | case OP_INTERNALVAR: | |
170 | (*pos) += 2; | |
10147c02 | 171 | fprintf_filtered (stream, "$%s", |
bd5635a1 RP |
172 | internalvar_name (exp->elts[pc + 1].internalvar)); |
173 | return; | |
174 | ||
175 | case OP_FUNCALL: | |
176 | (*pos) += 2; | |
10147c02 | 177 | nargs = longest_to_int (exp->elts[pc + 1].longconst); |
bd5635a1 | 178 | print_subexp (exp, pos, stream, PREC_SUFFIX); |
10147c02 | 179 | fputs_filtered (" (", stream); |
bd5635a1 RP |
180 | for (tem = 0; tem < nargs; tem++) |
181 | { | |
182 | if (tem != 0) | |
10147c02 | 183 | fputs_filtered (", ", stream); |
bd5635a1 RP |
184 | print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); |
185 | } | |
10147c02 | 186 | fputs_filtered (")", stream); |
bd5635a1 RP |
187 | return; |
188 | ||
189 | case OP_STRING: | |
190 | nargs = strlen (&exp->elts[pc + 1].string); | |
191 | (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element); | |
10147c02 | 192 | fputs_filtered ("\"", stream); |
bd5635a1 RP |
193 | for (tem = 0; tem < nargs; tem++) |
194 | printchar ((&exp->elts[pc + 1].string)[tem], stream, '"'); | |
10147c02 | 195 | fputs_filtered ("\"", stream); |
bd5635a1 RP |
196 | return; |
197 | ||
198 | case TERNOP_COND: | |
199 | if ((int) prec > (int) PREC_COMMA) | |
10147c02 | 200 | fputs_filtered ("(", stream); |
bd5635a1 RP |
201 | /* Print the subexpressions, forcing parentheses |
202 | around any binary operations within them. | |
203 | This is more parentheses than are strictly necessary, | |
204 | but it looks clearer. */ | |
205 | print_subexp (exp, pos, stream, PREC_HYPER); | |
10147c02 | 206 | fputs_filtered (" ? ", stream); |
bd5635a1 | 207 | print_subexp (exp, pos, stream, PREC_HYPER); |
10147c02 | 208 | fputs_filtered (" : ", stream); |
bd5635a1 RP |
209 | print_subexp (exp, pos, stream, PREC_HYPER); |
210 | if ((int) prec > (int) PREC_COMMA) | |
10147c02 | 211 | fputs_filtered (")", stream); |
bd5635a1 RP |
212 | return; |
213 | ||
214 | case STRUCTOP_STRUCT: | |
215 | tem = strlen (&exp->elts[pc + 1].string); | |
216 | (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); | |
217 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
10147c02 JG |
218 | fputs_filtered (".", stream); |
219 | fputs_filtered (&exp->elts[pc + 1].string, stream); | |
bd5635a1 RP |
220 | return; |
221 | ||
222 | case STRUCTOP_PTR: | |
223 | tem = strlen (&exp->elts[pc + 1].string); | |
224 | (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); | |
225 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
10147c02 JG |
226 | fputs_filtered ("->", stream); |
227 | fputs_filtered (&exp->elts[pc + 1].string, stream); | |
bd5635a1 RP |
228 | return; |
229 | ||
230 | case BINOP_SUBSCRIPT: | |
231 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
10147c02 | 232 | fputs_filtered ("[", stream); |
bd5635a1 | 233 | print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); |
10147c02 | 234 | fputs_filtered ("]", stream); |
bd5635a1 RP |
235 | return; |
236 | ||
237 | case UNOP_POSTINCREMENT: | |
238 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
10147c02 | 239 | fputs_filtered ("++", stream); |
bd5635a1 RP |
240 | return; |
241 | ||
242 | case UNOP_POSTDECREMENT: | |
243 | print_subexp (exp, pos, stream, PREC_SUFFIX); | |
10147c02 | 244 | fputs_filtered ("--", stream); |
bd5635a1 RP |
245 | return; |
246 | ||
247 | case UNOP_CAST: | |
248 | (*pos) += 2; | |
249 | if ((int) prec > (int) PREC_PREFIX) | |
10147c02 JG |
250 | fputs_filtered ("(", stream); |
251 | fputs_filtered ("(", stream); | |
bd5635a1 | 252 | type_print (exp->elts[pc + 1].type, "", stream, 0); |
10147c02 | 253 | fputs_filtered (") ", stream); |
bd5635a1 RP |
254 | print_subexp (exp, pos, stream, PREC_PREFIX); |
255 | if ((int) prec > (int) PREC_PREFIX) | |
10147c02 | 256 | fputs_filtered (")", stream); |
bd5635a1 RP |
257 | return; |
258 | ||
259 | case UNOP_MEMVAL: | |
260 | (*pos) += 2; | |
261 | if ((int) prec > (int) PREC_PREFIX) | |
10147c02 JG |
262 | fputs_filtered ("(", stream); |
263 | fputs_filtered ("{", stream); | |
bd5635a1 | 264 | type_print (exp->elts[pc + 1].type, "", stream, 0); |
10147c02 | 265 | fputs_filtered ("} ", stream); |
bd5635a1 RP |
266 | print_subexp (exp, pos, stream, PREC_PREFIX); |
267 | if ((int) prec > (int) PREC_PREFIX) | |
10147c02 | 268 | fputs_filtered (")", stream); |
bd5635a1 RP |
269 | return; |
270 | ||
271 | case BINOP_ASSIGN_MODIFY: | |
272 | opcode = exp->elts[pc + 1].opcode; | |
273 | (*pos) += 2; | |
274 | myprec = PREC_ASSIGN; | |
275 | assoc = 1; | |
276 | assign_modify = 1; | |
277 | for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++) | |
278 | if (op_print_tab[tem].opcode == opcode) | |
279 | { | |
280 | op_str = op_print_tab[tem].string; | |
281 | break; | |
282 | } | |
81919cc8 | 283 | break; |
bd5635a1 RP |
284 | |
285 | case OP_THIS: | |
286 | ++(*pos); | |
10147c02 | 287 | fputs_filtered ("this", stream); |
bd5635a1 RP |
288 | return; |
289 | ||
290 | default: | |
291 | for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++) | |
292 | if (op_print_tab[tem].opcode == opcode) | |
293 | { | |
294 | op_str = op_print_tab[tem].string; | |
295 | myprec = op_print_tab[tem].precedence; | |
296 | assoc = op_print_tab[tem].right_assoc; | |
297 | break; | |
298 | } | |
299 | } | |
300 | ||
301 | if ((int) myprec < (int) prec) | |
10147c02 | 302 | fputs_filtered ("(", stream); |
bd5635a1 RP |
303 | if ((int) opcode > (int) BINOP_END) |
304 | { | |
305 | /* Unary prefix operator. */ | |
10147c02 | 306 | fputs_filtered (op_str, stream); |
bd5635a1 RP |
307 | print_subexp (exp, pos, stream, PREC_PREFIX); |
308 | } | |
309 | else | |
310 | { | |
311 | /* Binary operator. */ | |
312 | /* Print left operand. | |
313 | If operator is right-associative, | |
314 | increment precedence for this operand. */ | |
10147c02 JG |
315 | print_subexp (exp, pos, stream, |
316 | (enum precedence) ((int) myprec + assoc)); | |
bd5635a1 RP |
317 | /* Print the operator itself. */ |
318 | if (assign_modify) | |
10147c02 | 319 | fprintf_filtered (stream, " %s= ", op_str); |
bd5635a1 | 320 | else if (op_str[0] == ',') |
10147c02 | 321 | fprintf_filtered (stream, "%s ", op_str); |
bd5635a1 | 322 | else |
10147c02 | 323 | fprintf_filtered (stream, " %s ", op_str); |
bd5635a1 RP |
324 | /* Print right operand. |
325 | If operator is left-associative, | |
326 | increment precedence for this operand. */ | |
10147c02 JG |
327 | print_subexp (exp, pos, stream, |
328 | (enum precedence) ((int) myprec + !assoc)); | |
bd5635a1 RP |
329 | } |
330 | if ((int) myprec < (int) prec) | |
10147c02 | 331 | fputs_filtered (")", stream); |
bd5635a1 | 332 | } |