You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
10 KiB

36 years ago
/* Print in infix form a struct expression.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
36 years ago
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
36 years ago
This program is distributed in the hope that it will be useful,
36 years ago
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
36 years ago
#include <stdio.h>
#include "defs.h"
#include "symtab.h"
#include "param.h"
#include "expression.h"
#include "value.h"
/* These codes indicate operator precedences, least tightly binding first. */
/* Adding 1 to a precedence value is done for binary operators,
on the operand which is more tightly bound, so that operators
of equal precedence within that operand will get parentheses. */
/* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
they are used as the "surrounding precedence" to force
various kinds of things to be parenthesized. */
enum precedence
{ PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND,
PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER,
PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
PREC_HYPER, PREC_PREFIX, PREC_SUFFIX };
/* Table mapping opcodes into strings for printing operators
and precedences of the operators. */
struct op_print
{
char *string;
enum exp_opcode opcode;
/* Precedence of operator. These values are used only by comparisons. */
enum precedence precedence;
int right_assoc;
};
const static struct op_print op_print_tab[] =
36 years ago
{
{",", BINOP_COMMA, PREC_COMMA, 0},
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
{"||", BINOP_OR, PREC_OR, 0},
{"&&", BINOP_AND, PREC_AND, 0},
{"|", BINOP_LOGIOR, PREC_LOGIOR, 0},
{"&", BINOP_LOGAND, PREC_LOGAND, 0},
{"^", BINOP_LOGXOR, PREC_LOGXOR, 0},
{"==", BINOP_EQUAL, PREC_EQUAL, 0},
{"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
{"<=", BINOP_LEQ, PREC_ORDER, 0},
{">=", BINOP_GEQ, PREC_ORDER, 0},
{">", BINOP_GTR, PREC_ORDER, 0},
{"<", BINOP_LESS, PREC_ORDER, 0},
{">>", BINOP_RSH, PREC_SHIFT, 0},
{"<<", BINOP_LSH, PREC_SHIFT, 0},
{"+", BINOP_ADD, PREC_ADD, 0},
{"-", BINOP_SUB, PREC_ADD, 0},
{"*", BINOP_MUL, PREC_MUL, 0},
{"/", BINOP_DIV, PREC_MUL, 0},
{"%", BINOP_REM, PREC_MUL, 0},
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
{"-", UNOP_NEG, PREC_PREFIX, 0},
{"!", UNOP_ZEROP, PREC_PREFIX, 0},
{"~", UNOP_LOGNOT, PREC_PREFIX, 0},
{"*", UNOP_IND, PREC_PREFIX, 0},
{"&", UNOP_ADDR, PREC_PREFIX, 0},
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
/* C++ */
{"::", BINOP_SCOPE, PREC_PREFIX, 0},
};
static void print_subexp ();
void
print_expression (exp, stream)
struct expression *exp;
FILE *stream;
{
int pc = 0;
print_subexp (exp, &pc, stream, PREC_NULL);
}
/* Print the subexpression of EXP that starts in position POS, on STREAM.
PREC is the precedence of the surrounding operator;
if the precedence of the main operator of this subexpression is less,
parentheses are needed here. */
static void
print_subexp (exp, pos, stream, prec)
register struct expression *exp;
register int *pos;
FILE *stream;
enum precedence prec;
{
register unsigned tem;
register int pc;
unsigned nargs;
register char *op_str;
int assign_modify = 0;
enum exp_opcode opcode;
enum precedence myprec;
/* Set to 1 for a right-associative operator. */
int assoc;
pc = (*pos)++;
opcode = exp->elts[pc].opcode;
switch (opcode)
{
case OP_SCOPE:
myprec = PREC_PREFIX;
assoc = 0;
(*pos) += 2;
print_subexp (exp, pos, stream,
(enum precedence) ((int) myprec + assoc));
fputs_filtered (" :: ", stream);
36 years ago
nargs = strlen (&exp->elts[pc + 2].string);
(*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
fputs_filtered (&exp->elts[pc + 2].string, stream);
36 years ago
return;
case OP_LONG:
(*pos) += 3;
value_print (value_from_long (exp->elts[pc + 1].type,
exp->elts[pc + 2].longconst),
stream, 0, Val_no_prettyprint);
return;
case OP_DOUBLE:
(*pos) += 3;
value_print (value_from_double (exp->elts[pc + 1].type,
exp->elts[pc + 2].doubleconst),
stream, 0, Val_no_prettyprint);
return;
case OP_VAR_VALUE:
(*pos) += 2;
fputs_filtered (SYMBOL_NAME (exp->elts[pc + 1].symbol), stream);
36 years ago
return;
case OP_LAST:
(*pos) += 2;
fprintf_filtered (stream, "$%d",
longest_to_int (exp->elts[pc + 1].longconst));
36 years ago
return;
case OP_REGISTER:
(*pos) += 2;
fprintf_filtered (stream, "$%s",
longest_to_int (reg_names[exp->elts[pc + 1].longconst]));
36 years ago
return;
case OP_INTERNALVAR:
(*pos) += 2;
fprintf_filtered (stream, "$%s",
36 years ago
internalvar_name (exp->elts[pc + 1].internalvar));
return;
case OP_FUNCALL:
(*pos) += 2;
nargs = longest_to_int (exp->elts[pc + 1].longconst);
36 years ago
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered (" (", stream);
36 years ago
for (tem = 0; tem < nargs; tem++)
{
if (tem != 0)
fputs_filtered (", ", stream);
36 years ago
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
}
fputs_filtered (")", stream);
36 years ago
return;
case OP_STRING:
nargs = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
fputs_filtered ("\"", stream);
36 years ago
for (tem = 0; tem < nargs; tem++)
printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
fputs_filtered ("\"", stream);
36 years ago
return;
case TERNOP_COND:
if ((int) prec > (int) PREC_COMMA)
fputs_filtered ("(", stream);
36 years ago
/* Print the subexpressions, forcing parentheses
around any binary operations within them.
This is more parentheses than are strictly necessary,
but it looks clearer. */
print_subexp (exp, pos, stream, PREC_HYPER);
fputs_filtered (" ? ", stream);
36 years ago
print_subexp (exp, pos, stream, PREC_HYPER);
fputs_filtered (" : ", stream);
36 years ago
print_subexp (exp, pos, stream, PREC_HYPER);
if ((int) prec > (int) PREC_COMMA)
fputs_filtered (")", stream);
36 years ago
return;
case STRUCTOP_STRUCT:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered (".", stream);
fputs_filtered (&exp->elts[pc + 1].string, stream);
36 years ago
return;
case STRUCTOP_PTR:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered ("->", stream);
fputs_filtered (&exp->elts[pc + 1].string, stream);
36 years ago
return;
case BINOP_SUBSCRIPT:
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered ("[", stream);
36 years ago
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
fputs_filtered ("]", stream);
36 years ago
return;
case UNOP_POSTINCREMENT:
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered ("++", stream);
36 years ago
return;
case UNOP_POSTDECREMENT:
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered ("--", stream);
36 years ago
return;
case UNOP_CAST:
(*pos) += 2;
if ((int) prec > (int) PREC_PREFIX)
fputs_filtered ("(", stream);
fputs_filtered ("(", stream);
36 years ago
type_print (exp->elts[pc + 1].type, "", stream, 0);
fputs_filtered (") ", stream);
36 years ago
print_subexp (exp, pos, stream, PREC_PREFIX);
if ((int) prec > (int) PREC_PREFIX)
fputs_filtered (")", stream);
36 years ago
return;
case UNOP_MEMVAL:
(*pos) += 2;
if ((int) prec > (int) PREC_PREFIX)
fputs_filtered ("(", stream);
fputs_filtered ("{", stream);
36 years ago
type_print (exp->elts[pc + 1].type, "", stream, 0);
fputs_filtered ("} ", stream);
36 years ago
print_subexp (exp, pos, stream, PREC_PREFIX);
if ((int) prec > (int) PREC_PREFIX)
fputs_filtered (")", stream);
36 years ago
return;
case BINOP_ASSIGN_MODIFY:
opcode = exp->elts[pc + 1].opcode;
(*pos) += 2;
myprec = PREC_ASSIGN;
assoc = 1;
assign_modify = 1;
for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
if (op_print_tab[tem].opcode == opcode)
{
op_str = op_print_tab[tem].string;
break;
}
break;
36 years ago
case OP_THIS:
++(*pos);
fputs_filtered ("this", stream);
36 years ago
return;
default:
for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
if (op_print_tab[tem].opcode == opcode)
{
op_str = op_print_tab[tem].string;
myprec = op_print_tab[tem].precedence;
assoc = op_print_tab[tem].right_assoc;
break;
}
}
if ((int) myprec < (int) prec)
fputs_filtered ("(", stream);
36 years ago
if ((int) opcode > (int) BINOP_END)
{
/* Unary prefix operator. */
fputs_filtered (op_str, stream);
36 years ago
print_subexp (exp, pos, stream, PREC_PREFIX);
}
else
{
/* Binary operator. */
/* Print left operand.
If operator is right-associative,
increment precedence for this operand. */
print_subexp (exp, pos, stream,
(enum precedence) ((int) myprec + assoc));
36 years ago
/* Print the operator itself. */
if (assign_modify)
fprintf_filtered (stream, " %s= ", op_str);
36 years ago
else if (op_str[0] == ',')
fprintf_filtered (stream, "%s ", op_str);
36 years ago
else
fprintf_filtered (stream, " %s ", op_str);
36 years ago
/* Print right operand.
If operator is left-associative,
increment precedence for this operand. */
print_subexp (exp, pos, stream,
(enum precedence) ((int) myprec + !assoc));
36 years ago
}
if ((int) myprec < (int) prec)
fputs_filtered (")", stream);
36 years ago
}