rsalz@uunet.uu.net (Rich Salz) (03/29/90)
Submitted-by: Dave Gillespie <daveg@csvax.caltech.edu> Posting-number: Volume 21, Issue 69 Archive-name: p2c/part24 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 24 (of 32)." # Contents: src/pexpr.c.2 # Wrapped by rsalz@litchi.bbn.com on Mon Mar 26 14:29:47 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'src/pexpr.c.2' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/pexpr.c.2'\" else echo shar: Extracting \"'src/pexpr.c.2'\" \(48796 characters\) sed "s/^X//" >'src/pexpr.c.2' <<'END_OF_FILE' X ex = makeexpr_var(tvar); X } else X ex3 = NULL; X ex4 = copyexpr(ex); X if (ex->kind == EK_CONST && smallsetconst) X ex = makesmallsetconst(1<<ex->val.i, ex2->val.type); X else X ex = makeexpr_bin(EK_LSH, ex2->val.type, X makeexpr_longcast(makeexpr_long(1), 1), X enum_to_int(ex)); X ex = makeexpr_rel(EK_NE, makeexpr_bin(EK_BAND, tp_integer, ex, ex2), X makeexpr_long(0)); X if (*name_SETBITS || X ((ex4->kind == EK_CONST) ? ((unsigned long)ex4->val.i >= setbits) X : !(0 <= smin && smax < setbits))) { X ex = makeexpr_and(makeexpr_range(enum_to_int(ex4), X makeexpr_long(0), X makeexpr_setbits(), 0), X ex); X } else X freeexpr(ex4); X ex = makeexpr_comma(ex3, ex); X return ex; X } else { X ex3 = ex2; X while (ex3->kind == EK_BICALL && X (!strcmp(ex3->val.s, setaddname) || X !strcmp(ex3->val.s, setaddrangename))) X ex3 = ex3->args[0]; X if (ex3->kind == EK_BICALL && !strcmp(ex3->val.s, setexpandname) && X (tvar = istempvar(ex3->args[0])) != NULL && X isconstexpr(ex3->args[1], &mask)) { X canceltempvar(tvar); X if (!nosideeffects(ex, 0)) { X tvar = makestmttempvar(ex->val.type, name_TEMP); X ex3 = makeexpr_assign(makeexpr_var(tvar), ex); X ex = makeexpr_var(tvar); X } else X ex3 = NULL; X type = ord_type(ex2->val.type->indextype); X ex4 = NULL; X i = 0; X while (i < setbits) { X if (mask & (1<<i++)) { X if (i+1 < setbits && (mask & (2<<i))) { X for (j = i; j < setbits && (mask & (1<<j)); j++) ; X ex4 = makeexpr_or(ex4, X makeexpr_range(copyexpr(ex), X makeexpr_val(make_ord(type, i-1)), X makeexpr_val(make_ord(type, j-1)), 1)); X i = j; X } else { X ex4 = makeexpr_or(ex4, X makeexpr_rel(EK_EQ, copyexpr(ex), X makeexpr_val(make_ord(type, i-1)))); X } X } X } X mask = 0; X for (;;) { X if (!strcmp(ex2->val.s, setaddrangename)) { X if (checkconst(ex2->args[1], 'a') && X checkconst(ex2->args[2], 'z')) { X mask |= 0x1; X } else if (checkconst(ex2->args[1], 'A') && X checkconst(ex2->args[2], 'Z')) { X mask |= 0x2; X } else if (checkconst(ex2->args[1], '0') && X checkconst(ex2->args[2], '9')) { X mask |= 0x4; X } else { X ex4 = makeexpr_or(ex4, X makeexpr_range(copyexpr(ex), ex2->args[1], ex2->args[2], 1)); X } X } else if (!strcmp(ex2->val.s, setaddname)) { X ex4 = makeexpr_or(ex4, X makeexpr_rel(EK_EQ, copyexpr(ex), ex2->args[1])); X } else X break; X ex2 = ex2->args[0]; X } X /* do these now so that EK_OR optimizations will work: */ X if (mask & 0x1) X ex4 = makeexpr_or(ex4, makeexpr_range(copyexpr(ex), X makeexpr_char('a'), X makeexpr_char('z'), 1)); X if (mask & 0x2) X ex4 = makeexpr_or(ex4, makeexpr_range(copyexpr(ex), X makeexpr_char('A'), X makeexpr_char('Z'), 1)); X if (mask & 0x4) X ex4 = makeexpr_or(ex4, makeexpr_range(copyexpr(ex), X makeexpr_char('0'), X makeexpr_char('9'), 1)); X freeexpr(ex); X return makeexpr_comma(ex3, ex4); X } X return makeexpr_bicall_2(setinname, tp_boolean, X makeexpr_arglong(ex, 0), ex2); X } X X default: X return ex; X } X} X X X X X X X X/* Parse a C expression; used by VarMacro, etc. */ X XType *nametotype(name) Xchar *name; X{ X if (!strcicmp(name, "malloc") || X !strcicmp(name, mallocname)) { X return tp_anyptr; X } X return tp_integer; X} X X Xint istypespec() X{ X switch (curtok) { X X case TOK_CONST: X return 1; X X case TOK_IDENT: X return !strcmp(curtokcase, "volatile") || X !strcmp(curtokcase, "void") || X !strcmp(curtokcase, "char") || X !strcmp(curtokcase, "short") || X !strcmp(curtokcase, "int") || X !strcmp(curtokcase, "long") || X !strcmp(curtokcase, "float") || X !strcmp(curtokcase, "double") || X !strcmp(curtokcase, "signed") || X !strcmp(curtokcase, "unsigned") || X !strcmp(curtokcase, "struct") || X !strcmp(curtokcase, "union") || X !strcmp(curtokcase, "class") || X !strcmp(curtokcase, "enum") || X !strcmp(curtokcase, "typedef") || X (curtokmeaning && X curtokmeaning->kind == MK_TYPE); X X default: X return 0; X } X} X X X XExpr *pc_parentype(cp) Xchar *cp; X{ X Expr *ex; X X if (curtok == TOK_IDENT && X curtokmeaning && X curtokmeaning->kind == MK_TYPE) { X ex = makeexpr_type(curtokmeaning->type); X gettok(); X skipcloseparen(); X } else if (curtok == TOK_IDENT && !strcmp(curtokcase, "typedef")) { X ex = makeexpr_name(getparenstr(inbufptr), tp_integer); X gettok(); X } else { X ex = makeexpr_name(getparenstr(cp), tp_integer); X gettok(); X } X return ex; X} X X X X XExpr *pc_expr2(); X XExpr *pc_factor() X{ X Expr *ex; X char *cp; X Strlist *sl; X int i; X X switch (curtok) { X X case TOK_BANG: X gettok(); X return makeexpr_not(pc_expr2(14)); X X case TOK_TWIDDLE: X gettok(); X return makeexpr_un(EK_BNOT, tp_integer, pc_expr2(14)); X X case TOK_PLPL: X gettok(); X ex = pc_expr2(14); X return makeexpr_assign(ex, makeexpr_plus(copyexpr(ex), makeexpr_long(1))); X X case TOK_MIMI: X gettok(); X ex = pc_expr2(14); X return makeexpr_assign(ex, makeexpr_minus(copyexpr(ex), makeexpr_long(1))); X X case TOK_STAR: X gettok(); X ex = pc_expr2(14); X if (ex->val.type->kind != TK_POINTER) X ex->val.type = makepointertype(ex->val.type); X return makeexpr_hat(ex, 0); X X case TOK_AMP: X gettok(); X return makeexpr_addr(pc_expr2(14)); X X case TOK_PLUS: X gettok(); X return pc_expr2(14); X X case TOK_MINUS: X gettok(); X return makeexpr_neg(pc_expr2(14)); X X case TOK_LPAR: X cp = inbufptr; X gettok(); X if (istypespec()) { X ex = pc_parentype(cp); X return makeexpr_bin(EK_LITCAST, tp_integer, ex, pc_expr2(14)); X } X ex = pc_expr(); X skipcloseparen(); X return ex; X X case TOK_IDENT: X if (!strcmp(curtokcase, "sizeof")) { X gettok(); X if (curtok != TOK_LPAR) X return makeexpr_sizeof(pc_expr2(14), 1); X cp = inbufptr; X gettok(); X if (istypespec()) { X ex = makeexpr_sizeof(pc_parentype(cp), 1); X } else { X ex = makeexpr_sizeof(pc_expr(), 1); X skipcloseparen(); X } X return ex; X } X if (curtoksym->flags & FMACREC) { X ex = makeexpr(EK_MACARG, 0); X ex->val.type = tp_integer; X ex->val.i = 0; X for (sl = funcmacroargs, i = 1; sl; sl = sl->next, i++) { X if (sl->value == (long)curtoksym) { X ex->val.i = i; X break; X } X } X } else X ex = makeexpr_name(curtokcase, nametotype(curtokcase)); X gettok(); X return ex; X X case TOK_INTLIT: X ex = makeexpr_long(curtokint); X if (curtokbuf[strlen(curtokbuf)-1] == 'L') X ex = makeexpr_longcast(ex, 1); X gettok(); X return ex; X X case TOK_HEXLIT: X ex = makeexpr_long(curtokint); X insertarg(&ex, 0, makeexpr_name("%#lx", tp_integer)); X if (curtokbuf[strlen(curtokbuf)-1] == 'L') X ex = makeexpr_longcast(ex, 1); X gettok(); X return ex; X X case TOK_OCTLIT: X ex = makeexpr_long(curtokint); X insertarg(&ex, 0, makeexpr_name("%#lo", tp_integer)); X if (curtokbuf[strlen(curtokbuf)-1] == 'L') X ex = makeexpr_longcast(ex, 1); X gettok(); X return ex; X X case TOK_REALLIT: X ex = makeexpr_real(curtokbuf); X gettok(); X return ex; X X case TOK_STRLIT: X ex = makeexpr_lstring(curtokbuf, curtokint); X gettok(); X return ex; X X case TOK_CHARLIT: X ex = makeexpr_char(curtokint); X gettok(); X return ex; X X default: X wexpected("a C expression"); X return makeexpr_long(0); X } X} X X X X X#define pc_prec(pr) if (prec > (pr)) return ex; gettok(); X XExpr *pc_expr2(prec) Xint prec; X{ X Expr *ex, *ex2; X int i; X X ex = pc_factor(); X for (;;) { X switch (curtok) { X X case TOK_COMMA: X pc_prec(1); X ex = makeexpr_comma(ex, pc_expr2(2)); X break; X X case TOK_EQ: X pc_prec(2); X ex = makeexpr_assign(ex, pc_expr2(2)); X break; X X case TOK_QM: X pc_prec(3); X ex2 = pc_expr(); X if (wneedtok(TOK_COLON)) X ex = makeexpr_cond(ex, ex2, pc_expr2(3)); X else X ex = makeexpr_cond(ex, ex2, makeexpr_long(0)); X break; X X case TOK_OROR: X pc_prec(4); X ex = makeexpr_or(ex, pc_expr2(5)); X break; X X case TOK_ANDAND: X pc_prec(5); X ex = makeexpr_and(ex, pc_expr2(6)); X break; X X case TOK_VBAR: X pc_prec(6); X ex = makeexpr_bin(EK_BOR, tp_integer, ex, pc_expr2(7)); X break; X X case TOK_HAT: X pc_prec(7); X ex = makeexpr_bin(EK_BXOR, tp_integer, ex, pc_expr2(8)); X break; X X case TOK_AMP: X pc_prec(8); X ex = makeexpr_bin(EK_BAND, tp_integer, ex, pc_expr2(9)); X break; X X case TOK_EQEQ: X pc_prec(9); X ex = makeexpr_rel(EK_EQ, ex, pc_expr2(10)); X break; X X case TOK_BANGEQ: X pc_prec(9); X ex = makeexpr_rel(EK_NE, ex, pc_expr2(10)); X break; X X case TOK_LT: X pc_prec(10); X ex = makeexpr_rel(EK_LT, ex, pc_expr2(11)); X break; X X case TOK_LE: X pc_prec(10); X ex = makeexpr_rel(EK_LE, ex, pc_expr2(11)); X break; X X case TOK_GT: X pc_prec(10); X ex = makeexpr_rel(EK_GT, ex, pc_expr2(11)); X break; X X case TOK_GE: X pc_prec(10); X ex = makeexpr_rel(EK_GE, ex, pc_expr2(11)); X break; X X case TOK_LTLT: X pc_prec(11); X ex = makeexpr_bin(EK_LSH, tp_integer, ex, pc_expr2(12)); X break; X X case TOK_GTGT: X pc_prec(11); X ex = makeexpr_bin(EK_RSH, tp_integer, ex, pc_expr2(12)); X break; X X case TOK_PLUS: X pc_prec(12); X ex = makeexpr_plus(ex, pc_expr2(13)); X break; X X case TOK_MINUS: X pc_prec(12); X ex = makeexpr_minus(ex, pc_expr2(13)); X break; X X case TOK_STAR: X pc_prec(13); X ex = makeexpr_times(ex, pc_expr2(14)); X break; X X case TOK_SLASH: X pc_prec(13); X ex = makeexpr_div(ex, pc_expr2(14)); X break; X X case TOK_PERC: X pc_prec(13); X ex = makeexpr_mod(ex, pc_expr2(14)); X break; X X case TOK_PLPL: X pc_prec(15); X ex = makeexpr_un(EK_POSTINC, tp_integer, ex); X break; X X case TOK_MIMI: X pc_prec(15); X ex = makeexpr_un(EK_POSTDEC, tp_integer, ex); X break; X X case TOK_LPAR: X pc_prec(16); X if (ex->kind == EK_NAME) { X ex->kind = EK_BICALL; X } else { X ex = makeexpr_un(EK_SPCALL, tp_integer, ex); X } X while (curtok != TOK_RPAR) { X insertarg(&ex, ex->nargs, pc_expr2(2)); X if (curtok != TOK_RPAR) X if (!wneedtok(TOK_COMMA)) X skiptotoken2(TOK_RPAR, TOK_SEMI); X } X gettok(); X break; X X case TOK_LBR: X pc_prec(16); X ex = makeexpr_index(ex, pc_expr(), NULL); X if (!wneedtok(TOK_RBR)) X skippasttoken(TOK_RBR); X break; X X case TOK_ARROW: X pc_prec(16); X if (!wexpecttok(TOK_IDENT)) X break; X if (ex->val.type->kind != TK_POINTER) X ex->val.type = makepointertype(ex->val.type); X ex = makeexpr_dotq(makeexpr_hat(ex, 0), X curtokcase, tp_integer); X gettok(); X break; X X case TOK_DOT: X pc_prec(16); X if (!wexpecttok(TOK_IDENT)) X break; X ex = makeexpr_dotq(ex, curtokcase, tp_integer); X gettok(); X break; X X case TOK_COLONCOLON: X if (prec > 16) X return ex; X i = C_lex; X C_lex = 0; X gettok(); X if (curtok == TOK_IDENT && X curtokmeaning && curtokmeaning->kind == MK_TYPE) { X ex->val.type = curtokmeaning->type; X } else if (curtok == TOK_LPAR) { X gettok(); X ex->val.type = p_type(NULL); X if (!wexpecttok(TOK_RPAR)) X skiptotoken(TOK_RPAR); X } else X wexpected("a type name"); X C_lex = i; X gettok(); X break; X X default: X return ex; X } X } X} X X X X XExpr *pc_expr() X{ X return pc_expr2(0); X} X X X XExpr *pc_expr_str(buf) Xchar *buf; X{ X Strlist *defsl, *sl; X Expr *ex; X X defsl = NULL; X sl = strlist_append(&defsl, buf); X C_lex++; X push_input_strlist(defsl, buf); X ex = pc_expr(); X if (curtok != TOK_EOF) X warning(format_s("Junk (%s) at end of C expression [306]", X tok_name(curtok))); X pop_input(); X C_lex--; X strlist_empty(&defsl); X return ex; X} X X X X X X X/* Simplify an expression */ X XExpr *fixexpr(ex, env) XExpr *ex; Xint env; X{ X Expr *ex2, *ex3, **ep; X Type *type, *type2; X Meaning *mp; X char *cp; X char sbuf[5]; X int i; X Value val; X X if (!ex) X return NULL; X switch (ex->kind) { X X case EK_BICALL: X ex2 = fix_bicall(ex, env); X if (ex2) { X ex = ex2; X break; X } X cp = ex->val.s; X if (!strcmp(cp, "strlen")) { X if (ex->args[0]->kind == EK_BICALL && X !strcmp(ex->args[0]->val.s, "sprintf") && X sprintf_value == 0) { /* does sprintf return char count? */ X ex = grabarg(ex, 0); X strchange(&ex->val.s, "*sprintf"); X ex = fixexpr(ex, env); X } else { X ex->args[0] = fixexpr(ex->args[0], ENV_EXPR); X } X } else if (!strcmp(cp, name_SETIO)) { X ex->args[0] = fixexpr(ex->args[0], ENV_BOOL); X } else if (!strcmp(cp, "~~SETIO")) { X ex->args[0] = fixexpr(ex->args[0], ENV_BOOL); X ex = makeexpr_cond(ex->args[0], X makeexpr_long(0), X makeexpr_bicall_1(name_ESCIO, tp_int, ex->args[1])); X } else if (!strcmp(cp, name_CHKIO)) { X ex->args[0] = fixexpr(ex->args[0], ENV_BOOL); X ex->args[2] = fixexpr(ex->args[2], env); X ex->args[3] = fixexpr(ex->args[3], env); X } else if (!strcmp(cp, "~~CHKIO")) { X ex->args[0] = fixexpr(ex->args[0], ENV_BOOL); X ex->args[2] = fixexpr(ex->args[2], env); X ex->args[3] = fixexpr(ex->args[3], env); X ex2 = makeexpr_bicall_1(name_ESCIO, tp_int, ex->args[1]); X if (ord_type(ex->args[3]->val.type)->kind != TK_INTEGER) X ex2 = makeexpr_cast(ex2, ex->args[3]->val.type); X ex = makeexpr_cond(ex->args[0], ex->args[2], ex2); X } else if (!strcmp(cp, "assert")) { X ex->args[0] = fixexpr(ex->args[0], ENV_BOOL); X } else { X for (i = 0; i < ex->nargs; i++) X ex->args[i] = fixexpr(ex->args[i], ENV_EXPR); X ex = cleansprintf(ex); X if (!strcmp(cp, "sprintf")) { X if (checkstring(ex->args[1], "%s")) { X delfreearg(&ex, 1); X strchange(&ex->val.s, "strcpy"); X ex = fixexpr(ex, env); X } else if (sprintf_value != 1 && env != ENV_STMT) { X if (*sprintfname) { X strchange(&ex->val.s, format_s("*%s", sprintfname)); X } else { X strchange(&ex->val.s, "*sprintf"); X ex = makeexpr_comma(ex, copyexpr(ex->args[0])); X } X } X } else if (!strcmp(cp, "strcpy")) { X if (env == ENV_STMT && X ex->args[1]->kind == EK_BICALL && X !strcmp(ex->args[1]->val.s, "strcpy") && X nosideeffects(ex->args[1]->args[0], 1)) { X ex2 = ex->args[1]; X ex->args[1] = copyexpr(ex2->args[0]); X ex = makeexpr_comma(ex2, ex); X } X } else if (!strcmp(cp, "memcpy")) { X strchange(&ex->val.s, format_s("*%s", memcpyname)); X if (!strcmp(memcpyname, "*bcopy")) { X swapexprs(ex->args[0], ex->args[1]); X if (env != ENV_STMT) X ex = makeexpr_comma(ex, copyexpr(ex->args[1])); X } X } else if (!strcmp(cp, setunionname) && X (ex3 = singlevar(ex->args[0])) != NULL && X ((i=1, exprsame(ex->args[0], ex->args[i], 0)) || X (i=2, exprsame(ex->args[0], ex->args[i], 0))) && X !exproccurs(ex3, ex->args[3-i])) { X ep = &ex->args[3-i]; X while ((ex2 = *ep)->kind == EK_BICALL && X (!strcmp(ex2->val.s, setaddname) || X !strcmp(ex2->val.s, setaddrangename))) X ep = &ex2->args[0]; X if (ex2->kind == EK_BICALL && X !strcmp(ex2->val.s, setexpandname) && X checkconst(ex2->args[1], 0) && X (mp = istempvar(ex2->args[0])) != NULL) { X if (ex2 == ex->args[3-i]) { X ex = grabarg(ex, i); X } else { X freeexpr(ex2); X *ep = ex->args[i]; X ex = ex->args[3-i]; X } X } X } else if (!strcmp(cp, setdiffname) && *setremname && X (ex3 = singlevar(ex->args[0])) != NULL && X exprsame(ex->args[0], ex->args[1], 0) && X !exproccurs(ex3, ex->args[2])) { X ep = &ex->args[2]; X while ((ex2 = *ep)->kind == EK_BICALL && X !strcmp(ex2->val.s, setaddname)) X ep = &ex2->args[0]; X if (ex2->kind == EK_BICALL && X !strcmp(ex2->val.s, setexpandname) && X checkconst(ex2->args[1], 0) && X (mp = istempvar(ex2->args[0])) != NULL) { X if (ex2 == ex->args[2]) { X ex = grabarg(ex, 1); X } else { X ex2 = ex->args[2]; X while (ex2->kind == EK_BICALL && X !strcmp(ex2->val.s, setaddname)) { X strchange(&ex2->val.s, setremname); X ex2 = ex2->args[0]; X } X freeexpr(ex2); X *ep = ex->args[1]; X ex = ex->args[2]; X } X } X } else if (!strcmp(cp, setexpandname) && env == ENV_STMT && X checkconst(ex->args[1], 0)) { X ex = makeexpr_assign(makeexpr_hat(ex->args[0], 0), X ex->args[1]); X } else if (!strcmp(cp, getbitsname)) { X type = ex->args[0]->val.type; X if (type->kind == TK_POINTER) X type = type->basetype; X sbuf[0] = (type->issigned) ? 'S' : 'U'; X sbuf[1] = (type->kind == TK_ARRAY) ? 'B' : 'S'; X sbuf[2] = 0; X if (sbuf[1] == 'S' && X type->smax->val.type == tp_boolean) { X ex = makeexpr_rel(EK_NE, X makeexpr_bin(EK_BAND, tp_integer, X ex->args[0], X makeexpr_bin(EK_LSH, tp_integer, X makeexpr_longcast(makeexpr_long(1), X type->basetype X == tp_unsigned), X ex->args[1])), X makeexpr_long(0)); X ex = fixexpr(ex, env); X } else X strchange(&ex->val.s, format_s(cp, sbuf)); X } else if (!strcmp(cp, putbitsname)) { X type = ex->args[0]->val.type; X if (type->kind == TK_POINTER) X type = type->basetype; X sbuf[0] = (type->issigned) ? 'S' : 'U'; X sbuf[1] = (type->kind == TK_ARRAY) ? 'B' : 'S'; X sbuf[2] = 0; X if (sbuf[1] == 'S' && X type->smax->val.type == tp_boolean) { X ex = makeexpr_assign(ex->args[0], X makeexpr_bin(EK_BOR, tp_integer, X copyexpr(ex->args[0]), X makeexpr_bin(EK_LSH, tp_integer, X makeexpr_longcast(ex->args[2], X type->basetype X == tp_unsigned), X ex->args[1]))); X } else X strchange(&ex->val.s, format_s(cp, sbuf)); X } else if (!strcmp(cp, storebitsname)) { X type = ex->args[0]->val.type; X if (type->kind == TK_POINTER) X type = type->basetype; X sbuf[0] = (type->issigned) ? 'S' : 'U'; X sbuf[1] = (type->kind == TK_ARRAY) ? 'B' : 'S'; X sbuf[2] = 0; X strchange(&ex->val.s, format_s(cp, sbuf)); X } else if (!strcmp(cp, clrbitsname)) { X type = ex->args[0]->val.type; X if (type->kind == TK_POINTER) X type = type->basetype; X sbuf[0] = (type->kind == TK_ARRAY) ? 'B' : 'S'; X sbuf[1] = 0; X if (sbuf[0] == 'S' && X type->smax->val.type == tp_boolean) { X ex = makeexpr_assign(ex->args[0], X makeexpr_bin(EK_BAND, tp_integer, X copyexpr(ex->args[0]), X makeexpr_un(EK_BNOT, tp_integer, X makeexpr_bin(EK_LSH, tp_integer, X makeexpr_longcast(makeexpr_long(1), X type->basetype X == tp_unsigned), X ex->args[1])))); X } else X strchange(&ex->val.s, format_s(cp, sbuf)); X } else if (!strcmp(cp, "fopen")) { X if (which_lang == LANG_HP && X ex->args[0]->kind == EK_CONST && X ex->args[0]->val.type->kind == TK_STRING && X ex->args[0]->val.i >= 1 && X ex->args[0]->val.i <= 2 && X isdigit(ex->args[0]->val.s[0]) && X (ex->args[0]->val.i == 1 || X isdigit(ex->args[0]->val.s[1]))) { X strchange(&ex->val.s, "fdopen"); X ex->args[0] = makeexpr_long(atoi(ex->args[0]->val.s)); X } X } X } X break; X X case EK_NOT: X ex = makeexpr_not(fixexpr(grabarg(ex, 0), ENV_BOOL)); X break; X X case EK_AND: X case EK_OR: X for (i = 0; i < ex->nargs; i++) X ex->args[i] = fixexpr(ex->args[i], ENV_BOOL); X break; X X case EK_EQ: X case EK_NE: X ex->args[0] = fixexpr(ex->args[0], ENV_EXPR); X ex->args[1] = fixexpr(ex->args[1], ENV_EXPR); X if (checkconst(ex->args[1], 0) && env == ENV_BOOL && X ord_type(ex->args[1]->val.type)->kind != TK_ENUM && X (implicitzero > 0 || X (implicitzero < 0 && ex->args[0]->kind == EK_BICALL && X boolean_bicall(ex->args[0]->val.s)))) { X if (ex->kind == EK_EQ) X ex = makeexpr_not(grabarg(ex, 0)); X else { X ex = grabarg(ex, 0); X ex->val.type = tp_boolean; X } X } X break; X X case EK_COND: X ex->args[0] = fixexpr(ex->args[0], ENV_BOOL); X#if 0 X val = eval_expr(ex->args[0]); X#else X val = ex->args[0]->val; X if (ex->args[0]->kind != EK_CONST) X val.type = NULL; X#endif X if (val.type == tp_boolean) { X ex = grabarg(ex, (val.i) ? 1 : 2); X ex = fixexpr(ex, env); X } else { X ex->args[1] = fixexpr(ex->args[1], env); X ex->args[2] = fixexpr(ex->args[2], env); X } X break; X X case EK_COMMA: X for (i = 0; i < ex->nargs-1; ) { X ex->args[i] = fixexpr(ex->args[i], ENV_STMT); X if (nosideeffects(ex->args[i], 1)) X delfreearg(&ex, i); X else X i++; X } X ex->args[ex->nargs-1] = fixexpr(ex->args[ex->nargs-1], env); X if (ex->nargs == 1) X ex = grabarg(ex, 0); X break; X X case EK_CHECKNIL: X ex->args[0] = fixexpr(ex->args[0], ENV_EXPR); X if (ex->nargs == 2) { X ex->args[1] = fixexpr(ex->args[1], ENV_EXPR); X ex2 = makeexpr_assign(copyexpr(ex->args[1]), ex->args[0]); X ex3 = ex->args[1]; X } else { X ex2 = copyexpr(ex->args[0]); X ex3 = ex->args[0]; X } X type = ex->args[0]->val.type; X type2 = ex->val.type; X ex = makeexpr_cond(makeexpr_rel(EK_NE, ex2, makeexpr_nil()), X ex3, X makeexpr_cast(makeexpr_bicall_0(name_NILCHECK, X tp_int), X type)); X ex->val.type = type2; X ex = fixexpr(ex, env); X break; X X case EK_CAST: X case EK_ACTCAST: X if (env == ENV_STMT) { X ex = fixexpr(grabarg(ex, 0), ENV_STMT); X } else { X ex->args[0] = fixexpr(ex->args[0], ENV_EXPR); X } X break; X X default: X for (i = 0; i < ex->nargs; i++) X ex->args[i] = fixexpr(ex->args[i], ENV_EXPR); X break; X } X return fix_expression(ex, env); X} X X X X X X X X X/* Output an expression */ X X X#define bitOp(k) ((k)==EK_BAND || (k)==EK_BOR || (k)==EK_BXOR) X X#define shfOp(k) ((k)==EK_LSH || (k)==EK_RSH) X X#define logOp(k) ((k)==EK_AND || (k)==EK_OR) X X#define relOp(k) ((k)==EK_EQ || (k)==EK_LT || (k)==EK_GT || \ X (k)==EK_NE || (k)==EK_GE || (k)==EK_LE) X X#define mathOp(k) ((k)==EK_PLUS || (k)==EK_TIMES || (k)==EK_NEG || \ X (k)==EK_DIV || (k)==EK_DIVIDE || (k)==EK_MOD) X X#define divOp(k) ((k)==EK_DIV || (k)==EK_DIVIDE) X X XStatic int incompat(ex, num, prec) XExpr *ex; Xint num, prec; X{ X Expr *subex = ex->args[num]; X X if (extraparens == 0) X return prec; X if (ex->kind == subex->kind) { X if (logOp(ex->kind) || bitOp(ex->kind) || X (divOp(ex->kind) && num == 0)) X return -99; /* not even invisible parens */ X else if (extraparens != 2) X return prec; X } X if (extraparens == 2) X return 15; X if (divOp(ex->kind) && num == 0 && X (subex->kind == EK_TIMES || divOp(subex->kind))) X return -99; X if (bitOp(ex->kind) || shfOp(ex->kind)) X return 15; X if (relOp(ex->kind) && relOp(subex->kind)) X return 15; X if ((relOp(ex->kind) || logOp(ex->kind)) && bitOp(subex->kind)) X return 15; X if (ex->kind == EK_COMMA) X return 15; X if (ex->kind == EK_ASSIGN && relOp(subex->kind)) X return 15; X if (extraparens != 1) X return prec; X if (ex->kind == EK_ASSIGN) X return prec; X if (relOp(ex->kind) && mathOp(subex->kind)) X return prec; X return 15; X} X X X X X#define EXTRASPACE() if (spaceexprs == 1) output(" ") X#define NICESPACE() if (spaceexprs != 0) output(" ") X X#define setprec(p) \ X if ((subprec=(p)) <= prec) { \ X parens = 1; output("("); \ X } X X#define setprec2(p) \ X if ((subprec=(p)) <= prec) { \ X parens = 1; output("("); \ X } else if (prec != -99) { \ X parens = 2; output((breakparens == 1) ? "\010" : "\003"); \ X } X X#define setprec3(p) \ X if ((subprec=(p)) <= prec) { \ X parens = 1; output("("); \ X } else if (prec != -99) { \ X parens = 2; output((prec > 2 && breakparens != 0) ? "\010" \ X : "\003"); \ X } X X XStatic void outop3(breakbefore, name) Xint breakbefore; Xchar *name; X{ X if (breakbefore & BRK_LEFT) { X output("\002"); X if (breakbefore & BRK_RPREF) X output("\013"); X } X output(name); X if (breakbefore & BRK_HANG) X output("\015"); X if (breakbefore & BRK_RIGHT) { X output("\002"); X if (breakbefore & BRK_LPREF) X output("\013"); X } X} X X#define outop(name) do { \ X NICESPACE(); outop3(breakflag, name); NICESPACE(); \ X} while (0) X X#define outop2(name) do { \ X EXTRASPACE(); outop3(breakflag, name); EXTRASPACE(); \ X} while (0) X X#define checkbreak(code) do { \ X breakflag=(code); \ X if ((prec != -99) && (breakflag & BRK_ALLNONE)) output("\007"); \ X} while (0) X X XStatic void out_ctx(ctx, address) XMeaning *ctx; Xint address; X{ X Meaning *ctx2; X int breakflag = breakbeforedot; X X if (ctx->kind == MK_FUNCTION && ctx->varstructflag) { X if (curctx != ctx) { X if (address && curctx->ctx && curctx->ctx != ctx) { X output("\003"); X if (breakflag & BRK_ALLNONE) X output("\007"); X } X output(format_s(name_LINK, curctx->ctx->name)); X ctx2 = curctx->ctx; X while (ctx2 && ctx2 != ctx) { X outop2("->"); X output(format_s(name_LINK, ctx2->ctx->name)); X ctx2 = ctx2->ctx; X } X if (ctx2 != ctx) X intwarning("out_ctx", X format_s("variable from %s not present in context path [307]", X ctx->name)); X if (address && curctx->ctx && curctx->ctx != ctx) X output("\004"); X if (!address) X outop2("->"); X } else { X if (address) { X output("&"); X EXTRASPACE(); X } X output(format_s(name_VARS, curctx->name)); X if (!address) { X outop2("."); X } X } X } else { X if (address) X output("NULL"); X } X} X X X Xvoid out_var(mp, prec) XMeaning *mp; Xint prec; X{ X switch (mp->kind) { X X case MK_CONST: X output(mp->name); X return; X X case MK_VAR: X case MK_VARREF: X case MK_VARMAC: X case MK_PARAM: X case MK_VARPARAM: X if (mp->varstructflag) { X output("\003"); X out_ctx(mp->ctx, 0); X output(mp->name); X output("\004"); X } else X output(mp->name); X return; X X default: X if (mp->name) X output(mp->name); X else X intwarning("out_var", "mp->sym == NULL [308]"); X return; X } X} X X X XStatic int scanfield(variants, unions, lev, mp, field) XMeaning **variants, *mp, *field; Xshort *unions; Xint lev; X{ X int i, num, breakflag; X Value v; X X unions[lev] = (mp && mp->kind == MK_VARIANT); X while (mp && mp->kind == MK_FIELD) { X if (mp == field) { X for (i = 0; i < lev; i++) { X v = variants[i]->val; /* sidestep a Sun 386i compiler bug */ X num = ord_value(v); X breakflag = breakbeforedot; X if (!unions[i]) { X output(format_s(name_UNION, "")); X outop2("."); X } X if (variants[i]->ctx->cnext || X variants[i]->ctx->kind != MK_FIELD) { X output(format_s(name_VARIANT, variantfieldname(num))); X outop2("."); X } X } X output(mp->name); X return 1; X } X mp = mp->cnext; X } X while (mp && mp->kind == MK_VARIANT) { X variants[lev] = mp; X if (scanfield(variants, unions, lev+1, mp->ctx, field)) X return 1; X mp = mp->cnext; X } X return 0; X} X X Xvoid out_field(mp) XMeaning *mp; X{ X Meaning *variants[50]; X short unions[51]; X X if (!scanfield(variants, unions, 0, mp->rectype->fbase, mp)) X intwarning("out_field", "field name not in tree [309]"); X else if (mp->warnifused) { X if (mp->rectype->meaning) X note(format_ss("Reference to field %s of record %s [282]", X mp->name, mp->rectype->meaning->name)); X else X note(format_s("Reference to field %s [282]", mp->name)); X } X} X X X X XStatic void wrexpr(ex, prec) XExpr *ex; Xint prec; X{ X short parens = 0; X int subprec, i, j, minusflag, breakflag = 0; X int saveindent; X Expr *ex2, *ex3; X char *cp; X Meaning *mp; X Symbol *sp; X X if (debug>2) { fprintf(outf,"wrexpr{"); dumpexpr(ex); fprintf(outf,", %d}\n", prec); } X switch (ex->kind) { X X case EK_VAR: X mp = (Meaning *)ex->val.i; X if (mp->warnifused) X note(format_s("Reference to %s [283]", mp->name)); X out_var(mp, prec); X break; X X case EK_NAME: X output(ex->val.s); X break; X X case EK_MACARG: X output("<meef>"); X intwarning("wrexpr", "Stray EK_MACARG encountered [310]"); X break; X X case EK_CTX: X out_ctx((Meaning *)ex->val.i, 1); X break; X X case EK_CONST: X if (ex->nargs > 0) X cp = value_name(ex->val, ex->args[0]->val.s, 0); X else X cp = value_name(ex->val, NULL, 0); X if (*cp == '-') X setprec(14); X output(cp); X break; X X case EK_LONGCONST: X if (ex->nargs > 0) X cp = value_name(ex->val, ex->args[0]->val.s, 1); X else X cp = value_name(ex->val, NULL, 1); X if (*cp == '-') X setprec(14); X output(cp); X break; X X case EK_STRUCTCONST: X ex3 = NULL; X for (i = 0; i < ex->nargs; i++) { X ex2 = ex->args[i]; X if (ex2->kind == EK_STRUCTOF) { X j = ex2->val.i; X ex2 = ex2->args[0]; X } else X j = 1; X if (ex2->kind == EK_VAR) { X mp = (Meaning *)ex2->val.i; X if (mp->kind == MK_CONST && X (mp->val.type->kind == TK_RECORD || X mp->val.type->kind == TK_ARRAY)) { X if (foldconsts != 1) X note(format_s("Expanding constant %s into another constant [284]", X mp->name)); X ex2 = (Expr *)mp->val.i; X } X } X while (--j >= 0) { X if (ex3) { X if (ex3->kind == EK_STRUCTCONST || X ex2->kind == EK_STRUCTCONST) X output(",\n"); X else X output(",\001 "); X } X if (ex2->kind == EK_STRUCTCONST) { X output("{ \005"); X saveindent = outindent; X moreindent(extrainitindent); X out_expr(ex2); X outindent = saveindent; X output(" }"); X } else X out_expr(ex2); X ex3 = ex2; X } X } X break; X X case EK_FUNCTION: X mp = (Meaning *)ex->val.i; X sp = findsymbol_opt(mp->name); X if ((sp && (sp->flags & WARNLIBR)) || mp->warnifused) X note(format_s("Called procedure %s [285]", mp->name)); X output(mp->name); X output("(\002"); X j = sp ? (sp->flags & FUNCBREAK) : 0; X if (j == FALLBREAK) X output("\007"); X for (i = 0; i < ex->nargs; i++) { X if ((j == FSPCARG1 && i == 1) || X (j == FSPCARG2 && i == 2) || X (j == FSPCARG3 && i == 3)) X output(",\011 "); X else if (i > 0) X output(",\002 "); X out_expr(ex->args[i]); X } X if (mp->ctx->kind == MK_FUNCTION && mp->ctx->varstructflag) { X if (i > 0) X output(",\002 "); X out_ctx(mp->ctx, 1); X } X output(")"); X break; X X case EK_BICALL: X cp = ex->val.s; X while (*cp == '*') X cp++; X sp = findsymbol_opt(cp); X if (sp && (sp->flags & WARNLIBR)) X note(format_s("Called library procedure %s [286]", cp)); X output(cp); X output("(\002"); X j = sp ? (sp->flags & FUNCBREAK) : 0; X if (j == FALLBREAK) X output("\007"); X for (i = 0; i < ex->nargs; i++) { X if ((j == FSPCARG1 && i == 1) || X (j == FSPCARG2 && i == 2) || X (j == FSPCARG3 && i == 3)) X output(",\011 "); X else if (i > 0) X output(",\002 "); X out_expr(ex->args[i]); X } X output(")"); X break; X X case EK_SPCALL: X setprec(16); X if (starfunctions) { X output("(\002*"); X wrexpr(ex->args[0], 13); X output(")"); X } else X wrexpr(ex->args[0], subprec-1); X output("(\002"); X for (i = 1; i < ex->nargs; i++) { X if (i > 1) X output(",\002 "); X out_expr(ex->args[i]); X } X output(")"); X break; X X case EK_INDEX: X setprec(16); X wrexpr(ex->args[0], subprec-1); X if (lookback(1) == ']') X output("\001"); X output("["); X out_expr(ex->args[1]); X output("]"); X break; X X case EK_DOT: X setprec2(16); X checkbreak(breakbeforedot); X if (ex->args[0]->kind == EK_HAT) { X wrexpr(ex->args[0]->args[0], subprec-1); X outop2("->"); X } else if (ex->args[0]->kind == EK_CTX) { X out_ctx((Meaning *)ex->args[0]->val.i, 0); X } else { X wrexpr(ex->args[0], subprec-1); X outop2("."); X } X if (ex->val.i) X out_field((Meaning *)ex->val.i); X else X output(ex->val.s); X break; X X case EK_POSTINC: X if (prec == 0 && !postincrement) { X setprec(14); X output("++"); X EXTRASPACE(); X wrexpr(ex->args[0], subprec); X } else { X setprec(15); X wrexpr(ex->args[0], subprec); X EXTRASPACE(); X output("++"); X } X break; X X case EK_POSTDEC: X if (prec == 0 && !postincrement) { X setprec(14); X output("--"); X EXTRASPACE(); X wrexpr(ex->args[0], subprec); X } else { X setprec(15); X wrexpr(ex->args[0], subprec); X EXTRASPACE(); X output("--"); X } X break; X X case EK_HAT: X setprec(14); X if (lookback_prn(1) == '/') X output(" "); X output("*"); X EXTRASPACE(); X wrexpr(ex->args[0], subprec-1); X break; X X case EK_ADDR: X setprec(14); X if (lookback_prn(1) == '&') X output(" "); X output("&"); X EXTRASPACE(); X wrexpr(ex->args[0], subprec-1); X break; X X case EK_NEG: X setprec(14); X output("-"); X EXTRASPACE(); X if (ex->args[0]->kind == EK_TIMES) X wrexpr(ex->args[0], 12); X else X wrexpr(ex->args[0], subprec-1); X break; X X case EK_NOT: X setprec(14); X output("!"); X EXTRASPACE(); X wrexpr(ex->args[0], subprec-1); X break; X X case EK_BNOT: X setprec(14); X output("~"); X EXTRASPACE(); X wrexpr(ex->args[0], subprec-1); X break; X X case EK_CAST: X case EK_ACTCAST: X if (similartypes(ex->val.type, ex->args[0]->val.type)) { X wrexpr(ex->args[0], prec); X } else if (ord_type(ex->args[0]->val.type)->kind == TK_ENUM && X ex->val.type == tp_int && !useenum) { X wrexpr(ex->args[0], prec); X } else { X setprec2(14); X output("("); X out_type(ex->val.type, 0); X output(")\002"); X EXTRASPACE(); X if (extraparens != 0) X wrexpr(ex->args[0], 15); X else X wrexpr(ex->args[0], subprec-1); X } X break; X X case EK_LITCAST: X setprec2(14); X output("("); X out_expr(ex->args[0]); X output(")\002"); X EXTRASPACE(); X if (extraparens != 0) X wrexpr(ex->args[1], 15); X else X wrexpr(ex->args[1], subprec-1); X break; X X case EK_SIZEOF: X setprec(14); X output("sizeof("); X out_expr(ex->args[0]); X output(")"); X break; X X case EK_TYPENAME: X out_type(ex->val.type, 1); X break; X X case EK_TIMES: X setprec2(13); X checkbreak(breakbeforearith); X ex2 = copyexpr(ex); X if (expr_looks_neg(ex2->args[ex2->nargs-1])) { X ex2->args[0] = makeexpr_neg(ex2->args[0]); X ex2->args[ex2->nargs-1] = makeexpr_neg(ex2->args[ex2->nargs-1]); X } X wrexpr(ex2->args[0], incompat(ex2, 0, subprec-1)); X for (i = 1; i < ex2->nargs; i++) { X outop("*"); X wrexpr(ex2->args[i], incompat(ex2, i, subprec)); X } X freeexpr(ex2); X break; X X case EK_DIV: X case EK_DIVIDE: X setprec2(13); X checkbreak(breakbeforearith); X wrexpr(ex->args[0], incompat(ex, 0, subprec-1)); X outop("/"); X wrexpr(ex->args[1], incompat(ex, 1, subprec)); X break; X X case EK_MOD: X setprec2(13); X checkbreak(breakbeforearith); X wrexpr(ex->args[0], incompat(ex, 0, subprec-1)); X outop("%"); X wrexpr(ex->args[1], incompat(ex, 1, subprec)); X break; X X case EK_PLUS: X setprec2(12); X checkbreak(breakbeforearith); X ex2 = copyexpr(ex); X minusflag = 0; X if (expr_looks_neg(ex2->args[0])) { X j = 1; X while (j < ex2->nargs && expr_looks_neg(ex2->args[j])) j++; X if (j < ex2->nargs) X swapexprs(ex2->args[0], ex2->args[j]); X } else if (ex2->val.i && ex2->nargs == 2) { /* this was originally "a-b" */ X if (isliteralconst(ex2->args[1], NULL) != 2) { X if (expr_neg_cost(ex2->args[1]) <= 0) { X minusflag = 1; X } else if (expr_neg_cost(ex2->args[0]) <= 0) { X swapexprs(ex2->args[0], ex2->args[1]); X if (isliteralconst(ex2->args[0], NULL) != 2) X minusflag = 1; X } X } X } X wrexpr(ex2->args[0], incompat(ex, 0, subprec)); X for (i = 1; i < ex2->nargs; i++) { X if (expr_looks_neg(ex2->args[i]) || minusflag) { X outop("-"); X ex2->args[i] = makeexpr_neg(ex2->args[i]); X } else X outop("+"); X wrexpr(ex2->args[i], incompat(ex, i, subprec)); X } X freeexpr(ex2); X break; X X case EK_LSH: X setprec3(11); X checkbreak(breakbeforearith); X wrexpr(ex->args[0], incompat(ex, 0, subprec)); X outop("<<"); X wrexpr(ex->args[1], incompat(ex, 1, subprec)); X break; X X case EK_RSH: X setprec3(11); X checkbreak(breakbeforearith); X wrexpr(ex->args[0], incompat(ex, 0, subprec)); X outop(">>"); X wrexpr(ex->args[1], incompat(ex, 1, subprec)); X break; X X case EK_LT: X setprec2(10); X checkbreak(breakbeforerel); X wrexpr(ex->args[0], incompat(ex, 0, subprec)); X outop("<"); X wrexpr(ex->args[1], incompat(ex, 0, subprec)); X break; X X case EK_GT: END_OF_FILE if test 48796 -ne `wc -c <'src/pexpr.c.2'`; then echo shar: \"'src/pexpr.c.2'\" unpacked with wrong size! fi # end of 'src/pexpr.c.2' fi echo shar: End of archive 24 \(of 32\). cp /dev/null ark24isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 32 archives. echo "Now see PACKNOTES and the README" rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.