]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/expprint.c
gdb-2.4+.aux.coff
[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 "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 };
84 \f
85 static void print_subexp ();
86
87 void
88 print_expression (exp, stream)
89 struct expression *exp;
90 FILE *stream;
91 {
92 int pc = 0;
93 print_subexp (exp, &pc, stream, PREC_NULL);
94 }
95
96 /* Print the subexpression of EXP that starts in position POS, on STREAM.
97 PREC is the precedence of the surrounding operator;
98 if the precedence of the main operator of this subexpression is less,
99 parentheses are needed here. */
100
101 static void
102 print_subexp (exp, pos, stream, prec)
103 register struct expression *exp;
104 register int *pos;
105 FILE *stream;
106 enum precedence prec;
107 {
108 register int tem;
109 register int pc;
110 int nargs;
111 register char *op_str;
112 int assign_modify = 0;
113 enum exp_opcode opcode;
114 enum precedence myprec;
115 /* Set to 1 for a right-associative operator. */
116 int assoc;
117
118 pc = (*pos)++;
119 opcode = exp->elts[pc].opcode;
120 switch (opcode)
121 {
122 case OP_LONG:
123 (*pos) += 3;
124 value_print (value_from_long (exp->elts[pc + 1].type,
125 exp->elts[pc + 2].longconst),
126 stream);
127 return;
128
129 case OP_DOUBLE:
130 (*pos) += 3;
131 value_print (value_from_double (exp->elts[pc + 1].type,
132 exp->elts[pc + 2].doubleconst),
133 stream);
134 return;
135
136 case OP_VAR_VALUE:
137 (*pos) += 2;
138 fprintf (stream, "%s", SYMBOL_NAME (exp->elts[pc + 1].symbol));
139 return;
140
141 case OP_LAST:
142 (*pos) += 2;
143 fprintf (stream, "$%d", exp->elts[pc + 1].longconst);
144 return;
145
146 case OP_REGISTER:
147 (*pos) += 2;
148 fprintf (stream, "$%s", reg_names[exp->elts[pc + 1].longconst]);
149 return;
150
151 case OP_INTERNALVAR:
152 (*pos) += 2;
153 fprintf (stream, "$%s",
154 internalvar_name (exp->elts[pc + 1].internalvar));
155 return;
156
157 case OP_FUNCALL:
158 (*pos) += 2;
159 nargs = exp->elts[pc + 1].longconst;
160 print_subexp (exp, pos, stream, PREC_SUFFIX);
161 fprintf (stream, " (");
162 for (tem = 0; tem < nargs; tem++)
163 {
164 if (tem > 0)
165 fprintf (stream, ", ");
166 print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
167 }
168 fprintf (stream, ")");
169 return;
170
171 case OP_STRING:
172 nargs = strlen (&exp->elts[pc + 1].string);
173 (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
174 fprintf (stream, "\"");
175 for (tem = 0; tem < nargs; tem++)
176 printchar ((&exp->elts[pc + 1].string)[tem], stream);
177 fprintf (stream, "\"");
178 return;
179
180 case TERNOP_COND:
181 if ((int) prec > (int) PREC_COMMA)
182 fprintf (stream, "(");
183 /* Print the subexpressions, forcing parentheses
184 around any binary operations within them.
185 This is more parentheses than are strictly necessary,
186 but it looks clearer. */
187 print_subexp (exp, pos, stream, PREC_HYPER);
188 fprintf (stream, " ? ");
189 print_subexp (exp, pos, stream, PREC_HYPER);
190 fprintf (stream, " : ");
191 print_subexp (exp, pos, stream, PREC_HYPER);
192 if ((int) prec > (int) PREC_COMMA)
193 fprintf (stream, ")");
194 return;
195
196 case STRUCTOP_STRUCT:
197 tem = strlen (&exp->elts[pc + 1].string);
198 (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
199 print_subexp (exp, pos, stream, PREC_SUFFIX);
200 fprintf (stream, ".%s", &exp->elts[pc + 1].string);
201 return;
202
203 case STRUCTOP_PTR:
204 tem = strlen (&exp->elts[pc + 1].string);
205 (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
206 print_subexp (exp, pos, stream, PREC_SUFFIX);
207 fprintf (stream, "->%s", &exp->elts[pc + 1].string);
208 return;
209
210 case BINOP_SUBSCRIPT:
211 print_subexp (exp, pos, stream, PREC_SUFFIX);
212 fprintf (stream, "[");
213 print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
214 fprintf (stream, "]");
215 return;
216
217 case UNOP_POSTINCREMENT:
218 print_subexp (exp, pos, stream, PREC_SUFFIX);
219 fprintf (stream, "++");
220 return;
221
222 case UNOP_POSTDECREMENT:
223 print_subexp (exp, pos, stream, PREC_SUFFIX);
224 fprintf (stream, "--");
225 return;
226
227 case UNOP_CAST:
228 (*pos) += 2;
229 if ((int) prec > (int) PREC_PREFIX)
230 fprintf (stream, "(");
231 fprintf (stream, "(");
232 type_print (exp->elts[pc + 1].type, "", stream, 0);
233 fprintf (stream, ") ");
234 print_subexp (exp, pos, stream, PREC_PREFIX);
235 if ((int) prec > (int) PREC_PREFIX)
236 fprintf (stream, ")");
237 return;
238
239 case UNOP_MEMVAL:
240 (*pos) += 2;
241 if ((int) prec > (int) PREC_PREFIX)
242 fprintf (stream, "(");
243 fprintf (stream, "{");
244 type_print (exp->elts[pc + 1].type, "", stream, 0);
245 fprintf (stream, "} ");
246 print_subexp (exp, pos, stream, PREC_PREFIX);
247 if ((int) prec > (int) PREC_PREFIX)
248 fprintf (stream, ")");
249 return;
250
251 case BINOP_ASSIGN_MODIFY:
252 opcode = exp->elts[pc + 1].opcode;
253 (*pos) += 2;
254 myprec = PREC_ASSIGN;
255 assoc = 1;
256 assign_modify = 1;
257 for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
258 if (op_print_tab[tem].opcode == opcode)
259 {
260 op_str = op_print_tab[tem].string;
261 break;
262 }
263
264 default:
265 for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
266 if (op_print_tab[tem].opcode == opcode)
267 {
268 op_str = op_print_tab[tem].string;
269 myprec = op_print_tab[tem].precedence;
270 assoc = op_print_tab[tem].right_assoc;
271 break;
272 }
273 }
274
275 if ((int) myprec < (int) prec)
276 fprintf (stream, "(");
277 if ((int) opcode > (int) BINOP_END)
278 {
279 /* Unary prefix operator. */
280 fprintf (stream, "%s", op_str);
281 print_subexp (exp, pos, stream, PREC_PREFIX);
282 }
283 else
284 {
285 /* Binary operator. */
286 /* Print left operand.
287 If operator is right-associative,
288 increment precedence for this operand. */
289 print_subexp (exp, pos, stream, (int) myprec + assoc);
290 /* Print the operator itself. */
291 if (assign_modify)
292 fprintf (stream, " %s= ", op_str);
293 else if (op_str[0] == ',')
294 fprintf (stream, "%s ", op_str);
295 else
296 fprintf (stream, " %s ", op_str);
297 /* Print right operand.
298 If operator is left-associative,
299 increment precedence for this operand. */
300 print_subexp (exp, pos, stream, (int) myprec + !assoc);
301 }
302 if ((int) myprec < (int) prec)
303 fprintf (stream, ")");
304 }