📄 addop.c
字号:
* is none or if it has been undefined */longgetuserfunc(char *name){ long index; index = findstr(&funcnames, name); if (index >= 0 && functions[index] != NULL) return index; return -1L;}/* * Clear any optimization that may be done for the next opcode. * This is used when defining a label. */voidclearopt(void){ oldop = OP_NOP; oldoldop = OP_NOP; debugline = 0;}/* * Find a function structure given its index. */FUNC *findfunc(long index){ if (index >= funccount) { math_error("Undefined function"); /*NOTREACHED*/ } return functions[index];}/* * Return the name of a function given its index. */char *namefunc(long index){ return namestr(&funcnames, index);}/* * Let a matrix indexing operation know that it will be treated as a write * reference instead of just as a read reference. */voidwriteindexop(void){ if (oldop == OP_INDEXADDR) curfunc->f_opcodes[curfunc->f_opcodecount - 1] = TRUE;}/* * Add an opcode to the current function being compiled. * Note: This can change the curfunc global variable when the * function needs expanding. */voidaddop(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; warning("Constant before comma operator"); 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;}/* * Add an opcode and and one integer argument to the current function * being compiled. */voidaddopone(long op, long arg){ if (op == OP_DEBUG) { if ((conf->traceflags & TRACE_NODEBUG) || (arg == debugline)) return; debugline = arg; if (oldop == OP_DEBUG) { curfunc->f_opcodes[curfunc->f_opcodecount - 1] = arg; return; } } addop(op); curfunc->f_opcodes[curfunc->f_opcodecount] = arg; curfunc->f_opcodecount++;}/* * Add an opcode and and two integer arguments to the current function * being compiled. */voidaddoptwo(long op, long arg1, long arg2){ addop(op); curfunc->f_opcodes[curfunc->f_opcodecount++] = arg1; curfunc->f_opcodes[curfunc->f_opcodecount++] = arg2;}/* * Add an opcode and a character pointer to the function being compiled. */voidaddopptr(long op, char *ptr){ char **ptraddr; addop(op); ptraddr = (char **) &curfunc->f_opcodes[curfunc->f_opcodecount]; *ptraddr = ptr; curfunc->f_opcodecount += PTR_SIZE;}/* * Add an opcode and an index and an argument count for a function call. */voidaddopfunction(long op, long index, int count){ long newop; if ((op == OP_CALL) && ((newop = builtinopcode(index)) != OP_NOP)) { if ((newop == OP_SETCONFIG) && (count == 1)) newop = OP_GETCONFIG; if ((newop == OP_SETEPSILON) && (count == 0)) newop = OP_GETEPSILON; if ((newop == OP_ABS) && (count == 1)) addop(OP_GETEPSILON); addop(newop); return; } addop(op); curfunc->f_opcodes[curfunc->f_opcodecount++] = index; curfunc->f_opcodes[curfunc->f_opcodecount++] = count;}/* * Add a jump-type opcode and a label to the function being compiled. * * given: * label label to be added */voidaddoplabel(long op, LABEL *label){ addop(op); uselabel(label);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -