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