expr.c.1
上传用户:upcnvip
上传日期:2007-01-06
资源大小:474k
文件大小:48k
- /* "p2c", a Pascal to C translator.
- Copyright (C) 1989 David Gillespie.
- Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
- This program 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 (any version).
- This program 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 this program; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- #define PROTO_EXPR_C
- #include "trans.h"
- void free_value(val)
- Value *val;
- {
- if (!val || !val->type)
- return;
- switch (val->type->kind) {
- case TK_STRING:
- case TK_REAL:
- case TK_ARRAY:
- case TK_RECORD:
- case TK_SET:
- if (val->s)
- FREE(val->s);
- break;
- default:
- break;
- }
- }
- Value copyvalue(val)
- Value val;
- {
- char *cp;
- switch (val.type->kind) {
- case TK_STRING:
- case TK_SET:
- if (val.s) {
- cp = ALLOC(val.i+1, char, literals);
- memcpy(cp, val.s, val.i);
- cp[val.i] = 0;
- val.s = cp;
- }
- break;
- case TK_REAL:
- case TK_ARRAY:
- case TK_RECORD:
- if (val.s)
- val.s = stralloc(val.s);
- break;
- default:
- break;
- }
- return val;
- }
- int valuesame(a, b)
- Value a, b;
- {
- if (a.type != b.type)
- return 0;
- switch (a.type->kind) {
- case TK_INTEGER:
- case TK_CHAR:
- case TK_BOOLEAN:
- case TK_ENUM:
- case TK_SMALLSET:
- case TK_SMALLARRAY:
- return (a.i == b.i);
- case TK_STRING:
- case TK_SET:
- return (a.i == b.i && !memcmp(a.s, b.s, a.i));
- case TK_REAL:
- case TK_ARRAY:
- case TK_RECORD:
- return (!strcmp(a.s, b.s));
- default:
- return 1;
- }
- }
- char *value_name(val, intfmt, islong)
- Value val;
- char *intfmt;
- int islong;
- {
- Meaning *mp;
- Type *type = val.type;
- if (type->kind == TK_SUBR)
- type = type->basetype;
- switch (type->kind) {
- case TK_INTEGER:
- case TK_SMALLSET:
- case TK_SMALLARRAY:
- if (!intfmt)
- intfmt = "%ld";
- if (*intfmt == ''') {
- if (val.i >= -'~' && val.i <= -' ') {
- intfmt = format_s("-%s", intfmt);
- val.i = -val.i;
- }
- if (val.i < ' ' || val.i > '~' || islong)
- intfmt = "%ld";
- }
- if (islong)
- intfmt = format_s("%sL", intfmt);
- return format_d(intfmt, val.i);
- case TK_REAL:
- return val.s;
- case TK_ARRAY: /* obsolete */
- case TK_RECORD: /* obsolete */
- return val.s;
- case TK_STRING:
- return makeCstring(val.s, val.i);
- case TK_BOOLEAN:
- if (!intfmt)
- if (val.i == 1 && *name_TRUE &&
- strcmp(name_TRUE, "1") && !islong)
- intfmt = name_TRUE;
- else if (val.i == 0 && *name_FALSE &&
- strcmp(name_FALSE, "0") && !islong)
- intfmt = name_FALSE;
- else
- intfmt = "%ld";
- if (islong)
- intfmt = format_s("%sL", intfmt);
- return format_d(intfmt, val.i);
- case TK_CHAR:
- if (islong)
- return format_d("%ldL", val.i);
- else if ((val.i < 0 || val.i > 127) && highcharints)
- return format_d("%ld", val.i);
- else
- return makeCchar(val.i);
- case TK_POINTER:
- return (*name_NULL) ? name_NULL : "NULL";
- case TK_ENUM:
- mp = val.type->fbase;
- while (mp && mp->val.i != val.i)
- mp = mp->xnext;
- if (!mp) {
- intwarning("value_name", "bad enum value [152]");
- return format_d("%ld", val.i);
- }
- return mp->name;
- default:
- intwarning("value_name", format_s("bad type for constant: %s [153]",
- typekindname(type->kind)));
- return "<spam>";
- }
- }
- Value value_cast(val, type)
- Value val;
- Type *type;
- {
- char buf[20];
- if (type->kind == TK_SUBR)
- type = type->basetype;
- if (val.type == type)
- return val;
- if (type && val.type) {
- switch (type->kind) {
- case TK_REAL:
- if (ord_type(val.type)->kind == TK_INTEGER) {
- sprintf(buf, "%d.0", val.i);
- val.s = stralloc(buf);
- val.type = tp_real;
- return val;
- }
- break;
- case TK_CHAR:
- if (val.type->kind == TK_STRING) {
- if (val.i != 1)
- if (val.i > 0)
- warning("Char constant with more than one character [154]");
- else
- warning("Empty char constant [155]");
- val.i = val.s[0] & 0xff;
- val.s = NULL;
- val.type = tp_char;
- return val;
- }
- case TK_POINTER:
- if (val.type == tp_anyptr && castnull != 1) {
- val.type = type;
- return val;
- }
- default:
- break;
- }
- }
- val.type = NULL;
- return val;
- }
- Type *ord_type(tp)
- Type *tp;
- {
- if (!tp) {
- warning("Expected a constant [127]");
- return tp_integer;
- }
- switch (tp->kind) {
- case TK_SUBR:
- tp = tp->basetype;
- break;
- case TK_STRING:
- if (!CHECKORDEXPR(tp->indextype->smax, 1))
- tp = tp_char;
- break;
- default:
- break;
- }
- return tp;
- }
- int long_type(tp)
- Type *tp;
- {
- switch (tp->kind) {
- case TK_INTEGER:
- return (tp != tp_int && tp != tp_uint && tp != tp_sint);
- case TK_SUBR:
- return (findbasetype(tp, 0) == tp_integer);
- default:
- return 0;
- }
- }
- Value make_ord(type, i)
- Type *type;
- long i;
- {
- Value val;
- if (type->kind == TK_ENUM)
- type = findbasetype(type, 0);
- if (type->kind == TK_SUBR)
- type = type->basetype;
- val.type = type;
- val.i = i;
- val.s = NULL;
- return val;
- }
- long ord_value(val)
- Value val;
- {
- switch (val.type->kind) {
- case TK_INTEGER:
- case TK_ENUM:
- case TK_CHAR:
- case TK_BOOLEAN:
- return val.i;
- case TK_STRING:
- if (val.i == 1)
- return val.s[0] & 0xff;
- /* fall through */
- default:
- warning("Expected an ordinal type [156]");
- return 0;
- }
- }
- void ord_range_expr(type, smin, smax)
- Type *type;
- Expr **smin, **smax;
- {
- if (!type) {
- warning("Expected a constant [127]");
- type = tp_integer;
- }
- if (type->kind == TK_STRING)
- type = tp_char;
- switch (type->kind) {
- case TK_SUBR:
- case TK_INTEGER:
- case TK_ENUM:
- case TK_CHAR:
- case TK_BOOLEAN:
- if (smin) *smin = type->smin;
- if (smax) *smax = type->smax;
- break;
- default:
- warning("Expected an ordinal type [156]");
- if (smin) *smin = makeexpr_long(0);
- if (smax) *smax = makeexpr_long(1);
- break;
- }
- }
- int ord_range(type, smin, smax)
- Type *type;
- long *smin, *smax;
- {
- Expr *emin, *emax;
- Value vmin, vmax;
- ord_range_expr(type, &emin, &emax);
- if (smin) {
- vmin = eval_expr(emin);
- if (!vmin.type)
- return 0;
- }
- if (smax) {
- vmax = eval_expr(emax);
- if (!vmax.type)
- return 0;
- }
- if (smin) *smin = ord_value(vmin);
- if (smax) *smax = ord_value(vmax);
- return 1;
- }
- void freeexpr(ex)
- register Expr *ex;
- {
- register int i;
- if (ex) {
- for (i = 0; i < ex->nargs; i++)
- freeexpr(ex->args[i]);
- switch (ex->kind) {
- case EK_CONST:
- case EK_LONGCONST:
- free_value(&ex->val);
- break;
- case EK_DOT:
- case EK_NAME:
- case EK_BICALL:
- if (ex->val.s)
- FREE(ex->val.s);
- break;
- default:
- break;
- }
- FREE(ex);
- }
- }
- Expr *makeexpr(kind, n)
- enum exprkind kind;
- int n;
- {
- Expr *ex;
- ex = ALLOCV(sizeof(Expr) + (n-1)*sizeof(Expr *), Expr, exprs);
- ex->val.i = 0;
- ex->val.s = NULL;
- ex->kind = kind;
- ex->nargs = n;
- return ex;
- }
- Expr *makeexpr_un(kind, type, arg1)
- enum exprkind kind;
- Type *type;
- Expr *arg1;
- {
- Expr *ex;
- ex = makeexpr(kind, 1);
- ex->val.type = type;
- ex->args[0] = arg1;
- if (debug>2) { fprintf(outf,"makeexpr_un returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_bin(kind, type, arg1, arg2)
- enum exprkind kind;
- Type *type;
- Expr *arg1, *arg2;
- {
- Expr *ex;
- ex = makeexpr(kind, 2);
- ex->val.type = type;
- ex->args[0] = arg1;
- ex->args[1] = arg2;
- if (debug>2) { fprintf(outf,"makeexpr_bin returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_val(val)
- Value val;
- {
- Expr *ex;
- if (val.type->kind == TK_INTEGER &&
- (val.i < -32767 || val.i > 32767) &&
- sizeof_int < 32)
- ex = makeexpr(EK_LONGCONST, 0);
- else
- ex = makeexpr(EK_CONST, 0);
- ex->val = val;
- if (debug>2) { fprintf(outf,"makeexpr_val returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_char(c)
- int c;
- {
- return makeexpr_val(make_ord(tp_char, c));
- }
- Expr *makeexpr_long(i)
- long i;
- {
- return makeexpr_val(make_ord(tp_integer, i));
- }
- Expr *makeexpr_real(r)
- char *r;
- {
- Value val;
- val.type = tp_real;
- val.i = 0;
- val.s = stralloc(r);
- return makeexpr_val(val);
- }
- Expr *makeexpr_lstring(msg, len)
- char *msg;
- int len;
- {
- Value val;
- val.type = tp_str255;
- val.i = len;
- val.s = ALLOC(len+1, char, literals);
- memcpy(val.s, msg, len);
- val.s[len] = 0;
- return makeexpr_val(val);
- }
- Expr *makeexpr_string(msg)
- char *msg;
- {
- Value val;
- val.type = tp_str255;
- val.i = strlen(msg);
- val.s = stralloc(msg);
- return makeexpr_val(val);
- }
- int checkstring(ex, msg)
- Expr *ex;
- char *msg;
- {
- if (!ex || ex->val.type->kind != TK_STRING || ex->kind != EK_CONST)
- return 0;
- if (ex->val.i != strlen(msg))
- return 0;
- return memcmp(ex->val.s, msg, ex->val.i) == 0;
- }
- Expr *makeexpr_var(mp)
- Meaning *mp;
- {
- Expr *ex;
- ex = makeexpr(EK_VAR, 0);
- ex->val.i = (long) mp;
- ex->val.type = mp->type;
- if (debug>2) { fprintf(outf,"makeexpr_var returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_name(name, type)
- char *name;
- Type *type;
- {
- Expr *ex;
- ex = makeexpr(EK_NAME, 0);
- ex->val.s = stralloc(name);
- ex->val.type = type;
- if (debug>2) { fprintf(outf,"makeexpr_name returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_setbits()
- {
- if (*name_SETBITS)
- return makeexpr_name(name_SETBITS, tp_integer);
- else
- return makeexpr_long(setbits);
- }
- /* Note: BICALL's to the following functions should obey the ANSI standard. */
- /* Non-ANSI transformations occur while writing the expression. */
- /* char *sprintf(buf, fmt, ...) [returns buf] */
- /* void *memcpy(dest, src, size) [returns dest] */
- Expr *makeexpr_bicall_0(name, type)
- char *name;
- Type *type;
- {
- Expr *ex;
- if (!name || !*name) {
- intwarning("makeexpr_bicall_0", "Required name of built-in procedure is missing [157]");
- name = "MissingProc";
- }
- ex = makeexpr(EK_BICALL, 0);
- ex->val.s = stralloc(name);
- ex->val.type = type;
- if (debug>2) { fprintf(outf,"makeexpr_bicall returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_bicall_1(name, type, arg1)
- char *name;
- Type *type;
- Expr *arg1;
- {
- Expr *ex;
- if (!name || !*name) {
- intwarning("makeexpr_bicall_1", "Required name of built-in procedure is missing [157]");
- name = "MissingProc";
- }
- ex = makeexpr(EK_BICALL, 1);
- ex->val.s = stralloc(name);
- ex->val.type = type;
- ex->args[0] = arg1;
- if (debug>2) { fprintf(outf,"makeexpr_bicall returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_bicall_2(name, type, arg1, arg2)
- char *name;
- Type *type;
- Expr *arg1, *arg2;
- {
- Expr *ex;
- if (!name || !*name) {
- intwarning("makeexpr_bicall_2", "Required name of built-in procedure is missing [157]");
- name = "MissingProc";
- }
- ex = makeexpr(EK_BICALL, 2);
- if (!strcmp(name, "~SETIO"))
- name = (iocheck_flag) ? "~~SETIO" : name_SETIO;
- ex->val.s = stralloc(name);
- ex->val.type = type;
- ex->args[0] = arg1;
- ex->args[1] = arg2;
- if (debug>2) { fprintf(outf,"makeexpr_bicall returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_bicall_3(name, type, arg1, arg2, arg3)
- char *name;
- Type *type;
- Expr *arg1, *arg2, *arg3;
- {
- Expr *ex;
- if (!name || !*name) {
- intwarning("makeexpr_bicall_3", "Required name of built-in procedure is missing [157]");
- name = "MissingProc";
- }
- ex = makeexpr(EK_BICALL, 3);
- ex->val.s = stralloc(name);
- ex->val.type = type;
- ex->args[0] = arg1;
- ex->args[1] = arg2;
- ex->args[2] = arg3;
- if (debug>2) { fprintf(outf,"makeexpr_bicall returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_bicall_4(name, type, arg1, arg2, arg3, arg4)
- char *name;
- Type *type;
- Expr *arg1, *arg2, *arg3, *arg4;
- {
- Expr *ex;
- if (!name || !*name) {
- intwarning("makeexpr_bicall_4", "Required name of built-in procedure is missing [157]");
- name = "MissingProc";
- }
- ex = makeexpr(EK_BICALL, 4);
- if (!strcmp(name, "~CHKIO"))
- name = (iocheck_flag) ? "~~CHKIO" : name_CHKIO;
- ex->val.s = stralloc(name);
- ex->val.type = type;
- ex->args[0] = arg1;
- ex->args[1] = arg2;
- ex->args[2] = arg3;
- ex->args[3] = arg4;
- if (debug>2) { fprintf(outf,"makeexpr_bicall returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *makeexpr_bicall_5(name, type, arg1, arg2, arg3, arg4, arg5)
- char *name;
- Type *type;
- Expr *arg1, *arg2, *arg3, *arg4, *arg5;
- {
- Expr *ex;
- if (!name || !*name) {
- intwarning("makeexpr_bicall_5", "Required name of built-in procedure is missing [157]");
- name = "MissingProc";
- }
- ex = makeexpr(EK_BICALL, 5);
- ex->val.s = stralloc(name);
- ex->val.type = type;
- ex->args[0] = arg1;
- ex->args[1] = arg2;
- ex->args[2] = arg3;
- ex->args[3] = arg4;
- ex->args[4] = arg5;
- if (debug>2) { fprintf(outf,"makeexpr_bicall returns "); dumpexpr(ex); fprintf(outf,"n"); }
- return ex;
- }
- Expr *copyexpr(ex)
- register Expr *ex;
- {
- register int i;
- register Expr *ex2;
- if (ex) {
- ex2 = makeexpr(ex->kind, ex->nargs);
- for (i = 0; i < ex->nargs; i++)
- ex2->args[i] = copyexpr(ex->args[i]);
- switch (ex->kind) {
- case EK_CONST:
- case EK_LONGCONST:
- ex2->val = copyvalue(ex->val);
- break;
- case EK_DOT:
- case EK_NAME:
- case EK_BICALL:
- ex2->val.type = ex->val.type;
- ex2->val.i = ex->val.i;
- if (ex->val.s)
- ex2->val.s = stralloc(ex->val.s);
- break;
- default:
- ex2->val = ex->val;
- break;
- }
- return ex2;
- } else
- return NULL;
- }
- int exprsame(a, b, strict)
- register Expr *a, *b;
- int strict;
- {
- register int i;
- if (!a)
- return (!b);
- if (!b)
- return 0;
- if (a->val.type != b->val.type && strict != 2) {
- if (strict ||
- !((a->val.type->kind == TK_POINTER &&
- a->val.type->basetype == b->val.type) ||
- (b->val.type->kind == TK_POINTER &&
- b->val.type->basetype == a->val.type)))
- return 0;
- }
- if (a->kind != b->kind || a->nargs != b->nargs)
- return 0;
- switch (a->kind) {
- case EK_CONST:
- case EK_LONGCONST:
- if (!valuesame(a->val, b->val))
- return 0;
- break;
- case EK_BICALL:
- case EK_NAME:
- if (strcmp(a->val.s, b->val.s))
- return 0;
- break;
- case EK_VAR:
- case EK_FUNCTION:
- case EK_CTX:
- case EK_MACARG:
- if (a->val.i != b->val.i)
- return 0;
- break;
- case EK_DOT:
- if (a->val.i != b->val.i ||
- (!a->val.i && strcmp(a->val.s, b->val.s)))
- return 0;
- break;
- default:
- break;
- }
- i = a->nargs;
- while (--i >= 0)
- if (!exprsame(a->args[i], b->args[i], (strict == 2) ? 1 : strict))
- return 0;
- return 1;
- }
- int exprequiv(a, b)
- register Expr *a, *b;
- {
- register int i, j, k;
- enum exprkind kind2;
- if (!a)
- return (!b);
- if (!b)
- return 0;
- switch (a->kind) {
- case EK_PLUS:
- case EK_TIMES:
- case EK_BAND:
- case EK_BOR:
- case EK_BXOR:
- case EK_EQ:
- case EK_NE:
- if (b->kind != a->kind || b->nargs != a->nargs ||
- b->val.type != a->val.type)
- return 0;
- if (a->nargs > 3)
- break;
- for (i = 0; i < b->nargs; i++) {
- if (exprequiv(a->args[0], b->args[i])) {
- for (j = 0; j < b->nargs; j++) {
- if (j != i &&
- exprequiv(a->args[1], b->args[i])) {
- if (a->nargs == 2)
- return 1;
- for (k = 0; k < b->nargs; k++) {
- if (k != i && k != j &&
- exprequiv(a->args[2], b->args[k]))
- return 1;
- }
- }
- }
- }
- }
- break;
- case EK_LT:
- case EK_GT:
- case EK_LE:
- case EK_GE:
- switch (a->kind) {
- case EK_LT: kind2 = EK_GT; break;
- case EK_GT: kind2 = EK_LT; break;
- case EK_LE: kind2 = EK_GE; break;
- default: kind2 = EK_LE; break;
- }
- if (b->kind != kind2 || b->val.type != a->val.type)
- break;
- if (exprequiv(a->args[0], b->args[1]) &&
- exprequiv(a->args[1], b->args[0])) {
- return 1;
- }
- break;
- case EK_CONST:
- case EK_LONGCONST:
- case EK_BICALL:
- case EK_NAME:
- case EK_VAR:
- case EK_FUNCTION:
- case EK_CTX:
- case EK_DOT:
- return exprsame(a, b, 0);
- default:
- break;
- }
- if (b->kind != a->kind || b->nargs != a->nargs ||
- b->val.type != a->val.type)
- return 0;
- i = a->nargs;
- while (--i >= 0)
- if (!exprequiv(a->args[i], b->args[i]))
- return 0;
- return 1;
- }
- void deletearg(ex, n)
- Expr **ex;
- register int n;
- {
- register Expr *ex1 = *ex, *ex2;
- register int i;
- if (debug>2) { fprintf(outf,"deletearg("); dumpexpr(*ex); fprintf(outf,", %d)n", n); }
- if (n < 0 || n >= (*ex)->nargs) {
- intwarning("deletearg", "argument number out of range [158]");
- return;
- }
- ex2 = makeexpr(ex1->kind, ex1->nargs-1);
- ex2->val = ex1->val;
- for (i = 0; i < n; i++)
- ex2->args[i] = ex1->args[i];
- for (; i < ex2->nargs; i++)
- ex2->args[i] = ex1->args[i+1];
- *ex = ex2;
- FREE(ex1);
- if (debug>2) { fprintf(outf,"deletearg returns "); dumpexpr(*ex); fprintf(outf,"n"); }
- }
- void insertarg(ex, n, arg)
- Expr **ex;
- Expr *arg;
- register int n;
- {
- register Expr *ex1 = *ex, *ex2;
- register int i;
- if (debug>2) { fprintf(outf,"insertarg("); dumpexpr(*ex); fprintf(outf,", %d)n", n); }
- if (n < 0 || n > (*ex)->nargs) {
- intwarning("insertarg", "argument number out of range [159]");
- return;
- }
- ex2 = makeexpr(ex1->kind, ex1->nargs+1);
- ex2->val = ex1->val;
- for (i = 0; i < n; i++)
- ex2->args[i] = ex1->args[i];
- ex2->args[n] = arg;
- for (; i < ex1->nargs; i++)
- ex2->args[i+1] = ex1->args[i];
- *ex = ex2;
- FREE(ex1);
- if (debug>2) { fprintf(outf,"insertarg returns "); dumpexpr(*ex); fprintf(outf,"n"); }
- }
- Expr *grabarg(ex, n)
- Expr *ex;
- int n;
- {
- Expr *ex2;
- if (n < 0 || n >= ex->nargs) {
- intwarning("grabarg", "argument number out of range [160]");
- return ex;
- }
- ex2 = ex->args[n];
- ex->args[n] = makeexpr_long(0); /* placeholder */
- freeexpr(ex);
- return ex2;
- }
- void delsimparg(ep, n)
- Expr **ep;
- int n;
- {
- if (n < 0 || n >= (*ep)->nargs) {
- intwarning("delsimparg", "argument number out of range [161]");
- return;
- }
- deletearg(ep, n);
- switch ((*ep)->kind) {
- case EK_PLUS:
- case EK_TIMES:
- case EK_COMMA:
- if ((*ep)->nargs == 1)
- *ep = grabarg(*ep, 0);
- break;
- default:
- break;
- }
- }
- Expr *resimplify(ex)
- Expr *ex;
- {
- Expr *ex2;
- Type *type;
- int i;
- if (debug>2) { fprintf(outf,"resimplify("); dumpexpr(ex); fprintf(outf,")n"); }
- if (!ex)
- return NULL;
- type = ex->val.type;
- switch (ex->kind) {
- case EK_PLUS:
- ex2 = ex->args[0];
- for (i = 1; i < ex->nargs; i++)
- ex2 = makeexpr_plus(ex2, ex->args[i]);
- FREE(ex);
- return ex2;
- case EK_TIMES:
- ex2 = ex->args[0];
- for (i = 1; i < ex->nargs; i++)
- ex2 = makeexpr_times(ex2, ex->args[i]);
- FREE(ex);
- return ex2;
- case EK_NEG:
- ex = makeexpr_neg(grabarg(ex, 0));
- ex->val.type = type;
- return ex;
- case EK_NOT:
- ex = makeexpr_not(grabarg(ex, 0));
- ex->val.type = type;
- return ex;
- case EK_HAT:
- ex = makeexpr_hat(grabarg(ex, 0), 0);
- if (ex->kind == EK_HAT)
- ex->val.type = type;
- return ex;
- case EK_ADDR:
- ex = makeexpr_addr(grabarg(ex, 0));
- ex->val.type = type;
- return ex;
- case EK_ASSIGN:
- ex2 = makeexpr_assign(ex->args[0], ex->args[1]);
- FREE(ex);
- return ex2;
- default:
- break;
- }
- return ex;
- }
- int realzero(s)
- register char *s;
- {
- if (*s == '-') s++;
- while (*s == '0' || *s == '.') s++;
- return (!isdigit(*s));
- }
- int checkconst(ex, val)
- Expr *ex;
- long val;
- {
- Meaning *mp;
- Value exval;
- if (!ex)
- return 0;
- if (ex->kind == EK_CAST || ex->kind == EK_ACTCAST)
- ex = ex->args[0];
- if (ex->kind == EK_CONST || ex->kind == EK_LONGCONST)
- exval = ex->val;
- else if (ex->kind == EK_VAR &&
- (mp = (Meaning *)ex->val.i)->kind == MK_CONST &&
- foldconsts != 0)
- exval = mp->val;
- else
- return 0;
- switch (exval.type->kind) {
- case TK_BOOLEAN:
- case TK_INTEGER:
- case TK_CHAR:
- case TK_ENUM:
- case TK_SUBR:
- case TK_SMALLSET:
- case TK_SMALLARRAY:
- return exval.i == val;
- case TK_POINTER:
- case TK_STRING:
- return (val == 0 && exval.i == 0);
- case TK_REAL:
- return (val == 0 && realzero(exval.s));
- default:
- return 0;
- }
- }
- int isliteralconst(ex, valp)
- Expr *ex;
- Value *valp;
- {
- Meaning *mp;
- if (ex) {
- switch (ex->kind) {
- case EK_CONST:
- case EK_LONGCONST:
- if (valp)
- *valp = ex->val;
- return 2;
- case EK_VAR:
- mp = (Meaning *)ex->val.i;
- if (mp->kind == MK_CONST) {
- if (valp) {
- if (foldconsts == 0)
- valp->type = NULL;
- else
- *valp = mp->val;
- }
- return 1;
- }
- break;
- default:
- break;
- }
- }
- if (valp)
- valp->type = NULL;
- return 0;
- }
- int isconstexpr(ex, valp)
- Expr *ex;
- long *valp;
- {
- Value exval;
- if (debug>2) { fprintf(outf,"isconstexpr("); dumpexpr(ex); fprintf(outf,")n"); }
- exval = eval_expr(ex);
- if (exval.type) {
- if (valp)
- *valp = exval.i;
- return 1;
- } else
- return 0;
- }
- int isconstantexpr(ex)
- Expr *ex;
- {
- Meaning *mp;
- int i;
- switch (ex->kind) {
- case EK_CONST:
- case EK_LONGCONST:
- case EK_SIZEOF:
- return 1;
- case EK_ADDR:
- if (ex->args[0]->kind == EK_VAR) {
- mp = (Meaning *)ex->val.i;
- return (!mp->ctx || mp->ctx->kind == MK_MODULE);
- }
- return 0;
- case EK_VAR:
- mp = (Meaning *)ex->val.i;
- return (mp->kind == MK_CONST);
- case EK_BICALL:
- case EK_FUNCTION:
- if (!deterministic_func(ex))
- return 0;
- /* fall through */
- case EK_EQ:
- case EK_NE:
- case EK_LT:
- case EK_GT:
- case EK_LE:
- case EK_GE:
- case EK_PLUS:
- case EK_NEG:
- case EK_TIMES:
- case EK_DIVIDE:
- case EK_DIV:
- case EK_MOD:
- case EK_AND:
- case EK_OR:
- case EK_NOT:
- case EK_BAND:
- case EK_BOR:
- case EK_BXOR:
- case EK_BNOT:
- case EK_LSH:
- case EK_RSH:
- case EK_CAST:
- case EK_ACTCAST:
- case EK_COND:
- for (i = 0; i < ex->nargs; i++) {
- if (!isconstantexpr(ex->args[i]))
- return 0;
- }
- return 1;
- case EK_COMMA:
- return isconstantexpr(ex->args[ex->nargs-1]);
- default:
- return 0;
- }
- }
- Static Expr *docast(a, type)
- Expr *a;
- Type *type;
- {
- Value val;
- Meaning *mp;
- int i;
- Expr *ex;
- if (a->val.type->kind == TK_SMALLSET && type->kind == TK_SET) {
- mp = makestmttempvar(type, name_SET);
- return makeexpr_bicall_2(setexpandname, type,
- makeexpr_var(mp),
- makeexpr_arglong(a, 1));
- } else if (a->val.type->kind == TK_SET && type->kind == TK_SMALLSET) {
- return packset(a, type);
- }
- switch (a->kind) {
- case EK_VAR:
- mp = (Meaning *) a->val.i;
- if (mp->kind == MK_CONST) {
- if (mp->val.type->kind == TK_STRING && type->kind == TK_CHAR) {
- val = value_cast(mp->val, type);
- a->kind = EK_CONST;
- a->val = val;
- return a;
- }
- }
- break;
- case EK_CONST:
- case EK_LONGCONST:
- val = value_cast(a->val, type);
- if (val.type) {
- a->val = val;
- return a;
- }
- break;
- case EK_PLUS:
- case EK_NEG:
- case EK_TIMES:
- if (type->kind == TK_REAL) {
- for (i = 0; i < a->nargs; i++) {
- ex = docast(a->args[i], type);
- if (ex) {
- a->args[i] = ex;
- a->val.type = type;
- return a;
- }
- }
- }
- break;
- default:
- break;
- }
- return NULL;
- }
- /* Make an "active" cast, i.e., one that performs an explicit operation */
- Expr *makeexpr_actcast(a, type)
- Expr *a;
- Type *type;
- {
- if (debug>2) { fprintf(outf,"makeexpr_actcast("); dumpexpr(a); fprintf(outf,", "); dumptypename(type, 1); fprintf(outf,")n"); }
- if (similartypes(a->val.type, type)) {
- a->val.type = type;
- return a;
- }
- return makeexpr_un(EK_ACTCAST, type, a);
- }
- Expr *makeexpr_cast(a, type)
- Expr *a;
- Type *type;
- {
- Expr *ex;
- if (debug>2) { fprintf(outf,"makeexpr_cast("); dumpexpr(a); fprintf(outf,", "); dumptypename(type, 1); fprintf(outf,")n"); }
- if (a->val.type == type)
- return a;
- ex = docast(a, type);
- if (ex)
- return ex;
- if (a->kind == EK_CAST &&
- a->args[0]->val.type->kind == TK_POINTER &&
- similartypes(type, a->args[0]->val.type)) {
- a = grabarg(a, 0);
- a->val.type = type;
- return a;
- }
- if ((a->kind == EK_CAST &&
- ((a->val.type->kind == TK_POINTER && type->kind == TK_POINTER) ||
- (ord_type(a->val.type)->kind == TK_INTEGER && ord_type(type)->kind == TK_INTEGER))) ||
- similartypes(type, a->val.type)) {
- a->val.type = type;
- return a;
- }
- return makeexpr_un(EK_CAST, type, a);
- }
- Expr *gentle_cast(a, type)
- Expr *a;
- Type *type;
- {
- Expr *ex;
- Type *btype;
- long smin, smax;
- if (debug>2) { fprintf(outf,"gentle_cast("); dumpexpr(a); fprintf(outf,", "); dumptypename(type, 1); fprintf(outf,")n"); }
- if (!type) {
- intwarning("gentle_cast", "type == NULL");
- return a;
- }
- if (a->val.type->kind == TK_POINTER && type->kind == TK_POINTER) {
- if (voidstar && (type == tp_anyptr || a->val.type == tp_anyptr)) {
- if (type == tp_anyptr && a->kind == EK_CAST &&
- a->args[0]->val.type->kind == TK_POINTER)
- return a->args[0]; /* remove explicit cast since casting implicitly */
- return a; /* casting to/from "void *" */
- }
- return makeexpr_cast(a, type);
- }
- if (type->kind == TK_STRING)
- return makeexpr_stringify(a);
- if (type->kind == TK_ARRAY && a->val.type->kind == TK_STRING &&
- a->kind == EK_CONST && ord_range(type->indextype, &smin, &smax)) {
- smax = smax - smin + 1;
- if (a->val.i > smax) {
- warning("Too many characters for packed array of char [162]");
- } else if (a->val.i < smax) {
- ex = makeexpr_lstring(a->val.s, smax);
- while (smax > a->val.i)
- ex->val.s[--smax] = ' ';
- freeexpr(a);
- return ex;
- }
- }
- btype = (type->kind == TK_SUBR) ? type->basetype : type;
- if ((a->kind == EK_CAST || a->kind == EK_ACTCAST) &&
- btype->kind == TK_INTEGER &&
- ord_type(a->val.type)->kind == TK_INTEGER)
- return makeexpr_longcast(a, long_type(type));
- if (a->val.type == btype)
- return a;
- ex = docast(a, btype);
- if (ex)
- return ex;
- if (btype->kind == TK_CHAR && a->val.type->kind == TK_STRING)
- return makeexpr_hat(a, 0);
- return a;
- }
- Expr *makeexpr_charcast(ex)
- Expr *ex;
- {
- Meaning *mp;
- if (ex->kind == EK_CONST && ex->val.type->kind == TK_STRING &&
- ex->val.i == 1) {
- ex->val.type = tp_char;
- ex->val.i = ex->val.s[0] & 0xff;
- ex->val.s = NULL;
- }
- if (ex->kind == EK_VAR &&
- (mp = (Meaning *)ex->val.i)->kind == MK_CONST &&
- mp->val.type->kind == TK_STRING &&
- mp->val.i == 1) {
- ex->kind = EK_CONST;
- ex->val.type = tp_char;
- ex->val.i = mp->val.s[0] & 0xff;
- ex->val.s = NULL;
- }
- return ex;
- }
- Expr *makeexpr_stringcast(ex)
- Expr *ex;
- {
- char ch;
- if (ex->kind == EK_CONST && ord_type(ex->val.type)->kind == TK_CHAR) {
- ch = ex->val.i;
- freeexpr(ex);
- ex = makeexpr_lstring(&ch, 1);
- }
- return ex;
- }
- /* 0/1 = force to int/long, 2/3 = check if int/long */
- Static Expr *dolongcast(a, tolong)
- Expr *a;
- int tolong;
- {
- Meaning *mp;
- Expr *ex;
- Type *type;
- int i;
- switch (a->kind) {
- case EK_DOT:
- if (!a->val.i) {
- if (long_type(a->val.type) == (tolong&1))
- return a;
- break;
- }
- /* fall through */
- case EK_VAR:
- mp = (Meaning *)a->val.i;
- if (mp->kind == MK_FIELD && mp->val.i) {
- if (mp->val.i <= ((sizeof_int > 0) ? sizeof_int : 16) &&
- !(tolong&1))
- return a;
- } else if (mp->kind == MK_VAR ||
- mp->kind == MK_VARREF ||
- mp->kind == MK_PARAM ||
- mp->kind == MK_VARPARAM ||
- mp->kind == MK_FIELD) {
- if (long_type(mp->type) == (tolong&1))
- return a;
- }
- break;
- case EK_FUNCTION:
- mp = (Meaning *)a->val.i;
- if (long_type(mp->type->basetype) == (tolong&1))
- return a;
- break;
- case EK_BICALL:
- if (!strcmp(a->val.s, signextname) && *signextname) {
- i = 0;
- goto unary;
- }
- if (!strcmp(a->val.s, "strlen"))
- goto size_t_case;
- /* fall through */
- case EK_HAT: /* get true type from a->val.type */
- case EK_INDEX:
- case EK_SPCALL:
- case EK_NAME:
- if (long_type(a->val.type) == (tolong&1))
- return a;
- break;
- case EK_ASSIGN: /* destination determines type, */
- case EK_POSTINC: /* but must not be changed */
- case EK_POSTDEC:
- return dolongcast(a->args[0], tolong|2);
- case EK_CAST:
- if (ord_type(a->val.type)->kind == TK_INTEGER &&
- long_type(a->val.type) == (tolong&1))
- return a;
- if (tolong == 0) {
- a->val.type = tp_int;
- return a;
- } else if (tolong == 1) {
- a->val.type = tp_integer;
- return a;
- }
- break;
- case EK_ACTCAST:
- if (ord_type(a->val.type)->kind == TK_INTEGER &&
- long_type(a->val.type) == (tolong&1))
- return a;
- break;
- case EK_CONST:
- type = ord_type(a->val.type);
- if (type->kind == TK_INTEGER || type->kind == TK_SMALLSET) {
- if (tolong == 1)
- a->kind = EK_LONGCONST;
- if (tolong != 3)
- return a;
- }
- break;
- case EK_LONGCONST:
- if (tolong == 0) {
- if (a->val.i >= -32767 && a->val.i <= 32767)
- a->kind = EK_CONST;
- else
- return NULL;
- }
- if (tolong != 2)
- return a;
- break;
- case EK_SIZEOF:
- size_t_case:
- if (size_t_long > 0 && tolong&1)
- return a;
- if (size_t_long == 0 && !(tolong&1))
- return a;
- break;
- case EK_PLUS: /* usual arithmetic conversions apply */
- case EK_TIMES:
- case EK_DIV:
- case EK_MOD:
- case EK_BAND:
- case EK_BOR:
- case EK_BXOR:
- case EK_COND:
- i = (a->kind == EK_COND) ? 1 : 0;
- if (tolong&1) {
- for (; i < a->nargs; i++) {
- ex = dolongcast(a->args[i], tolong);
- if (ex) {
- a->args[i] = ex;
- return a;
- }
- }
- } else {
- for (; i < a->nargs; i++) {
- if (!dolongcast(a->args[i], tolong))
- return NULL;
- }
- return a;
- }
- break;
- case EK_BNOT: /* single argument defines result type */
- case EK_NEG:
- case EK_LSH:
- case EK_RSH:
- case EK_COMMA:
- i = (a->kind == EK_COMMA) ? a->nargs-1 : 0;
- unary:
- if (tolong&1) {
- ex = dolongcast(a->args[i], tolong);
- if (ex) {
- a->args[i] = ex;
- return a;
- }
- } else {
- if (dolongcast(a->args[i], tolong))
- return a;
- }
- break;
- case EK_AND: /* operators which always return int */
- case EK_OR:
- case EK_EQ:
- case EK_NE:
- case EK_LT:
- case EK_GT:
- case EK_LE:
- case EK_GE:
- if (tolong&1)
- break;
- return a;
- default:
- break;
- }
- return NULL;
- }
- /* Return -1 if short int or plain int, 1 if long, 0 if can't tell */
- int exprlongness(ex)
- Expr *ex;
- {
- if (sizeof_int >= 32)
- return -1;
- return (dolongcast(ex, 3) != NULL) -
- (dolongcast(ex, 2) != NULL);
- }
- Expr *makeexpr_longcast(a, tolong)
- Expr *a;
- int tolong;
- {
- Expr *ex;
- Type *type;
- if (sizeof_int >= 32)
- return a;
- type = ord_type(a->val.type);
- if (type->kind != TK_INTEGER && type->kind != TK_SMALLSET)
- return a;
- a = makeexpr_unlongcast(a);
- if (tolong) {
- ex = dolongcast(a, 1);
- } else {
- ex = dolongcast(copyexpr(a), 0);
- if (ex) {
- if (!dolongcast(ex, 2)) {
- freeexpr(ex);
- ex = NULL;
- }
- }
- }
- if (ex)
- return ex;
- return makeexpr_un(EK_CAST, (tolong) ? tp_integer : tp_int, a);
- }
- Expr *makeexpr_arglong(a, tolong)
- Expr *a;
- int tolong;
- {
- int cast = castlongargs;
- if (cast < 0)
- cast = castargs;
- if (cast > 0 || (cast < 0 && prototypes == 0)) {
- return makeexpr_longcast(a, tolong);
- }
- return a;
- }
- Expr *makeexpr_unlongcast(a)
- Expr *a;
- {
- switch (a->kind) {
- case EK_LONGCONST:
- if (a->val.i >= -32767 && a->val.i <= 32767)
- a->kind = EK_CONST;
- break;
- case EK_CAST:
- if ((a->val.type == tp_integer ||
- a->val.type == tp_int) &&
- ord_type(a->args[0]->val.type)->kind == TK_INTEGER) {
- a = grabarg(a, 0);
- }
- break;
- default:
- break;
- }
- return a;
- }
- Expr *makeexpr_forcelongness(a) /* force a to have a definite longness */
- Expr *a;
- {
- Expr *ex;
- ex = makeexpr_unlongcast(copyexpr(a));
- if (exprlongness(ex)) {
- freeexpr(a);
- return ex;
- }
- freeexpr(ex);
- if (exprlongness(a) == 0)
- return makeexpr_longcast(a, 1);
- else
- return a;
- }
- Expr *makeexpr_ord(ex)
- Expr *ex;
- {
- ex = makeexpr_charcast(ex);
- switch (ord_type(ex->val.type)->kind) {
- case TK_ENUM:
- return makeexpr_cast(ex, tp_int);
- case TK_CHAR:
- if (ex->kind == EK_CONST &&
- (ex->val.i >= 32 && ex->val.i < 127)) {
- insertarg(&ex, 0, makeexpr_name("'%lc'", tp_integer));
- }
- ex->val.type = tp_int;
- return ex;
- case TK_BOOLEAN:
- ex->val.type = tp_int;
- return ex;
- case TK_POINTER:
- return makeexpr_cast(ex, tp_integer);
- default:
- return ex;
- }
- }
- /* Tell whether an expression "looks" negative */
- int expr_looks_neg(ex)
- Expr *ex;
- {
- int i;
- switch (ex->kind) {
- case EK_NEG:
- return 1;
- case EK_CONST:
- case EK_LONGCONST:
- switch (ord_type(ex->val.type)->kind) {
- case TK_INTEGER:
- case TK_CHAR:
- return (ex->val.i < 0);
- case TK_REAL:
- return (ex->val.s && ex->val.s[0] == '-');
- default:
- return 0;
- }
- case EK_TIMES:
- case EK_DIVIDE:
- for (i = 0; i < ex->nargs; i++) {
- if (expr_looks_neg(ex->args[i]))
- return 1;
- }
- return 0;
- case EK_CAST:
- return expr_looks_neg(ex->args[0]);
- default:
- return 0;
- }
- }
- /* Tell whether an expression is probably negative */
- int expr_is_neg(ex)
- Expr *ex;
- {
- int i;
- i = possiblesigns(ex) & (1|4);
- if (i == 1)
- return 1; /* if expression really is negative! */
- if (i == 4)
- return 0; /* if expression is definitely positive. */
- return expr_looks_neg(ex);
- }
- int expr_neg_cost(a)
- Expr *a;
- {
- int i, c;
- switch (a->kind) {
- case EK_CONST:
- case EK_LONGCONST:
- switch (ord_type(a->val.type)->kind) {
- case TK_INTEGER:
- case TK_CHAR:
- case TK_REAL:
- return 0;
- default:
- return 1;
- }
- case EK_NEG:
- return -1;
- case EK_TIMES:
- case EK_DIVIDE:
- for (i = 0; i < a->nargs; i++) {
- c = expr_neg_cost(a->args[i]);
- if (c <= 0)
- return c;
- }
- return 1;
- case EK_PLUS:
- for (i = 0; i < a->nargs; i++) {
- if (expr_looks_neg(a->args[i]))
- return 0;
- }
- return 1;
- default:
- return 1;
- }
- }
- Expr *enum_to_int(a)
- Expr *a;
- {
- if (ord_type(a->val.type)->kind == TK_ENUM) {
- if (a->kind == EK_CAST &&
- ord_type(a->args[0]->val.type)->kind == TK_INTEGER)
- return grabarg(a, 0);
- else
- return makeexpr_cast(a, tp_integer);
- } else
- return a;
- }
- Expr *neg_inside_sum(a)
- Expr *a;
- {
- int i;
- for (i = 0; i < a->nargs; i++)
- a->args[i] = makeexpr_neg(a->args[i]);
- return a;
- }
- Expr *makeexpr_neg(a)
- Expr *a;
- {
- int i;
- if (debug>2) { fprintf(outf,"makeexpr_neg("); dumpexpr(a); fprintf(outf,")n"); }
- a = enum_to_int(a);
- switch (a->kind) {
- case EK_CONST:
- case EK_LONGCONST:
- switch (ord_type(a->val.type)->kind) {
- case TK_INTEGER:
- case TK_CHAR:
- if (a->val.i == MININT)
- valrange();
- else
- a->val.i = - a->val.i;
- return a;
- case TK_REAL:
- if (!realzero(a->val.s)) {
- if (a->val.s[0] == '-')
- strchange(&a->val.s, a->val.s+1);
- else
- strchange(&a->val.s, format_s("-%s", a->val.s));
- }
- return a;
- default:
- break;
- }
- break;
- case EK_PLUS:
- if (expr_neg_cost(a) <= 0)
- return neg_inside_sum(a);
- break;
- case EK_TIMES:
- case EK_DIVIDE:
- for (i = 0; i < a->nargs; i++) {
- if (expr_neg_cost(a->args[i]) <= 0) {
- a->args[i] = makeexpr_neg(a->args[i]);
- return a;
- }
- }
- break;
- case EK_CAST:
- if (a->val.type != tp_unsigned &&
- a->val.type != tp_uint &&
- a->val.type != tp_ushort &&
- a->val.type != tp_ubyte &&
- a->args[0]->val.type != tp_unsigned &&
- a->args[0]->val.type != tp_uint &&
- a->args[0]->val.type != tp_ushort &&
- a->args[0]->val.type != tp_ubyte &&
- expr_looks_neg(a->args[0])) {
- a->args[0] = makeexpr_neg(a->args[0]);
- return a;
- }
- break;
- case EK_NEG:
- return grabarg(a, 0);
- default:
- break;
- }
- return makeexpr_un(EK_NEG, promote_type(a->val.type), a);
- }
- #define ISCONST(kind) ((kind)==EK_CONST || (kind)==EK_LONGCONST)
- #define MOVCONST(ex) (ISCONST((ex)->kind) && (ex)->val.type->kind != TK_STRING)
- #define COMMUTATIVE (kind != EK_COMMA && type->kind != TK_REAL)
- Type *true_type(ex)
- Expr *ex;
- {
- Meaning *mp;
- Type *type, *tp;
- while (ex->kind == EK_CAST)
- ex = ex->args[0];
- type = ex->val.type;
- if (ex->kind == EK_VAR || ex->kind == EK_FUNCTION || ex->kind == EK_DOT) {
- mp = (Meaning *)ex->val.i;
- if (mp && mp->type && mp->type->kind != TK_VOID)
- type = mp->type;
- }
- if (ex->kind == EK_INDEX) {
- tp = true_type(ex->args[0]);
- if ((tp->kind == TK_ARRAY || tp->kind == TK_SMALLARRAY ||
- tp->kind == TK_STRING) &&
- tp->basetype && tp->basetype->kind != TK_VOID)
- type = tp->basetype;
- }
- if (type->kind == TK_SUBR)
- type = findbasetype(type, 0);
- return type;
- }
- int ischartype(ex)
- Expr *ex;
- {
- if (ord_type(ex->val.type)->kind == TK_CHAR)
- return 1;
- if (true_type(ex)->kind == TK_CHAR)
- return 1;
- if (ISCONST(ex->kind) && ex->nargs > 0 &&
- ex->args[0]->kind == EK_NAME &&
- ex->args[0]->val.s[0] == ''')
- return 1;
- return 0;
- }
- Static Expr *commute(a, b, kind)
- Expr *a, *b;
- enum exprkind kind;
- {
- int i, di;
- Type *type;
- if (debug>2) { fprintf(outf,"commute("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")n"); }
- #if 1
- type = promote_type_bin(a->val.type, b->val.type);
- #else
- type = a->val.type;
- if (b->val.type->kind == TK_REAL)
- type = b->val.type;
- #endif
- if (MOVCONST(a) && !MOVCONST(b) && COMMUTATIVE)
- swapexprs(a, b); /* put constant last */
- if (a->kind == kind) {
- di = (MOVCONST(a->args[a->nargs-1]) && COMMUTATIVE) ? -1 : 0;
- if (b->kind == kind) {
- for (i = 0; i < b->nargs; i++)
- insertarg(&a, a->nargs + di, b->args[i]);
- FREE(b);
- } else
- insertarg(&a, a->nargs + di, b);
- a->val.type = type;
- } else if (b->kind == kind) {
- if (MOVCONST(a) && COMMUTATIVE)
- insertarg(&b, b->nargs, a);
- else
- insertarg(&b, 0, a);
- a = b;
- a->val.type = type;
- } else {
- a = makeexpr_bin(kind, type, a, b);
- }
- if (debug>2) { fprintf(outf,"commute returns "); dumpexpr(a); fprintf(outf,"n"); }
- return a;
- }
- Expr *makeexpr_plus(a, b)
- Expr *a, *b;
- {
- int i, j, k;
- Type *type;
- if (debug>2) { fprintf(outf,"makeexpr_plus("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")n"); }
- if (!a)
- return b;
- if (!b)
- return a;
- if (a->kind == EK_NEG && a->args[0]->kind == EK_PLUS)
- a = neg_inside_sum(grabarg(a, 0));
- if (b->kind == EK_NEG && b->args[0]->kind == EK_PLUS)
- b = neg_inside_sum(grabarg(b, 0));
- a = commute(enum_to_int(a), enum_to_int(b), EK_PLUS);
- type = NULL;
- for (i = 0; i < a->nargs; i++) {
- if (ord_type(a->args[i]->val.type)->kind == TK_CHAR ||
- a->args[i]->val.type->kind == TK_POINTER ||
- a->args[i]->val.type->kind == TK_STRING) { /* for string literals */
- if (type == ord_type(a->args[i]->val.type))
- type = tp_integer; /* 'z'-'a' and p1-p2 are integers */
- else
- type = ord_type(a->args[i]->val.type);
- }
- }
- if (type)
- a->val.type = type;
- for (i = 0; i < a->nargs && !ISCONST(a->args[i]->kind); i++) ;
- if (i < a->nargs-1) {
- for (j = i+1; j < a->nargs; j++) {
- if (ISCONST(a->args[j]->kind)) {
- if ((ord_type(a->args[i]->val.type) == ord_type(a->args[j]->val.type) ||
- ord_type(a->args[i]->val.type)->kind == TK_INTEGER ||
- ord_type(a->args[j]->val.type)->kind == TK_INTEGER) &&
- (!ischartype(a->args[i]) || !ischartype(a->args[j])) &&
- (a->args[i]->val.type->kind != TK_REAL &&
- a->args[i]->val.type->kind != TK_STRING &&
- a->args[j]->val.type->kind != TK_REAL &&
- a->args[j]->val.type->kind != TK_STRING)) {
- a->args[i]->val.i += a->args[j]->val.i;
- delfreearg(&a, j);
- j--;
- } else if (a->args[i]->val.type->kind == TK_STRING &&
- ord_type(a->args[j]->val.type)->kind == TK_INTEGER &&
- a->args[j]->val.i < 0 &&
- a->args[j]->val.i >= -stringleaders) {
- /* strictly speaking, the following is illegal pointer arithmetic */
- a->args[i] = makeexpr_lstring(a->args[i]->val.s + a->args[j]->val.i,