xref: /386bsd/usr/src/usr.bin/gdb/expprint.c (revision a2142627)
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 GDB 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 1, or (at your option)
9 any later version.
10 
11 GDB 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 GDB; see the file COPYING.  If not, write to
18 the Free Software Foundation, 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 
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 
88 static void print_subexp ();
89 
90 void
print_expression(exp,stream)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
print_subexp(exp,pos,stream,prec)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, Val_no_prettyprint);
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, Val_no_prettyprint);
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", (int) 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     case OP_THIS:
280       ++(*pos);
281       fprintf (stream, "this");
282       return;
283 
284     default:
285       for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
286 	if (op_print_tab[tem].opcode == opcode)
287 	  {
288 	    op_str = op_print_tab[tem].string;
289 	    myprec = op_print_tab[tem].precedence;
290 	    assoc = op_print_tab[tem].right_assoc;
291 	    break;
292 	  }
293     }
294 
295   if ((int) myprec < (int) prec)
296     fprintf (stream, "(");
297   if ((int) opcode > (int) BINOP_END)
298     {
299       /* Unary prefix operator.  */
300       fprintf (stream, "%s", op_str);
301       print_subexp (exp, pos, stream, PREC_PREFIX);
302     }
303   else
304     {
305       /* Binary operator.  */
306       /* Print left operand.
307 	 If operator is right-associative,
308 	 increment precedence for this operand.  */
309       print_subexp (exp, pos, stream, (int) myprec + assoc);
310       /* Print the operator itself.  */
311       if (assign_modify)
312 	fprintf (stream, " %s= ", op_str);
313       else if (op_str[0] == ',')
314 	fprintf (stream, "%s ", op_str);
315       else
316 	fprintf (stream, " %s ", op_str);
317       /* Print right operand.
318 	 If operator is left-associative,
319 	 increment precedence for this operand.  */
320       print_subexp (exp, pos, stream, (int) myprec + !assoc);
321     }
322   if ((int) myprec < (int) prec)
323     fprintf (stream, ")");
324 }
325