* infrun.c: Move DO_DEFERRED_STORES from proceed() to resume().
[platform/upstream/binutils.git] / gdb / expprint.c
1 /* Print in infix form a struct expression.
2    Copyright (C) 1986, 1989 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <stdio.h>
21 #include "defs.h"
22 #include "symtab.h"
23 #include "param.h"
24 #include "expression.h"
25 #include "value.h"
26
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 const 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 unsigned tem;
112   register int pc;
113   unsigned 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,
130                     (enum precedence) ((int) myprec + assoc));
131       fputs_filtered (" :: ", stream);
132       nargs = strlen (&exp->elts[pc + 2].string);
133       (*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
134
135       fputs_filtered (&exp->elts[pc + 2].string, stream);
136       return;
137
138     case OP_LONG:
139       (*pos) += 3;
140       value_print (value_from_long (exp->elts[pc + 1].type,
141                                     exp->elts[pc + 2].longconst),
142                    stream, 0, Val_no_prettyprint);
143       return;
144
145     case OP_DOUBLE:
146       (*pos) += 3;
147       value_print (value_from_double (exp->elts[pc + 1].type,
148                                       exp->elts[pc + 2].doubleconst),
149                    stream, 0, Val_no_prettyprint);
150       return;
151
152     case OP_VAR_VALUE:
153       (*pos) += 2;
154       fputs_filtered (SYMBOL_NAME (exp->elts[pc + 1].symbol), stream);
155       return;
156
157     case OP_LAST:
158       (*pos) += 2;
159       fprintf_filtered (stream, "$%d",
160                         longest_to_int (exp->elts[pc + 1].longconst));
161       return;
162
163     case OP_REGISTER:
164       (*pos) += 2;
165       fprintf_filtered (stream, "$%s",
166                longest_to_int (reg_names[exp->elts[pc + 1].longconst]));
167       return;
168
169     case OP_INTERNALVAR:
170       (*pos) += 2;
171       fprintf_filtered (stream, "$%s",
172                internalvar_name (exp->elts[pc + 1].internalvar));
173       return;
174
175     case OP_FUNCALL:
176       (*pos) += 2;
177       nargs = longest_to_int (exp->elts[pc + 1].longconst);
178       print_subexp (exp, pos, stream, PREC_SUFFIX);
179       fputs_filtered (" (", stream);
180       for (tem = 0; tem < nargs; tem++)
181         {
182           if (tem != 0)
183             fputs_filtered (", ", stream);
184           print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
185         }
186       fputs_filtered (")", stream);
187       return;
188
189     case OP_STRING:
190       nargs = strlen (&exp->elts[pc + 1].string);
191       (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
192       fputs_filtered ("\"", stream);
193       for (tem = 0; tem < nargs; tem++)
194         printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
195       fputs_filtered ("\"", stream);
196       return;
197
198     case TERNOP_COND:
199       if ((int) prec > (int) PREC_COMMA)
200         fputs_filtered ("(", stream);
201       /* Print the subexpressions, forcing parentheses
202          around any binary operations within them.
203          This is more parentheses than are strictly necessary,
204          but it looks clearer.  */
205       print_subexp (exp, pos, stream, PREC_HYPER);
206       fputs_filtered (" ? ", stream);
207       print_subexp (exp, pos, stream, PREC_HYPER);
208       fputs_filtered (" : ", stream);
209       print_subexp (exp, pos, stream, PREC_HYPER);
210       if ((int) prec > (int) PREC_COMMA)
211         fputs_filtered (")", stream);
212       return;
213
214     case STRUCTOP_STRUCT:
215       tem = strlen (&exp->elts[pc + 1].string);
216       (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
217       print_subexp (exp, pos, stream, PREC_SUFFIX);
218       fputs_filtered (".", stream);
219       fputs_filtered (&exp->elts[pc + 1].string, stream);
220       return;
221
222     case STRUCTOP_PTR:
223       tem = strlen (&exp->elts[pc + 1].string);
224       (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
225       print_subexp (exp, pos, stream, PREC_SUFFIX);
226       fputs_filtered ("->", stream);
227       fputs_filtered (&exp->elts[pc + 1].string, stream);
228       return;
229
230     case BINOP_SUBSCRIPT:
231       print_subexp (exp, pos, stream, PREC_SUFFIX);
232       fputs_filtered ("[", stream);
233       print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
234       fputs_filtered ("]", stream);
235       return;
236
237     case UNOP_POSTINCREMENT:
238       print_subexp (exp, pos, stream, PREC_SUFFIX);
239       fputs_filtered ("++", stream);
240       return;
241
242     case UNOP_POSTDECREMENT:
243       print_subexp (exp, pos, stream, PREC_SUFFIX);
244       fputs_filtered ("--", stream);
245       return;
246
247     case UNOP_CAST:
248       (*pos) += 2;
249       if ((int) prec > (int) PREC_PREFIX)
250         fputs_filtered ("(", stream);
251       fputs_filtered ("(", stream);
252       type_print (exp->elts[pc + 1].type, "", stream, 0);
253       fputs_filtered (") ", stream);
254       print_subexp (exp, pos, stream, PREC_PREFIX);
255       if ((int) prec > (int) PREC_PREFIX)
256         fputs_filtered (")", stream);
257       return;
258
259     case UNOP_MEMVAL:
260       (*pos) += 2;
261       if ((int) prec > (int) PREC_PREFIX)
262         fputs_filtered ("(", stream);
263       fputs_filtered ("{", stream);
264       type_print (exp->elts[pc + 1].type, "", stream, 0);
265       fputs_filtered ("} ", stream);
266       print_subexp (exp, pos, stream, PREC_PREFIX);
267       if ((int) prec > (int) PREC_PREFIX)
268         fputs_filtered (")", stream);
269       return;
270
271     case BINOP_ASSIGN_MODIFY:
272       opcode = exp->elts[pc + 1].opcode;
273       (*pos) += 2;
274       myprec = PREC_ASSIGN;
275       assoc = 1;
276       assign_modify = 1;
277       for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
278         if (op_print_tab[tem].opcode == opcode)
279           {
280             op_str = op_print_tab[tem].string;
281             break;
282           }
283       break;
284
285     case OP_THIS:
286       ++(*pos);
287       fputs_filtered ("this", stream);
288       return;
289
290     default:
291       for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
292         if (op_print_tab[tem].opcode == opcode)
293           {
294             op_str = op_print_tab[tem].string;
295             myprec = op_print_tab[tem].precedence;
296             assoc = op_print_tab[tem].right_assoc;
297             break;
298           }
299     }
300
301   if ((int) myprec < (int) prec)
302     fputs_filtered ("(", stream);
303   if ((int) opcode > (int) BINOP_END)
304     {
305       /* Unary prefix operator.  */
306       fputs_filtered (op_str, stream);
307       print_subexp (exp, pos, stream, PREC_PREFIX);
308     }
309   else
310     {
311       /* Binary operator.  */
312       /* Print left operand.
313          If operator is right-associative,
314          increment precedence for this operand.  */
315       print_subexp (exp, pos, stream,
316                     (enum precedence) ((int) myprec + assoc));
317       /* Print the operator itself.  */
318       if (assign_modify)
319         fprintf_filtered (stream, " %s= ", op_str);
320       else if (op_str[0] == ',')
321         fprintf_filtered (stream, "%s ", op_str);
322       else
323         fprintf_filtered (stream, " %s ", op_str);
324       /* Print right operand.
325          If operator is left-associative,
326          increment precedence for this operand.  */
327       print_subexp (exp, pos, stream,
328                     (enum precedence) ((int) myprec + !assoc));
329     }
330   if ((int) myprec < (int) prec)
331     fputs_filtered (")", stream);
332 }