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

📄 interpret.c

📁 nedit 是一款linux下的开发源码的功能强大的编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
        /* pop past local variables */    StackP = FrameP;        /* get stored return information */    nArgs = (--StackP)->val.n;    FrameP = (--StackP)->val.dataval;    PC = (--StackP)->val.inst;        /* pop past function arguments */    StackP -= nArgs;        /* push returned value, if requsted */    if (PC == NULL) {	if (valOnStack) {    	    PUSH(retVal);	} else {	    PUSH(noValue);	}    } else if (*PC == fetchRetVal) {	if (valOnStack) {    	    PUSH(retVal);	    PC++;	} else {	    return execError(	    	"using return value of %s which does not return a value",	    	((Symbol *)*(PC - 2))->name);	}    }        /* NULL return PC indicates end of program */    return PC == NULL ? STAT_DONE : STAT_OK;}/*** Unconditional branch offset by immediate operand**** Before: Prog->  [branchDest], next, ..., (branchdest)next** After:  Prog->  branchDest, next, ..., (branchdest)[next]*/static int branch(void){    DISASM_RT(PC-1, 2);    STACKDUMP(0, 3);    PC += (int)*PC;    return STAT_OK;}/*** Conditional branches if stack value is True/False (non-zero/0) to address** of immediate operand (pops stack)**** Before: Prog->  [branchDest], next, ..., (branchdest)next** After:  either: Prog->  branchDest, [next], ...** After:  or:     Prog->  branchDest, next, ..., (branchdest)[next]*/static int branchTrue(void){    int value;    Inst *addr;        DISASM_RT(PC-1, 2);    STACKDUMP(1, 3);    POP_INT(value)    addr = PC + (int)*PC;    PC++;        if (value)    	PC = addr;    return STAT_OK;}static int branchFalse(void){    int value;    Inst *addr;        DISASM_RT(PC-1, 2);    STACKDUMP(1, 3);    POP_INT(value)    addr = PC + (int)*PC;    PC++;        if (!value)    	PC = addr;    return STAT_OK;}/*** Ignore the address following the instruction and continue.  Why? So** some code that uses conditional branching doesn't have to figure out** whether to store a branch address.**** Before: Prog->  [branchDest], next, ...** After:  Prog->  branchDest, [next], ...*/static int branchNever(void){    DISASM_RT(PC-1, 2);    STACKDUMP(0, 3);    PC++;    return STAT_OK;}/*** recursively copy(duplicate) the sparse array nodes of an array** this does not duplicate the key/node data since they are never** modified, only replaced*/int ArrayCopy(DataValue *dstArray, DataValue *srcArray){    SparseArrayEntry *srcIter;        dstArray->tag = ARRAY_TAG;    dstArray->val.arrayPtr = ArrayNew();        srcIter = arrayIterateFirst(srcArray);    while (srcIter) {        if (srcIter->value.tag == ARRAY_TAG) {            int errNum;            DataValue tmpArray;                        errNum = ArrayCopy(&tmpArray, &srcIter->value);            if (errNum != STAT_OK) {                return(errNum);            }            if (!ArrayInsert(dstArray, srcIter->key, &tmpArray)) {                return(execError("array copy failed", NULL));            }        }        else {            if (!ArrayInsert(dstArray, srcIter->key, &srcIter->value)) {                return(execError("array copy failed", NULL));            }        }        srcIter = arrayIterateNext(srcIter);    }    return(STAT_OK);}/*** creates an allocated string of a single key for all the sub-scripts** using ARRAY_DIM_SEP as a separator** this function uses the PEEK macros in order to remove most limits on** the number of arguments to an array** I really need to optimize the size approximation rather than assuming** a worst case size for every integer argument*/static int makeArrayKeyFromArgs(int nArgs, char **keyString, int leaveParams){    DataValue tmpVal;    int maxIntDigits = (sizeof(tmpVal.val.n) * 3) + 1;    int sepLen = strlen(ARRAY_DIM_SEP);    int keyLength = 0;    int i;    keyLength = sepLen * (nArgs - 1);    for (i = nArgs - 1; i >= 0; --i) {        PEEK(tmpVal, i)        if (tmpVal.tag == INT_TAG) {            keyLength += maxIntDigits;        }        else if (tmpVal.tag == STRING_TAG) {            keyLength += strlen(tmpVal.val.str);        }        else {            return(execError("can only index array with string or int.", NULL));        }    }    *keyString = AllocString(keyLength + 1);    (*keyString)[0] = 0;    for (i = nArgs - 1; i >= 0; --i) {        if (i != nArgs - 1) {            strcat(*keyString, ARRAY_DIM_SEP);        }        PEEK(tmpVal, i)        if (tmpVal.tag == INT_TAG) {            sprintf(&((*keyString)[strlen(*keyString)]), "%d", tmpVal.val.n);        }        else if (tmpVal.tag == STRING_TAG) {            strcat(*keyString, tmpVal.val.str);        }        else {            return(execError("can only index array with string or int.", NULL));        }    }    if (!leaveParams) {        for (i = nArgs - 1; i >= 0; --i) {            POP(tmpVal)        }    }    return(STAT_OK);}/*** allocate an empty array node, this is used as the root node and never** contains any data, only refernces to other nodes*/static rbTreeNode *arrayEmptyAllocator(void){    SparseArrayEntry *newNode = allocateSparseArrayEntry();    if (newNode) {        newNode->key = NULL;        newNode->value.tag = NO_TAG;    }    return((rbTreeNode *)newNode);}/*** create and copy array node and copy contents, we merely copy pointers** since they are never modified, only replaced*/static rbTreeNode *arrayAllocateNode(rbTreeNode *src){    SparseArrayEntry *newNode = allocateSparseArrayEntry();    if (newNode) {        newNode->key = ((SparseArrayEntry *)src)->key;        newNode->value = ((SparseArrayEntry *)src)->value;    }    return((rbTreeNode *)newNode);}/*** copy array node data, we merely copy pointers since they are never** modified, only replaced*/static int arrayEntryCopyToNode(rbTreeNode *dst, rbTreeNode *src){    ((SparseArrayEntry *)dst)->key = ((SparseArrayEntry *)src)->key;    ((SparseArrayEntry *)dst)->value = ((SparseArrayEntry *)src)->value;    return(1);}/*** compare two array nodes returning an integer value similar to strcmp()*/static int arrayEntryCompare(rbTreeNode *left, rbTreeNode *right){    return(strcmp(((SparseArrayEntry *)left)->key, ((SparseArrayEntry *)right)->key));}/*** dispose an array node, garbage collection handles this, so we mark it** to allow iterators in macro language to determine they have been unlinked*/static void arrayDisposeNode(rbTreeNode *src){    /* Let garbage collection handle this but mark it so iterators can tell */    src->left = NULL;    src->right = NULL;    src->parent = NULL;    src->color = -1;}struct SparseArrayEntry *ArrayNew(void){	return((struct SparseArrayEntry *)rbTreeNew(arrayEmptyAllocator));}/*** insert a DataValue into an array, allocate the array if needed** keyStr must be a string that was allocated with AllocString()*/int ArrayInsert(DataValue *theArray, char *keyStr, DataValue *theValue){    SparseArrayEntry tmpEntry;    rbTreeNode *insertedNode;        tmpEntry.key = keyStr;    tmpEntry.value = *theValue;        if (theArray->val.arrayPtr == NULL) {        theArray->val.arrayPtr = ArrayNew();    }    if (theArray->val.arrayPtr != NULL) {        insertedNode = rbTreeInsert((rbTreeNode *)(theArray->val.arrayPtr),            (rbTreeNode *)&tmpEntry,            arrayEntryCompare, arrayAllocateNode, arrayEntryCopyToNode);        if (insertedNode) {            return(1);        }        else {            return(0);        }    }    return(0);}/*** remove a node from an array whose key matches keyStr*/void ArrayDelete(DataValue *theArray, char *keyStr){    SparseArrayEntry searchEntry;    if (theArray->val.arrayPtr) {        searchEntry.key = keyStr;        rbTreeDelete((rbTreeNode *)theArray->val.arrayPtr, (rbTreeNode *)&searchEntry,                    arrayEntryCompare, arrayDisposeNode);    }}/*** remove all nodes from an array*/void ArrayDeleteAll(DataValue *theArray){        if (theArray->val.arrayPtr) {        rbTreeNode *iter = rbTreeBegin((rbTreeNode *)theArray->val.arrayPtr);        while (iter) {            rbTreeNode *nextIter = rbTreeNext(iter);            rbTreeDeleteNode((rbTreeNode *)theArray->val.arrayPtr,                        iter, arrayDisposeNode);            iter = nextIter;        }    }}/*** returns the number of elements (nodes containing values) of an array*/int ArraySize(DataValue *theArray){    if (theArray->val.arrayPtr) {        return(rbTreeSize((rbTreeNode *)theArray->val.arrayPtr));    }    else {        return(0);    }}/*** retrieves an array node whose key matches** returns 1 for success 0 for not found*/int ArrayGet(DataValue *theArray, char *keyStr, DataValue *theValue){    SparseArrayEntry searchEntry;    rbTreeNode *foundNode;    if (theArray->val.arrayPtr) {        searchEntry.key = keyStr;        foundNode = rbTreeFind((rbTreeNode *)theArray->val.arrayPtr,                (rbTreeNode *)&searchEntry, arrayEntryCompare);        if (foundNode) {            *theValue = ((SparseArrayEntry *)foundNode)->value;            return(1);        }    }    return(0);}/*** get pointer to start iterating an array*/SparseArrayEntry *arrayIterateFirst(DataValue *theArray){    SparseArrayEntry *startPos;    if (theArray->val.arrayPtr) {        startPos = (SparseArrayEntry *)rbTreeBegin((rbTreeNode *)theArray->val.arrayPtr);    }    else {        startPos = NULL;    }    return(startPos);}/*** move iterator to next entry in array*/SparseArrayEntry *arrayIterateNext(SparseArrayEntry *iterator){    SparseArrayEntry *nextPos;    if (iterator) {        nextPos = (SparseArrayEntry *)rbTreeNext((rbTreeNode *)iterator);    }    else {        nextPos = NULL;    }    return(nextPos);}/*** evaluate an array element and push the result onto the stack**** Before: Prog->  [nDim], next, ...**         Stack-> indnDim, ... ind1, ArraySym, next, ...** After:  Prog->  nDim, [next], ...**         Stack-> indexedArrayVal, next, ...*/static int arrayRef(void){    int errNum;    DataValue srcArray, valueItem;    char *keyString = NULL;    int nDim;        nDim = (int)*PC;    PC++;    DISASM_RT(PC-2, 2);    STACKDUMP(nDim, 3);    if (nDim > 0) {        errNum = makeArrayKeyFromArgs(nDim, &keyString, 0);        if (errNum != STAT_OK) {            return(errNum);        }        POP(srcArray)        if (srcArray.tag == ARRAY_TAG) {            if (!ArrayGet(&srcArray, keyString, &valueItem)) {                return(execError("referenced array value not in array: %s", keyString));            }            PUSH(valueItem)            return(STAT_OK);        }        else {            return(execError("operator [] on non-array", NULL));        }    }    else {        POP(srcArray)        if (srcArray.tag == ARRAY_TAG) {            PUSH_INT(ArraySize(&srcArray))            return(STAT_OK);        }        else {            return(execError("operator [] on non-array", NULL));        }    }}/*** assign to an array element of a referenced array on the stack**** Before: Prog->  [nDim], next, ...**         Stack-> rhs, indnDim, ... ind1, ArraySym, next, ...** After:  Prog->  nDim, [next], ...**         Stack-> next, ...*/static int arrayAssign(void){    char *keyString = NULL;    DataValue srcValue, dstArray;    int errNum;    int nDim;        nDim = (int)*PC;    PC++;    DISASM_RT(PC-2, 1);    STACKDUMP(nDim, 3);    if (nDim > 0) {   

⌨️ 快捷键说明

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