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

📄 interpret.c

📁 nedit 是一款linux下的开发源码的功能强大的编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
    context->stackP->val.subr = NULL;    context->stackP->tag = NO_TAG;    context->stackP++;    *(context->stackP++) = noValue;    context->stackP->tag = NO_TAG;    context->stackP->val.n = nArgs;    context->stackP++;    context->frameP = context->stackP;        /* Initialize and make room on the stack for local variables */    for (s = prog->localSymList; s != NULL; s = s->next) {    	*(context->frameP + s->value.val.n) = noValue;    	context->stackP++;    }        /* Begin execution, return on error or preemption */    return ContinueMacro(context, result, msg);}/*** Continue the execution of a suspended macro whose state is described in** "continuation"*/int ContinueMacro(RestartData *continuation, DataValue *result, char **msg){    register int status, instCount = 0;    register Inst *inst;    RestartData oldContext;        /* To allow macros to be invoked arbitrarily (such as those automatically       triggered within smart-indent) within executing macros, this call is       reentrant. */    saveContext(&oldContext);        /*    ** Execution Loop:  Call the succesive routine addresses in the program    ** until one returns something other than STAT_OK, then take action    */    restoreContext(continuation);    ErrMsg = NULL;    for (;;) {    	    	/* Execute an instruction */    	inst = PC++;	status = (*inst)();    	    	/* If error return was not STAT_OK, return to caller */    	if (status != STAT_OK) {    	    if (status == STAT_PREEMPT) {    		saveContext(continuation);    		restoreContext(&oldContext);    		return MACRO_PREEMPT;    	    } else if (status == STAT_ERROR) {		*msg = ErrMsg;		FreeRestartData(continuation);		restoreContext(&oldContext);		return MACRO_ERROR;	    } else if (status == STAT_DONE) {		*msg = "";		*result = *--StackP;		FreeRestartData(continuation);		restoreContext(&oldContext);		return MACRO_DONE;	    }    	}		/* Count instructions executed.  If the instruction limit is hit,	   preempt, store re-start information in continuation and give	   X, other macros, and other shell scripts a chance to execute */    	instCount++;	if (instCount >= INSTRUCTION_LIMIT) {    	    saveContext(continuation);    	    restoreContext(&oldContext);    	    return MACRO_TIME_LIMIT;	}    }}/*** If a macro is already executing, and requests that another macro be run,** this can be called instead of ExecuteMacro to run it in the same context** as if it were a subroutine.  This saves the caller from maintaining** separate contexts, and serializes processing of the two macros without** additional work.*/void RunMacroAsSubrCall(Program *prog){    Symbol *s;    static DataValue noValue = {NO_TAG, {0}};    /* See subroutine "callSubroutine" for a description of the stack frame       for a subroutine call */    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 = 0;    StackP++;    FrameP = StackP;    PC = prog->code;    for (s = prog->localSymList; s != NULL; s = s->next) {	*(FrameP + s->value.val.n) = noValue;	StackP++;    }}void FreeRestartData(RestartData *context){    XtFree((char *)context->stack);    XtFree((char *)context);}/*** Cause a macro in progress to be preempted (called by commands which take** a long time, or want to return to the event loop.  Call ResumeMacroExecution** to resume.*/void PreemptMacro(void){    PreemptRequest = True;}/*** Reset the return value for a subroutine which caused preemption (this is** how to return a value from a routine which preempts instead of returning** a value directly).*/void ModifyReturnedValue(RestartData *context, DataValue dv){    if (*(context->pc-1) == fetchRetVal)	*(context->stackP-1) = dv;}/*** Called within a routine invoked from a macro, returns the window in** which the macro is executing (where the banner is, not where it is focused)*/WindowInfo *MacroRunWindow(void){    return InitiatingWindow;}/*** Called within a routine invoked from a macro, returns the window to which** the currently executing macro is focused (the window which macro commands** modify, not the window from which the macro is being run)*/WindowInfo *MacroFocusWindow(void){    return FocusWindow;}/*** Set the window to which macro subroutines and actions which operate on an** implied window are directed.*/void SetMacroFocusWindow(WindowInfo *window){    FocusWindow = window;}/*** install an array iteration symbol** it is tagged as an integer but holds an array node pointer*/Symbol *InstallIteratorSymbol(){    char symbolName[10 + TYPE_INT_STR_SIZE(int)];    DataValue value;    static int interatorNameIndex = 0;    sprintf(symbolName, "aryiter #%d", interatorNameIndex);    ++interatorNameIndex;    value.tag = INT_TAG;    value.val.arrayPtr = NULL;    return(InstallSymbol(symbolName, LOCAL_SYM, value));}/*** Lookup a constant string by its value. This allows reuse of string** constants and fixing a leak in the interpreter.*/Symbol *LookupStringConstSymbol(const char *value){    Symbol *s;    for (s = GlobalSymList; s != NULL; s = s->next) {        if (s->type == CONST_SYM &&            s->value.tag == STRING_TAG &&            !strcmp(s->value.val.str, value)) {            return(s);        }    }    return(NULL);}/*** install string str in the global symbol table with a string name*/Symbol *InstallStringConstSymbol(const char *str){    static int stringConstIndex = 0;    char stringName[35];    DataValue value;    Symbol *sym = LookupStringConstSymbol(str);    if (sym) {        return sym;    }    sprintf(stringName, "string #%d", stringConstIndex++);    value.tag = STRING_TAG;    value.val.str = AllocStringCpy(str);    return(InstallSymbol(stringName, CONST_SYM, value));}/*** find a symbol in the symbol table*/Symbol *LookupSymbol(const char *name){    Symbol *s;    for (s = LocalSymList; s != NULL; s = s->next)	if (strcmp(s->name, name) == 0)	    return s;    for (s = GlobalSymList; s != NULL; s = s->next)	if (strcmp(s->name, name) == 0)	    return s;    return NULL;}/*** install symbol name in symbol table*/Symbol *InstallSymbol(const char *name, enum symTypes type, DataValue value){    Symbol *s;    s = (Symbol *)malloc(sizeof(Symbol));    s->name = (char *)malloc(strlen(name)+1); /* +1 for '\0' */    strcpy(s->name, name);    s->type = type;    s->value = value;    if (type == LOCAL_SYM) {    	s->next = LocalSymList;    	LocalSymList = s;    } else {    	s->next = GlobalSymList;    	GlobalSymList = s;    }    return s;}/*** Promote a symbol from local to global, removing it from the local symbol** list.*/Symbol *PromoteToGlobal(Symbol *sym){    Symbol *s;    static DataValue noValue = {NO_TAG, {0}};    if (sym->type != LOCAL_SYM)	return sym;    /* Remove sym from the local symbol list */    if (sym == LocalSymList)	LocalSymList = sym->next;    else {	for (s = LocalSymList; s != NULL; s = s->next) {	    if (s->next == sym) {		s->next = sym->next;		break;	    }	}    }        s = LookupSymbol(sym->name);    if (s != NULL)	return s;    return InstallSymbol(sym->name, GLOBAL_SYM, noValue);}/*** Allocate memory for a string, and keep track of it, such that it** can be recovered later using GarbageCollectStrings.  (A linked list** of pointers is maintained by threading through the memory behind** the returned pointers).  Length does not include the terminating null** character, so to allocate space for a string of strlen == n, you must** use AllocString(n+1).*//*#define TRACK_GARBAGE_LEAKS*/#ifdef TRACK_GARBAGE_LEAKSstatic int numAllocatedStrings = 0;static int numAllocatedSparseArrayElements = 0;#endif/* Allocate a new string buffer of length chars */char *AllocString(int length){    char *mem;        mem = XtMalloc(length + sizeof(char *) + 1);    *((char **)mem) = AllocatedStrings;    AllocatedStrings = mem;#ifdef TRACK_GARBAGE_LEAKS    ++numAllocatedStrings;#endif    return mem + sizeof(char *) + 1;}/* Allocate a new string buffer of length chars, and copy in the string s */char *AllocStringNCpy(const char *s, int length){    char *p = AllocString(length + 1);  /* add extra char for forced \0 */    if (!p)        return p;    if (!s)        s = "";    p[length] = '\0';                   /* forced \0 */    return strncpy(p, s, length);}/* Allocate a new copy of string s */char *AllocStringCpy(const char *s){    return AllocStringNCpy(s, s ? strlen(s) : 0);}static SparseArrayEntry *allocateSparseArrayEntry(void){    SparseArrayEntryWrapper *mem;    mem = (SparseArrayEntryWrapper *)XtMalloc(sizeof(SparseArrayEntryWrapper));    mem->next = (struct SparseArrayEntryWrapper *)AllocatedSparseArrayEntries;    AllocatedSparseArrayEntries = mem;#ifdef TRACK_GARBAGE_LEAKS    ++numAllocatedSparseArrayElements;#endif    return(&(mem->data));}static void MarkArrayContentsAsUsed(SparseArrayEntry *arrayPtr){    SparseArrayEntry *globalSEUse;    if (arrayPtr) {        ((SparseArrayEntryWrapper *)arrayPtr)->inUse = 1;        for (globalSEUse = (SparseArrayEntry *)rbTreeBegin((rbTreeNode *)arrayPtr);            globalSEUse != NULL;            globalSEUse = (SparseArrayEntry *)rbTreeNext((rbTreeNode *)globalSEUse)) {            ((SparseArrayEntryWrapper *)globalSEUse)->inUse = 1;            /* test first because it may be read-only static string */            if (!(*(globalSEUse->key - 1))) {                *(globalSEUse->key - 1) = 1;            }            if (globalSEUse->value.tag == STRING_TAG) {                /* test first because it may be read-only static string */                if (!(*(globalSEUse->value.val.str - 1))) {                    *(globalSEUse->value.val.str - 1) = 1;                }            }            else if (globalSEUse->value.tag == ARRAY_TAG) {                MarkArrayContentsAsUsed((SparseArrayEntry *)globalSEUse->value.val.arrayPtr);            }        }    }}/*** Collect strings that are no longer referenced from the global symbol** list.  THIS CAN NOT BE RUN WHILE ANY MACROS ARE EXECUTING.  It must** only be run after all macro activity has ceased.*/void GarbageCollectStrings(void){    SparseArrayEntryWrapper *nextAP, *thisAP;    char *p, *next;    Symbol *s;    /* mark all strings as unreferenced */    for (p = AllocatedStrings; p != NULL; p = *((char **)p)) {    	*(p + sizeof(char *)) = 0;    }        for (thisAP = AllocatedSparseArrayEntries;        thisAP != NULL; thisAP = (SparseArrayEntryWrapper *)thisAP->next) {        thisAP->inUse = 0;    }    /* Sweep the global symbol list, marking which strings are still       referenced */    for (s = GlobalSymList; s != NULL; s = s->next) {    	if (s->value.tag == STRING_TAG) {            /* test first because it may be read-only static string */            if (!(*(s->value.val.str - 1))) {    	        *(s->value.val.str - 1) = 1;            }        }        else if (s->value.tag == ARRAY_TAG) {            MarkArrayContentsAsUsed((SparseArrayEntry *)s->value.val.arrayPtr);        }    }    /* Collect all of the strings which remain unreferenced */    next = AllocatedStrings;    AllocatedStrings = NULL;    while (next != NULL) {    	p = next;    	next = *((char **)p);    	if (*(p + sizeof(char *)) != 0) {    	    *((char **)p) = AllocatedStrings;    	    AllocatedStrings = p;    	}        else {#ifdef TRACK_GARBAGE_LEAKS            --numAllocatedStrings;#endif    	    XtFree(p);    	}    }        nextAP = AllocatedSparseArrayEntries;    AllocatedSparseArrayEntries = NULL;    while (nextAP != NULL) {        thisAP = nextAP;        nextAP = (SparseArrayEntryWrapper *)nextAP->next;        if (thisAP->inUse != 0) {            thisAP->next = (struct SparseArrayEntryWrapper *)AllocatedSparseArrayEntries;            AllocatedSparseArrayEntries = thisAP;        }        else {#ifdef TRACK_GARBAGE_LEAKS            --numAllocatedSparseArrayElements;#endif            XtFree((void *)thisAP);        }    }#ifdef TRACK_GARBAGE_LEAKS    printf("str count = %d\nary count = %d\n", numAllocatedStrings, numAllocatedSparseArrayElements);#endif}/*** Save and restore execution context to data structure "context"*/static void saveContext(RestartData *context){    context->stack = Stack;    context->stackP = StackP;    context->frameP = FrameP;    context->pc = PC;    context->runWindow = InitiatingWindow;    context->focusWindow = FocusWindow;}

⌨️ 快捷键说明

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