]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/expprint.c
gdb-3.1
[thirdparty/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 "param.h"
24 #include "expression.h"
25
26 #include <stdio.h>
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
53 static struct op_print op_print_tab[] =
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 int tem;
112 register int pc;
113 int 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;
129 print_subexp (exp, pos, stream, (int) myprec + assoc);
130 fprintf (stream, " :: ");
131 nargs = strlen (&exp->elts[pc + 2].string);
132 (*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
133
134 fprintf (stream, &exp->elts[pc + 2].string);
135 return;
136
137 case OP_LONG:
138 (*pos) += 3;
139 value_print (value_from_long (exp->elts[pc + 1].type,
140 exp->elts[pc + 2].longconst),
141 stream, 0);
142 return;
143
144 case OP_DOUBLE:
145 (*pos) += 3;
146 value_print (value_from_double (exp->elts[pc + 1].type,
147 exp->elts[pc + 2].doubleconst),
148 stream, 0);
149 return;
150
151 case OP_VAR_VALUE:
152 (*pos) += 2;
153 fprintf (stream, "%s", SYMBOL_NAME (exp->elts[pc + 1].symbol));
154 return;
155
156 case OP_LAST:
157 (*pos) += 2;
158 fprintf (stream, "$%d", exp->elts[pc + 1].longconst);
159 return;
160
161 case OP_REGISTER:
162 (*pos) += 2;
163 fprintf (stream, "$%s", reg_names[exp->elts[pc + 1].longconst]);
164 return;
165
166 case OP_INTERNALVAR:
167 (*pos) += 2;
168 fprintf (stream, "$%s",
169 internalvar_name (exp->elts[pc + 1].internalvar));
170 return;
171
172 case OP_FUNCALL:
173 (*pos) += 2;
174 nargs = exp->elts[pc + 1].longconst;
175 print_subexp (exp, pos, stream, PREC_SUFFIX);
176 fprintf (stream, " (");
177 for (tem = 0; tem < nargs; tem++)
178 {
179 if (tem > 0)
180 fprintf (stream, ", ");
181 print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
182 }
183 fprintf (stream, ")");
184 return;
185
186 case OP_STRING:
187 nargs = strlen (&exp->elts[pc + 1].string);
188 (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
189 fprintf (stream, "\"");
190 for (tem = 0; tem < nargs; tem++)
191 printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
192 fprintf (stream, "\"");
193 return;
194
195 case TERNOP_COND:
196 if ((int) prec > (int) PREC_COMMA)
197 fprintf (stream, "(");
198 /* Print the subexpressions, forcing parentheses
199 around any binary operations within them.
200 This is more parentheses than are strictly necessary,
201 but it looks clearer. */
202 print_subexp (exp, pos, stream, PREC_HYPER);
203 fprintf (stream, " ? ");
204 print_subexp (exp, pos, stream, PREC_HYPER);
205 fprintf (stream, " : ");
206 print_subexp (exp, pos, stream, PREC_HYPER);
207 if ((int) prec > (int) PREC_COMMA)
208 fprintf (stream, ")");
209 return;
210
211 case STRUCTOP_STRUCT:
212 tem = strlen (&exp->elts[pc + 1].string);
213 (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
214 print_subexp (exp, pos, stream, PREC_SUFFIX);
215 fprintf (stream, ".%s", &exp->elts[pc + 1].string);
216 return;
217
218 case STRUCTOP_PTR:
219 tem = strlen (&exp->elts[pc + 1].string);
220 (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
221 print_subexp (exp, pos, stream, PREC_SUFFIX);
222 fprintf (stream, "->%s", &exp->elts[pc + 1].string);
223 return;
224
225 case BINOP_SUBSCRIPT:
226 print_subexp (exp, pos, stream, PREC_SUFFIX);
227 fprintf (stream, "[");
228 print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
229 fprintf (stream, "]");
230 return;
231
232 case UNOP_POSTINCREMENT:
233 print_subexp (exp, pos, stream, PREC_SUFFIX);
234 fprintf (stream, "++");
235 return;
236
237 case UNOP_POSTDECREMENT:
238 print_subexp (exp, pos, stream, PREC_SUFFIX);
239 fprintf (stream, "--");
240 return;
241
242 case UNOP_CAST:
243 (*pos) += 2;
244 if ((int) prec > (int) PREC_PREFIX)
245 fprintf (stream, "(");
246 fprintf (stream, "(");
247 type_print (exp->elts[pc + 1].type, "", stream, 0);
248 fprintf (stream, ") ");
249 print_subexp (exp, pos, stream, PREC_PREFIX);
250 if ((int) prec > (int) PREC_PREFIX)
251 fprintf (stream, ")");
252 return;
253
254 case UNOP_MEMVAL:
255 (*pos) += 2;
256 if ((int) prec > (int) PREC_PREFIX)
257 fprintf (stream, "(");
258 fprintf (stream, "{");
259 type_print (exp->elts[pc + 1].type, "", stream, 0);
260 fprintf (stream, "} ");
261 print_subexp (exp, pos, stream, PREC_PREFIX);
262 if ((int) prec > (int) PREC_PREFIX)
263 fprintf (stream, ")");
264 return;
265
266 case BINOP_ASSIGN_MODIFY:
267 opcode = exp->elts[pc + 1].opcode;
268 (*pos) += 2;
269 myprec = PREC_ASSIGN;
270 assoc = 1;
271 assign_modify = 1;
272 for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
273 if (op_print_tab[tem].opcode == opcode)
274 {
275 op_str = op_print_tab[tem].string;
276 break;
277 }
278
279 default:
280 for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
281 if (op_print_tab[tem].opcode == opcode)
282 {
283 op_str = op_print_tab[tem].string;
284 myprec = op_print_tab[tem].precedence;
285 assoc = op_print_tab[tem].right_assoc;
286 break;
287 }
288 }
289
290 if ((int) myprec < (int) prec)
291 fprintf (stream, "(");
292 if ((int) opcode > (int) BINOP_END)
293 {
294 /* Unary prefix operator. */
295 fprintf (stream, "%s", op_str);
296 print_subexp (exp, pos, stream, PREC_PREFIX);
297 }
298 else
299 {
300 /* Binary operator. */
301 /* Print left operand.
302 If operator is right-associative,
303 increment precedence for this operand. */
304 print_subexp (exp, pos, stream, (int) myprec + assoc);
305 /* Print the operator itself. */
306 if (assign_modify)
307 fprintf (stream, " %s= ", op_str);
308 else if (op_str[0] == ',')
309 fprintf (stream, "%s ", op_str);
310 else
311 fprintf (stream, " %s ", op_str);
312 /* Print right operand.
313 If operator is left-associative,
314 increment precedence for this operand. */
315 print_subexp (exp, pos, stream, (int) myprec + !assoc);
316 }
317 if ((int) myprec < (int) prec)
318 fprintf (stream, ")");
319 }