home *** CD-ROM | disk | FTP | other *** search
- /* "p2c", a Pascal to C translator.
- Copyright (C) 1989, 1990, 1991 Free Software Foundation.
- 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, ODECL_NOPRES) == tp_integer);
-
- default:
- return 0;
- }
- }
-
-
-
- Value make_ord(type, i)
- Type *type;
- long i;
- {
- Value val;
-
- if (type->kind == TK_ENUM)
- type = findbasetype(type, ODECL_NOPRES);
- 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 realint(s, i)
- register char *s;
- int i;
- {
- if (i == 0)
- return realzero(s);
- if (*s == '-') {
- s++;
- i = -i;
- }
- if (i < 0 || i > 9) return 0; /* we don't care about large values here */
- while (*s == '0') s++;
- if (*s++ != i + '0') return 0;
- if (*s == '.')
- while (*++s == '0') ;
- 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 &&
- mp->val.type &&
- 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 realint(exval.s, val);
-
- 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 && 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;
- Value val;
- char c;
-
- 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->val.type->kind == TK_CHAR) &&
- isliteralconst(a, &val) && val.type &&
- ord_range(type->indextype, &smin, &smax)) {
- smax = smax - smin + 1;
- if (a->val.type->kind == TK_CHAR) {
- val.s = &c;
- c = val.i;
- val.i = 1;
- }
- if (val.i > smax) {
- warning("Too many characters for packed array of char [162]");
- } else if (val.i < smax || a->val.type->kind == TK_CHAR) {
- ex = makeexpr_lstring(val.s, smax);
- while (smax > 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 &&
- 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, ODECL_NOPRES);
- 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, castdouble = 0;
- 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.i == - a->args[j]->val.i ||
- a->args[i]->val.i == 0 || a->args[j]->val.i == 0) &&
- (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,
- a->args[i]->val.i - a->args[j]->val.i);
- for (k = 0; k < - a->args[j]->val.i; k++)
- a->args[i]->val.s[k] = '>';
- delfreearg(&a, j);
- j--;
- }
- }
- }
- }
- if (checkconst(a->args[a->nargs-1], 0)) {
- if (a->args[a->nargs-1]->val.type->kind == TK_REAL &&
- a->args[0]->val.type->kind != TK_REAL)
- castdouble = 1;
- delfreearg(&a, a->nargs-1);
- }
- for (i = 0; i < a->nargs; i++) {
- if (a->args[i]->kind == EK_NEG && nosideeffects(a->args[i], 1)) {
- for (j = 0; j < a->nargs; j++) {
- if (exprsame(a->args[j], a->args[i]->args[0], 1)) {
- delfreearg(&a, i);
- if (i < j) j--; else i--;
- delfreearg(&a, j);
- i--;
- break;
- }
- }
- }
- }
- if (a->nargs == 0) {
- type = a->val.type;
- FREE(a);
- a = gentle_cast(makeexpr_long(0), type);
- a->val.type = type;
- return a;
- } else if (a->nargs == 1) {
- b = a->args[0];
- FREE(a);
- a = b;
- } else {
- if (a->nargs == 2 && ISCONST(a->args[1]->kind) &&
- a->args[1]->val.i <= -127 &&
- true_type(a->args[0]) == tp_char && signedchars != 0) {
- a->args[0] = force_unsigned(a->args[0]);
- }
- if (a->nargs > 2 &&
- ISCONST(a->args[a->nargs-1]->kind) &&
- ISCONST(a->args[a->nargs-2]->kind) &&
- ischartype(a->args[a->nargs-1]) &&
- ischartype(a->args[a->nargs-2])) {
- i = a->args[a->nargs-1]->val.i;
- j = a->args[a->nargs-2]->val.i;
- if ((i == 'a' || i == 'A' || i == -'a' || i == -'A') &&
- (j == 'a' || j == 'A' || j == -'a' || j == -'A')) {
- if (abs(i+j) == 32) {
- delfreearg(&a, a->nargs-1);
- delsimpfreearg(&a, a->nargs-1);
- a = makeexpr_bicall_1((i+j > 0) ? "_tolower" : "_toupper",
- tp_char, a);
- }
- }
- }
- }
- if (castdouble)
- a = makeexpr_cast(a, tp_real);
- return a;
- }
-
-
- Expr *makeexpr_minus(a, b)
- Expr *a, *b;
- {
- int okneg;
-
- if (debug>2) { fprintf(outf,"makeexpr_minus("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); }
- if (ISCONST(b->kind) && b->val.i == 0 && /* kludge for array indexing */
- ord_type(b->val.type)->kind == TK_ENUM) {
- b->val.type = tp_integer;
- }
- okneg = (a->kind != EK_PLUS && b->kind != EK_PLUS);
- a = makeexpr_plus(a, makeexpr_neg(b));
- if (okneg && a->kind == EK_PLUS)
- a->val.i = 1; /* this flag says to write as "a-b" if possible */
- return a;
- }
-
-
- Expr *makeexpr_inc(a, b)
- Expr *a, *b;
- {
- Type *type;
-
- type = a->val.type;
- a = makeexpr_plus(makeexpr_charcast(a), b);
- if (ord_type(type)->kind != TK_INTEGER &&
- ord_type(type)->kind != TK_CHAR)
- a = makeexpr_cast(a, type);
- return a;
- }
-
-
-
- /* Apply the distributive law for a sum of products */
- Expr *distribute_plus(ex)
- Expr *ex;
- {
- int i, j, icom;
- Expr *common, *outer, *ex2, **exp;
-
- if (debug>2) { fprintf(outf,"distribute_plus("); dumpexpr(ex); fprintf(outf,")\n"); }
- if (ex->kind != EK_PLUS)
- return ex;
- for (i = 0; i < ex->nargs; i++)
- if (ex->args[i]->kind == EK_TIMES)
- break;
- if (i == ex->nargs)
- return ex;
- outer = NULL;
- icom = 0;
- for (;;) {
- ex2 = ex->args[0];
- if (ex2->kind == EK_NEG)
- ex2 = ex2->args[0];
- if (ex2->kind == EK_TIMES) {
- if (icom >= ex2->nargs)
- break;
- common = ex2->args[icom];
- if (common->kind == EK_NEG)
- common = common->args[0];
- } else {
- if (icom > 0)
- break;
- common = ex2;
- icom++;
- }
- for (i = 1; i < ex->nargs; i++) {
- ex2 = ex->args[i];
- if (ex2->kind == EK_NEG)
- ex2 = ex2->args[i];
- if (ex2->kind == EK_TIMES) {
- for (j = ex2->nargs; --j >= 0; ) {
- if (exprsame(ex2->args[j], common, 1) ||
- (ex2->args[j]->kind == EK_NEG &&
- exprsame(ex2->args[j]->args[0], common, 1)))
- break;
- }
- if (j < 0)
- break;
- } else {
- if (!exprsame(ex2, common, 1))
- break;
- }
- }
- if (i == ex->nargs) {
- if (debug>2) { fprintf(outf,"distribute_plus does "); dumpexpr(common); fprintf(outf,"\n"); }
- common = copyexpr(common);
- for (i = 0; i < ex->nargs; i++) {
- if (ex->args[i]->kind == EK_NEG)
- ex2 = *(exp = &ex->args[i]->args[0]);
- else
- ex2 = *(exp = &ex->args[i]);
- if (ex2->kind == EK_TIMES) {
- for (j = ex2->nargs; --j >= 0; ) {
- if (exprsame(ex2->args[j], common, 1)) {
- delsimpfreearg(exp, j);
- break;
- } else if (ex2->args[j]->kind == EK_NEG &&
- exprsame(ex2->args[j]->args[0], common,1)) {
- freeexpr(ex2->args[j]);
- ex2->args[j] = makeexpr_long(-1);
- break;
- }
- }
- } else {
- freeexpr(ex2);
- *exp = makeexpr_long(1);
- }
- ex->args[i] = resimplify(ex->args[i]);
- }
- outer = makeexpr_times(common, outer);
- } else
- icom++;
- }
- return makeexpr_times(resimplify(ex), outer);
- }
-
-
-
-
-
- Expr *makeexpr_times(a, b)
- Expr *a, *b;
- {
- int i, n, castdouble = 0;
- Type *type;
-
- if (debug>2) { fprintf(outf,"makeexpr_times("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); }
- if (!a)
- return b;
- if (!b)
- return a;
- a = commute(a, b, EK_TIMES);
- if (a->val.type->kind == TK_INTEGER) {
- i = a->nargs-1;
- if (i > 0 && ISCONST(a->args[i-1]->kind)) {
- a->args[i-1]->val.i *= a->args[i]->val.i;
- delfreearg(&a, i);
- }
- }
- for (i = n = 0; i < a->nargs; i++) {
- if (expr_neg_cost(a->args[i]) < 0)
- n++;
- }
- if (n & 1) {
- for (i = 0; i < a->nargs; i++) {
- if (ISCONST(a->args[i]->kind) &&
- expr_neg_cost(a->args[i]) >= 0) {
- a->args[i] = makeexpr_neg(a->args[i]);
- n++;
- break;
- }
- }
- } else
- n++;
- for (i = 0; i < a->nargs && n >= 2; i++) {
- if (expr_neg_cost(a->args[i]) < 0) {
- a->args[i] = makeexpr_neg(a->args[i]);
- n--;
- }
- }
- if (checkconst(a->args[a->nargs-1], 1)) {
- if (a->args[a->nargs-1]->val.type->kind == TK_REAL &&
- a->args[0]->val.type->kind != TK_REAL)
- castdouble = 1;
- delfreearg(&a, a->nargs-1);
- } else if (checkconst(a->args[a->nargs-1], -1)) {
- if (a->args[a->nargs-1]->val.type->kind == TK_REAL &&
- a->args[0]->val.type->kind != TK_REAL)
- castdouble = 1;
- delfreearg(&a, a->nargs-1);
- a->args[0] = makeexpr_neg(a->args[0]);
- } else if (checkconst(a->args[a->nargs-1], 0) && nosideeffects(a, 1)) {
- if (a->args[a->nargs-1]->val.type->kind == TK_REAL)
- type = a->args[a->nargs-1]->val.type;
- else
- type = a->val.type;
- return makeexpr_cast(grabarg(a, a->nargs-1), type);
- }
- if (a->nargs < 2) {
- if (a->nargs < 1) {
- FREE(a);
- a = makeexpr_long(1);
- } else {
- b = a->args[0];
- FREE(a);
- a = b;
- }
- }
- if (castdouble)
- a = makeexpr_cast(a, tp_real);
- return a;
- }
-
-
-
- Expr *makeexpr_sqr(ex, cube)
- Expr *ex;
- int cube;
- {
- Expr *ex2;
- Meaning *tvar;
- Type *type;
-
- if (exprspeed(ex) <= 2 && nosideeffects(ex, 0)) {
- ex2 = NULL;
- } else {
- type = (ex->val.type->kind == TK_REAL) ? tp_longreal : tp_integer;
- tvar = makestmttempvar(type, name_TEMP);
- ex2 = makeexpr_assign(makeexpr_var(tvar), ex);
- ex = makeexpr_var(tvar);
- }
- if (cube)
- ex = makeexpr_times(ex, makeexpr_times(copyexpr(ex), copyexpr(ex)));
- else
- ex = makeexpr_times(ex, copyexpr(ex));
- return makeexpr_comma(ex2, ex);
- }
-
-
-
- Expr *makeexpr_divide(a, b)
- Expr *a, *b;
- {
- Expr *ex;
- int p;
-
- if (debug>2) { fprintf(outf,"makeexpr_divide("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); }
- if (a->val.type->kind != TK_REAL &&
- b->val.type->kind != TK_REAL) { /* must do a real division */
- ex = docast(a, tp_longreal);
- if (ex)
- a = ex;
- else {
- ex = docast(b, tp_longreal);
- if (ex)
- b = ex;
- else
- a = makeexpr_cast(a, tp_longreal);
- }
- }
- if (a->kind == EK_TIMES) {
- for (p = 0; p < a->nargs; p++)
- if (exprsame(a->args[p], b, 1))
- break;
- if (p < a->nargs) {
- delfreearg(&a, p);
- freeexpr(b);
- if (a->nargs == 1)
- return grabarg(a, 0);
- else
- return a;
- }
- }
- if (expr_neg_cost(a) < 0 && expr_neg_cost(b) < 0) {
- a = makeexpr_neg(a);
- b = makeexpr_neg(b);
- }
- if (checkconst(b, 0))
- warning("Division by zero [163]");
- return makeexpr_bin(EK_DIVIDE, tp_longreal, a, b);
- }
-
-
-
-
- int gcd(a, b)
- int a, b;
- {
- if (a < 0) a = -a;
- if (b < 0) b = -b;
- while (a != 0) {
- b %= a;
- if (b != 0)
- a %= b;
- else
- return a;
- }
- return b;
- }
-
-
-
- /* possible signs of ex: 1=may be neg, 2=may be zero, 4=may be pos */
-
- int negsigns(mask)
- int mask;
- {
- return (mask & 2) |
- ((mask & 1) << 2) |
- ((mask & 4) >> 2);
- }
-
-
- int possiblesigns(ex)
- Expr *ex;
- {
- Value val;
- Type *tp;
- char *cp;
- int i, mask, mask2;
-
- if (isliteralconst(ex, &val) && val.type) {
- if (val.type == tp_real || val.type == tp_longreal) {
- if (realzero(val.s))
- return 2;
- if (*val.s == '-')
- return 1;
- return 4;
- } else
- return (val.i < 0) ? 1 : (val.i == 0) ? 2 : 4;
- }
- if (ex->kind == EK_CAST &&
- similartypes(ex->val.type, ex->args[0]->val.type))
- return possiblesigns(ex->args[0]);
- if (ex->kind == EK_NEG)
- return negsigns(possiblesigns(ex->args[0]));
- if (ex->kind == EK_TIMES || ex->kind == EK_DIVIDE) {
- mask = possiblesigns(ex->args[0]);
- for (i = 1; i < ex->nargs; i++) {
- mask2 = possiblesigns(ex->args[i]);
- if (mask2 & 2)
- mask |= 2;
- if ((mask2 & (1|4)) == 1)
- mask = negsigns(mask);
- else if ((mask2 & (1|4)) != 4)
- mask = 1|2|4;
- }
- return mask;
- }
- if (ex->kind == EK_DIV || ex->kind == EK_MOD) {
- mask = possiblesigns(ex->args[0]);
- mask2 = possiblesigns(ex->args[1]);
- if (!((mask | mask2) & 1))
- return 2|4;
- }
- if (ex->kind == EK_PLUS) {
- mask = 0;
- for (i = 0; i < ex->nargs; i++) {
- mask2 = possiblesigns(ex->args[i]);
- if ((mask & negsigns(mask2)) & (1|4))
- mask |= (1|2|4);
- else
- mask |= mask2;
- }
- return mask;
- }
- if (ex->kind == EK_COND) {
- return possiblesigns(ex->args[1]) | possiblesigns(ex->args[2]);
- }
- if (ex->kind == EK_EQ || ex->kind == EK_LT || ex->kind == EK_GT ||
- ex->kind == EK_NE || ex->kind == EK_LE || ex->kind == EK_GE ||
- ex->kind == EK_AND || ex->kind == EK_OR || ex->kind == EK_NOT)
- return 2|4;
- if (ex->kind == EK_BICALL) {
- cp = ex->val.s;
- if (!strcmp(cp, "strlen") ||
- !strcmp(cp, "abs") ||
- !strcmp(cp, "labs") ||
- !strcmp(cp, "fabs"))
- return 2|4;
- }
- tp = (ex->kind == EK_VAR) ? ((Meaning *)ex->val.i)->type : ex->val.type;
- if (ord_range(ex->val.type, &val.i, NULL)) {
- if (val.i > 0)
- return 4;
- if (val.i >= 0)
- return 2|4;
- }
- if (ord_range(ex->val.type, NULL, &val.i)) {
- if (val.i < 0)
- return 1;
- if (val.i <= 0)
- return 1|2;
- }
- return 1|2|4;
- }
-
-
-
-
-
- Expr *dodivmod(funcname, ekind, a, b)
- char *funcname;
- enum exprkind ekind;
- Expr *a, *b;
- {
- Meaning *tvar;
- Type *type;
- Expr *asn;
- int sa, sb;
-
- type = promote_type_bin(a->val.type, b->val.type);
- tvar = NULL;
- sa = possiblesigns(a);
- sb = possiblesigns(b);
- if ((sa & 1) || (sb & 1)) {
- if (*funcname) {
- asn = NULL;
- if (*funcname == '*') {
- if (exprspeed(a) >= 5 || !nosideeffects(a, 0)) {
- tvar = makestmttempvar(a->val.type, name_TEMP);
- asn = makeexpr_assign(makeexpr_var(tvar), a);
- a = makeexpr_var(tvar);
- }
- if (exprspeed(b) >= 5 || !nosideeffects(b, 0)) {
- tvar = makestmttempvar(b->val.type, name_TEMP);
- asn = makeexpr_comma(asn,
- makeexpr_assign(makeexpr_var(tvar),
- b));
- b = makeexpr_var(tvar);
- }
- }
- return makeexpr_comma(asn,
- makeexpr_bicall_2(funcname, type, a, b));
- } else {
- if ((sa & 1) && (ekind == EK_MOD))
- note("Using % for possibly-negative arguments [317]");
- return makeexpr_bin(ekind, type, a, b);
- }
- } else
- return makeexpr_bin(ekind, type, a, b);
- }
-
-
-
- Expr *makeexpr_div(a, b)
- Expr *a, *b;
- {
- Meaning *mp;
- Type *type;
- long i;
- int p;
-
- if (ISCONST(a->kind) && ISCONST(b->kind)) {
- if (a->val.i >= 0 && b->val.i > 0) {
- a->val.i /= b->val.i;
- freeexpr(b);
- return a;
- }
- i = gcd(a->val.i, b->val.i);
- if (i >= 0) {
- a->val.i /= i;
- b->val.i /= i;
- }
- }
- if (((b->kind == EK_CONST && (i = b->val.i)) ||
- (b->kind == EK_VAR && (mp = (Meaning *)b->val.i)->kind == MK_CONST &&
- mp->val.type && (i = mp->val.i) && foldconsts != 0)) && i > 0) {
- if (i == 1)
- return a;
- if (div_po2 > 0) {
- p = 0;
- while (!(i&1))
- p++, i >>= 1;
- if (i == 1) {
- type = promote_type_bin(a->val.type, b->val.type);
- return makeexpr_bin(EK_RSH, type, a, makeexpr_long(p));
- }
- }
- }
- if (a->kind == EK_TIMES) {
- for (p = 0; p < a->nargs; p++) {
- if (exprsame(a->args[p], b, 1)) {
- delfreearg(&a, p);
- freeexpr(b);
- if (a->nargs == 1)
- return grabarg(a, 0);
- else
- return a;
- } else if (ISCONST(a->args[p]->kind) && ISCONST(b->kind)) {
- i = gcd(a->args[p]->val.i, b->val.i);
- if (i > 1) {
- a->args[p]->val.i /= i;
- b->val.i /= i;
- i = a->args[p]->val.i;
- delfreearg(&a, p);
- a = makeexpr_times(a, makeexpr_long(i)); /* resimplify */
- p = -1; /* start the loop over */
- }
- }
- }
- }
- if (checkconst(b, 1)) {
- freeexpr(b);
- return a;
- } else if (checkconst(b, -1)) {
- freeexpr(b);
- return makeexpr_neg(a);
- } else {
- if (checkconst(b, 0))
- warning("Division by zero [163]");
- return dodivmod(divname, EK_DIV, a, b);
- }
- }
-
-
-
- Expr *makeexpr_mod(a, b)
- Expr *a, *b;
- {
- Meaning *mp;
- Type *type;
- long i;
-
- if (a->kind == EK_CONST && b->kind == EK_CONST &&
- a->val.i >= 0 && b->val.i > 0) {
- a->val.i %= b->val.i;
- freeexpr(b);
- return a;
- }
- if (((b->kind == EK_CONST && (i = b->val.i)) ||
- (b->kind == EK_VAR && (mp = (Meaning *)b->val.i)->kind == MK_CONST &&
- mp->val.type && (i = mp->val.i) && foldconsts != 0)) && i > 0) {
- if (i == 1)
- return makeexpr_long(0);
- if (mod_po2 != 0) {
- while (!(i&1))
- i >>= 1;
- if (i == 1) {
- type = promote_type_bin(a->val.type, b->val.type);
- return makeexpr_bin(EK_BAND, type, a,
- makeexpr_minus(b, makeexpr_long(1)));
- }
- }
- }
- if (checkconst(b, 0))
- warning("Division by zero [163]");
- return dodivmod(modname, EK_MOD, a, b);
- }
-
-
-
- Expr *makeexpr_rem(a, b)
- Expr *a, *b;
- {
- if (!(possiblesigns(a) & 1) && !(possiblesigns(b) & 1))
- return makeexpr_mod(a, b);
- if (checkconst(b, 0))
- warning("Division by zero [163]");
- if (!*remname)
- note("Translating REM same as MOD [141]");
- return dodivmod(*remname ? remname : modname, EK_MOD, a, b);
- }
-
-
-
-
-
- int expr_not_cost(a)
- Expr *a;
- {
- int i, c;
-
- switch (a->kind) {
-
- case EK_CONST:
- return 0;
-
- case EK_NOT:
- return -1;
-
- case EK_EQ:
- case EK_NE:
- case EK_LT:
- case EK_GT:
- case EK_LE:
- case EK_GE:
- return 0;
-
- case EK_AND:
- case EK_OR:
- c = 0;
- for (i = 0; i < a->nargs; i++)
- c += expr_not_cost(a->args[i]);
- return (c > 1) ? 1 : c;
-
- case EK_BICALL:
- if (!strcmp(a->val.s, oddname) ||
- !strcmp(a->val.s, evenname))
- return 0;
- return 1;
-
- default:
- return 1;
- }
- }
-
-
-
- Expr *makeexpr_not(a)
- Expr *a;
- {
- Expr *ex;
- int i;
-
- if (debug>2) { fprintf(outf,"makeexpr_not("); dumpexpr(a); fprintf(outf,")\n"); }
- switch (a->kind) {
-
- case EK_CONST:
- if (a->val.type == tp_boolean) {
- a->val.i = !a->val.i;
- return a;
- }
- break;
-
- case EK_EQ:
- a->kind = EK_NE;
- return a;
-
- case EK_NE:
- a->kind = EK_EQ;
- return a;
-
- case EK_LT:
- a->kind = EK_GE;
- return a;
-
- case EK_GT:
- a->kind = EK_LE;
- return a;
-
- case EK_LE:
- a->kind = EK_GT;
- return a;
-
- case EK_GE:
- a->kind = EK_LT;
- return a;
-
- case EK_AND:
- case EK_OR:
- if (expr_not_cost(a) > 0)
- break;
- a->kind = (a->kind == EK_OR) ? EK_AND : EK_OR;
- for (i = 0; i < a->nargs; i++)
- a->args[i] = makeexpr_not(a->args[i]);
- return a;
-
- case EK_NOT:
- ex = a->args[0];
- FREE(a);
- ex->val.type = tp_boolean;
- return ex;
-
- case EK_BICALL:
- if (!strcmp(a->val.s, oddname) && *evenname) {
- strchange(&a->val.s, evenname);
- return a;
- } else if (!strcmp(a->val.s, evenname)) {
- strchange(&a->val.s, oddname);
- return a;
- }
- break;
-
- default:
- break;
- }
- return makeexpr_un(EK_NOT, tp_boolean, a);
- }
-
-
-
-
- Type *mixsets(ep1, ep2)
- Expr **ep1, **ep2;
- {
- Expr *ex1 = *ep1, *ex2 = *ep2;
- Meaning *tvar;
- long min1, max1, min2, max2;
- Type *type;
-
- if (ex1->val.type->kind == TK_SMALLSET &&
- ex2->val.type->kind == TK_SMALLSET)
- return ex1->val.type;
- if (ex1->val.type->kind == TK_SMALLSET) {
- tvar = makestmttempvar(ex2->val.type, name_SET);
- ex1 = makeexpr_bicall_2(setexpandname, ex2->val.type,
- makeexpr_var(tvar),
- makeexpr_arglong(ex1, 1));
- }
- if (ex2->val.type->kind == TK_SMALLSET) {
- tvar = makestmttempvar(ex1->val.type, name_SET);
- ex2 = makeexpr_bicall_2(setexpandname, ex1->val.type,
- makeexpr_var(tvar),
- makeexpr_arglong(ex2, 1));
- }
- if (ord_range(ex1->val.type->indextype, &min1, &max1) &&
- ord_range(ex2->val.type->indextype, &min2, &max2)) {
- if (min1 <= min2 && max1 >= max2)
- type = ex1->val.type;
- else if (min2 <= min1 && max2 >= max1)
- type = ex2->val.type;
- else {
- if (min2 < min1) min1 = min2;
- if (max2 > max1) max1 = max2;
- type = maketype(TK_SET);
- type->basetype = tp_integer;
- type->indextype = maketype(TK_SUBR);
- type->indextype->basetype = ord_type(ex1->val.type->indextype);
- type->indextype->smin = makeexpr_long(min1);
- type->indextype->smax = makeexpr_long(max1);
- }
- } else
- type = ex1->val.type;
- *ep1 = ex1, *ep2 = ex2;
- return type;
- }
-
-
-
- Meaning *istempprocptr(ex)
- Expr *ex;
- {
- Meaning *mp;
-
- if (debug>2) { fprintf(outf,"istempprocptr("); dumpexpr(ex); fprintf(outf,")\n"); }
- if (ex->kind == EK_COMMA && ex->nargs == 3) {
- if ((mp = istempvar(ex->args[2])) != NULL &&
- mp->type->kind == TK_PROCPTR &&
- ex->args[0]->kind == EK_ASSIGN &&
- ex->args[0]->args[0]->kind == EK_DOT &&
- exprsame(ex->args[0]->args[0]->args[0], ex->args[2], 1) &&
- ex->args[1]->kind == EK_ASSIGN &&
- ex->args[1]->args[0]->kind == EK_DOT &&
- exprsame(ex->args[1]->args[0]->args[0], ex->args[2], 1))
- return mp;
- }
- if (ex->kind == EK_COMMA && ex->nargs == 2) {
- if ((mp = istempvar(ex->args[1])) != NULL &&
- mp->type->kind == TK_CPROCPTR &&
- ex->args[0]->kind == EK_ASSIGN &&
- exprsame(ex->args[0]->args[0], ex->args[1], 1))
- return mp;
- }
- return NULL;
- }
-
-
-
-
- Expr *makeexpr_stringify(ex)
- Expr *ex;
- {
- ex = makeexpr_stringcast(ex);
- if (ex->val.type->kind == TK_STRING)
- return ex;
- return makeexpr_sprintfify(ex);
- }
-
-
-
- Expr *makeexpr_rel(rel, a, b)
- enum exprkind rel;
- Expr *a, *b;
- {
- int i, sign;
- Expr *ex, *ex2;
- Meaning *mp;
- char *name;
-
- if (debug>2) { fprintf(outf,"makeexpr_rel(%s,", exprkindname(rel)); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); }
-
- a = makeexpr_unlongcast(a);
- b = makeexpr_unlongcast(b);
- if ((compenums == 0 || (compenums < 0 && ansiC <= 0)) &&
- (rel != EK_EQ && rel != EK_NE)){
- a = enum_to_int(a);
- b = enum_to_int(b);
- }
- if (a->val.type != b->val.type) {
- if (a->val.type->kind == TK_STRING &&
- a->kind != EK_CONST) {
- b = makeexpr_stringify(b);
- } else if (b->val.type->kind == TK_STRING &&
- b->kind != EK_CONST) {
- a = makeexpr_stringify(a);
- } else if (ord_type(a->val.type)->kind == TK_CHAR ||
- a->val.type->kind == TK_ARRAY) {
- b = gentle_cast(b, ord_type(a->val.type));
- } else if (ord_type(b->val.type)->kind == TK_CHAR ||
- b->val.type->kind == TK_ARRAY) {
- a = gentle_cast(a, ord_type(b->val.type));
- } else if (a->val.type == tp_anyptr && !voidstar) {
- a = gentle_cast(a, b->val.type);
- } else if (b->val.type == tp_anyptr && !voidstar) {
- b = gentle_cast(b, a->val.type);
- }
- }
- if (useisspace && b->val.type->kind == TK_CHAR && checkconst(b, ' ')) {
- if (rel == EK_EQ) {
- freeexpr(b);
- return makeexpr_bicall_1("isspace", tp_boolean, a);
- } else if (rel == EK_NE) {
- freeexpr(b);
- return makeexpr_not(makeexpr_bicall_1("isspace", tp_boolean, a));
- }
- }
- if (rel == EK_LT || rel == EK_GE)
- sign = 1;
- else if (rel == EK_GT || rel == EK_LE)
- sign = -1;
- else
- sign = 0;
- if (ord_type(b->val.type)->kind == TK_INTEGER ||
- ord_type(b->val.type)->kind == TK_CHAR) {
- for (;;) {
- if (a->kind == EK_PLUS && ISCONST(a->args[a->nargs-1]->kind) &&
- a->args[a->nargs-1]->val.i &&
- (ISCONST(b->kind) ||
- (b->kind == EK_PLUS && ISCONST(b->args[b->nargs-1]->kind)))) {
- b = makeexpr_minus(b, copyexpr(a->args[a->nargs-1]));
- a = makeexpr_minus(a, copyexpr(a->args[a->nargs-1]));
- continue;
- }
- if (b->kind == EK_PLUS && ISCONST(b->args[b->nargs-1]->kind) &&
- b->args[b->nargs-1]->val.i &&
- ISCONST(a->kind)) {
- a = makeexpr_minus(a, copyexpr(b->args[b->nargs-1]));
- b = makeexpr_minus(b, copyexpr(b->args[b->nargs-1]));
- continue;
- }
- if (b->kind == EK_PLUS && sign &&
- ISCONST(b->args[b->nargs-1]->kind) &&
- checkconst(b->args[b->nargs-1], sign)) {
- b = makeexpr_plus(b, makeexpr_long(-sign));
- switch (rel) {
- case EK_LT:
- rel = EK_LE;
- break;
- case EK_GT:
- rel = EK_GE;
- break;
- case EK_LE:
- rel = EK_LT;
- break;
- case EK_GE:
- rel = EK_GT;
- break;
- default:
- break;
- }
- sign = -sign;
- continue;
- }
- if (a->kind == EK_TIMES && checkconst(b, 0) && !sign) {
- for (i = 0; i < a->nargs; i++) {
- if (ISCONST(a->args[i]->kind) && a->args[i]->val.i)
- break;
- if (a->args[i]->kind == EK_SIZEOF)
- break;
- }
- if (i < a->nargs) {
- delfreearg(&a, i);
- continue;
- }
- }
- break;
- }
- if (a->kind == EK_BICALL && !strcmp(a->val.s, "strlen") &&
- checkconst(b, 0)) {
- if (rel == EK_LT || rel == EK_GE) {
- note("Unusual use of STRLEN encountered [142]");
- } else {
- freeexpr(b);
- a = makeexpr_hat(grabarg(a, 0), 0);
- b = makeexpr_char(0); /* "strlen(a) = 0" => "*a == 0" */
- if (rel == EK_EQ || rel == EK_LE)
- return makeexpr_rel(EK_EQ, a, b);
- else
- return makeexpr_rel(EK_NE, a, b);
- }
- }
- if (ISCONST(a->kind) && ISCONST(b->kind)) {
- if ((a->val.i == b->val.i && (rel == EK_EQ || rel == EK_GE || rel == EK_LE)) ||
- (a->val.i < b->val.i && (rel == EK_NE || rel == EK_LE || rel == EK_LT)) ||
- (a->val.i > b->val.i && (rel == EK_NE || rel == EK_GE || rel == EK_GT)))
- return makeexpr_val(make_ord(tp_boolean, 1));
- else
- return makeexpr_val(make_ord(tp_boolean, 0));
- }
- if ((a->val.type == tp_char || true_type(a) == tp_char) &&
- ISCONST(b->kind) && signedchars != 0) {
- i = (b->val.i == 128 && sign == 1) ||
- (b->val.i == 127 && sign == -1);
- if (highcharbits && (highcharbits > 0 || signedchars < 0) && i) {
- if (highcharbits == 2)
- b = makeexpr_long(128);
- else
- b = makeexpr_un(EK_BNOT, tp_integer, makeexpr_long(127));
- return makeexpr_rel((rel == EK_GE || rel == EK_GT)
- ? EK_NE : EK_EQ,
- makeexpr_bin(EK_BAND, tp_integer,
- eatcasts(a), b),
- makeexpr_long(0));
- } else if (signedchars == 1 && i) {
- return makeexpr_rel((rel == EK_GE || rel == EK_GT)
- ? EK_LT : EK_GE,
- eatcasts(a), makeexpr_long(0));
- } else if (signedchars == 1 && b->val.i >= 128 && sign == 0) {
- b->val.i -= 256;
- } else if (b->val.i >= 128 ||
- (b->val.i == 127 && sign != 0)) {
- if (highcharbits && (highcharbits > 0 || signedchars < 0))
- a = makeexpr_bin(EK_BAND, a->val.type, eatcasts(a),
- makeexpr_long(255));
- else
- a = force_unsigned(a);
- }
- }
- } else if (a->val.type->kind == TK_STRING &&
- b->val.type->kind == TK_STRING) {
- if (b->kind == EK_CONST && b->val.i == 0 && !sign) {
- a = makeexpr_hat(a, 0);
- b = makeexpr_char(0); /* "a = ''" => "*a == 0" */
- } else {
- a = makeexpr_bicall_2("strcmp", tp_int, a, b);
- b = makeexpr_long(0);
- }
- } else if ((a->val.type->kind == TK_ARRAY ||
- a->val.type->kind == TK_STRING ||
- a->val.type->kind == TK_RECORD) &&
- (b->val.type->kind == TK_ARRAY ||
- b->val.type->kind == TK_STRING ||
- b->val.type->kind == TK_RECORD)) {
- if (a->val.type->kind == TK_ARRAY) {
- if (b->val.type->kind == TK_ARRAY) {
- ex = makeexpr_sizeof(copyexpr(a), 0);
- ex2 = makeexpr_sizeof(copyexpr(b), 0);
- if (!exprsame(ex, ex2, 1))
- warning("Incompatible array sizes [164]");
- freeexpr(ex2);
- } else {
- ex = makeexpr_sizeof(copyexpr(a), 0);
- }
- } else
- ex = makeexpr_sizeof(copyexpr(b), 0);
- name = (usestrncmp &&
- a->val.type->kind == TK_ARRAY &&
- a->val.type->basetype->kind == TK_CHAR) ? "strncmp" : "memcmp";
- a = makeexpr_bicall_3(name, tp_int,
- makeexpr_addr(a),
- makeexpr_addr(b), ex);
- b = makeexpr_long(0);
- } else if (a->val.type->kind == TK_SET ||
- a->val.type->kind == TK_SMALLSET) {
- if (rel == EK_GE) {
- swapexprs(a, b);
- rel = EK_LE;
- }
- if (mixsets(&a, &b)->kind == TK_SMALLSET) {
- if (rel == EK_LE) {
- a = makeexpr_bin(EK_BAND, tp_integer,
- a, makeexpr_un(EK_BNOT, tp_integer, b));
- b = makeexpr_long(0);
- rel = EK_EQ;
- }
- } else if (b->kind == EK_BICALL &&
- !strcmp(b->val.s, setexpandname) &&
- (mp = istempvar(b->args[0])) != NULL &&
- checkconst(b->args[1], 0)) {
- canceltempvar(mp);
- a = makeexpr_hat(a, 0);
- b = grabarg(b, 1);
- if (rel == EK_LE)
- rel = EK_EQ;
- } else {
- ex = makeexpr_bicall_2((rel == EK_LE) ? subsetname : setequalname,
- tp_boolean, a, b);
- return (rel == EK_NE) ? makeexpr_not(ex) : ex;
- }
- } else if (a->val.type->kind == TK_PROCPTR ||
- a->val.type->kind == TK_CPROCPTR) {
- /* we compare proc only (not link) -- same as Pascal compiler! */
- if (a->val.type->kind == TK_PROCPTR)
- a = makeexpr_dotq(a, "proc", tp_anyptr);
- if ((mp = istempprocptr(b)) != NULL) {
- canceltempvar(mp);
- b = grabarg(grabarg(b, 0), 1);
- if (!voidstar)
- b = makeexpr_cast(b, tp_anyptr);
- } else if (b->val.type->kind == TK_PROCPTR)
- b = makeexpr_dotq(b, "proc", tp_anyptr);
- }
- return makeexpr_bin(rel, tp_boolean, a, b);
- }
-
-
-
-
- Expr *makeexpr_and(a, b)
- Expr *a, *b;
- {
- Expr *ex, **exp, *low;
-
- if (!a)
- return b;
- if (!b)
- return a;
- for (exp = &a; (ex = *exp)->kind == EK_AND; exp = &ex->args[1]) ;
- if ((b->kind == EK_LT || b->kind == EK_LE) &&
- ((ex->kind == EK_LE && exprsame(ex->args[1], b->args[0], 1)) ||
- (ex->kind == EK_GE && exprsame(ex->args[0], b->args[0], 1)))) {
- low = (ex->kind == EK_LE) ? ex->args[0] : ex->args[1];
- if (unsignedtrick && checkconst(low, 0)) {
- freeexpr(ex);
- b->args[0] = force_unsigned(b->args[0]);
- *exp = b;
- return a;
- }
- if (b->args[1]->val.type->kind == TK_CHAR && useisalpha) {
- if (checkconst(low, 'A') && checkconst(b->args[1], 'Z')) {
- freeexpr(ex);
- *exp = makeexpr_bicall_1("isupper", tp_boolean, grabarg(b, 0));
- return a;
- }
- if (checkconst(low, 'a') && checkconst(b->args[1], 'z')) {
- freeexpr(ex);
- *exp = makeexpr_bicall_1("islower", tp_boolean, grabarg(b, 0));
- return a;
- }
- if (checkconst(low, '0') && checkconst(b->args[1], '9')) {
- freeexpr(ex);
- *exp = makeexpr_bicall_1("isdigit", tp_boolean, grabarg(b, 0));
- return a;
- }
- }
- }
- return makeexpr_bin(EK_AND, tp_boolean, a, b);
- }
-
-
-
- Expr *makeexpr_or(a, b)
- Expr *a, *b;
- {
- Expr *ex, **exp, *low;
-
- if (!a)
- return b;
- if (!b)
- return a;
- for (exp = &a; (ex = *exp)->kind == EK_OR; exp = &ex->args[1]) ;
- if (((b->kind == EK_BICALL && !strcmp(b->val.s, "isdigit") &&
- ex->kind == EK_BICALL && !strcmp(ex->val.s, "isalpha")) ||
- (b->kind == EK_BICALL && !strcmp(b->val.s, "isalpha") &&
- ex->kind == EK_BICALL && !strcmp(ex->val.s, "isdigit"))) &&
- exprsame(ex->args[0], b->args[0], 1)) {
- strchange(&ex->val.s, "isalnum");
- freeexpr(b);
- return a;
- }
- if (((b->kind == EK_BICALL && !strcmp(b->val.s, "islower") &&
- ex->kind == EK_BICALL && !strcmp(ex->val.s, "isupper")) ||
- (b->kind == EK_BICALL && !strcmp(b->val.s, "isupper") &&
- ex->kind == EK_BICALL && !strcmp(ex->val.s, "islower"))) &&
- exprsame(ex->args[0], b->args[0], 1)) {
- strchange(&ex->val.s, "isalpha");
- freeexpr(b);
- return a;
- }
- if ((b->kind == EK_GT || b->kind == EK_GE) &&
- ((ex->kind == EK_GT && exprsame(ex->args[1], b->args[0], 1)) ||
- (ex->kind == EK_LT && exprsame(ex->args[0], b->args[0], 1)))) {
- low = (ex->kind == EK_GT) ? ex->args[0] : ex->args[1];
- if (unsignedtrick && checkconst(low, 0)) {
- freeexpr(ex);
- b->args[0] = force_unsigned(b->args[0]);
- *exp = b;
- return a;
- }
- }
- return makeexpr_bin(EK_OR, tp_boolean, a, b);
- }
-
-
-
- Expr *makeexpr_range(ex, exlow, exhigh, higheq)
- Expr *ex, *exlow, *exhigh;
- int higheq;
- {
- Expr *ex2;
- enum exprkind rel = (higheq) ? EK_LE : EK_LT;
-
- if (exprsame(exlow, exhigh, 1) && higheq)
- return makeexpr_rel(EK_EQ, ex, exlow);
- ex2 = makeexpr_rel(rel, copyexpr(ex), exhigh);
- if (lelerange)
- return makeexpr_and(makeexpr_rel(EK_LE, exlow, ex), ex2);
- else
- return makeexpr_and(makeexpr_rel(EK_GE, ex, exlow), ex2);
- }
-
-
-
-
- Expr *makeexpr_cond(c, a, b)
- Expr *c, *a, *b;
- {
- Expr *ex;
-
- ex = makeexpr(EK_COND, 3);
- ex->val.type = a->val.type;
- ex->args[0] = c;
- ex->args[1] = a;
- ex->args[2] = b;
- if (debug>2) { fprintf(outf,"makeexpr_cond returns "); dumpexpr(ex); fprintf(outf,"\n"); }
- return ex;
- }
-
-
-
-
- int expr_is_lvalue(ex)
- Expr *ex;
- {
- Meaning *mp;
-
- switch (ex->kind) {
-
- case EK_VAR:
- mp = (Meaning *)ex->val.i;
- return (mp->kind == MK_VAR || mp->kind == MK_PARAM ||
- mp->kind == MK_VARPARAM ||
- (mp->kind == MK_CONST &&
- (mp->type->kind == TK_ARRAY ||
- mp->type->kind == TK_RECORD ||
- mp->type->kind == TK_SET)));
-
- case EK_HAT:
- case EK_NAME:
- return 1;
-
- case EK_INDEX:
- case EK_DOT:
- return expr_is_lvalue(ex->args[0]);
-
- case EK_COMMA:
- return expr_is_lvalue(ex->args[ex->nargs-1]);
-
- default:
- return 0;
- }
- }
-
-
- int expr_has_address(ex)
- Expr *ex;
- {
- if (ex->kind == EK_DOT &&
- ((Meaning *)ex->val.i)->val.i)
- return 0; /* bit fields do not have an address */
- return expr_is_lvalue(ex);
- }
-
-
-
- Expr *checknil(ex)
- Expr *ex;
- {
- if (nilcheck == 1) {
- if (singlevar(ex)) {
- ex = makeexpr_un(EK_CHECKNIL, ex->val.type, ex);
- } else {
- ex = makeexpr_bin(EK_CHECKNIL, ex->val.type, ex,
- makeexpr_var(makestmttempvar(ex->val.type,
- name_PTR)));
- }
- }
- return ex;
- }
-
-
- int checkvarinlists(yes, no, def, mp)
- Strlist *yes, *no;
- int def;
- Meaning *mp;
- {
- char *cp;
- Meaning *ctx;
-
- if (mp->kind == MK_FIELD)
- ctx = mp->rectype->meaning;
- else
- ctx = mp->ctx;
- if (ctx && ctx->name)
- cp = format_ss("%s.%s", ctx->name, mp->name);
- else
- cp = NULL;
- if (strlist_cifind(yes, cp))
- return 1;
- if (strlist_cifind(no, cp))
- return 0;
- if (strlist_cifind(yes, mp->name))
- return 1;
- if (strlist_cifind(no, mp->name))
- return 0;
- if (strlist_cifind(yes, "1"))
- return 1;
- if (strlist_cifind(no, "1"))
- return 0;
- return def;
- }
-
-
- void requirefilebuffer(ex)
- Expr *ex;
- {
- Meaning *mp;
-
- if (!isfiletype(ex->val.type, 0))
- return;
- mp = isfilevar(ex);
- if (!mp) {
- if (ex->kind == EK_HAT)
- ex = ex->args[0];
- if (ex->kind == EK_VAR) {
- mp = (Meaning *)ex->val.i;
- if (mp->kind == MK_PARAM || mp->kind == MK_VARPARAM)
- note(format_s("File parameter %s can't access buffers (try StructFiles = 1) [318]",
- mp->name));
- }
- } else if (!mp->bufferedfile &&
- checkvarinlists(bufferedfiles, unbufferedfiles, 1, mp)) {
- if (mp->wasdeclared)
- note(format_s("Discovered too late that %s should be buffered [143]",
- mp->name));
- mp->bufferedfile = 1;
- }
- }
-
-
- Expr *makeexpr_hat(a, check)
- Expr *a;
- int check;
- {
- Expr *ex;
-
- if (debug>2) { fprintf(outf,"makeexpr_hat("); dumpexpr(a); fprintf(outf,")\n"); }
- if (isfiletype(a->val.type, -1)) {
- requirefilebuffer(a);
- if (*chargetfbufname &&
- filebasetype(a->val.type)->kind == TK_CHAR)
- return makeexpr_bicall_1(chargetfbufname,
- filebasetype(a->val.type),
- filebasename(a));
- else if (*arraygetfbufname &&
- filebasetype(a->val.type)->kind == TK_ARRAY)
- return makeexpr_bicall_2(arraygetfbufname,
- filebasetype(a->val.type),
- filebasename(a),
- makeexpr_type(filebasetype(a->val.type)));
- else
- return makeexpr_bicall_2(getfbufname,
- filebasetype(a->val.type),
- filebasename(a),
- makeexpr_type(filebasetype(a->val.type)));
- }
- if (a->kind == EK_PLUS &&
- (ex = a->args[0])->val.type->kind == TK_POINTER &&
- (ex->val.type->basetype->kind == TK_ARRAY ||
- ex->val.type->basetype->kind == TK_STRING ||
- ex->val.type->basetype->kind == TK_SET)) {
- ex->val.type = ex->val.type->basetype; /* convert *(a+n) to a[n] */
- deletearg(&a, 0);
- if (a->nargs == 1)
- a = grabarg(a, 0);
- return makeexpr_bin(EK_INDEX, ex->val.type->basetype, ex, a);
- }
- if (a->val.type->kind == TK_STRING ||
- a->val.type->kind == TK_ARRAY ||
- a->val.type->kind == TK_SET) {
- if (starindex == 0)
- return makeexpr_bin(EK_INDEX, a->val.type->basetype, a, makeexpr_long(0));
- else
- return makeexpr_un(EK_HAT, a->val.type->basetype, a);
- }
- if (a->val.type->kind != TK_POINTER || !a->val.type->basetype) {
- warning("bad pointer dereference [165]");
- return a;
- }
- if (a->kind == EK_CAST &&
- a->val.type->basetype->kind == TK_POINTER &&
- a->args[0]->val.type->kind == TK_POINTER &&
- a->args[0]->val.type->basetype->kind == TK_POINTER) {
- return makeexpr_cast(makeexpr_hat(a->args[0], 0),
- a->val.type->basetype);
- }
- switch (a->val.type->basetype->kind) {
-
- case TK_ARRAY:
- case TK_STRING:
- case TK_SET:
- if (a->kind != EK_HAT || 1 ||
- a->val.type == a->args[0]->val.type->basetype) {
- a->val.type = a->val.type->basetype;
- return a;
- }
-
- default:
- if (a->kind == EK_ADDR) {
- ex = a->args[0];
- FREE(a);
- return ex;
- } else {
- if (check)
- ex = checknil(a);
- else
- ex = a;
- return makeexpr_un(EK_HAT, a->val.type->basetype, ex);
- }
- }
- }
-
-
-
- Expr *un_sign_extend(a)
- Expr *a;
- {
- if (a->kind == EK_BICALL &&
- !strcmp(a->val.s, signextname) && *signextname) {
- return grabarg(a, 0);
- }
- return a;
- }
-
-
-
- Expr *makeexpr_addr(a)
- Expr *a;
- {
- Expr *ex;
- Type *type;
- Meaning *mp;
-
- a = un_sign_extend(a);
- type = makepointertype(a->val.type);
- if (debug>2) { fprintf(outf,"makeexpr_addr("); dumpexpr(a); fprintf(outf,", "); dumptypename(type, 1); fprintf(outf,")\n"); }
- if (a->kind == EK_CONST && a->val.type->kind == TK_STRING) {
- return a; /* kludge to help assignments */
- } else if (a->kind == EK_INDEX &&
- (a->val.type->kind != TK_ARRAY &&
- a->val.type->kind != TK_SET &&
- a->val.type->kind != TK_STRING) &&
- (addindex == 1 ||
- (addindex != 0 && checkconst(a->args[1], 0)))) {
- ex = makeexpr_plus(makeexpr_addr(a->args[0]), a->args[1]);
- FREE(a);
- ex->val.type = type;
- return ex;
- } else if (a->kind == EK_CAST) {
- return makeexpr_cast(makeexpr_addr(a->args[0]), type);
- } else if (a->kind == EK_ACTCAST) {
- return makeexpr_actcast(makeexpr_addr(a->args[0]), type);
- } else if (a->kind == EK_LITCAST) {
- if (a->args[0]->kind == EK_NAME) {
- if (my_strchr(a->args[0]->val.s, '(') ||
- my_strchr(a->args[0]->val.s, '['))
- note("Constructing pointer type by adding '*' may be incorrect [322]");
- return makeexpr_bin(EK_LITCAST, tp_integer,
- makeexpr_name(format_s("%s*",
- a->args[0]->val.s),
- tp_integer),
- makeexpr_addr(a->args[1]));
- } else
- return makeexpr_bin(EK_LITCAST, tp_integer, makeexpr_type(type),
- makeexpr_addr(a->args[1]));
- } else {
- switch (a->val.type->kind) {
-
- case TK_ARRAY:
- case TK_STRING:
- case TK_SET:
- if (a->val.type->smin) {
- return makeexpr_un(EK_ADDR, type,
- makeexpr_index(a,
- copyexpr(a->val.type->smin),
- NULL));
- }
- a->val.type = type;
- return a;
-
- default:
- if (a->kind == EK_HAT) {
- ex = a->args[0];
- FREE(a);
- return ex;
- } else if (a->kind == EK_ACTCAST)
- return makeexpr_actcast(makeexpr_addr(grabarg(a, 0)), type);
- else if (a->kind == EK_CAST)
- return makeexpr_cast(makeexpr_addr(grabarg(a, 0)), type);
- else {
- if (a->kind == EK_VAR &&
- (mp = (Meaning *)a->val.i)->kind == MK_PARAM &&
- mp->type != promote_type(mp->type) &&
- fixpromotedargs) {
- note(format_s("Taking & of possibly promoted param %s [324]",
- mp->name));
- if (fixpromotedargs == 1) {
- mp->varstructflag = 1;
- mp->ctx->varstructflag = 1;
- }
- }
- return makeexpr_un(EK_ADDR, type, a);
- }
- }
- }
- }
-
-
-
- Expr *makeexpr_addrstr(a)
- Expr *a;
- {
- if (debug>2) { fprintf(outf,"makeexpr_addrstr("); dumpexpr(a); fprintf(outf,")\n"); }
- if (a->val.type->kind == TK_POINTER)
- return a;
- return makeexpr_addr(a);
- }
-
-
-
- Expr *makeexpr_addrf(a)
- Expr *a;
- {
- Meaning *mp, *tvar;
-
- mp = (Meaning *)a->val.i;
- if (is_std_file(a)) {
- if (addrstdfiles == 0) {
- note(format_s("Taking address of %s; consider setting VarFiles = 0 [144]",
- (a->kind == EK_VAR) ? ((Meaning *)a->val.i)->name
- : a->val.s));
- tvar = makestmttempvar(tp_text, name_TEMP);
- return makeexpr_comma(makeexpr_assign(makeexpr_var(tvar), a),
- makeexpr_addr(makeexpr_var(tvar)));
- }
- }
- if ((a->kind == EK_VAR &&
- mp->kind == MK_FIELD && mp->val.i) ||
- (a->kind == EK_BICALL &&
- !strcmp(a->val.s, getbitsname))) {
- warning("Can't take the address of a bit-field [166]");
- }
- return makeexpr_addr(a);
- }
-
-
-
- Expr *makeexpr_index(a, b, offset)
- Expr *a, *b, *offset;
- {
- Type *indextype, *btype;
-
- if (debug>2) { fprintf(outf,"makeexpr_index("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b);
- fprintf(outf,", "); dumpexpr(offset); fprintf(outf,")\n"); }
- indextype = (a->val.type->kind == TK_ARRAY) ? a->val.type->indextype
- : tp_integer;
- b = gentle_cast(b, indextype);
- if (!offset)
- offset = makeexpr_long(0);
- b = makeexpr_minus(b, gentle_cast(offset, indextype));
- btype = a->val.type;
- if (btype->basetype)
- btype = btype->basetype;
- if (checkconst(b, 0) && starindex == 1)
- return makeexpr_un(EK_HAT, btype, a);
- else
- return makeexpr_bin(EK_INDEX, btype, a,
- gentle_cast(b, indextype));
- }
-
-
-
- Expr *makeexpr_type(type)
- Type *type;
- {
- Expr *ex;
-
- ex = makeexpr(EK_TYPENAME, 0);
- ex->val.type = type;
- return ex;
- }
-
-
- Expr *makeexpr_sizeof(ex, incskipped)
- Expr *ex;
- int incskipped;
- {
- Expr *ex2, *ex3;
- Type *btype;
- char *name;
-
- if (ex->val.type->meaning) {
- name = find_special_variant(ex->val.type->meaning->name,
- "SpecialSizeOf", specialsizeofs, 1);
- if (name) {
- freeexpr(ex);
- return pc_expr_str(name);
- }
- }
- switch (ex->val.type->kind) {
-
- case TK_CHAR:
- case TK_BOOLEAN:
- freeexpr(ex);
- return makeexpr_long(1);
-
- case TK_SUBR:
- btype = findbasetype(ex->val.type, ODECL_NOPRES);
- if (btype->kind == TK_CHAR || btype == tp_abyte) {
- freeexpr(ex);
- return makeexpr_long(1);
- }
- break;
-
- case TK_STRING:
- case TK_ARRAY:
- if (!ex->val.type->meaning || ex->val.type->kind == TK_STRING ||
- (!incskipped && ex->val.type->smin)) {
- ex3 = arraysize(ex->val.type, incskipped);
- return makeexpr_times(ex3,
- makeexpr_sizeof(makeexpr_type(
- ex->val.type->basetype), 1));
- }
- break;
-
- case TK_SET:
- ord_range_expr(ex->val.type->indextype, NULL, &ex2);
- freeexpr(ex);
- return makeexpr_times(makeexpr_plus(makeexpr_div(copyexpr(ex2),
- makeexpr_setbits()),
- makeexpr_long(2)),
- makeexpr_sizeof(makeexpr_type(tp_integer), 0));
-
- default:
- break;
- }
- if (ex->kind != EK_CONST &&
- (findbasetype(ex->val.type,0)->meaning || /* if type has a name... */
- ex->val.type->kind == TK_STRING || /* if C sizeof(expr) will give wrong answer */
- ex->val.type->kind == TK_ARRAY ||
- ex->val.type->kind == TK_SET)) {
- ex2 = makeexpr_type(ex->val.type);
- freeexpr(ex);
- ex = ex2;
- }
- return makeexpr_un(EK_SIZEOF, tp_integer, ex);
- }
-
-
-
-
- /* Compute a measure of how fast or slow the expression is likely to be.
- 0 is a constant, 1 is a variable, extra points added per "operation". */
-
- int exprspeed(ex)
- Expr *ex;
- {
- Meaning *mp, *mp2;
- int i, cost, speed;
-
- switch (ex->kind) {
-
- case EK_VAR:
- mp = (Meaning *)ex->val.i;
- if (mp->kind == MK_CONST)
- return 0;
- if (!mp->ctx || mp->ctx->kind == MK_FUNCTION)
- return 1;
- i = 1;
- for (mp2 = curctx; mp2 && mp2 != mp->ctx; mp2 = mp2->ctx)
- i++; /* cost of following static links */
- return (i);
-
- case EK_CONST:
- case EK_LONGCONST:
- case EK_SIZEOF:
- return 0;
-
- case EK_ADDR:
- speed = exprspeed(ex->args[0]);
- return (speed > 1) ? speed : 0;
-
- case EK_DOT:
- return exprspeed(ex->args[0]);
-
- case EK_NEG:
- return exprspeed(ex->args[0]) + 1;
-
- case EK_CAST:
- case EK_ACTCAST:
- i = (ord_type(ex->val.type)->kind == TK_REAL) !=
- (ord_type(ex->args[0]->val.type)->kind == TK_REAL);
- return (i + exprspeed(ex->args[0]));
-
- case EK_COND:
- return 2 + exprspeed(ex->args[0]) +
- MAX(exprspeed(ex->args[1]), exprspeed(ex->args[2]));
-
- case EK_AND:
- case EK_OR:
- case EK_COMMA:
- speed = 2;
- for (i = 0; i < ex->nargs; i++)
- speed += exprspeed(ex->args[i]);
- return speed;
-
- case EK_FUNCTION:
- case EK_BICALL:
- case EK_SPCALL:
- return 1000;
-
- case EK_ASSIGN:
- case EK_POSTINC:
- case EK_POSTDEC:
- return 100 + exprspeed(ex->args[0]) + exprspeed(ex->args[1]);
-
- default:
- cost = (ex->kind == EK_PLUS) ? 1 : 2;
- if (ex->val.type->kind == TK_REAL)
- cost *= 2;
- speed = -cost;
- for (i = 0; i < ex->nargs; i++) {
- if (!isliteralconst(ex->args[i], NULL) ||
- ex->val.type->kind == TK_REAL)
- speed += exprspeed(ex->args[i]) + cost;
- }
- return MAX(speed, 0);
- }
- }
-
-
-
-
- int noargdependencies(ex, vars)
- Expr *ex;
- int vars;
- {
- int i;
-
- for (i = 0; i < ex->nargs; i++) {
- if (!nodependencies(ex->args[i], vars))
- return 0;
- }
- return 1;
- }
-
-
- int nodependencies(ex, vars)
- Expr *ex;
- int vars; /* 1 if explicit dependencies on vars count as dependencies */
- { /* 2 if global but not local vars count as dependencies */
- Meaning *mp;
-
- if (debug>2) { fprintf(outf,"nodependencies("); dumpexpr(ex); fprintf(outf,")\n"); }
- if (!noargdependencies(ex, vars))
- return 0;
- switch (ex->kind) {
-
- case EK_VAR:
- mp = (Meaning *)ex->val.i;
- if (mp->kind == MK_CONST)
- return 1;
- if (vars == 2 &&
- mp->ctx == curctx &&
- mp->ctx->kind == MK_FUNCTION &&
- !mp->varstructflag)
- return 1;
- return (mp->kind == MK_CONST ||
- (!vars &&
- (mp->kind == MK_VAR || mp->kind == MK_VARREF ||
- mp->kind == MK_PARAM || mp->kind == MK_VARPARAM)));
-
- case EK_BICALL:
- return nosideeffects_func(ex);
-
- case EK_FUNCTION:
- case EK_SPCALL:
- case EK_ASSIGN:
- case EK_POSTINC:
- case EK_POSTDEC:
- case EK_HAT:
- case EK_INDEX:
- return 0;
-
- default:
- return 1;
- }
- }
-
-
-
- int exprdependsvar(ex, mp)
- Expr *ex;
- Meaning *mp;
- {
- int i;
-
- i = ex->nargs;
- while (--i >= 0)
- if (exprdependsvar(ex->args[i], mp))
- return 1;
- switch (ex->kind) {
-
- case EK_VAR:
- return ((Meaning *)ex->val.i == mp);
-
- case EK_BICALL:
- if (nodependencies(ex, 1))
- return 0;
-
- /* fall through */
- case EK_FUNCTION:
- case EK_SPCALL:
- return (mp->ctx != curctx ||
- mp->ctx->kind != MK_FUNCTION ||
- mp->varstructflag);
-
- case EK_HAT:
- return 1;
-
- default:
- return 0;
- }
- }
-
-
- int exprdepends(ex, ex2)
- Expr *ex, *ex2; /* Expression ex somehow depends on value of ex2 */
- {
- switch (ex2->kind) {
-
- case EK_VAR:
- return exprdependsvar(ex, (Meaning *)ex2->val.i);
-
- case EK_CONST:
- case EK_LONGCONST:
- return 0;
-
- case EK_INDEX:
- case EK_DOT:
- return exprdepends(ex, ex2->args[0]);
-
- default:
- return !nodependencies(ex, 1);
- }
- }
-
-
- int nosideeffects_func(ex)
- Expr *ex;
- {
- Meaning *mp;
- Symbol *sp;
-
- switch (ex->kind) {
-
- case EK_FUNCTION:
- mp = (Meaning *)ex->val.i;
- sp = findsymbol_opt(mp->name);
- return sp && (sp->flags & (NOSIDEEFF|DETERMF));
-
- case EK_BICALL:
- sp = findsymbol_opt(ex->val.s);
- return sp && (sp->flags & (NOSIDEEFF|DETERMF));
-
- default:
- return 0;
- }
- }
-
-
-
- int deterministic_func(ex)
- Expr *ex;
- {
- Meaning *mp;
- Symbol *sp;
-
- switch (ex->kind) {
-
- case EK_FUNCTION:
- mp = (Meaning *)ex->val.i;
- sp = findsymbol_opt(mp->name);
- return sp && (sp->flags & DETERMF);
-
- case EK_BICALL:
- sp = findsymbol_opt(ex->val.s);
- return sp && (sp->flags & DETERMF);
-
- default:
- return 0;
- }
- }
-
-
-
-
- int noargsideeffects(ex, mode)
- Expr *ex;
- int mode;
- {
- int i;
-
- for (i = 0; i < ex->nargs; i++) {
- if (!nosideeffects(ex->args[i], mode))
- return 0;
- }
- return 1;
- }
-
-
- /* mode=0: liberal about bicall's: safe unless sideeffects_bicall() */
- /* mode=1: conservative about bicall's: must be explicitly NOSIDEEFF */
-
- int nosideeffects(ex, mode)
- Expr *ex;
- int mode;
- {
- if (debug>2) { fprintf(outf,"nosideeffects("); dumpexpr(ex); fprintf(outf,")\n"); }
- if (!noargsideeffects(ex, mode))
- return 0;
- switch (ex->kind) {
-
- case EK_BICALL:
- if (mode == 0)
- return !sideeffects_bicall(ex->val.s);
-
- /* fall through */
- case EK_FUNCTION:
- return nosideeffects_func(ex);
-
- case EK_SPCALL:
- case EK_ASSIGN:
- case EK_POSTINC:
- case EK_POSTDEC:
- return 0;
-
- default:
- return 1;
- }
- }
-
-
-
- int exproccurs(ex, ex2)
- Expr *ex, *ex2;
- {
- int i, count = 0;
-
- if (debug>2) { fprintf(outf,"exproccurs("); dumpexpr(ex); fprintf(outf,", "); dumpexpr(ex2); fprintf(outf,")\n"); }
- for (i = 0; i < ex->nargs; i++)
- count += exproccurs(ex->args[i], ex2);
- if (exprsame(ex, ex2, 0))
- count++;
- return count;
- }
-
-
-
- Expr *singlevar(ex)
- Expr *ex;
- {
- if (debug>2) { fprintf(outf,"singlevar("); dumpexpr(ex); fprintf(outf,")\n"); }
- switch (ex->kind) {
-
- case EK_VAR:
- case EK_MACARG:
- return ex;
-
- case EK_HAT:
- case EK_ADDR:
- case EK_DOT:
- return singlevar(ex->args[0]);
-
- case EK_INDEX:
- #if 0
- if (!nodependencies(ex->args[1], 1))
- return NULL;
- #endif
- return singlevar(ex->args[0]);
-
- default:
- return NULL;
- }
- }
-
-
-
- /* Is "ex" a function which takes a return buffer pointer as its
- first argument, and returns a copy of that pointer? */
-
- int structuredfunc(ex)
- Expr *ex;
- {
- Meaning *mp;
- Symbol *sp;
-
- if (debug>2) { fprintf(outf,"structuredfunc("); dumpexpr(ex); fprintf(outf,")\n"); }
- switch (ex->kind) {
-
- case EK_FUNCTION:
- mp = (Meaning *)ex->val.i;
- if (mp->isfunction && mp->cbase && mp->cbase->kind == MK_VARPARAM)
- return 1;
- sp = findsymbol_opt(mp->name);
- return sp && (sp->flags & (STRUCTF|STRLAPF));
-
- case EK_BICALL:
- sp = findsymbol_opt(ex->val.s);
- return sp && (sp->flags & (STRUCTF|STRLAPF));
-
- default:
- return 0;
- }
- }
-
-
-
- int strlapfunc(ex)
- Expr *ex;
- {
- Meaning *mp;
- Symbol *sp;
-
- switch (ex->kind) {
-
- case EK_FUNCTION:
- mp = (Meaning *)ex->val.i;
- sp = findsymbol_opt(mp->name);
- return sp && (sp->flags & STRLAPF);
-
- case EK_BICALL:
- sp = findsymbol_opt(ex->val.s);
- return sp && (sp->flags & STRLAPF);
-
- default:
- return 0;
- }
- }
-
-
-
- Meaning *istempvar(ex)
- Expr *ex;
- {
- Meaning *mp;
-
- if (debug>2) { fprintf(outf,"istempvar("); dumpexpr(ex); fprintf(outf,")\n"); }
- if (ex->kind == EK_VAR) {
- mp = (Meaning *)ex->val.i;
- if (mp->istemporary)
- return mp;
- else
- return NULL;
- }
- return NULL;
- }
-
-
- Meaning *totempvar(ex)
- Expr *ex;
- {
- while (structuredfunc(ex))
- ex = ex->args[0];
- return istempvar(ex);
- }
-
-
-
- Meaning *isretvar(ex)
- Expr *ex;
- {
- Meaning *mp;
-
- if (debug>2) { fprintf(outf,"isretvar("); dumpexpr(ex); fprintf(outf,")\n"); }
- if (ex->kind == EK_HAT)
- ex = ex->args[0];
- if (ex->kind == EK_VAR) {
- mp = (Meaning *)ex->val.i;
- if (mp->ctx && mp->ctx->kind == MK_FUNCTION &&
- mp->ctx->isfunction && mp == mp->ctx->cbase)
- return mp;
- else
- return NULL;
- }
- return NULL;
- }
-
-
-
- Expr *bumpstring(ex, index, offset)
- Expr *ex, *index;
- int offset;
- {
- if (checkconst(index, offset)) {
- freeexpr(index);
- return ex;
- }
- if (addindex != 0)
- ex = makeexpr_plus(makeexpr_addrstr(ex),
- makeexpr_minus(index, makeexpr_long(offset)));
- else
- ex = makeexpr_addr(makeexpr_index(ex, index, makeexpr_long(offset)));
- ex->val.type = tp_str255;
- return ex;
- }
-
-
-
- long po2m1(n)
- int n;
- {
- if (n == 32)
- return -1;
- else if (n == 31)
- return 0x7fffffff;
- else
- return (1<<n) - 1;
- }
-
-
-
- int isarithkind(kind)
- enum exprkind kind;
- {
- return (kind == EK_EQ || kind == EK_LT || kind == EK_GT ||
- kind == EK_NE || kind == EK_LE || kind == EK_GE ||
- kind == EK_PLUS || kind == EK_TIMES || kind == EK_DIVIDE ||
- kind == EK_DIV || kind == EK_MOD || kind == EK_NEG ||
- kind == EK_AND || kind == EK_OR || kind == EK_NOT ||
- kind == EK_BAND || kind == EK_BOR || kind == EK_BXOR ||
- kind == EK_LSH || kind == EK_RSH || kind == EK_BNOT ||
- kind == EK_FUNCTION || kind == EK_BICALL);
- }
-
-
- Expr *makeexpr_assign(a, b)
- Expr *a, *b;
- {
- int i, j;
- Expr *ex, *ex2, *ex3, **ep;
- Meaning *mp;
- Type *tp;
-
- if (debug>2) { fprintf(outf,"makeexpr_assign("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); }
- if (stringtrunclimit > 0 &&
- a->val.type->kind == TK_STRING &&
- (i = strmax(a)) <= stringtrunclimit &&
- strmax(b) > i) {
- note("Possible string truncation in assignment [145]");
- }
- a = un_sign_extend(a);
- b = gentle_cast(b, a->val.type);
- if (b->kind == EK_BICALL && !strcmp(b->val.s, "sprintf") &&
- (mp = istempvar(b->args[0])) != NULL &&
- b->nargs >= 2 &&
- b->args[1]->kind == EK_CONST && /* all this handles string appending */
- b->args[1]->val.i > 2 && /* of the form, "s := s + ..." */
- !strncmp(b->args[1]->val.s, "%s", 2) &&
- exprsame(a, b->args[2], 1) &&
- nosideeffects(a, 0) &&
- (ex = singlevar(a)) != NULL) {
- ex2 = copyexpr(b);
- delfreearg(&ex2, 2);
- freeexpr(ex2->args[1]);
- ex2->args[1] = makeexpr_lstring(b->args[1]->val.s+2,
- b->args[1]->val.i-2);
- if (/*(ex = singlevar(a)) != NULL && */
- /* noargdependencies(ex2) && */ !exproccurs(ex2, ex)) {
- freeexpr(b);
- if (ex2->args[1]->val.i == 2 && /* s := s + s2 */
- !strncmp(ex2->args[1]->val.s, "%s", 2)) {
- canceltempvar(mp);
- tp = ex2->val.type;
- return makeexpr_bicall_2("strcat", tp,
- makeexpr_addrstr(a), grabarg(ex2, 2));
- } else if (sprintflength(ex2, 0) >= 0) { /* s := s + 's2' */
- tp = ex2->val.type;
- return makeexpr_bicall_2("strcat", tp,
- makeexpr_addrstr(a),
- makeexpr_unsprintfify(ex2));
- } else { /* general case */
- canceltempvar(mp);
- freeexpr(ex2->args[0]);
- ex = makeexpr_bicall_1("strlen", tp_int, copyexpr(a));
- ex2->args[0] = bumpstring(a, ex, 0);
- return ex2;
- }
- } else
- freeexpr(ex2);
- }
- if (b->kind == EK_BICALL && !strcmp(b->val.s, "sprintf") &&
- istempvar(b->args[0]) &&
- (ex = singlevar(a)) != NULL) {
- j = -1; /* does lhs var appear exactly once on rhs? */
- for (i = 2; i < b->nargs; i++) {
- if (exprsame(b->args[i], ex, 1) && j < 0)
- j = i;
- else if (exproccurs(b->args[i], ex))
- break;
- }
- if (i == b->nargs && j > 0) {
- b->args[j] = makeexpr_bicall_2("strcpy", tp_str255,
- makeexpr_addrstr(b->args[0]),
- makeexpr_addrstr(b->args[j]));
- b->args[0] = makeexpr_addrstr(a);
- return b;
- }
- }
- if (structuredfunc(b) && (ex2 = singlevar(a)) != NULL) {
- ep = &b->args[0];
- i = strlapfunc(b);
- while (structuredfunc((ex = *ep))) {
- i = i && strlapfunc(ex);
- ep = &ex->args[0];
- }
- if ((mp = istempvar(ex)) != NULL &&
- (i || !exproccurs(b, ex2))) {
- canceltempvar(mp);
- freeexpr(*ep);
- *ep = makeexpr_addrstr(a);
- return b;
- }
- }
- if (a->val.type->kind == TK_PROCPTR &&
- (mp = istempprocptr(b)) != NULL &&
- nosideeffects(a, 0)) {
- freeexpr(b->args[0]->args[0]->args[0]);
- b->args[0]->args[0]->args[0] = copyexpr(a);
- if (b->nargs == 3) {
- freeexpr(b->args[1]->args[0]->args[0]);
- b->args[1]->args[0]->args[0] = a;
- delfreearg(&b, 2);
- } else {
- freeexpr(b->args[1]);
- b->args[1] = makeexpr_assign(makeexpr_dotq(a, "link", tp_anyptr),
- makeexpr_nil());
- }
- canceltempvar(mp);
- return b;
- }
- if (a->val.type->kind == TK_PROCPTR &&
- (b->val.type->kind == TK_CPROCPTR ||
- checkconst(b, 0))) {
- ex = makeexpr_dotq(copyexpr(a), "proc", tp_anyptr);
- b = makeexpr_comma(makeexpr_assign(ex, b),
- makeexpr_assign(makeexpr_dotq(a, "link", tp_anyptr),
- makeexpr_nil()));
- return b;
- }
- if (a->val.type->kind == TK_CPROCPTR &&
- (mp = istempprocptr(b)) != NULL &&
- nosideeffects(a, 0)) {
- freeexpr(b->args[0]->args[0]);
- b->args[0]->args[0] = a;
- if (b->nargs == 3)
- delfreearg(&b, 1);
- delfreearg(&b, 1);
- canceltempvar(mp);
- return b;
- }
- if (a->val.type->kind == TK_CPROCPTR &&
- b->val.type->kind == TK_PROCPTR) {
- b = makeexpr_dotq(b, "proc", tp_anyptr);
- }
- if (a->val.type->kind == TK_STRING) {
- if (b->kind == EK_CONST && b->val.i == 0 && !isretvar(a)) {
- /* optimizing retvar would mess up "return" optimization */
- return makeexpr_assign(makeexpr_hat(a, 0),
- makeexpr_char(0));
- }
- a = makeexpr_addrstr(a);
- b = makeexpr_addrstr(b);
- return makeexpr_bicall_2("strcpy", a->val.type, a, b);
- }
- if (a->kind == EK_BICALL && !strcmp(a->val.s, "strlen")) {
- if (b->kind == EK_CAST &&
- ord_type(b->args[0]->val.type)->kind == TK_INTEGER) {
- b = grabarg(b, 0);
- }
- j = (b->kind == EK_PLUS && /* handle "s[0] := xxx" */
- b->args[0]->kind == EK_BICALL &&
- !strcmp(b->args[0]->val.s, "strlen") &&
- exprsame(a->args[0], b->args[0]->args[0], 0) &&
- isliteralconst(b->args[1], NULL) == 2);
- if (j && b->args[1]->val.i > 0 &&
- b->args[1]->val.i <= 5) { /* lengthening the string */
- a = grabarg(a, 0);
- i = b->args[1]->val.i;
- freeexpr(b);
- if (i == 1)
- b = makeexpr_string(" ");
- else
- b = makeexpr_lstring("12345", i);
- return makeexpr_bicall_2("strcat", a->val.type, a, b);
- } else { /* maybe shortening the string */
- if (!j && !isconstexpr(b, NULL))
- note("Modification of string length may translate incorrectly [146]");
- a = grabarg(a, 0);
- b = makeexpr_ord(b);
- return makeexpr_assign(makeexpr_index(a, b, NULL),
- makeexpr_char(0));
- }
- }
- if (a->val.type->kind == TK_ARRAY ||
- (a->val.type->kind == TK_PROCPTR && copystructs < 1) ||
- (a->val.type->kind == TK_RECORD &&
- (copystructs < 1 || a->val.type != b->val.type))) {
- ex = makeexpr_sizeof(copyexpr(a), 0);
- ex2 = makeexpr_sizeof(copyexpr(b), 0);
- if (!exprsame(ex, ex2, 1)) {
- if (a->val.type->kind == TK_ARRAY &&
- b->val.type->kind == TK_ARRAY &&
- a->val.type->basetype->kind == TK_CHAR &&
- (!ISCONST(ex->kind) || !ISCONST(ex2->kind) ||
- ex->val.i > ex2->val.i)) {
- ex = makeexpr_arglong(ex, (size_t_long != 0));
- ex2 = makeexpr_arglong(ex2, (size_t_long != 0));
- a = makeexpr_addrstr(a);
- b = makeexpr_addrstr(b);
- b = makeexpr_bicall_3("memcpy", a->val.type,
- copyexpr(a), b, copyexpr(ex2));
- ex3 = copyexpr(ex2);
- return makeexpr_comma(b,
- makeexpr_bicall_3("memset", a->val.type,
- makeexpr_plus(a, ex3),
- makeexpr_char(' '),
- makeexpr_minus(ex,
- ex2)));
- } else if (!(a->val.type->kind == TK_ARRAY &&
- b->val.type->kind != TK_ARRAY))
- warning("Incompatible types or sizes [167]");
- }
- freeexpr(ex2);
- ex = makeexpr_arglong(ex, (size_t_long != 0));
- a = makeexpr_addrstr(a);
- b = makeexpr_addrstr(b);
- return makeexpr_bicall_3("memcpy", a->val.type, a, b, ex);
- }
- if (a->val.type->kind == TK_SET) {
- a = makeexpr_addrstr(a);
- b = makeexpr_addrstr(b);
- return makeexpr_bicall_2(setcopyname, a->val.type, a, b);
- }
- for (ep = &a; (ex3 = *ep); ) {
- if (ex3->kind == EK_COMMA)
- ep = &ex3->args[ex3->nargs-1];
- else if (ex3->kind == EK_CAST || ex3->kind == EK_ACTCAST)
- ep = &ex3->args[0];
- else
- break;
- }
- if (ex3->kind == EK_BICALL) {
- if (!strcmp(ex3->val.s, getbitsname)) {
- tp = ex3->args[0]->val.type;
- if (tp->kind == TK_ARRAY)
- ex3->args[0] = makeexpr_addr(ex3->args[0]);
- ex3->val.type = tp_void;
- if (checkconst(b, 0) && *clrbitsname) {
- strchange(&ex3->val.s, clrbitsname);
- } else if (*putbitsname &&
- ((ISCONST(b->kind) &&
- (b->val.i | ~((1 << (1 << tp->escale)) - 1)) == -1) ||
- checkconst(b, (1 << (1 << tp->escale)) - 1))) {
- strchange(&ex3->val.s, putbitsname);
- insertarg(ep, 2, makeexpr_arglong(makeexpr_ord(b), 0));
- } else {
- b = makeexpr_arglong(makeexpr_ord(b), 0);
- if (*storebitsname) {
- strchange(&ex3->val.s, storebitsname);
- insertarg(ep, 2, b);
- } else {
- if (exproccurs(b, ex3->args[0])) {
- mp = makestmttempvar(b->val.type, name_TEMP);
- ex2 = makeexpr_assign(makeexpr_var(mp), b);
- b = makeexpr_var(mp);
- } else
- ex2 = NULL;
- ex = copyexpr(ex3);
- strchange(&ex3->val.s, putbitsname);
- insertarg(&ex3, 2, b);
- strchange(&ex->val.s, clrbitsname);
- *ep = makeexpr_comma(ex2, makeexpr_comma(ex, ex3));
- }
- }
- return a;
- } else if (!strcmp(ex3->val.s, getfbufname)) {
- ex3->val.type = tp_void;
- strchange(&ex3->val.s, putfbufname);
- insertarg(ep, 2, b);
- return a;
- } else if (!strcmp(ex3->val.s, chargetfbufname)) {
- ex3->val.type = tp_void;
- if (*charputfbufname) {
- strchange(&ex3->val.s, charputfbufname);
- insertarg(ep, 1, b);
- } else {
- strchange(&ex3->val.s, putfbufname);
- insertarg(ep, 1, makeexpr_type(ex3->val.type->basetype->basetype));
- insertarg(ep, 2, b);
- }
- return a;
- } else if (!strcmp(ex3->val.s, arraygetfbufname)) {
- ex3->val.type = tp_void;
- if (*arrayputfbufname) {
- strchange(&ex3->val.s, arrayputfbufname);
- insertarg(ep, 1, b);
- } else {
- strchange(&ex3->val.s, putfbufname);
- insertarg(ep, 1, makeexpr_type(ex3->val.type->basetype->basetype));
- insertarg(ep, 2, b);
- }
- return a;
- }
- }
- while (a->kind == EK_CAST || a->kind == EK_ACTCAST ||
- a->kind == EK_LITCAST) {
- if (a->kind == EK_LITCAST) {
- b = makeexpr_cast(b, a->args[1]->val.type);
- a = grabarg(a, 1);
- } else if (ansiC < 2 || /* in GNU C, a cast is an lvalue */
- isarithkind(a->args[0]->kind) ||
- (a->val.type->kind == TK_POINTER &&
- a->args[0]->val.type->kind == TK_POINTER)) {
- if (a->kind == EK_CAST)
- b = makeexpr_cast(b, a->args[0]->val.type);
- else
- b = makeexpr_actcast(b, a->args[0]->val.type);
- a = grabarg(a, 0);
- } else
- break;
- }
- if (a->kind == EK_NEG)
- return makeexpr_assign(grabarg(a, 0), makeexpr_neg(b));
- if (a->kind == EK_NOT)
- return makeexpr_assign(grabarg(a, 0), makeexpr_not(b));
- if (a->kind == EK_BNOT)
- return makeexpr_assign(grabarg(a, 0),
- makeexpr_un(EK_BNOT, b->val.type, b));
- if (a->kind == EK_PLUS) {
- for (i = 0; i < a->nargs && a->nargs > 1; ) {
- if (isconstantexpr(a->args[i])) {
- b = makeexpr_minus(b, a->args[i]);
- deletearg(&a, i);
- } else
- i++;
- }
- if (a->nargs == 1)
- return makeexpr_assign(grabarg(a, 0), b);
- }
- if (a->kind == EK_TIMES) {
- for (i = 0; i < a->nargs && a->nargs > 1; ) {
- if (isconstantexpr(a->args[i])) {
- if (a->val.type->kind == TK_REAL)
- b = makeexpr_divide(b, a->args[i]);
- else {
- if (ISCONST(b->kind) && ISCONST(a->args[i]->kind) &&
- (b->val.i % a->args[i]->val.i) != 0) {
- break;
- }
- b = makeexpr_div(b, a->args[i]);
- }
- deletearg(&a, i);
- } else
- i++;
- }
- if (a->nargs == 1)
- return makeexpr_assign(grabarg(a, 0), b);
- }
- if ((a->kind == EK_DIVIDE || a->kind == EK_DIV) &&
- isconstantexpr(a->args[1])) {
- b = makeexpr_times(b, a->args[1]);
- return makeexpr_assign(a->args[0], b);
- }
- if (a->kind == EK_LSH && isconstantexpr(a->args[1])) {
- if (ISCONST(b->kind) && ISCONST(a->args[1]->kind)) {
- if ((b->val.i & ((1L << a->args[1]->val.i)-1)) == 0) {
- b->val.i >>= a->args[1]->val.i;
- return makeexpr_assign(grabarg(a, 0), b);
- }
- } else {
- b = makeexpr_bin(EK_RSH, b->val.type, b, a->args[1]);
- return makeexpr_assign(a->args[0], b);
- }
- }
- if (a->kind == EK_RSH && isconstantexpr(a->args[1])) {
- if (ISCONST(b->kind) && ISCONST(a->args[1]->kind))
- b->val.i <<= a->args[1]->val.i;
- else
- b = makeexpr_bin(EK_LSH, b->val.type, b, a->args[1]);
- return makeexpr_assign(a->args[0], b);
- }
- if (isarithkind(a->kind))
- warning("Invalid assignment [168]");
- return makeexpr_bin(EK_ASSIGN, a->val.type, a, makeexpr_unlongcast(b));
- }
-
-
-
-
- Expr *makeexpr_comma(a, b)
- Expr *a, *b;
- {
- Type *type;
-
- if (!a || nosideeffects(a, 1))
- return b;
- if (!b)
- return a;
- type = b->val.type;
- a = commute(a, b, EK_COMMA);
- a->val.type = type;
- return a;
- }
-
-
-
-
- int strmax(ex)
- Expr *ex;
- {
- Meaning *mp;
- long smin, smax;
- Value val;
- Type *type;
-
- type = ex->val.type;
- if (type->kind == TK_POINTER)
- type = type->basetype;
- if (type->kind == TK_CHAR)
- return 1;
- if (type->kind == TK_ARRAY && type->basetype->kind == TK_CHAR) {
- if (ord_range(type->indextype, &smin, &smax))
- return smax - smin + 1;
- else
- return stringceiling;
- }
- if (type->kind != TK_STRING) {
- intwarning("strmax", "strmax encountered a non-string value [169]");
- return stringceiling;
- }
- if (ex->kind == EK_CONST)
- return ex->val.i;
- if (ex->kind == EK_VAR && foldstrconsts != 0 &&
- (mp = (Meaning *)(ex->val.i))->kind == MK_CONST && mp->val.type)
- return mp->val.i;
- if (ex->kind == EK_BICALL) {
- if (!strcmp(ex->val.s, strsubname)) {
- if (isliteralconst(ex->args[3], &val) && val.type)
- return val.i;
- }
- }
- if (ord_range(type->indextype, NULL, &smax))
- return smax;
- else
- return stringceiling;
- }
-
-
-
-
- int strhasnull(val)
- Value val;
- {
- int i;
-
- for (i = 0; i < val.i; i++) {
- if (!val.s[i])
- return (i == val.i-1) ? 1 : 2;
- }
- return 0;
- }
-
-
-
- int istempsprintf(ex)
- Expr *ex;
- {
- return (ex->kind == EK_BICALL && !strcmp(ex->val.s, "sprintf") &&
- ex->nargs >= 2 &&
- istempvar(ex->args[0]) &&
- ex->args[1]->kind == EK_CONST &&
- ex->args[1]->val.type->kind == TK_STRING);
- }
-
-
-
- Expr *makeexpr_sprintfify(ex)
- Expr *ex;
- {
- Meaning *tvar;
- char stringbuf[500];
- char *cp, ch;
- int j, nnulls;
- Expr *ex2;
-
- if (debug>2) { fprintf(outf,"makeexpr_sprintfify("); dumpexpr(ex); fprintf(outf,")\n"); }
- if (istempsprintf(ex))
- return ex;
- ex = makeexpr_stringcast(ex);
- tvar = makestmttempvar(tp_str255, name_STRING);
- if (ex->kind == EK_CONST && ex->val.type->kind == TK_STRING) {
- cp = stringbuf;
- nnulls = 0;
- for (j = 0; j < ex->val.i; j++) {
- ch = ex->val.s[j];
- if (!ch) {
- if (j < ex->val.i-1)
- note("Null character in sprintf control string [147]");
- else
- note("Null character at end of sprintf control string [148]");
- if (keepnulls) {
- *cp++ = '%';
- *cp++ = 'c';
- nnulls++;
- }
- } else {
- *cp++ = ch;
- if (ch == '%')
- *cp++ = ch;
- }
- }
- *cp = 0;
- ex = makeexpr_bicall_2("sprintf", tp_str255,
- makeexpr_var(tvar),
- makeexpr_string(stringbuf));
- while (--nnulls >= 0)
- insertarg(&ex, 2, makeexpr_char(0));
- return ex;
- } else if (ex->val.type->kind == TK_ARRAY &&
- ex->val.type->basetype->kind == TK_CHAR) {
- ex2 = arraysize(ex->val.type, 0);
- return cleansprintf(
- makeexpr_bicall_4("sprintf", tp_str255,
- makeexpr_var(tvar),
- makeexpr_string("%.*s"),
- ex2,
- makeexpr_addrstr(ex)));
- } else {
- if (ord_type(ex->val.type)->kind == TK_CHAR)
- cp = "%c";
- else if (ex->val.type->kind == TK_STRING)
- cp = "%s";
- else {
- warning("Mixing non-strings with strings [170]");
- return ex;
- }
- return makeexpr_bicall_3("sprintf", tp_str255,
- makeexpr_var(tvar),
- makeexpr_string(cp),
- ex);
- }
- }
-
-
-
- Expr *makeexpr_unsprintfify(ex)
- Expr *ex;
- {
- char stringbuf[500];
- char *cp, ch;
- int i;
-
- if (debug>2) { fprintf(outf,"makeexpr_unsprintfify("); dumpexpr(ex); fprintf(outf,")\n"); }
- if (!istempsprintf(ex))
- return ex;
- canceltempvar(istempvar(ex->args[0]));
- for (i = 2; i < ex->nargs; i++) {
- if (ex->args[i]->val.type->kind != TK_CHAR ||
- !checkconst(ex, 0))
- return ex;
- }
- cp = stringbuf;
- for (i = 0; i < ex->args[1]->val.i; i++) {
- ch = ex->args[1]->val.s[i];
- *cp++ = ch;
- if (ch == '%') {
- if (++i == ex->args[1]->val.i)
- return ex;
- ch = ex->args[1]->val.s[i];
- if (ch == 'c')
- cp[-1] = 0;
- else if (ch != '%')
- return ex;
- }
- }
- freeexpr(ex);
- return makeexpr_lstring(stringbuf, cp - stringbuf);
- }
-
-
-
- /* Returns >= 0 iff unsprintfify would return a string constant */
-
- int sprintflength(ex, allownulls)
- Expr *ex;
- int allownulls;
- {
- int i, len;
-
- if (!istempsprintf(ex))
- return -1;
- for (i = 2; i < ex->nargs; i++) {
- if (!allownulls ||
- ex->args[i]->val.type->kind != TK_CHAR ||
- !checkconst(ex, 0))
- return -1;
- }
- len = 0;
- for (i = 0; i < ex->args[1]->val.i; i++) {
- len++;
- if (ex->args[1]->val.s[i] == '%') {
- if (++i == ex->args[1]->val.i)
- return -1;
- if (ex->args[1]->val.s[i] != 'c' &&
- ex->args[1]->val.s[i] != '%')
- return -1;
- }
- }
- return len;
- }
-
-
-
- Expr *makeexpr_concat(a, b, usesprintf)
- Expr *a, *b;
- int usesprintf;
- {
- int i, ii, j, len, nargs;
- Type *type;
- Meaning *mp, *tvar;
- Expr *ex, *args[2];
- int akind[2];
- Value val, val1, val2;
- char formatstr[300];
-
- if (debug>2) { fprintf(outf,"makeexpr_concat("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); }
- if (!a)
- return b;
- if (!b)
- return a;
- a = makeexpr_stringcast(a);
- b = makeexpr_stringcast(b);
- if (checkconst(a, 0)) {
- freeexpr(a);
- return b;
- }
- if (checkconst(b, 0)) {
- freeexpr(b);
- return a;
- }
- len = strmax(a) + strmax(b);
- type = makestringtype(len);
- if (a->kind == EK_CONST && b->kind == EK_CONST) {
- val1 = a->val;
- val2 = b->val;
- val.i = val1.i + val2.i;
- val.s = ALLOC(val.i+1, char, literals);
- val.s[val.i] = 0;
- val.type = type;
- memcpy(val.s, val1.s, val1.i);
- memcpy(val.s + val1.i, val2.s, val2.i);
- freeexpr(a);
- freeexpr(b);
- return makeexpr_val(val);
- }
- tvar = makestmttempvar(type, name_STRING);
- if (sprintf_value != 2 || usesprintf) {
- nargs = 2; /* Generate a call to sprintf(), unfolding */
- args[0] = a; /* nested sprintf()'s. */
- args[1] = b;
- *formatstr = 0;
- for (i = 0; i < 2; i++) {
- #if 1
- ex = args[i] = makeexpr_sprintfify(args[i]);
- if (!ex->args[1] || !ex->args[1]->val.s)
- intwarning("makeexpr_concat", "NULL in ex->args[1]");
- else
- strncat(formatstr, ex->args[1]->val.s, ex->args[1]->val.i);
- canceltempvar(istempvar(ex->args[0]));
- nargs += (ex->nargs - 2);
- akind[i] = 0; /* now obsolete */
- #else
- ex = args[i];
- if (ex->kind == EK_CONST)
- ex = makeexpr_sprintfify(ex);
- if (istempsprintf(ex)) {
- strncat(formatstr, ex->args[1]->val.s, ex->args[1]->val.i);
- canceltempvar(istempvar(ex->args[0]));
- nargs += (ex->nargs - 2);
- akind[i] = 0;
- } else {
- strcat(formatstr, "%s");
- nargs++;
- akind[i] = 1;
- }
- #endif
- }
- ex = makeexpr(EK_BICALL, nargs);
- ex->val.type = type;
- ex->val.s = stralloc("sprintf");
- ex->args[0] = makeexpr_var(tvar);
- ex->args[1] = makeexpr_string(formatstr);
- j = 2;
- for (i = 0; i < 2; i++) {
- switch (akind[i]) {
- case 0: /* flattened sub-sprintf */
- for (ii = 2; ii < args[i]->nargs; ii++)
- ex->args[j++] = copyexpr(args[i]->args[ii]);
- freeexpr(args[i]);
- break;
- case 1: /* included string expr */
- ex->args[j++] = args[i];
- break;
- }
- }
- } else {
- ex = a;
- while (ex->kind == EK_BICALL && !strcmp(ex->val.s, "strcat"))
- ex = ex->args[0];
- if (ex->kind == EK_BICALL && !strcmp(ex->val.s, "strcpy") &&
- (mp = istempvar(ex->args[0])) != NULL) {
- canceltempvar(mp);
- freeexpr(ex->args[0]);
- ex->args[0] = makeexpr_var(tvar);
- } else {
- a = makeexpr_bicall_2("strcpy", type, makeexpr_var(tvar), a);
- }
- ex = makeexpr_bicall_2("strcat", type, a, b);
- }
- if (debug>2) { fprintf(outf,"makeexpr_concat returns "); dumpexpr(ex); fprintf(outf,"\n"); }
- return ex;
- }
-
-
-
- Expr *cleansprintf(ex)
- Expr *ex;
- {
- int fidx, i, j, k, len, changed = 0;
- char *cp, *bp;
- char fmtbuf[300];
-
- if (ex->kind != EK_BICALL)
- return ex;
- if (!strcmp(ex->val.s, "printf"))
- fidx = 0;
- else if (!strcmp(ex->val.s, "sprintf") ||
- !strcmp(ex->val.s, "fprintf"))
- fidx = 1;
- else
- return ex;
- len = ex->args[fidx]->val.i;
- cp = ex->args[fidx]->val.s; /* printf("%*d",17,x) => printf("%17d",x) */
- bp = fmtbuf;
- j = fidx + 1;
- for (i = 0; i < len; i++) {
- *bp++ = cp[i];
- if (cp[i] == '%') {
- if (cp[i+1] == 's' && ex->args[j]->kind == EK_CONST) {
- bp--;
- for (k = 0; k < ex->args[j]->val.i; k++)
- *bp++ = ex->args[j]->val.s[k];
- delfreearg(&ex, j);
- changed = 1;
- i++;
- continue;
- }
- for (i++; i < len &&
- !(isalpha(cp[i]) && cp[i] != 'l'); i++) {
- if (cp[i] == '*') {
- if (isliteralconst(ex->args[j], NULL) == 2) {
- sprintf(bp, "%ld", ex->args[j]->val.i);
- bp += strlen(bp);
- delfreearg(&ex, j);
- changed = 1;
- } else {
- *bp++ = cp[i];
- j++;
- }
- } else
- *bp++ = cp[i];
- }
- if (i < len)
- *bp++ = cp[i];
- j++;
- }
- }
- *bp = 0;
- if (changed) {
- freeexpr(ex->args[fidx]);
- ex->args[fidx] = makeexpr_string(fmtbuf);
- }
- return ex;
- }
-
-
-
- Expr *makeexpr_substring(vex, ex, exi, exj)
- Expr *vex, *ex, *exi, *exj;
- {
- exi = makeexpr_unlongcast(exi);
- exj = makeexpr_longcast(exj, 0);
- ex = bumpstring(ex, exi, 1);
- return cleansprintf(makeexpr_bicall_4("sprintf", tp_str255,
- vex,
- makeexpr_string("%.*s"),
- exj,
- ex));
- }
-
-
-
-
- Expr *makeexpr_dot(ex, mp)
- Expr *ex;
- Meaning *mp;
- {
- Type *ot1, *ot2;
- Expr *ex2, *ex3, *nex;
- Meaning *tvar;
-
- if (ex->kind == EK_FUNCTION && copystructfuncs > 0) {
- tvar = makestmttempvar(ex->val.type, name_TEMP);
- ex2 = makeexpr_assign(makeexpr_var(tvar), ex);
- ex = makeexpr_var(tvar);
- } else
- ex2 = NULL;
- if (mp->constdefn) {
- nex = makeexpr(EK_MACARG, 0);
- nex->val.type = tp_integer;
- ex3 = replaceexprexpr(copyexpr(mp->constdefn), nex, ex, 0);
- freeexpr(ex);
- freeexpr(nex);
- ex = gentle_cast(ex3, mp->val.type);
- } else {
- ex = makeexpr_un(EK_DOT, mp->type, ex);
- ex->val.i = (long)mp;
- ot1 = ord_type(mp->type);
- ot2 = ord_type(mp->val.type);
- if (ot1->kind != ot2->kind && ot2->kind == TK_ENUM && ot2->meaning && useenum)
- ex = makeexpr_cast(ex, mp->val.type);
- else if (mp->val.i && !hassignedchar &&
- (mp->type == tp_sint || mp->type == tp_abyte)) {
- if (*signextname) {
- ex = makeexpr_bicall_2(signextname, tp_integer,
- ex, makeexpr_long(mp->val.i));
- } else
- note(format_s("Unable to sign-extend field %s [149]", mp->name));
- }
- }
- ex->val.type = mp->val.type;
- return makeexpr_comma(ex2, ex);
- }
-
-
-
- Expr *makeexpr_dotq(ex, name, type)
- Expr *ex;
- char *name;
- Type *type;
- {
- ex = makeexpr_un(EK_DOT, type, ex);
- ex->val.s = stralloc(name);
- return ex;
- }
-
-
-
- Expr *strmax_func(ex)
- Expr *ex;
- {
- Meaning *mp;
- Expr *ex2;
- Type *type;
-
- type = ex->val.type;
- if (type->kind == TK_POINTER) {
- intwarning("strmax_func", "got a pointer instead of a string [171]");
- type = type->basetype;
- }
- if (type->kind == TK_CHAR)
- return makeexpr_long(1);
- if (type->kind != TK_STRING) {
- warning("STRMAX of non-string value [172]");
- return makeexpr_long(stringceiling);
- }
- if (ex->kind == EK_CONST)
- return makeexpr_long(ex->val.i);
- if (ex->kind == EK_VAR &&
- (mp = (Meaning *)ex->val.i)->kind == MK_CONST &&
- mp->type == tp_str255 && mp->val.type)
- return makeexpr_long(mp->val.i);
- if (ex->kind == EK_VAR &&
- (mp = (Meaning *)ex->val.i)->kind == MK_VARPARAM &&
- mp->type == tp_strptr) {
- if (mp->anyvarflag) {
- if (mp->ctx != curctx && mp->ctx->kind == MK_FUNCTION)
- note(format_s("Reference to STRMAX of parent proc's \"%s\" must be fixed [150]",
- mp->name));
- return makeexpr_name(format_s(name_STRMAX, mp->name), tp_int);
- } else
- note(format_s("STRMAX of \"%s\" wants VarStrings=1 [151]", mp->name));
- }
- ord_range_expr(type->indextype, NULL, &ex2);
- return copyexpr(ex2);
- }
-
-
-
-
- Expr *makeexpr_nil()
- {
- Expr *ex;
-
- ex = makeexpr(EK_CONST, 0);
- ex->val.type = tp_anyptr;
- ex->val.i = 0;
- ex->val.s = NULL;
- return ex;
- }
-
-
-
- Expr *makeexpr_ctx(ctx)
- Meaning *ctx;
- {
- Expr *ex;
-
- ex = makeexpr(EK_CTX, 0);
- ex->val.type = tp_text; /* handy pointer type */
- ex->val.i = (long)ctx;
- return ex;
- }
-
-
-
-
- Expr *force_signed(ex)
- Expr *ex;
- {
- Type *tp;
-
- if (isliteralconst(ex, NULL) == 2 && ex->nargs == 0)
- return ex;
- tp = true_type(ex);
- if (tp == tp_ushort || tp == tp_ubyte || tp == tp_uchar)
- return makeexpr_cast(ex, tp_sshort);
- else if (tp == tp_unsigned || tp == tp_uint) {
- if (exprlongness(ex) < 0)
- return makeexpr_cast(ex, tp_sint);
- else
- return makeexpr_cast(ex, tp_integer);
- }
- return ex;
- }
-
-
-
- Expr *force_unsigned(ex)
- Expr *ex;
- {
- Type *tp;
-
- if (isliteralconst(ex, NULL) == 2 && !expr_is_neg(ex))
- return ex;
- tp = true_type(ex);
- if (tp == tp_unsigned || tp == tp_uint || tp == tp_ushort ||
- tp == tp_ubyte || tp == tp_uchar)
- return ex;
- if (tp->kind == TK_CHAR)
- return makeexpr_actcast(ex, tp_uchar);
- else if (exprlongness(ex) < 0)
- return makeexpr_cast(ex, tp_uint);
- else
- return makeexpr_cast(ex, tp_unsigned);
- }
-
-
-
-
- #define CHECKSIZE(size) (((size) > 0 && (size)%charsize == 0) ? (size)/charsize : 0)
-
- long type_sizeof(type, pasc)
- Type *type;
- int pasc;
- {
- long s1, smin, smax;
- int charsize = (sizeof_char) ? sizeof_char : CHAR_BIT; /* from <limits.h> */
-
- switch (type->kind) {
-
- case TK_INTEGER:
- if (type == tp_integer ||
- type == tp_unsigned)
- return pasc ? 4 : CHECKSIZE(sizeof_integer);
- else
- return pasc ? 2 : CHECKSIZE(sizeof_short);
-
- case TK_CHAR:
- case TK_BOOLEAN:
- return 1;
-
- case TK_SUBR:
- type = findbasetype(type, ODECL_NOPRES);
- if (pasc) {
- if (type == tp_integer || type == tp_unsigned)
- return 4;
- else
- return 2;
- } else {
- if (type == tp_abyte || type == tp_ubyte || type == tp_sbyte)
- return 1;
- else if (type == tp_ushort || type == tp_sshort)
- return CHECKSIZE(sizeof_short);
- else
- return CHECKSIZE(sizeof_integer);
- }
-
- case TK_POINTER:
- return pasc ? 4 : CHECKSIZE(sizeof_pointer);
-
- case TK_REAL:
- if (type == tp_longreal)
- return pasc ? (which_lang == LANG_TURBO ? 6 : 8) : CHECKSIZE(sizeof_double);
- else
- return pasc ? 4 : CHECKSIZE(sizeof_float);
-
- case TK_ENUM:
- if (!pasc)
- return CHECKSIZE(sizeof_enum);
- type = findbasetype(type, ODECL_NOPRES);
- return type->kind != TK_ENUM ? type_sizeof(type, pasc)
- : CHECKSIZE(pascalenumsize);
-
- case TK_SMALLSET:
- case TK_SMALLARRAY:
- return pasc ? 0 : type_sizeof(type->basetype, pasc);
-
- case TK_ARRAY:
- s1 = type_sizeof(type->basetype, pasc);
- if (s1 && ord_range(type->indextype, &smin, &smax))
- return s1 * (smax - smin + 1);
- else
- return 0;
-
- case TK_RECORD:
- if (pasc && type->meaning) {
- if (!strcmp(type->meaning->sym->name, "NA_WORD"))
- return 2;
- else if (!strcmp(type->meaning->sym->name, "NA_LONGWORD"))
- return 4;
- else if (!strcmp(type->meaning->sym->name, "NA_QUADWORD"))
- return 8;
- else
- return 0;
- } else
- return 0;
-
- default:
- return 0;
- }
- }
-
-
-
- Static Value eval_expr_either(ex, pasc)
- Expr *ex;
- int pasc;
- {
- Value val, val2;
- Meaning *mp;
- int i;
-
- if (debug>2) { fprintf(outf,"eval_expr("); dumpexpr(ex); fprintf(outf,")\n"); }
- switch (ex->kind) {
-
- case EK_CONST:
- case EK_LONGCONST:
- return ex->val;
-
- case EK_VAR:
- mp = (Meaning *) ex->val.i;
- if (mp->kind == MK_CONST &&
- (foldconsts != 0 ||
- mp == mp_maxint || mp == mp_minint))
- return mp->val;
- break;
-
- case EK_SIZEOF:
- i = type_sizeof(ex->args[0]->val.type, pasc);
- if (i)
- return make_ord(tp_integer, i);
- break;
-
- case EK_PLUS:
- val = eval_expr_either(ex->args[0], pasc);
- if (!val.type || ord_type(val.type)->kind != TK_INTEGER)
- val.type = NULL;
- for (i = 1; val.type && i < ex->nargs; i++) {
- val2 = eval_expr_either(ex->args[i], pasc);
- if (!val2.type || ord_type(val2.type)->kind != TK_INTEGER)
- val.type = NULL;
- else {
- val.i += val2.i;
- val.type = tp_integer;
- }
- }
- return val;
-
- case EK_TIMES:
- val = eval_expr_either(ex->args[0], pasc);
- if (!val.type || ord_type(val.type)->kind != TK_INTEGER)
- val.type = NULL;
- for (i = 1; val.type && i < ex->nargs; i++) {
- val2 = eval_expr_either(ex->args[i], pasc);
- if (!val2.type || ord_type(val2.type)->kind != TK_INTEGER)
- val.type = NULL;
- else {
- val.i *= val2.i;
- val.type = tp_integer;
- }
- }
- return val;
-
- case EK_DIV:
- val = eval_expr_either(ex->args[0], pasc);
- val2 = eval_expr_either(ex->args[1], pasc);
- if (val.type && ord_type(val.type)->kind == TK_INTEGER &&
- val2.type && ord_type(val2.type)->kind == TK_INTEGER &&
- val2.i) {
- val.i /= val2.i;
- val.type = tp_integer;
- return val;
- }
- break;
-
- case EK_MOD:
- val = eval_expr_either(ex->args[0], pasc);
- val2 = eval_expr_either(ex->args[1], pasc);
- if (val.type && ord_type(val.type)->kind == TK_INTEGER &&
- val2.type && ord_type(val2.type)->kind == TK_INTEGER &&
- val2.i) {
- val.i %= val2.i;
- val.type = tp_integer;
- return val;
- }
- break;
-
- case EK_NEG:
- val = eval_expr_either(ex->args[0], pasc);
- if (val.type) {
- val.i = -val.i;
- return val;
- }
- break;
-
- case EK_LSH:
- val = eval_expr_either(ex->args[0], pasc);
- val2 = eval_expr_either(ex->args[1], pasc);
- if (val.type && val2.type) {
- val.i <<= val2.i;
- return val;
- }
- break;
-
- case EK_RSH:
- val = eval_expr_either(ex->args[0], pasc);
- val2 = eval_expr_either(ex->args[1], pasc);
- if (val.type && val2.type) {
- val.i >>= val2.i;
- return val;
- }
- break;
-
- case EK_BAND:
- val = eval_expr_either(ex->args[0], pasc);
- val2 = eval_expr_either(ex->args[1], pasc);
- if (val.type && val2.type) {
- val.i &= val2.i;
- return val;
- }
- break;
-
- case EK_BOR:
- val = eval_expr_either(ex->args[0], pasc);
- val2 = eval_expr_either(ex->args[1], pasc);
- if (val.type && val2.type) {
- val.i |= val2.i;
- return val;
- }
- break;
-
- case EK_BXOR:
- val = eval_expr_either(ex->args[0], pasc);
- val2 = eval_expr_either(ex->args[1], pasc);
- if (val.type && val2.type) {
- val.i ^= val2.i;
- return val;
- }
- break;
-
- case EK_BNOT:
- val = eval_expr_either(ex->args[0], pasc);
- if (val.type) {
- val.i = ~val.i;
- return val;
- }
- break;
-
- case EK_EQ:
- case EK_NE:
- case EK_GT:
- case EK_LT:
- case EK_GE:
- case EK_LE:
- val = eval_expr_either(ex->args[0], pasc);
- val2 = eval_expr_either(ex->args[1], pasc);
- if (val.type) {
- if (val.i == val2.i)
- val.i = (ex->kind == EK_EQ || ex->kind == EK_GE || ex->kind == EK_LE);
- else if (val.i < val2.i)
- val.i = (ex->kind == EK_LT || ex->kind == EK_LE || ex->kind == EK_NE);
- else
- val.i = (ex->kind == EK_GT || ex->kind == EK_GE || ex->kind == EK_NE);
- val.type = tp_boolean;
- return val;
- }
- break;
-
- case EK_NOT:
- val = eval_expr_either(ex->args[0], pasc);
- if (val.type)
- val.i = !val.i;
- return val;
-
- case EK_AND:
- for (i = 0; i < ex->nargs; i++) {
- val = eval_expr_either(ex->args[i], pasc);
- if (!val.type || !val.i)
- return val;
- }
- return val;
-
- case EK_OR:
- for (i = 0; i < ex->nargs; i++) {
- val = eval_expr_either(ex->args[i], pasc);
- if (!val.type || val.i)
- return val;
- }
- return val;
-
- case EK_COMMA:
- return eval_expr_either(ex->args[ex->nargs-1], pasc);
-
- default:
- break;
- }
- val.type = NULL;
- return val;
- }
-
-
- Value eval_expr(ex)
- Expr *ex;
- {
- return eval_expr_either(ex, 0);
- }
-
-
- Value eval_expr_consts(ex)
- Expr *ex;
- {
- Value val;
- short save_fold = foldconsts;
-
- foldconsts = 1;
- val = eval_expr_either(ex, 0);
- foldconsts = save_fold;
- return val;
- }
-
-
- Value eval_expr_pasc(ex)
- Expr *ex;
- {
- return eval_expr_either(ex, 1);
- }
-
-
-
- int expr_is_const(ex)
- Expr *ex;
- {
- int i;
-
- switch (ex->kind) {
-
- case EK_CONST:
- case EK_LONGCONST:
- case EK_SIZEOF:
- return 1;
-
- case EK_VAR:
- return (((Meaning *)ex->val.i)->kind == MK_CONST);
-
- case EK_HAT:
- case EK_ASSIGN:
- case EK_POSTINC:
- case EK_POSTDEC:
- return 0;
-
- case EK_ADDR:
- if (ex->args[0]->kind == EK_VAR)
- return 1;
- return 0; /* conservative */
-
- case EK_FUNCTION:
- if (!nosideeffects_func(ex))
- return 0;
- break;
-
- case EK_BICALL:
- if (!nosideeffects_func(ex))
- return 0;
- break;
-
- default:
- break;
- }
- for (i = 0; i < ex->nargs; i++) {
- if (!expr_is_const(ex->args[i]))
- return 0;
- }
- return 1;
- }
-
-
-
-
-
- Expr *eatcasts(ex)
- Expr *ex;
- {
- while (ex->kind == EK_CAST)
- ex = grabarg(ex, 0);
- return ex;
- }
-
-
-
-
-
- /* End. */
-
-
-
-