gdb-3.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 "param.h"
24 #include "expression.h"
25
26 #include <stdio.h>
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 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 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     {
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
137     case OP_LONG:
138       (*pos) += 3;
139       value_print (value_from_long (exp->elts[pc + 1].type,
140                                     exp->elts[pc + 2].longconst),
141                    stream, 0);
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),
148                    stream, 0);
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;
158       fprintf (stream, "$%d", exp->elts[pc + 1].longconst);
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++)
191         printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
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
279     default:
280       for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
281         if (op_print_tab[tem].opcode == opcode)
282           {
283             op_str = op_print_tab[tem].string;
284             myprec = op_print_tab[tem].precedence;
285             assoc = op_print_tab[tem].right_assoc;
286             break;
287           }
288     }
289
290   if ((int) myprec < (int) prec)
291     fprintf (stream, "(");
292   if ((int) opcode > (int) BINOP_END)
293     {
294       /* Unary prefix operator.  */
295       fprintf (stream, "%s", op_str);
296       print_subexp (exp, pos, stream, PREC_PREFIX);
297     }
298   else
299     {
300       /* Binary operator.  */
301       /* Print left operand.
302          If operator is right-associative,
303          increment precedence for this operand.  */
304       print_subexp (exp, pos, stream, (int) myprec + assoc);
305       /* Print the operator itself.  */
306       if (assign_modify)
307         fprintf (stream, " %s= ", op_str);
308       else if (op_str[0] == ',')
309         fprintf (stream, "%s ", op_str);
310       else
311         fprintf (stream, " %s ", op_str);
312       /* Print right operand.
313          If operator is left-associative,
314          increment precedence for this operand.  */
315       print_subexp (exp, pos, stream, (int) myprec + !assoc);
316     }
317   if ((int) myprec < (int) prec)
318     fprintf (stream, ")");
319 }