/* * 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; }
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(" <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(" update body of <i>" + op->name() + "</i><br>"); } } else if (verbose()) { write_trace_header(); UmlCom::trace(" body of <i>" + op->name() + "</i> unchanged<br>"); } *p2 = c; p1 += BodyPostfixLength + 8; } delete [] s; } }