📄 addop.c
字号:
/* * Copyright (c) 1994 David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. * * Add opcodes to a function being compiled. */#include "calc.h"#include "opcodes.h"#include "string.h"#include "func.h"#include "token.h"#include "label.h"#include "symbol.h"#define FUNCALLOCSIZE 20 /* reallocate size for functions */#define OPCODEALLOCSIZE 100 /* reallocate size for opcodes in functions */static long maxopcodes; /* number of opcodes available */static long newindex; /* index of new function */static long oldop; /* previous opcode */static long debugline; /* line number of latest debug opcode */static long funccount; /* number of functions */static long funcavail; /* available number of functions */static FUNC *functemplate; /* function definition template */static FUNC **functions; /* table of functions */static STRINGHEAD funcnames; /* function names */static int codeflag;/* * Initialize the table of user defined functions. */voidinitfunctions(){ initstr(&funcnames); maxopcodes = OPCODEALLOCSIZE; functemplate = (FUNC *) malloc(funcsize(maxopcodes)); if (functemplate == NULL) math_error("Cannot allocate function template"); functions = (FUNC **) malloc(sizeof(FUNC *) * FUNCALLOCSIZE); if (functions == NULL) math_error("Cannot allocate function table"); funccount = 0; funcavail = FUNCALLOCSIZE;}/* * Show the list of user defined functions. */voidshowfunctions(){ FUNC **fpp; /* pointer into function table */ FUNC *fp; /* current function */ if (funccount == 0) { printf("No user functions defined.\n"); return; } printf("Name Arguments\n"); printf("---- ---------\n"); for (fpp = &functions[funccount - 1]; fpp >= functions; fpp--) { fp = *fpp; if (fp == NULL) continue; printf("%-12s %-2d\n", fp->f_name, fp->f_paramcount); } printf("\n");}/* * Initialize a function for definition. * Newflag is TRUE if we should allocate a new function structure, * instead of the usual overwriting of the template function structure. * The new structure is returned in the global curfunc variable. */voidbeginfunc(name, newflag) char *name; /* name of function */ BOOL newflag; /* TRUE if need new structure */{ register FUNC *fp; /* current function */ newindex = adduserfunc(name); maxopcodes = OPCODEALLOCSIZE; fp = functemplate; if (newflag) { fp = (FUNC *) malloc(funcsize(maxopcodes)); if (fp == NULL) math_error("Cannot allocate temporary function"); } fp->f_next = NULL; fp->f_localcount = 0; fp->f_opcodecount = 0; fp->f_savedvalue.v_type = V_NULL; fp->f_name = namestr(&funcnames, newindex); curfunc = fp; initlocals(); initlabels(); oldop = OP_NOP; debugline = 0; errorcount = 0;}/* * Commit the just defined function for use. * This replaces any existing definition for the function. * This should only be called for normal user-defined functions. */voidendfunc(){ register FUNC *fp; /* function just finished */ long size; /* size of just created function */ checklabels(); if (errorcount) { printf("\"%s\": %ld error%s\n", curfunc->f_name, errorcount, ((errorcount == 1) ? "" : "s")); return; } size = funcsize(curfunc->f_opcodecount); fp = (FUNC *) malloc(size); if (fp == NULL) math_error("Cannot commit function"); memcpy((char *) fp, (char *) curfunc, size); if (curfunc != functemplate) free(curfunc); if (codeflag) { for (size = 0; size < fp->f_opcodecount; ) { printf("%ld: ", (long)size); size += dumpop(&fp->f_opcodes[size]); } } if (functions[newindex]) free(functions[newindex]); functions[newindex] = fp; objuncache(); if (inputisterminal()) printf("\"%s\" defined\n", fp->f_name);}/* * Find the user function with the specified name, and return its index. * If the function does not exist, its name is added to the function table * and an error will be generated when it is called if it is still undefined. */longadduserfunc(name) char *name; /* name of function */{ long index; /* index of function */ index = findstr(&funcnames, name); if (index >= 0) return index; if (funccount >= funcavail) { functions = (FUNC **) realloc(functions, sizeof(FUNC *) * (funcavail + FUNCALLOCSIZE)); if (functions == NULL) math_error("Failed to reallocate function table"); funcavail += FUNCALLOCSIZE; } if (addstr(&funcnames, name) == NULL) math_error("Cannot save function name"); index = funccount++; functions[index] = NULL; return index;}/* * Clear any optimization that may be done for the next opcode. * This is used when defining a label. */voidclearopt(){ oldop = OP_NOP; debugline = 0;}/* * Find a function structure given its index. */FUNC *findfunc(index) long index;{ if ((unsigned long) index >= funccount) math_error("Undefined function"); return functions[index];}/* * Return the name of a function given its index. */char *namefunc(index) 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(){ 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(op) long op;{ register FUNC *fp; /* current function */ NUMBER *q; fp = curfunc; if ((fp->f_opcodecount + 5) >= maxopcodes) { maxopcodes += OPCODEALLOCSIZE; fp = (FUNC *) malloc(funcsize(maxopcodes)); if (fp == NULL) math_error("cannot malloc function"); 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. */ if (op == 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: fp->f_opcodes[fp->f_opcodecount - 1] = OP_DUPVALUE; oldop = OP_DUPVALUE; return; case OP_FIADDR: fp->f_opcodes[fp->f_opcodecount - 1] = OP_FIVALUE; oldop = OP_FIVALUE; return; case OP_GLOBALADDR: fp->f_opcodes[fp->f_opcodecount - 2] = OP_GLOBALVALUE; oldop = OP_GLOBALVALUE; return; case OP_LOCALADDR: fp->f_opcodes[fp->f_opcodecount - 2] = OP_LOCALVALUE; oldop = OP_LOCALVALUE; return; case OP_PARAMADDR: fp->f_opcodes[fp->f_opcodecount - 2] = OP_PARAMVALUE; oldop = OP_PARAMVALUE; return; case OP_ELEMADDR: fp->f_opcodes[fp->f_opcodecount - 2] = OP_ELEMVALUE; oldop = OP_ELEMVALUE; return; } } if ((op == OP_NEGATE) && (oldop == OP_NUMBER)) { q = constvalue(fp->f_opcodes[fp->f_opcodecount - 1]); fp->f_opcodes[fp->f_opcodecount - 1] = addqconstant(qneg(q)); oldop = OP_NUMBER; return; } if ((op == OP_POWER) && (oldop == OP_NUMBER)) { if (qcmpi(constvalue(fp->f_opcodes[fp->f_opcodecount - 1]), 2L) == 0) { fp->f_opcodecount--; fp->f_opcodes[fp->f_opcodecount - 1] = OP_SQUARE; oldop = OP_SQUARE; return; } if (qcmpi(constvalue(fp->f_opcodes[fp->f_opcodecount - 1]), 4L) == 0) { fp->f_opcodes[fp->f_opcodecount - 2] = OP_SQUARE; fp->f_opcodes[fp->f_opcodecount - 1] = OP_SQUARE; oldop = OP_SQUARE; return; } } if ((op == OP_POP) && (oldop == OP_ASSIGN)) { /* optimize */ fp->f_opcodes[fp->f_opcodecount - 1] = OP_ASSIGNPOP; oldop = OP_ASSIGNPOP; return; } /* * No optimization possible, so store the opcode. */ fp->f_opcodes[fp->f_opcodecount] = op; fp->f_opcodecount++; oldop = op;}/* * Add an opcode and and one integer argument to the current function * being compiled. */voidaddopone(op, arg) long op; long arg;{ NUMBER *q; switch (op) { case OP_NUMBER: q = constvalue(arg); if (q == NULL) break; if (qiszero(q)) { addop(OP_ZERO); return; } if (qisone(q)) { addop(OP_ONE); return; } break; case OP_DEBUG: if ((traceflags & TRACE_NODEBUG) || (arg == debugline)) return; debugline = arg; if (oldop == OP_DEBUG) { curfunc->f_opcodes[curfunc->f_opcodecount - 1] = arg; return; } break; } 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(op, arg1, arg2) 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(op, ptr) 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(op, index, count) int count; long op; long index;{ 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. */voidaddoplabel(op, label) long op; LABEL *label; /* label to be added */{ addop(op); uselabel(label);}/* END CODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -