/* Print in infix form a struct expression.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
GDB is distributed in the hope that it will be useful,
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 GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* 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. */
{ 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. */
/* Precedence of operator. These values are used only by comparisons. */
enum precedence precedence
;
static struct op_print op_print_tab
[] =
{",", 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},
{"::", BINOP_SCOPE
, PREC_PREFIX
, 0},
static void print_subexp ();
print_expression (exp
, stream
)
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. */
print_subexp (exp
, pos
, stream
, prec
)
register struct expression
*exp
;
/* Set to 1 for a right-associative operator. */
opcode
= exp
->elts
[pc
].opcode
;
print_subexp (exp
, pos
, stream
, (int) myprec
+ assoc
);
fprintf (stream
, " :: ");
nargs
= strlen (&exp
->elts
[pc
+ 2].string
);
(*pos
) += 1 + (nargs
+ sizeof (union exp_element
)) / sizeof (union exp_element
);
fprintf (stream
, &exp
->elts
[pc
+ 2].string
);
value_print (value_from_long (exp
->elts
[pc
+ 1].type
,
exp
->elts
[pc
+ 2].longconst
),
stream
, 0, Val_no_prettyprint
);
value_print (value_from_double (exp
->elts
[pc
+ 1].type
,
exp
->elts
[pc
+ 2].doubleconst
),
stream
, 0, Val_no_prettyprint
);
fprintf (stream
, "%s", SYMBOL_NAME (exp
->elts
[pc
+ 1].symbol
));
fprintf (stream
, "$%d", (int) exp
->elts
[pc
+ 1].longconst
);
fprintf (stream
, "$%s", reg_names
[exp
->elts
[pc
+ 1].longconst
]);
internalvar_name (exp
->elts
[pc
+ 1].internalvar
));
nargs
= exp
->elts
[pc
+ 1].longconst
;
print_subexp (exp
, pos
, stream
, PREC_SUFFIX
);
for (tem
= 0; tem
< nargs
; tem
++)
print_subexp (exp
, pos
, stream
, PREC_ABOVE_COMMA
);
nargs
= strlen (&exp
->elts
[pc
+ 1].string
);
(*pos
) += 2 + (nargs
+ sizeof (union exp_element
)) / sizeof (union exp_element
);
for (tem
= 0; tem
< nargs
; tem
++)
printchar ((&exp
->elts
[pc
+ 1].string
)[tem
], stream
, '"');
if ((int) prec
> (int) PREC_COMMA
)
/* Print the subexpressions, forcing parentheses
around any binary operations within them.
This is more parentheses than are strictly necessary,
print_subexp (exp
, pos
, stream
, PREC_HYPER
);
print_subexp (exp
, pos
, stream
, PREC_HYPER
);
print_subexp (exp
, pos
, stream
, PREC_HYPER
);
if ((int) prec
> (int) PREC_COMMA
)
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
);
fprintf (stream
, ".%s", &exp
->elts
[pc
+ 1].string
);
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
);
fprintf (stream
, "->%s", &exp
->elts
[pc
+ 1].string
);
print_subexp (exp
, pos
, stream
, PREC_SUFFIX
);
print_subexp (exp
, pos
, stream
, PREC_ABOVE_COMMA
);
print_subexp (exp
, pos
, stream
, PREC_SUFFIX
);
print_subexp (exp
, pos
, stream
, PREC_SUFFIX
);
if ((int) prec
> (int) PREC_PREFIX
)
type_print (exp
->elts
[pc
+ 1].type
, "", stream
, 0);
print_subexp (exp
, pos
, stream
, PREC_PREFIX
);
if ((int) prec
> (int) PREC_PREFIX
)
if ((int) prec
> (int) PREC_PREFIX
)
type_print (exp
->elts
[pc
+ 1].type
, "", stream
, 0);
print_subexp (exp
, pos
, stream
, PREC_PREFIX
);
if ((int) prec
> (int) PREC_PREFIX
)
case BINOP_ASSIGN_MODIFY
:
opcode
= exp
->elts
[pc
+ 1].opcode
;
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
;
fprintf (stream
, "this");
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
;
if ((int) myprec
< (int) prec
)
if ((int) opcode
> (int) BINOP_END
)
/* Unary prefix operator. */
fprintf (stream
, "%s", op_str
);
print_subexp (exp
, pos
, stream
, PREC_PREFIX
);
If operator is right-associative,
increment precedence for this operand. */
print_subexp (exp
, pos
, stream
, (int) myprec
+ assoc
);
/* Print the operator itself. */
fprintf (stream
, " %s= ", op_str
);
else if (op_str
[0] == ',')
fprintf (stream
, "%s ", op_str
);
fprintf (stream
, " %s ", op_str
);
If operator is left-associative,
increment precedence for this operand. */
print_subexp (exp
, pos
, stream
, (int) myprec
+ !assoc
);
if ((int) myprec
< (int) prec
)