gdb-3.1
[deliverable/binutils-gdb.git] / gdb / expprint.c
CommitLineData
7b4ac7e1 1/* Print in infix form a struct expression.
2 Copyright (C) 1986 Free Software Foundation, Inc.
3
4GDB is distributed in the hope that it will be useful, but WITHOUT ANY
5WARRANTY. No author or distributor accepts responsibility to anyone
6for the consequences of using it or for whether it serves any
7particular purpose or works at all, unless he says so in writing.
8Refer to the GDB General Public License for full details.
9
10Everyone is granted permission to copy, modify and redistribute GDB,
11but only under the conditions described in the GDB General Public
12License. A copy of this license is supposed to have been given to you
13along with GDB so you can know your rights and responsibilities. It
14should be in a file named COPYING. Among other things, the copyright
15notice and this notice must be preserved on all copies.
16
17In other words, go ahead and share GDB, but don't try to stop
18anyone else from sharing it farther. Help stamp out software hoarding!
19*/
20
21#include "defs.h"
22#include "symtab.h"
e91b87a3 23#include "param.h"
7b4ac7e1 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. */
35enum 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
44struct 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
53static 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},
e91b87a3 83 {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
84 /* C++ */
85 {"::", BINOP_SCOPE, PREC_PREFIX, 0},
7b4ac7e1 86 };
87\f
88static void print_subexp ();
89
90void
91print_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
104static void
105print_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 {
e91b87a3 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
7b4ac7e1 137 case OP_LONG:
138 (*pos) += 3;
139 value_print (value_from_long (exp->elts[pc + 1].type,
140 exp->elts[pc + 2].longconst),
3bf57d21 141 stream, 0);
7b4ac7e1 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),
3bf57d21 148 stream, 0);
7b4ac7e1 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++)
3bf57d21 191 printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
7b4ac7e1 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}
This page took 0.036388 seconds and 4 git commands to generate.