expr.c.3
上传用户:upcnvip
上传日期:2007-01-06
资源大小:474k
文件大小:41k
- 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 (!nodependencies(ex->args[1], 1))
- return NULL;
- 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 *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) &&
- !(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) {
- 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)
- 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);
- 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)
- 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, 0);
- 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, 0);
- 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) != tp_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) != tp_integer)
- val.type = NULL;
- else
- val.i += val2.i;
- }
- return val;
- case EK_TIMES:
- val = eval_expr_either(ex->args[0], pasc);
- if (!val.type || ord_type(val.type) != tp_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) != tp_integer)
- val.type = NULL;
- else
- val.i *= val2.i;
- }
- 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) == tp_integer &&
- val2.type && ord_type(val2.type) == tp_integer && val2.i) {
- val.i /= val2.i;
- 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) == tp_integer &&
- val2.type && ord_type(val2.type) == tp_integer && val2.i) {
- val.i %= val2.i;
- 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. */