expr.c.2
上传用户:upcnvip
上传日期:2007-01-06
资源大小:474k
文件大小:48k
- 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))
- 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 < 2) {
- if (a->nargs < 1) {
- type = a->val.type;
- FREE(a);
- a = gentle_cast(makeexpr_long(0), type);
- a->val.type = type;
- return a;
- } else {
- b = a->args[0];
- FREE(a);
- return b;
- }
- }
- 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);
- }
- }
- }
- 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;
- 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))
- delfreearg(&a, a->nargs-1);
- if (checkconst(a->args[a->nargs-1], -1)) {
- delfreearg(&a, a->nargs-1);
- a->args[0] = makeexpr_neg(a->args[0]);
- }
- if (checkconst(a->args[a->nargs-1], 0) && nosideeffects(a, 1)) {
- 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;
- }
- }
- 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 &&
- (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 &&
- (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 &&
- 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_CONST &&
- (mp->type->kind == TK_ARRAY ||
- mp->type->kind == TK_RECORD ||
- mp->type->kind == TK_SET)));
- case EK_HAT:
- return 1;
- case EK_INDEX:
- return expr_is_lvalue(ex->args[0]);
- case EK_DOT:
- return expr_is_lvalue(ex->args[0]);
- 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;
- 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 needs its associated buffers [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)) {
- requirefilebuffer(a);
- if (*chargetfbufname &&
- a->val.type->basetype->basetype->kind == TK_CHAR)
- return makeexpr_bicall_1(chargetfbufname,
- a->val.type->basetype->basetype, a);
- else if (*arraygetfbufname &&
- a->val.type->basetype->basetype->kind == TK_ARRAY)
- return makeexpr_bicall_2(arraygetfbufname,
- a->val.type->basetype->basetype, a,
- makeexpr_type(a->val.type->basetype->basetype));
- else
- return makeexpr_bicall_2(getfbufname,
- a->val.type->basetype->basetype, a,
- makeexpr_type(a->val.type->basetype->basetype));
- }
- 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;
- 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 {
- 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
- 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 ((a->kind == EK_VAR &&
- (mp == mp_input || mp == mp_output)) ||
- (a->kind == EK_NAME &&
- !strcmp(a->val.s, "stderr"))) {
- 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, 0);
- 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) {
- 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));
- break;
- 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++) {