gdb-2.8
[platform/upstream/binutils.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, 0);
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, 0);
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 }