/*
* Copyright (c) 1995, 1996, 1998, 1999 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
*
* This file is part of Flick, the Flexible IDL Compiler Kit.
*
* Flick 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 2 of the License, or
* (at your option) any later version.
*
* Flick 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 Flick; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place #330, Boston, MA 02111, USA.
*/
#include <assert.h>
#include <ctype.h>
#include <mom/compiler.h>
#include <mom/c/libcast.h>
#define doprec(new_prec, stuff) \
if (new_prec < last_prec) w_putc('('); \
stuff; \
if (new_prec < last_prec) w_putc(')');
#define dolunary(prec, str) \
doprec(prec, \
w_printf(str); \
w_expr(expr->cast_expr_u_u.unary.expr, prec, 0); \
);
#define dorunary(prec, str) \
doprec(prec, \
w_expr(expr->cast_expr_u_u.unary.expr, prec+1, 0); \
w_printf(str); \
);
#define dobinary(prec, str) \
doprec(prec, \
w_expr(expr->cast_expr_u_u.binary.expr[0], prec, 0); \
w_printf(str); \
w_expr(expr->cast_expr_u_u.binary.expr[1], prec+1, 0); \
);
#define dobinaryop(prec, str) \
doprec(prec, \
w_expr(expr->cast_expr_u_u.op_assign.expr[0], prec, 0); \
w_printf(str); \
w_expr(expr->cast_expr_u_u.op_assign.expr[1], prec+1, 0); \
);
static void w_expr_prim_type(cast_primitive_modifier mod,
cast_primitive_kind kind)
{
if (mod != 0)
w_printf("(%s%s%s) ",
((mod & CAST_MOD_SIGNED) ? "signed " :
(mod & CAST_MOD_UNSIGNED) ? "unsigned " :
""),
((mod & CAST_MOD_LONG_LONG) ? "long long " :
(mod & CAST_MOD_LONG) ? "long " :
(mod & CAST_MOD_SHORT) ? "short " :
""),
((kind == CAST_PRIM_CHAR) ? "char" :
(kind == CAST_PRIM_INT) ? "int" :
(kind == CAST_PRIM_FLOAT) ? "float" :
(kind == CAST_PRIM_DOUBLE) ? "double" :
(panic("unknown kind %d in w_expr_prim_type", kind),
""))
);
}
static void w_expr(cast_expr expr, int last_prec, int indent)
{
int i;
w_indent(indent);
assert(expr);
switch (expr->kind) {
case CAST_EXPR_NAME:
cast_w_scoped_name(&expr->cast_expr_u_u.name);
break;
case CAST_EXPR_CONST_NAME:
cast_w_scoped_name(&expr->cast_expr_u_u.
const_name);
break;
case CAST_EXPR_LIT_PRIM:
w_expr_prim_type(expr->cast_expr_u_u.lit_prim.mod,
expr->cast_expr_u_u.lit_prim.u.kind);
switch (expr->cast_expr_u_u.lit_prim.u.kind) {
case CAST_PRIM_CHAR: {
int ch = expr->
cast_expr_u_u.lit_prim.u.cast_lit_prim_u_u.c;
w_printf(((ch == '\'') ? "'\\''" :
((ch >= ' ') && (ch < 127)) ? "'%c'" :
"%d"),
ch);
break;
}
case CAST_PRIM_INT: {
w_printf("%d",
expr->
cast_expr_u_u.lit_prim.u.cast_lit_prim_u_u.i);
break;
}
case CAST_PRIM_FLOAT: {
w_printf("%f",
expr->
cast_expr_u_u.lit_prim.u.cast_lit_prim_u_u.f);
break;
}
case CAST_PRIM_DOUBLE: {
w_printf("%f",
expr->
cast_expr_u_u.lit_prim.u.cast_lit_prim_u_u.d);
break;
}
case CAST_PRIM_BOOL: {
w_printf("%s",
expr->
cast_expr_u_u.lit_prim.u.cast_lit_prim_u_u.b ?
"true" :
"false");
break;
}
default:
panic("cast_w_expr: unknown lit_prim kind %d",
expr->cast_expr_u_u.lit_prim.u.kind);
}
break;
case CAST_EXPR_LIT_STRING: {
char *s;
w_putc('\"');
for (s = expr->cast_expr_u_u.lit_string; *s; ++s)
switch (*s) {
case '\a':
/* Bell. */
w_printf("\\a");
break;
case '\b':
/* Backspace. */
w_printf("\\b");
break;
case '\f':
/* Form feed. */
w_printf("\\f");
break;
case '\n':
/* Newline. */
w_printf("\\n");
break;
case '\r':
/* Carriage return. */
w_printf("\\r");
break;
case '\t':
/* Tab. */
w_printf("\\t");
break;
case '\v':
/* Vertical tab. */
w_printf("\\v");
break;
case '\'':
/* Single quote. */
w_printf("\\'");
break;
case '\"':
/* Double quote. */
w_printf("\\\"");
break;
case '\\':
/* Backslash. */
w_printf("\\\\");
break;
default:
/*
* Cast `*s' to `int' to avoid warning from
* gcc 2.8.0.
*/
if (isprint(((int) *s)))
w_putc(*s);
else
w_printf("\\%03o", *s);
break;
}
w_putc('\"');
break;
}
case CAST_EXPR_CALL:
doprec(14,
w_expr(expr->cast_expr_u_u.call.func, 14, 0);
w_putc('(');
for (i = 0;
i < (signed int)expr->cast_expr_u_u.call.params.cast_expr_array_len;
i++) {
if (i > 0) {
w_putc(',');
w_putc(' ');
}
w_expr(expr->
cast_expr_u_u.call.params.cast_expr_array_val[i],
1, 0);
}
w_putc(')');
);
break;
case CAST_EXPR_SEL: {
cast_expr_sel *sel = &expr->cast_expr_u_u.sel;
cast_unary_expr *ue = &sel->var->cast_expr_u_u.unary;
if ((sel->var->kind == CAST_EXPR_UNARY)
&& (ue->op == CAST_UNARY_DEREF)
&& ((ue->expr->kind != CAST_EXPR_BINARY)
|| (ue->expr->cast_expr_u_u.binary.op !=
CAST_BINARY_ADD))) {
/* Combine the (*). operators into a single ->
operator. */
doprec(14,
w_expr(ue->expr, 14, 0);
w_printf("->");
cast_w_scoped_name(&sel->member);
);
} else {
doprec(14,
w_expr(sel->var, 14, 0);
w_printf(".");
cast_w_scoped_name(&sel->member);
);
}
break;
}
case CAST_EXPR_UNARY:
switch (expr->cast_expr_u_u.unary.op) {
case CAST_UNARY_DEREF: {
cast_unary_expr *ue = &expr->cast_expr_u_u.unary;
cast_binary_expr *be = &ue->expr->cast_expr_u_u.binary;
cast_unary_expr *ue2 = &ue->expr->cast_expr_u_u.unary;
if ((ue->expr->kind == CAST_EXPR_BINARY)
&& (be->op == CAST_BINARY_ADD)) {
/* Use a single [] operator.
Note that this is legal even if the pointer
is the _second_ element of the + expression,
because C defines x[y] to be _exactly_
equivalent to *(x+y).
In other words,
idx[ptr] will work just as well as ptr[idx].
*/
doprec(14,
w_expr(be->expr[0], 14, 0);
w_putc('[');
w_expr(be->expr[1], 1, 0);
w_putc(']');
);
} else if ((ue->expr->kind == CAST_EXPR_UNARY)
&& (ue2->op == CAST_UNARY_ADDR)) {
/* The operators cancel each other. */
w_expr(ue2->expr, last_prec, 0);
} else {
dolunary(13, "*");
}
break;
}
case CAST_UNARY_ADDR: {
cast_unary_expr *ue = &expr->cast_expr_u_u.unary;
cast_unary_expr *ue2 = &ue->expr->cast_expr_u_u.unary;
if ((ue->expr->kind == CAST_EXPR_UNARY)
&& (ue2->op == CAST_UNARY_DEREF)) {
/* The operators cancel each other. */
w_expr(ue2->expr, last_prec, 0);
} else {
dolunary(13, "&");
}
break;
}
case CAST_UNARY_NEG:
dolunary(13, "-");
break;
case CAST_UNARY_LNOT:
dolunary(13, "!");
break;
case CAST_UNARY_BNOT:
dolunary(13, "~");
break;
case CAST_UNARY_PRE_INC:
dolunary(13, "++");
break;
case CAST_UNARY_PRE_DEC:
dolunary(13, "--");
break;
case CAST_UNARY_POST_INC:
dorunary(13, "++");
break;
case CAST_UNARY_POST_DEC:
dorunary(13, "--");
break;
default:
panic("cast_w_expr: unknown unary op %d",
expr->cast_expr_u_u.unary.op);
}
break;
case CAST_EXPR_CAST:
doprec(13,
w_putc('(');
cast_w_type(empty_scope_name,
expr->cast_expr_u_u.cast.type, 0);
w_putc(')');
w_expr(expr->cast_expr_u_u.cast.expr, 14+1, 0);
);
break;
case CAST_EXPR_SIZEOF_EXPR:
doprec(14,
w_printf("sizeof(");
w_expr(expr->cast_expr_u_u.sizeof_expr, 0, 0);
w_putc(')');
);
break;
case CAST_EXPR_SIZEOF_TYPE:
doprec(14,
w_printf("sizeof(");
cast_w_type(empty_scope_name,
expr->cast_expr_u_u.sizeof_type, 0);
w_putc(')');
);
break;
case CAST_EXPR_BINARY:
switch (expr->cast_expr_u_u.binary.op) {
case CAST_BINARY_MUL:
dobinary(12, " * ");
break;
case CAST_BINARY_DIV:
dobinary(12, " / ");
break;
case CAST_BINARY_MOD:
dobinary(12, " % ");
break;
case CAST_BINARY_ADD:
/* XXX - This is a silly hack to get around
a gcc warning that complains when an '&'
is surrounded by a '+' or a '-'. */
if( last_prec == 7 ) {
dobinary(6, " + ");
}
else {
dobinary(11, " + ");
}
break;
case CAST_BINARY_SUB:
if( last_prec == 7 ) {
dobinary(6, " - ");
}
else {
dobinary(11, " - ");
}
break;
case CAST_BINARY_SHL:
dobinary(10, " << ");
break;
case CAST_BINARY_SHR:
dobinary(10, " >> ");
break;
case CAST_BINARY_LT:
dobinary(9, " < ");
break;
case CAST_BINARY_GT:
dobinary(9, " > ");
break;
case CAST_BINARY_LE:
dobinary(9, " <= ");
break;
case CAST_BINARY_GE:
dobinary(9, " >= ");
break;
case CAST_BINARY_EQ:
dobinary(8, " == ");
break;
case CAST_BINARY_NE:
dobinary(8, " != ");
break;
case CAST_BINARY_BAND:
dobinary(7, " & ");
break;
case CAST_BINARY_BXOR:
dobinary(6, " ^ ");
break;
case CAST_BINARY_BOR:
dobinary(5, " | ");
break;
case CAST_BINARY_LAND:
dobinary(4, " && ");
break;
case CAST_BINARY_LOR:
dobinary(3, " || ");
break;
case CAST_BINARY_ASSIGN:
dobinary(1, " = ");
break;
case CAST_BINARY_COMMA:
dobinary(0, ", ");
break;
default:
panic("cast_w_expr: unknown binary op %d",
expr->cast_expr_u_u.binary.op);
}
break;
case CAST_EXPR_OP_ASSIGN:
switch (expr->cast_expr_u_u.op_assign.op) {
case CAST_BINARY_MUL:
dobinaryop(1, " *= ");
break;
case CAST_BINARY_DIV:
dobinaryop(1, " /= ");
break;
case CAST_BINARY_MOD:
dobinaryop(1, " %= ");
break;
case CAST_BINARY_ADD:
dobinaryop(1, " += ");
break;
case CAST_BINARY_SUB:
dobinaryop(1, " -= ");
break;
case CAST_BINARY_SHL:
dobinaryop(1, " <<= ");
break;
case CAST_BINARY_SHR:
dobinaryop(1, " >>= ");
break;
case CAST_BINARY_BAND:
dobinaryop(1, " &= ");
break;
case CAST_BINARY_BXOR:
dobinaryop(1, " ^= ");
break;
case CAST_BINARY_BOR:
dobinaryop(1, " |= ");
break;
case CAST_BINARY_ASSIGN:
/* Should this really be here? */
dobinaryop(1, " = ");
break;
default:
panic("cast_w_expr: unknown op_assign op %d",
expr->cast_expr_u_u.op_assign.op);
break;
}
break;
case CAST_EXPR_COND:
doprec(2,
w_expr(expr->cast_expr_u_u.cond.test, 2+1, 0);
w_printf(" ? ");
w_expr(expr->cast_expr_u_u.cond.true_expr, 2+1, 0);
w_printf(" : ");
w_expr(expr->cast_expr_u_u.cond.false_expr, 2, 0);
);
break;
case CAST_EXPR_CONST_CAST:
doprec(13,
w_printf("const_cast");
w_putc('<');
cast_w_type(empty_scope_name,
expr->cast_expr_u_u.c_cast.type,
0);
w_putc('>');
w_putc('(');
w_expr(expr->cast_expr_u_u.cast.expr, 14+1, 0);
w_putc(')');
);
break;
case CAST_EXPR_DYNAMIC_CAST:
doprec(13,
w_printf("dynamic_cast");
w_putc('<');
cast_w_type(empty_scope_name,
expr->cast_expr_u_u.d_cast.type,
0);
w_putc('>');
w_putc('(');
w_expr(expr->cast_expr_u_u.cast.expr, 14+1, 0);
w_putc(')');
);
break;
case CAST_EXPR_REINTERPRET_CAST:
doprec(13,
w_printf("reinterpret_cast");
w_putc('<');
cast_w_type(empty_scope_name,
expr->cast_expr_u_u.r_cast.type,
0);
w_putc('>');
w_putc('(');
w_expr(expr->cast_expr_u_u.cast.expr, 14+1, 0);
w_putc(')');
);
break;
case CAST_EXPR_STATIC_CAST:
doprec(13,
w_printf("static_cast");
w_putc('<');
cast_w_type(empty_scope_name,
expr->cast_expr_u_u.cast.type,
0);
w_putc('>');
w_putc('(');
w_expr(expr->cast_expr_u_u.cast.expr, 14+1, 0);
w_putc(')');
);
break;
case CAST_EXPR_OP_NEW: {
cast_op_new_expr *ne;
int is_simple;
w_printf("new ");
ne = &expr->cast_expr_u_u.op_new;
/*
* If the type is not a ``simple'' type, put parens around it.
* This avoids problems with some versions of `gcc' (2.7.2.1)
* that sometimes get confused by things like `new struct foo'.
*/
switch (ne->type->kind) {
case CAST_TYPE_NAME:
case CAST_TYPE_PRIMITIVE:
case CAST_TYPE_VOID:
case CAST_TYPE_TYPENAME:
is_simple = 1;
break;
default:
is_simple = 0;
break;
}
if (!is_simple)
w_printf("(");
cast_w_type(null_scope_name,
ne->type,
0);
if (!is_simple)
w_printf(")");
if (ne->init)
cast_w_init(ne->init, 0);
break;
}
case CAST_EXPR_OP_DELETE:
w_printf("delete %s",
expr->cast_expr_u_u.op_delete.array ? "[] " : "");
cast_w_expr(expr->cast_expr_u_u.op_delete.expr, 0);
break;
case CAST_EXPR_TYPEID_EXPR:
doprec(14,
w_printf("typeid(");
w_expr(expr->cast_expr_u_u.typeid_expr, 0, 0);
w_putc(')');
);
break;
case CAST_EXPR_TYPEID_TYPE:
doprec(14,
w_printf("typeid(");
cast_w_type(empty_scope_name,
expr->cast_expr_u_u.typeid_type, 0);
w_putc(')');
);
break;
case CAST_EXPR_TYPE:
doprec(14,
cast_w_type(empty_scope_name,
expr->cast_expr_u_u.type_expr, 0);
);
break;
default:
panic("cast_w_expr: unknown expr kind %d", expr->kind);
}
}
void cast_w_expr(cast_expr expr, int indent)
{
w_expr(expr, 0, indent);
}
void cast_w_expr_noncomma(cast_expr expr, int indent)
{
w_expr(expr, 1, indent);
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1