Static void wrexpr()

in MultiSource/Benchmarks/MallocBench/p2c/pexpr.c [2866:3554]


Static void wrexpr(ex, prec)
Expr *ex;
int prec;
{
    short parens = 0;
    int subprec, i, j, minusflag, breakflag = 0;
    int saveindent;
    Expr *ex2, *ex3;
    char *cp;
    Meaning *mp;
    Symbol *sp;

    if (debug>2) { fprintf(outf,"wrexpr{"); dumpexpr(ex); fprintf(outf,", %d}\n", prec); }
    switch (ex->kind) {

        case EK_VAR:
            mp = (Meaning *)ex->val.i;
            if (mp->warnifused)
                note(format_s("Reference to %s [283]", mp->name));
            out_var(mp, prec);
            break;

        case EK_NAME:
            output(ex->val.s);
            break;

        case EK_MACARG:
            output("<meef>");
            intwarning("wrexpr", "Stray EK_MACARG encountered [310]");
            break;

        case EK_CTX:
            out_ctx((Meaning *)ex->val.i, 1);
            break;

        case EK_CONST:
            if (ex->nargs > 0)
                cp = value_name(ex->val, ex->args[0]->val.s, 0);
            else
                cp = value_name(ex->val, NULL, 0);
            if (*cp == '-')
                setprec(14);
            output(cp);
            break;

        case EK_LONGCONST:
            if (ex->nargs > 0)
                cp = value_name(ex->val, ex->args[0]->val.s, 1);
            else
                cp = value_name(ex->val, NULL, 1);
            if (*cp == '-')
                setprec(14);
            output(cp);
            break;

        case EK_STRUCTCONST:
            ex3 = NULL;
            for (i = 0; i < ex->nargs; i++) {
                ex2 = ex->args[i];
                if (ex2->kind == EK_STRUCTOF) {
                    j = ex2->val.i;
                    ex2 = ex2->args[0];
                } else
                    j = 1;
                if (ex2->kind == EK_VAR) {
                    mp = (Meaning *)ex2->val.i;
                    if (mp->kind == MK_CONST &&
			mp->val.type &&
                        (mp->val.type->kind == TK_RECORD ||
                         mp->val.type->kind == TK_ARRAY)) {
                        if (foldconsts != 1)
                            note(format_s("Expanding constant %s into another constant [284]",
                                          mp->name));
                        ex2 = (Expr *)mp->val.i;
                    }
                }
                while (--j >= 0) {
                    if (ex3) {
                        if (ex3->kind == EK_STRUCTCONST ||
                            ex2->kind == EK_STRUCTCONST)
                            output(",\n");
                        else if (spacecommas)
                            output(",\001 ");
			else
			    output(",\001");
                    }
                    if (ex2->kind == EK_STRUCTCONST) {
                        output("{ \005");
			saveindent = outindent;
			moreindent(extrainitindent);
                        out_expr(ex2);
                        outindent = saveindent;
                        output(" }");
                    } else
                        out_expr(ex2);
                    ex3 = ex2;
                }
            }
            break;

        case EK_FUNCTION:
            mp = (Meaning *)ex->val.i;
	    sp = findsymbol_opt(mp->name);
	    if ((sp && (sp->flags & WARNLIBR)) || mp->warnifused)
                note(format_s("Called procedure %s [285]", mp->name));
            output(mp->name);
	    if (spacefuncs)
		output(" ");
            output("(\002");
	    j = sp ? (sp->flags & FUNCBREAK) : 0;
	    if (j == FALLBREAK)
		output("\007");
            for (i = 0; i < ex->nargs; i++) {
		if ((j == FSPCARG1 && i == 1) ||
		    (j == FSPCARG2 && i == 2) ||
		    (j == FSPCARG3 && i == 3))
		    if (spacecommas)
			output(",\011 ");
		    else
			output(",\011");
                else if (i > 0)
		    if (spacecommas)
			output(",\002 ");
		    else
			output(",\002");
                out_expr(ex->args[i]);
            }
            if (mp->ctx->kind == MK_FUNCTION && mp->ctx->varstructflag) {
                if (i > 0)
		    if (spacecommas)
			output(",\002 ");
		    else
			output(",\002");
                out_ctx(mp->ctx, 1);
            }
            output(")");
            break;

        case EK_BICALL:
            cp = ex->val.s;
            while (*cp == '*')
                cp++;
	    sp = findsymbol_opt(cp);
	    if (sp && (sp->flags & WARNLIBR))
                note(format_s("Called library procedure %s [286]", cp));
            output(cp);
	    if (spacefuncs)
		output(" ");
            output("(\002");
	    j = sp ? (sp->flags & FUNCBREAK) : 0;
	    if (j == FALLBREAK)
		output("\007");
            for (i = 0; i < ex->nargs; i++) {
		if ((j == FSPCARG1 && i == 1) ||
		    (j == FSPCARG2 && i == 2) ||
		    (j == FSPCARG3 && i == 3))
		    if (spacecommas)
			output(",\011 ");
		    else
			output(",\011");
                else if (i > 0)
		    if (spacecommas)
			output(",\002 ");
		    else
			output(",\002");
                out_expr(ex->args[i]);
            }
            output(")");
            break;

        case EK_SPCALL:
            setprec(16);
            if (starfunctions) {
                output("(\002*");
                wrexpr(ex->args[0], 13);
                output(")");
            } else
                wrexpr(ex->args[0], subprec-1);
	    if (spacefuncs)
		output(" ");
            output("(\002");
            for (i = 1; i < ex->nargs; i++) {
                if (i > 1)
		    if (spacecommas)
			output(",\002 ");
		    else
			output(",\002");
                out_expr(ex->args[i]);
            }
            output(")");
            break;

        case EK_INDEX:
            setprec(16);
            wrexpr(ex->args[0], subprec-1);
	    if (lookback(1) == ']')
		output("\001");
            output("[");
            out_expr(ex->args[1]);
            output("]");
            break;

        case EK_DOT:
            setprec2(16);
	    checkbreak(breakbeforedot);
            if (ex->args[0]->kind == EK_HAT) {
                wrexpr(ex->args[0]->args[0], subprec-1);
                outop2("->");
            } else if (ex->args[0]->kind == EK_CTX) {
                out_ctx((Meaning *)ex->args[0]->val.i, 0);
            } else {
                wrexpr(ex->args[0], subprec-1);
                outop2(".");
            }
            if (ex->val.i)
                out_field((Meaning *)ex->val.i);
            else
                output(ex->val.s);
            break;

        case EK_POSTINC:
	    if (prec == 0 && !postincrement) {
		setprec(14);
		output("++");
		EXTRASPACE();
		wrexpr(ex->args[0], subprec);
	    } else {
		setprec(15);
		wrexpr(ex->args[0], subprec);
		EXTRASPACE();
		output("++");
	    }
            break;

        case EK_POSTDEC:
	    if (prec == 0 && !postincrement) {
		setprec(14);
		output("--");
		EXTRASPACE();
		wrexpr(ex->args[0], subprec);
	    } else {
		setprec(15);
		wrexpr(ex->args[0], subprec);
		EXTRASPACE();
		output("--");
	    }
            break;

        case EK_HAT:
            setprec(14);
	    if (lookback_prn(1) == '/')
		output(" ");
            output("*");
            EXTRASPACE();
            wrexpr(ex->args[0], subprec-1);
            break;

        case EK_ADDR:
            setprec(14);
	    if (lookback_prn(1) == '&')
		output(" ");
            output("&");
            EXTRASPACE();
            wrexpr(ex->args[0], subprec-1);
            break;

        case EK_NEG:
            setprec(14);
            output("-");
            EXTRASPACE();
            if (ex->args[0]->kind == EK_TIMES)
                wrexpr(ex->args[0], 12);
            else
                wrexpr(ex->args[0], subprec-1);
            break;

        case EK_NOT:
            setprec(14);
            output("!");
            EXTRASPACE();
            wrexpr(ex->args[0], subprec-1);
            break;

        case EK_BNOT:
            setprec(14);
            output("~");
            EXTRASPACE();
            wrexpr(ex->args[0], subprec-1);
            break;

        case EK_CAST:
        case EK_ACTCAST:
            if (similartypes(ex->val.type, ex->args[0]->val.type)) {
                wrexpr(ex->args[0], prec);
            } else if (ord_type(ex->args[0]->val.type)->kind == TK_ENUM &&
                       ex->val.type == tp_int && !useenum) {
                wrexpr(ex->args[0], prec);
            } else {
                setprec2(14);
                output("(");
                out_type(ex->val.type, 0);
                output(")\002");
                EXTRASPACE();
                if (extraparens != 0)
                    wrexpr(ex->args[0], 15);
                else
                    wrexpr(ex->args[0], subprec-1);
            }
            break;

        case EK_LITCAST:
            setprec2(14);
            output("(");
            out_expr(ex->args[0]);
            output(")\002");
            EXTRASPACE();
            if (extraparens != 0)
                wrexpr(ex->args[1], 15);
            else
                wrexpr(ex->args[1], subprec-1);
            break;

        case EK_SIZEOF:
            setprec(14);
            output("sizeof");
	    if (spacefuncs)
		output(" ");
	    output("(");
	    out_expr(ex->args[0]);
            output(")");
            break;

	case EK_TYPENAME:
	    out_type(ex->val.type, 1);
	    break;

        case EK_TIMES:
	    setprec2(13);
	    checkbreak(breakbeforearith);
            ex2 = copyexpr(ex);
            if (expr_looks_neg(ex2->args[ex2->nargs-1])) {
                ex2->args[0] = makeexpr_neg(ex2->args[0]);
                ex2->args[ex2->nargs-1] = makeexpr_neg(ex2->args[ex2->nargs-1]);
            }
            wrexpr(ex2->args[0], incompat(ex2, 0, subprec-1));
            for (i = 1; i < ex2->nargs; i++) {
                outop("*");
                wrexpr(ex2->args[i], incompat(ex2, i, subprec));
            }
            freeexpr(ex2);
            break;

        case EK_DIV:
        case EK_DIVIDE:
            setprec2(13);
	    checkbreak(breakbeforearith);
	    wrexpr(ex->args[0], incompat(ex, 0, subprec-1));
            outop("/");
            wrexpr(ex->args[1], incompat(ex, 1, subprec));
            break;

        case EK_MOD:
            setprec2(13);
	    checkbreak(breakbeforearith);
            wrexpr(ex->args[0], incompat(ex, 0, subprec-1));
            outop("%");
            wrexpr(ex->args[1], incompat(ex, 1, subprec));
            break;

        case EK_PLUS:
            setprec2(12);
	    checkbreak(breakbeforearith);
            ex2 = copyexpr(ex);
            minusflag = 0;
            if (expr_looks_neg(ex2->args[0])) {
                j = 1;
                while (j < ex2->nargs && expr_looks_neg(ex2->args[j])) j++;
                if (j < ex2->nargs)
                    swapexprs(ex2->args[0], ex2->args[j]);
            } else if (ex2->val.i && ex2->nargs == 2) {   /* this was originally "a-b" */
                if (isliteralconst(ex2->args[1], NULL) != 2) {
                    if (expr_neg_cost(ex2->args[1]) <= 0) {
                        minusflag = 1;
                    } else if (expr_neg_cost(ex2->args[0]) <= 0) {
                        swapexprs(ex2->args[0], ex2->args[1]);
                        if (isliteralconst(ex2->args[0], NULL) != 2)
                            minusflag = 1;
                    }
                }
            }
            wrexpr(ex2->args[0], incompat(ex, 0, subprec));
            for (i = 1; i < ex2->nargs; i++) {
                if (expr_looks_neg(ex2->args[i]) || minusflag) {
                    outop("-");
                    ex2->args[i] = makeexpr_neg(ex2->args[i]);
                } else
                    outop("+");
                wrexpr(ex2->args[i], incompat(ex, i, subprec));
            }
            freeexpr(ex2);
            break;

        case EK_LSH:
            setprec3(11);
	    checkbreak(breakbeforearith);
            wrexpr(ex->args[0], incompat(ex, 0, subprec));
            outop("<<");
            wrexpr(ex->args[1], incompat(ex, 1, subprec));
            break;

        case EK_RSH:
            setprec3(11);
	    checkbreak(breakbeforearith);
	    wrexpr(ex->args[0], incompat(ex, 0, subprec));
            outop(">>");
            wrexpr(ex->args[1], incompat(ex, 1, subprec));
            break;

        case EK_LT:
            setprec2(10);
	    checkbreak(breakbeforerel);
            wrexpr(ex->args[0], incompat(ex, 0, subprec));
            outop("<");
            wrexpr(ex->args[1], incompat(ex, 0, subprec));
            break;

        case EK_GT:
            setprec2(10);
	    checkbreak(breakbeforerel);
            wrexpr(ex->args[0], incompat(ex, 0, subprec));
            outop(">");
            wrexpr(ex->args[1], incompat(ex, 0, subprec));
            break;

        case EK_LE:
            setprec2(10);
	    checkbreak(breakbeforerel);
            wrexpr(ex->args[0], incompat(ex, 0, subprec));
            outop("<=");
            wrexpr(ex->args[1], incompat(ex, 0, subprec));
            break;

        case EK_GE:
            setprec2(10);
	    checkbreak(breakbeforerel);
            wrexpr(ex->args[0], incompat(ex, 0, subprec));
            outop(">=");
            wrexpr(ex->args[1], incompat(ex, 0, subprec));
            break;

        case EK_EQ:
            setprec2(9);
	    checkbreak(breakbeforerel);
            wrexpr(ex->args[0], incompat(ex, 0, subprec));
            outop("==");
            wrexpr(ex->args[1], incompat(ex, 0, subprec));
            break;

        case EK_NE:
            setprec2(9);
	    checkbreak(breakbeforerel);
            wrexpr(ex->args[0], incompat(ex, 0, subprec));
            outop("!=");
            wrexpr(ex->args[1], incompat(ex, 0, subprec));
            break;

        case EK_BAND:
            setprec3(8);
	    if (ex->val.type == tp_boolean)
		checkbreak(breakbeforelog);
	    else
		checkbreak(breakbeforearith);
            wrexpr(ex->args[0], incompat(ex, 0, subprec-1));
	    outop("&");
            wrexpr(ex->args[1], incompat(ex, 1, subprec-1));
            break;

        case EK_BXOR:
            setprec3(7);
	    checkbreak(breakbeforearith);
            wrexpr(ex->args[0], incompat(ex, 0, subprec-1));
            outop("^");
            wrexpr(ex->args[1], incompat(ex, 1, subprec-1));
            break;

        case EK_BOR:
            setprec3(6);
	    if (ex->val.type == tp_boolean)
		checkbreak(breakbeforelog);
	    else
		checkbreak(breakbeforearith);
            wrexpr(ex->args[0], incompat(ex, 0, subprec-1));
	    outop("|");
            wrexpr(ex->args[1], incompat(ex, 1, subprec-1));
            break;

        case EK_AND:
            setprec3(5);
	    checkbreak(breakbeforelog);
	    wrexpr(ex->args[0], incompat(ex, 0, subprec-1));
            outop("&&");
	    wrexpr(ex->args[1], incompat(ex, 1, subprec-1));
            break;

        case EK_OR:
            setprec3(4);
	    checkbreak(breakbeforelog);
	    wrexpr(ex->args[0], incompat(ex, 0, subprec-1));
            outop("||");
	    wrexpr(ex->args[1], incompat(ex, 1, subprec-1));
            break;

        case EK_COND:
            setprec3(3);
	    i = 0;
	    for (;;) {
		i++;
		if (extraparens != 0)
		    wrexpr(ex->args[0], 15);
		else
		    wrexpr(ex->args[0], subprec);
		NICESPACE();
		output("\002?");
		NICESPACE();
		out_expr(ex->args[1]);
		if (ex->args[2]->kind == EK_COND) {
		    NICESPACE();
		    output("\002:");
		    NICESPACE();
		    ex = ex->args[2];
		} else {
		    NICESPACE();
		    output((i == 1) ? "\017:" : "\002:");
		    NICESPACE();
		    wrexpr(ex->args[2], subprec-1);
		    break;
		}
	    }
            break;

        case EK_ASSIGN:
            if (ex->args[1]->kind == EK_PLUS &&
                exprsame(ex->args[1]->args[0], ex->args[0], 2) &&
                ex->args[1]->args[1]->kind == EK_CONST &&
                ex->args[1]->args[1]->val.type->kind == TK_INTEGER &&
                abs(ex->args[1]->args[1]->val.i) == 1) {
		if (prec == 0 && postincrement) {
		    setprec(15);
		    wrexpr(ex->args[0], subprec);
		    EXTRASPACE();
		    if (ex->args[1]->args[1]->val.i == 1)
			output("++");
		    else
			output("--");
		} else {
		    setprec(14);
		    if (ex->args[1]->args[1]->val.i == 1)
			output("++");
		    else
			output("--");
		    EXTRASPACE();
		    wrexpr(ex->args[0], subprec-1);
		}
            } else {
                setprec2(2);
		checkbreak(breakbeforeassign);
                wrexpr(ex->args[0], subprec);
                ex2 = copyexpr(ex->args[1]);
                j = -1;
                switch (ex2->kind) {

                    case EK_PLUS:
                    case EK_TIMES:
                    case EK_BAND:
                    case EK_BOR:
                    case EK_BXOR:
                        for (i = 0; i < ex2->nargs; i++) {
                            if (exprsame(ex->args[0], ex2->args[i], 2)) {
                                j = i;
                                break;
                            }
                            if (ex2->val.type->kind == TK_REAL)
                                break;   /* non-commutative */
                        }
                        break;

                    case EK_DIVIDE:
                    case EK_DIV:
                    case EK_MOD:
                    case EK_LSH:
                    case EK_RSH:
                        if (exprsame(ex->args[0], ex2->args[0], 2))
                            j = 0;
                        break;

		    default:
			break;
                }
                if (j >= 0) {
                    if (ex2->nargs == 2)
                        ex2 = grabarg(ex2, 1-j);
                    else
                        delfreearg(&ex2, j);
                    switch (ex->args[1]->kind) {

                        case EK_PLUS:
                            if (expr_looks_neg(ex2)) {
                                outop("-=");
                                ex2 = makeexpr_neg(ex2);
                            } else
                                outop("+=");
                            break;

                        case EK_TIMES:
                            outop("*=");
                            break;

                        case EK_DIVIDE:
                        case EK_DIV:
                            outop("/=");
                            break;

                        case EK_MOD:
                            outop("%=");
                            break;

                        case EK_LSH:
                            outop("<<=");
                            break;

                        case EK_RSH:
                            outop(">>=");
                            break;

                        case EK_BAND:
                            outop("&=");
                            break;

                        case EK_BOR:
                            outop("|=");
                            break;

                        case EK_BXOR:
                            outop("^=");
                            break;

			default:
			    break;
                    }
                } else {
		    output(" ");
		    outop3(breakbeforeassign, "=");
		    output(" ");
                }
                if (extraparens != 0 &&
                    (ex2->kind == EK_EQ || ex2->kind == EK_NE ||
                     ex2->kind == EK_GT || ex2->kind == EK_LT ||
                     ex2->kind == EK_GE || ex2->kind == EK_LE ||
                     ex2->kind == EK_AND || ex2->kind == EK_OR))
                    wrexpr(ex2, 16);
                else
                    wrexpr(ex2, subprec-1);
                freeexpr(ex2);
            }
            break;

        case EK_COMMA:
            setprec3(1);
            for (i = 0; i < ex->nargs-1; i++) {
                wrexpr(ex->args[i], subprec);
                output(",\002");
		if (spacecommas)
		    NICESPACE();
            }
            wrexpr(ex->args[ex->nargs-1], subprec);
            break;

        default:
            intwarning("wrexpr", "bad ex->kind [311]");
    }
    switch (parens) {
      case 1:
        output(")");
	break;
      case 2:
	output("\004");
	break;
    }
}