⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interpret.c

📁 nedit 是一款linux下的开发源码的功能强大的编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
static int decrement(void){    UNARY_NUMERIC_OPERATION(--)}static int gt(void){    BINARY_NUMERIC_OPERATION(>)}static int lt(void){    BINARY_NUMERIC_OPERATION(<)}static int ge(void){    BINARY_NUMERIC_OPERATION(>=)}static int le(void){    BINARY_NUMERIC_OPERATION(<=)}/*** verify that compares are between integers and/or strings only** Before: Stack-> value1, value2, next, ...** After:  Stack-> resValue, next, ...** where resValue is 1 for true, 0 for false*/static int eq(void){    DataValue v1, v2;    DISASM_RT(PC-1, 1);    STACKDUMP(2, 3);    POP(v1)    POP(v2)    if (v1.tag == INT_TAG && v2.tag == INT_TAG) {        v1.val.n = v1.val.n == v2.val.n;    }    else if (v1.tag == STRING_TAG && v2.tag == STRING_TAG) {        v1.val.n = !strcmp(v1.val.str, v2.val.str);    }    else if (v1.tag == STRING_TAG && v2.tag == INT_TAG) {        int number;        if (!StringToNum(v1.val.str, &number)) {            v1.val.n = 0;        }        else {            v1.val.n = number == v2.val.n;        }    }    else if (v2.tag == STRING_TAG && v1.tag == INT_TAG) {        int number;        if (!StringToNum(v2.val.str, &number)) {            v1.val.n = 0;        }        else {            v1.val.n = number == v1.val.n;        }    }    else {        return(execError("incompatible types to compare", NULL));    }    v1.tag = INT_TAG;    PUSH(v1)    return(STAT_OK);}/* negated eq() call */static int ne(void){    eq();    return not();}/*** if left and right arguments are arrays, then the result is a new array** in which only the keys which exist in both the right or left are copied** the values from the right array are used in the result array** Before: Stack-> value2, value1, next, ...** After:  Stack-> resValue, next, ...*/static int bitAnd(void){     DataValue leftVal, rightVal, resultArray;    int n1, n2;        DISASM_RT(PC-1, 1);    STACKDUMP(2, 3);    PEEK(rightVal, 0)    if (rightVal.tag == ARRAY_TAG) {        PEEK(leftVal, 1)        if (leftVal.tag == ARRAY_TAG) {            SparseArrayEntry *leftIter, *rightIter;            resultArray.tag = ARRAY_TAG;            resultArray.val.arrayPtr = ArrayNew();                        POP(rightVal)            POP(leftVal)            leftIter = arrayIterateFirst(&leftVal);            rightIter = arrayIterateFirst(&rightVal);            while (leftIter && rightIter) {                int insertResult = 1;                int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter);                if (compareResult < 0) {                    leftIter = arrayIterateNext(leftIter);                }                else if (compareResult > 0) {                    rightIter = arrayIterateNext(rightIter);                }                else {                    insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);                    leftIter = arrayIterateNext(leftIter);                    rightIter = arrayIterateNext(rightIter);                }                if (!insertResult) {                    return(execError("array insertion failure", NULL));                }            }            PUSH(resultArray)        }        else {            return(execError("can't mix math with arrays and non-arrays", NULL));        }    }    else {        POP_INT(n2)        POP_INT(n1)        PUSH_INT(n1 & n2)    }    return(STAT_OK);}/*** if left and right arguments are arrays, then the result is a new array** in which only the keys which exist in either the right or left but not both** are copied** Before: Stack-> value2, value1, next, ...** After:  Stack-> resValue, next, ...*/static int bitOr(void){     DataValue leftVal, rightVal, resultArray;    int n1, n2;        DISASM_RT(PC-1, 1);    STACKDUMP(2, 3);    PEEK(rightVal, 0)    if (rightVal.tag == ARRAY_TAG) {        PEEK(leftVal, 1)        if (leftVal.tag == ARRAY_TAG) {            SparseArrayEntry *leftIter, *rightIter;            resultArray.tag = ARRAY_TAG;            resultArray.val.arrayPtr = ArrayNew();                        POP(rightVal)            POP(leftVal)            leftIter = arrayIterateFirst(&leftVal);            rightIter = arrayIterateFirst(&rightVal);            while (leftIter || rightIter) {                int insertResult = 1;                                if (leftIter && rightIter) {                    int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter);                    if (compareResult < 0) {                        insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value);                        leftIter = arrayIterateNext(leftIter);                    }                    else if (compareResult > 0) {                        insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);                        rightIter = arrayIterateNext(rightIter);                    }                    else {                        leftIter = arrayIterateNext(leftIter);                        rightIter = arrayIterateNext(rightIter);                    }                }                else if (leftIter) {                    insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value);                    leftIter = arrayIterateNext(leftIter);                }                else {                    insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);                    rightIter = arrayIterateNext(rightIter);                }                if (!insertResult) {                    return(execError("array insertion failure", NULL));                }            }            PUSH(resultArray)        }        else {            return(execError("can't mix math with arrays and non-arrays", NULL));        }    }    else {        POP_INT(n2)        POP_INT(n1)        PUSH_INT(n1 | n2)    }    return(STAT_OK);}static int and(void){     BINARY_NUMERIC_OPERATION(&&)}static int or(void){    BINARY_NUMERIC_OPERATION(||)}    static int not(void){    UNARY_NUMERIC_OPERATION(!)}/*** raise one number to the power of another** Before: Stack-> raisedBy, number, next, ...** After:  Stack-> result, next, ...*/static int power(void){    int n1, n2, n3;    DISASM_RT(PC-1, 1);    STACKDUMP(2, 3);    POP_INT(n2)    POP_INT(n1)    /*  We need to round to deal with pow() giving results slightly above        or below the real result since it deals with floating point numbers.        Note: We're not really wanting rounded results, we merely        want to deal with this simple issue. So, 2^-2 = .5, but we        don't want to round this to 1. This is mainly intended to deal with        4^2 = 15.999996 and 16.000001.    */    if (n2 < 0 && n1 != 1 && n1 != -1) {        if (n1 != 0) {            /* since we're integer only, nearly all negative exponents result in 0 */            n3 = 0;        }        else {            /* allow error to occur */            n3 = (int)pow((double)n1, (double)n2);        }    }    else {        if ((n1 < 0) && (n2 & 1)) {            /* round to nearest integer for negative values*/            n3 = (int)(pow((double)n1, (double)n2) - (double)0.5);        }        else {            /* round to nearest integer for positive values*/            n3 = (int)(pow((double)n1, (double)n2) + (double)0.5);        }    }    PUSH_INT(n3)    return errCheck("exponentiation");}/*** concatenate two top items on the stack** Before: Stack-> str2, str1, next, ...** After:  Stack-> result, next, ...*/static int concat(void){    char *s1, *s2, *out;    int len1, len2;    DISASM_RT(PC-1, 1);    STACKDUMP(2, 3);    POP_STRING(s2)    POP_STRING(s1)    len1 = strlen(s1);    len2 = strlen(s2);    out = AllocString(len1 + len2 + 1);    strncpy(out, s1, len1);    strcpy(&out[len1], s2);    PUSH_STRING(out)    return STAT_OK;}/*** Call a subroutine or function (user defined or built-in).  Args are the** subroutine's symbol, and the number of arguments which have been pushed** on the stack.**** For a macro subroutine, the return address, frame pointer, number of** arguments and space for local variables are added to the stack, and the** PC is set to point to the new function. For a built-in routine, the** arguments are popped off the stack, and the routine is just called.**** Before: Prog->  [subrSym], nArgs, next, ...**         Stack-> argN-arg1, next, ...** After:  Prog->  next, ...            -- (built-in called subr)**         Stack-> retVal?, next, ...**    or:  Prog->  (in called)next, ... -- (macro code called subr)**         Stack-> symN-sym1(FP), nArgs, oldFP, retPC, argN-arg1, next, ...*/static int callSubroutine(void){    Symbol *sym, *s;    int i, nArgs;    static DataValue noValue = {NO_TAG, {0}};    Program *prog;    char *errMsg;        sym = (Symbol *)*PC++;    nArgs = (int)*PC++;        DISASM_RT(PC-3, 3);    STACKDUMP(nArgs, 3);    if (nArgs > MAX_ARGS)    	return execError("too many arguments to subroutine %s (max 9)",    	    	sym->name);        /*    ** If the subroutine is built-in, call the built-in routine    */    if (sym->type == C_FUNCTION_SYM) {    	DataValue result;        /* "pop" stack back to the first argument in the call stack */    	StackP -= nArgs;    	/* Call the function and check for preemption */    	PreemptRequest = False;	if (!sym->value.val.subr(FocusWindow, StackP,	    	nArgs, &result, &errMsg))	    return execError(errMsg, sym->name);    	if (*PC == fetchRetVal) {    	    if (result.tag == NO_TAG)    	    	return execError("%s does not return a value", sym->name);    	    PUSH(result);	    PC++;    	}    	return PreemptRequest ? STAT_PREEMPT : STAT_OK;    }        /*    ** Call a macro subroutine:    **    ** Push all of the required information to resume, and make space on the    ** stack for local variables (and initialize them), on top of the argument    ** values which are already there.    */    if (sym->type == MACRO_FUNCTION_SYM) {    	StackP->tag = NO_TAG;    	StackP->val.inst = PC;    	StackP++;    	StackP->tag = NO_TAG;    	StackP->val.dataval = FrameP;    	StackP++;    	StackP->tag = NO_TAG;    	StackP->val.n = nArgs;    	StackP++;    	FrameP = StackP;    	prog = (Program *)sym->value.val.str;    	PC = prog->code;	for (s = prog->localSymList; s != NULL; s = s->next) {	    *(FrameP + s->value.val.n) = noValue;	    StackP++;	}   	return STAT_OK;    }        /*    ** Call an action routine    */    if (sym->type == ACTION_ROUTINE_SYM) {    	String argList[MAX_ARGS];    	Cardinal numArgs = nArgs;    	XKeyEvent key_event;	Display *disp;	Window win;    	/* Create a fake event with a timestamp suitable for actions which need	   timestamps, a marker to indicate that the call was from a macro	   (to stop shell commands from putting up their own separate banner) */        disp=XtDisplay(InitiatingWindow->shell);	win=XtWindow(InitiatingWindow->shell);	key_event.type = KeyPress;	key_event.send_event = MACRO_EVENT_MARKER;	key_event.time=XtLastTimestampProcessed(XtDisplay(InitiatingWindow->shell));		/* The following entries are just filled in to avoid problems	   in strange cases, like calling "self_insert()" directly from the	   macro menu. In fact the display was sufficient to cure this crash. */        key_event.display=disp;        key_event.window=key_event.root=key_event.subwindow=win;    	/* pop arguments off the stack and put them in the argument list */	for (i=nArgs-1; i>=0; i--) {    	    POP_STRING(argList[i])	}    	/* Call the action routine and check for preemption */    	PreemptRequest = False;    	sym->value.val.xtproc(FocusWindow->lastFocus,    	    	(XEvent *)&key_event, argList, &numArgs);    	if (*PC == fetchRetVal)    	    return execError("%s does not return a value", sym->name);    	return PreemptRequest ? STAT_PREEMPT : STAT_OK;    }    /* Calling a non subroutine symbol */    return execError("%s is not a function or subroutine", sym->name);}/*** This should never be executed, returnVal checks for the presence of this** instruction at the PC to decide whether to push the function's return** value, then skips over it without executing.*/static int fetchRetVal(void){    return execError("internal error: frv", NULL);}/* see comments for returnValOrNone() */static int returnNoVal(void){    return returnValOrNone(False);}static int returnVal(void){    return returnValOrNone(True);}/*** Return from a subroutine call** Before: Prog->  [next], ...**         Stack-> retVal?, ...(FP), nArgs, oldFP, retPC, argN-arg1, next, ...** After:  Prog->  next, ..., (in caller)[FETCH_RET_VAL?], ...**         Stack-> retVal?, next, ...*/static int returnValOrNone(int valOnStack){    DataValue retVal;    static DataValue noValue = {NO_TAG, {0}};    int nArgs;        DISASM_RT(PC-1, 1);    STACKDUMP(StackP - FrameP + FrameP[-1].val.n + 3, 3);    /* return value is on the stack */    if (valOnStack) {    	POP(retVal);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -