1*48112Sbostic /*- 2*48112Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48112Sbostic * All rights reserved. 4*48112Sbostic * 5*48112Sbostic * %sccs.include.redist.c% 622238Sdist */ 722238Sdist 822238Sdist #ifndef lint 9*48112Sbostic static char sccsid[] = "@(#)rval.c 5.2 (Berkeley) 04/16/91"; 10*48112Sbostic #endif /* not lint */ 1122238Sdist 1222238Sdist /* 132864Speter * pxp - Pascal execution profiler 142864Speter * 152864Speter * Bill Joy UCB 162864Speter * Version 1.2 January 1979 172864Speter */ 182864Speter 192864Speter #include "0.h" 202864Speter #include "tree.h" 212864Speter 222864Speter extern char *opnames[]; 232864Speter 242864Speter #define alph(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) 252864Speter /* 262864Speter * Rvalue reformats an expression. 272864Speter * Par is a flag indicating that the expression 282864Speter * should be parenthesized if it is non-atomic. 292864Speter */ 302864Speter rvalue(r, par) 312864Speter register int *r; 322864Speter int par; 332864Speter { 342864Speter register int *al; 352864Speter register char *opname; 362864Speter 372864Speter if (r == NIL) { 382864Speter ppid("{expr}"); 392864Speter return; 402864Speter } 412864Speter if (r[0] <= T_IN) 422864Speter opname = opnames[r[0]]; 432864Speter switch (r[0]) { 442864Speter case T_BINT: 452864Speter case T_INT: 462864Speter case T_FINT: 472864Speter ppnumb(r[2]); 482864Speter if (r[0] == T_BINT) 492864Speter ppsep("b"); 502864Speter return; 512864Speter case T_NIL: 522864Speter ppkw("nil"); 532864Speter return; 542864Speter case T_FCALL: 552864Speter funccod(r); 562864Speter return; 572864Speter case T_VAR: 582864Speter lvalue(r); 592864Speter return; 602864Speter case T_CSET: 612864Speter cset(r); 622864Speter return; 632864Speter case T_STRNG: 642864Speter ppstr(r[2]); 652864Speter return; 662864Speter } 672864Speter if (par) 682864Speter ppbra("("); 692864Speter switch (r[0]) { 702864Speter default: 712864Speter panic("rval"); 722864Speter case T_PLUS: 732864Speter case T_MINUS: 7416274Speter /* 7516274Speter * if child is relational (bogus) or adding operator, 7616274Speter * parenthesize child. 7716274Speter * this has the unaesthetic property that 7816274Speter * --i prints as -(-i), but is needed to catch 7916274Speter * -(a+b) which must print as -(a+b), not as -a+b. 8016274Speter * otherwise child has higher precedence 8116274Speter * and need not be parenthesized. 8216274Speter */ 832864Speter ppop(r[0] == T_PLUS ? "+" : "-"); 842864Speter al = r[2]; 8516274Speter rvalue(r[2], prec(al) <= prec(r) || full); 862864Speter break; 872864Speter case T_NOT: 8816274Speter /* 8916274Speter * if child is of lesser precedence 9016274Speter * (i.e. not another not operator) 9116274Speter * parenthesize it. 9216274Speter * nested not operators need not be parenthesized 9316274Speter * because it's a prefix operator. 9416274Speter */ 952864Speter ppkw(opname); 962864Speter ppspac(); 9716274Speter al = r[2]; 9816274Speter rvalue(r[2], prec(al) < prec(r) || full); 992864Speter break; 1002864Speter case T_EQ: 1012864Speter case T_NE: 1022864Speter case T_GE: 1032864Speter case T_LE: 1042864Speter case T_GT: 1052864Speter case T_LT: 10616274Speter /* 10716274Speter * make the aesthetic choice to 10816274Speter * fully parenthesize relational expressions, 10916274Speter * in spite of left to right associativity. 11016274Speter * note: there are no operators with lower precedence. 11116274Speter */ 1122864Speter al = r[2]; 1132864Speter rvalue(al, prec(al) <= prec(r) || full); 1142864Speter goto rest; 1152864Speter case T_AND: 1162864Speter case T_OR: 1172864Speter case T_MULT: 1182864Speter case T_ADD: 1192864Speter case T_SUB: 1202864Speter case T_DIVD: 1212864Speter case T_MOD: 1222864Speter case T_DIV: 1232864Speter case T_IN: 12416274Speter /* 12516274Speter * need not parenthesize left child 12616274Speter * if it has equal precedence, 12716274Speter * due to left to right associativity. 12816274Speter * right child needs to be parenthesized 12916274Speter * if it has equal (or lesser) precedence. 13016274Speter */ 1312864Speter al = r[2]; 1322864Speter rvalue(al, prec(al) < prec(r) || full); 1332864Speter rest: 1342864Speter ppspac(); 1352864Speter if (alph(opname[0])) 1362864Speter ppkw(opname); 1372864Speter else 1382864Speter ppop(opname); 1392864Speter ppspac(); 1402864Speter al = r[3]; 1412864Speter rvalue(al, prec(al) <= prec(r) || full); 1422864Speter break; 1432864Speter } 1442864Speter if (par) 1452864Speter ppket(")"); 1462864Speter } 1472864Speter 1482864Speter /* 1492864Speter * Prec returns the precedence of an operator, 1502864Speter * with larger numbers indicating stronger binding. 1512864Speter * This is used to determine when parenthesization 1522864Speter * is needed on subexpressions. 1532864Speter */ 1542864Speter prec(r) 1552864Speter register int *r; 1562864Speter { 1572864Speter 1582864Speter if (r == NIL) 1592864Speter return; 1602864Speter switch (r[0]) { 1612864Speter case T_NOT: 1622864Speter return (3); 1632864Speter case T_MULT: 1642864Speter case T_DIVD: 1652864Speter case T_DIV: 1662864Speter case T_MOD: 1672864Speter case T_AND: 1682864Speter return (2); 1692864Speter case T_ADD: 1702864Speter case T_SUB: 1712864Speter case T_OR: 1722864Speter case T_PLUS: 1732864Speter case T_MINUS: 1742864Speter return (1); 1752864Speter default: 1762864Speter return (0); 1772864Speter } 1782864Speter } 179