Example #1
0
/*
 * Add an opcode to the current function being compiled.
 * Note: This can change the curfunc global variable when the
 * function needs expanding.
 */
void
addop(long op)
{
    register FUNC *fp;		/* current function */
    NUMBER *q, *q1, *q2;
    unsigned long count;
    BOOL cut;
    int diff;

    fp = curfunc;
    count = fp->f_opcodecount;
    cut = TRUE;
    diff = 2;
    q = NULL;
    if ((count + 5) >= maxopcodes) {
        maxopcodes += OPCODEALLOCSIZE;
        fp = (FUNC *) malloc(funcsize(maxopcodes));
        if (fp == NULL) {
            math_error("cannot malloc function");
            /*NOTREACHED*/
        }
        memcpy((char *) fp, (char *) curfunc,
               funcsize(curfunc->f_opcodecount));
        if (curfunc != functemplate)
            free(curfunc);
        curfunc = fp;
    }

    /*
     * Check the current opcode against the previous opcode and try to
     * slightly optimize the code depending on the various combinations.
     */
    switch (op) {
    case OP_GETVALUE:
        switch (oldop) {
        case OP_NUMBER:
        case OP_ZERO:
        case OP_ONE:
        case OP_IMAGINARY:
        case OP_GETEPSILON:
        case OP_SETEPSILON:
        case OP_STRING:
        case OP_UNDEF:
        case OP_GETCONFIG:
        case OP_SETCONFIG:
            return;
        case OP_DUPLICATE:
            diff = 1;
            oldop = OP_DUPVALUE;
            break;
        case OP_FIADDR:
            diff = 1;
            oldop = OP_FIVALUE;
            break;
        case OP_GLOBALADDR:
            diff = 1 + PTR_SIZE;
            oldop = OP_GLOBALVALUE;
            break;
        case OP_LOCALADDR:
            oldop = OP_LOCALVALUE;
            break;
        case OP_PARAMADDR:
            oldop = OP_PARAMVALUE;
            break;
        case OP_ELEMADDR:
            oldop = OP_ELEMVALUE;
            break;
        default:
            cut = FALSE;

        }
        if (cut) {
            fp->f_opcodes[count - diff] = oldop;
            return;
        }
        break;
    case OP_POP:
        switch (oldop) {
        case OP_ASSIGN:
            fp->f_opcodes[count-1] = OP_ASSIGNPOP;
            oldop = OP_ASSIGNPOP;
            return;
        case OP_NUMBER:
        case OP_IMAGINARY:
            q = constvalue(fp->f_opcodes[count-1]);
            qfree(q);
            break;
        case OP_STRING:
            sfree(findstring((long)fp->f_opcodes[count-1]));
            break;
        case OP_LOCALADDR:
        case OP_PARAMADDR:
            break;
        case OP_GLOBALADDR:
            diff = 1 + PTR_SIZE;
            break;
        case OP_UNDEF:
            fp->f_opcodecount -= 1;
            oldop = OP_NOP;
            oldoldop = OP_NOP;
            return;
        default:
            cut = FALSE;
        }
        if (cut) {
            fp->f_opcodecount -= diff;
            oldop = OP_NOP;
            oldoldop = OP_NOP;
            fprintf(stderr,
                    "Line %ld: unused value ignored\n",
                    linenumber());
            return;
        }
        break;
    case OP_NEGATE:
        if (oldop == OP_NUMBER) {
            q = constvalue(fp->f_opcodes[count-1]);
            fp->f_opcodes[count-1] = addqconstant(qneg(q));
            qfree(q);
            return;
        }
    }
    if (oldop == OP_NUMBER) {
        if (oldoldop == OP_NUMBER) {
            q1 = constvalue(fp->f_opcodes[count - 3]);
            q2 = constvalue(fp->f_opcodes[count - 1]);
            switch (op) {
            case OP_DIV:
                if (qiszero(q2)) {
                    cut = FALSE;
                    break;
                }
                q = qqdiv(q1,q2);
                break;
            case OP_MUL:
                q = qmul(q1,q2);
                break;
            case OP_ADD:
                q = qqadd(q1,q2);
                break;
            case OP_SUB:
                q = qsub(q1,q2);
                break;
            case OP_POWER:
                if (qisfrac(q2) || qisneg(q2))
                    cut = FALSE;
                else
                    q = qpowi(q1,q2);
                break;
            default:
                cut = FALSE;
            }
            if (cut) {
                qfree(q1);
                qfree(q2);
                fp->f_opcodes[count - 3] = addqconstant(q);
                fp->f_opcodecount -= 2;
                oldoldop = OP_NOP;
                return;
            }
        } else if (op != OP_NUMBER) {
            q = constvalue(fp->f_opcodes[count - 1]);
            if (op == OP_POWER) {
                if (qcmpi(q, 2L) == 0) {
                    fp->f_opcodecount--;
                    fp->f_opcodes[count - 2] = OP_SQUARE;
                    qfree(q);
                    oldop = OP_SQUARE;
                    return;
                }
                if (qcmpi(q, 4L) == 0) {
                    fp->f_opcodes[count - 2] = OP_SQUARE;
                    fp->f_opcodes[count - 1] = OP_SQUARE;
                    qfree(q);
                    oldop = OP_SQUARE;
                    return;
                }
            }
            if (qiszero(q)) {
                qfree(q);
                fp->f_opcodes[count - 2] = OP_ZERO;
                fp->f_opcodecount--;
            } else if (qisone(q)) {
                qfree(q);
                fp->f_opcodes[count - 2] = OP_ONE;
                fp->f_opcodecount--;
            }
        }
    }
    /*
     * No optimization possible, so store the opcode.
     */
    fp->f_opcodes[fp->f_opcodecount] = op;
    fp->f_opcodecount++;
    oldoldop = oldop;
    oldop = op;
}
Example #2
0
void UmlOperation::roundtrip(const char * path, aLanguage who)
{
    char * s = read_file(path);

    if (s != 0) {
        char * p1 = s;
        char * p2;
        WrapperStr(UmlOperation::*get_body)();
        bool (UmlOperation::*set_body)(const char * s);
        bool (UmlOperation::*set_contextualbodyindent)(bool v);
        const char * prefix;
        const char * postfix;

        switch (who) {
        case cppLanguage:
            get_body = &UmlOperation::cppBody;
            set_body = &UmlOperation::set_CppBody;
            set_contextualbodyindent = &UmlOperation::set_CppContextualBodyIndent;
            prefix = BodyPrefix;
            postfix = BodyPostfix;
            break;

        case javaLanguage:
            get_body = &UmlOperation::javaBody;
            set_body = &UmlOperation::set_JavaBody;
            set_contextualbodyindent = &UmlOperation::set_JavaContextualBodyIndent;
            prefix = BodyPrefix;
            postfix = BodyPostfix;
            break;

        case phpLanguage:
            get_body = &UmlOperation::phpBody;
            set_body = &UmlOperation::set_PhpBody;
            set_contextualbodyindent = &UmlOperation::set_PhpContextualBodyIndent;
            prefix = BodyPrefix;
            postfix = BodyPostfix;
            break;

        default:
            // python
            get_body = &UmlOperation::pythonBody;
            set_body = &UmlOperation::set_PythonBody;
            set_contextualbodyindent = &UmlOperation::set_PythonContextualBodyIndent;
            prefix = BodyPythonPrefix;
            postfix = BodyPythonPostfix;
        }

        while ((p2 = strstr(p1, prefix)) != 0) {
            p2 += BodyPrefixLength;

            char * body;
            long id = strtol(p2, &body, 16);

            if (body != (p2 + 8)) {
                UmlCom::trace(WrapperStr("<font color =\"red\"> Error in ") + path +
                              linenumber(s, p2 - BodyPrefixLength) +
                              " : invalid preserve body identifier</font><br>");
                UmlCom::bye(n_errors() + 1);
                UmlCom::fatal_error("read_bodies 1");
            }

            if (*body == '\r')
                body += 1;

            if (*body == '\n')
                body += 1;
            else {
                UmlCom::trace(WrapperStr("<font  color =\"red\"> Error in ") + path +
                              linenumber(s, p2 - BodyPrefixLength) +
                              " : invalid preserve body block, end of line expected</font><br>");
                UmlCom::bye(n_errors() + 1);
                UmlCom::fatal_error("read_bodies 2");
            }

            UmlOperation * op = (UmlOperation *)
                                UmlBaseItem::from_id((unsigned) id, anOperation);

            if (op == 0) {
                QString n("%1");
                n.arg(QString::number((unsigned) id));
                UmlCom::trace(WrapperStr("<font  color =\"red\"> Error in ") + path +
                              linenumber(s, p2 - BodyPrefixLength) +
                              " : invalid operation id " + n + "</font><br>");
                UmlCom::bye(n_errors() + 1);
                UmlCom::fatal_error("read_bodies 3");
                return;
            }

            if (((p1 = strstr(body, postfix)) == 0) ||
                (strncmp(p1 + BodyPostfixLength, p2, 8) != 0)) {
                UmlCom::trace(WrapperStr("<font  color =\"red\"> Error in ") + path +
                              linenumber(s, p2 - BodyPrefixLength) +
                              " : invalid preserve body block, wrong balanced</font><br>");
                UmlCom::bye(n_errors() + 1);
                UmlCom::fatal_error("read_bodies 4");
            }

            p2 = p1;

            while ((p2 != body) && (p2[-1] != '\n'))
                p2 -= 1;

            char c = *p2;

            *p2 = 0;

            WrapperStr previous = (op->*get_body)();

            if (!op->isBodyGenerationForced() && (body != previous)) {
                if (!(op->*set_body)(body)) {
                    write_trace_header();
                    UmlCom::trace("&nbsp;&nbsp;&nbsp;&nbsp;<font color=\"red\"><b>cannot update body of <i>"
                                  + op->name() +
                                  ((op->isWritable()) ? "</i>, it is probably deleted</b></font><br>"
                                   : "</i>, it is read-only</b></font><br>"));
                    incr_error();
                }
                else {
                    (op->*set_contextualbodyindent)(FALSE);

                    write_trace_header();
                    UmlCom::trace("&nbsp;&nbsp;&nbsp;&nbsp;update body of <i>"
                                  + op->name() + "</i><br>");
                }
            }
            else if (verbose()) {
                write_trace_header();
                UmlCom::trace("&nbsp;&nbsp;&nbsp;&nbsp;body of <i>"
                              + op->name() + "</i> unchanged<br>");
            }

            *p2 = c;
            p1 += BodyPostfixLength + 8;
        }

        delete [] s;
    }
}