gdb-3.5
[deliverable/binutils-gdb.git] / gdb / expprint.c
CommitLineData
7b4ac7e1 1/* Print in infix form a struct expression.
4187119d 2 Copyright (C) 1986, 1989 Free Software Foundation, Inc.
7b4ac7e1 3
4187119d 4This file is part of GDB.
7b4ac7e1 5
4187119d 6GDB is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
7b4ac7e1 10
4187119d 11GDB is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GDB; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
7b4ac7e1 19
7a67dd45 20#include <stdio.h>
7b4ac7e1 21#include "defs.h"
22#include "symtab.h"
e91b87a3 23#include "param.h"
7b4ac7e1 24#include "expression.h"
4187119d 25#include "value.h"
7b4ac7e1 26
7b4ac7e1 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),
4187119d 141 stream, 0, Val_no_prettyprint);
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),
4187119d 148 stream, 0, Val_no_prettyprint);
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;
4187119d 158 fprintf (stream, "$%d", (int) exp->elts[pc + 1].longconst);
7b4ac7e1 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
4187119d 279 case OP_THIS:
280 ++(*pos);
281 fprintf (stream, "this");
282 return;
283
7b4ac7e1 284 default:
285 for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
286 if (op_print_tab[tem].opcode == opcode)
287 {
288 op_str = op_print_tab[tem].string;
289 myprec = op_print_tab[tem].precedence;
290 assoc = op_print_tab[tem].right_assoc;
291 break;
292 }
293 }
294
295 if ((int) myprec < (int) prec)
296 fprintf (stream, "(");
297 if ((int) opcode > (int) BINOP_END)
298 {
299 /* Unary prefix operator. */
300 fprintf (stream, "%s", op_str);
301 print_subexp (exp, pos, stream, PREC_PREFIX);
302 }
303 else
304 {
305 /* Binary operator. */
306 /* Print left operand.
307 If operator is right-associative,
308 increment precedence for this operand. */
309 print_subexp (exp, pos, stream, (int) myprec + assoc);
310 /* Print the operator itself. */
311 if (assign_modify)
312 fprintf (stream, " %s= ", op_str);
313 else if (op_str[0] == ',')
314 fprintf (stream, "%s ", op_str);
315 else
316 fprintf (stream, " %s ", op_str);
317 /* Print right operand.
318 If operator is left-associative,
319 increment precedence for this operand. */
320 print_subexp (exp, pos, stream, (int) myprec + !assoc);
321 }
322 if ((int) myprec < (int) prec)
323 fprintf (stream, ")");
324}
This page took 0.048965 seconds and 4 git commands to generate.