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