📄 itcl_util.c
字号:
/* * ------------------------------------------------------------------------ * PACKAGE: [incr Tcl] * DESCRIPTION: Object-Oriented Extensions to Tcl * * [incr Tcl] provides object-oriented extensions to Tcl, much as * C++ provides object-oriented extensions to C. It provides a means * of encapsulating related procedures together with their shared data * in a local namespace that is hidden from the outside world. It * promotes code re-use through inheritance. More than anything else, * it encourages better organization of Tcl applications through the * object-oriented paradigm, leading to code that is easier to * understand and maintain. * * This segment provides common utility functions used throughout * the other [incr Tcl] source files. * * ======================================================================== * AUTHOR: Michael J. McLennan * Bell Labs Innovations for Lucent Technologies * mmclennan@lucent.com * http://www.tcltk.com/itcl * * RCS: $Id: itcl_util.c 144 2003-02-05 10:56:26Z mdejong $ * ======================================================================== * Copyright (c) 1993-1998 Lucent Technologies, Inc. * ------------------------------------------------------------------------ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */#include "itclInt.h"#include "tclCompile.h"/* * POOL OF LIST ELEMENTS FOR LINKED LIST */static Itcl_ListElem *listPool = NULL;static int listPoolLen = 0;#define ITCL_VALID_LIST 0x01face10 /* magic bit pattern for validation */#define ITCL_LIST_POOL_SIZE 200 /* max number of elements in listPool *//* * These records are used to keep track of reference-counted data * for Itcl_PreserveData and Itcl_ReleaseData. */typedef struct ItclPreservedData { ClientData data; /* reference to data */ int usage; /* number of active uses */ Tcl_FreeProc *fproc; /* procedure used to free data */} ItclPreservedData;static Tcl_HashTable *ItclPreservedList = NULL;/* * This structure is used to take a snapshot of the interpreter * state in Itcl_SaveInterpState. You can snapshot the state, * execute a command, and then back up to the result or the * error that was previously in progress. */typedef struct InterpState { int validate; /* validation stamp */ int status; /* return code status */ Tcl_Obj *objResult; /* result object */ char *errorInfo; /* contents of errorInfo variable */ char *errorCode; /* contents of errorCode variable */} InterpState;#define TCL_STATE_VALID 0x01233210 /* magic bit pattern for validation *//* * ------------------------------------------------------------------------ * Itcl_Assert() * * Called whenever an assert() test fails. Prints a diagnostic * message and abruptly exits. * ------------------------------------------------------------------------ */voidItcl_Assert(testExpr, fileName, lineNumber) char *testExpr; /* string representing test expression */ char *fileName; /* file name containing this call */ int lineNumber; /* line number containing this call */{#ifndef NDEBUG fprintf(stderr, "Assertion failed: \"%s\" (line %d of %s)", testExpr, lineNumber, fileName); abort();#endif}/* * ------------------------------------------------------------------------ * Itcl_InitStack() * * Initializes a stack structure, allocating a certain amount of memory * for the stack and setting the stack length to zero. * ------------------------------------------------------------------------ */voidItcl_InitStack(stack) Itcl_Stack *stack; /* stack to be initialized */{ stack->values = stack->space; stack->max = sizeof(stack->space)/sizeof(ClientData); stack->len = 0;}/* * ------------------------------------------------------------------------ * Itcl_DeleteStack() * * Destroys a stack structure, freeing any memory that may have been * allocated to represent it. * ------------------------------------------------------------------------ */voidItcl_DeleteStack(stack) Itcl_Stack *stack; /* stack to be deleted */{ /* * If memory was explicitly allocated (instead of using the * built-in buffer) then free it. */ if (stack->values != stack->space) { ckfree((char*)stack->values); } stack->values = NULL; stack->len = stack->max = 0;}/* * ------------------------------------------------------------------------ * Itcl_PushStack() * * Pushes a piece of client data onto the top of the given stack. * If the stack is not large enough, it is automatically resized. * ------------------------------------------------------------------------ */voidItcl_PushStack(cdata,stack) ClientData cdata; /* data to be pushed onto stack */ Itcl_Stack *stack; /* stack */{ ClientData *newStack; if (stack->len+1 >= stack->max) { stack->max = 2*stack->max; newStack = (ClientData*) ckalloc((unsigned)(stack->max*sizeof(ClientData))); if (stack->values) { memcpy((char*)newStack, (char*)stack->values, (size_t)(stack->len*sizeof(ClientData))); if (stack->values != stack->space) ckfree((char*)stack->values); } stack->values = newStack; } stack->values[stack->len++] = cdata;}/* * ------------------------------------------------------------------------ * Itcl_PopStack() * * Pops a bit of client data from the top of the given stack. * ------------------------------------------------------------------------ */ClientDataItcl_PopStack(stack) Itcl_Stack *stack; /* stack to be manipulated */{ if (stack->values && (stack->len > 0)) { stack->len--; return stack->values[stack->len]; } return (ClientData)NULL;}/* * ------------------------------------------------------------------------ * Itcl_PeekStack() * * Gets the current value from the top of the given stack. * ------------------------------------------------------------------------ */ClientDataItcl_PeekStack(stack) Itcl_Stack *stack; /* stack to be examined */{ if (stack->values && (stack->len > 0)) { return stack->values[stack->len-1]; } return (ClientData)NULL;}/* * ------------------------------------------------------------------------ * Itcl_GetStackValue() * * Gets a value at some index within the stack. Index "0" is the * first value pushed onto the stack. * ------------------------------------------------------------------------ */ClientDataItcl_GetStackValue(stack,pos) Itcl_Stack *stack; /* stack to be examined */ int pos; /* get value at this index */{ if (stack->values && (stack->len > 0)) { assert(pos < stack->len); return stack->values[pos]; } return (ClientData)NULL;}/* * ------------------------------------------------------------------------ * Itcl_InitList() * * Initializes a linked list structure, setting the list to the empty * state. * ------------------------------------------------------------------------ */voidItcl_InitList(listPtr) Itcl_List *listPtr; /* list to be initialized */{ listPtr->validate = ITCL_VALID_LIST; listPtr->num = 0; listPtr->head = NULL; listPtr->tail = NULL;}/* * ------------------------------------------------------------------------ * Itcl_DeleteList() * * Destroys a linked list structure, deleting all of its elements and * setting it to an empty state. If the elements have memory associated * with them, this memory must be freed before deleting the list or it * will be lost. * ------------------------------------------------------------------------ */voidItcl_DeleteList(listPtr) Itcl_List *listPtr; /* list to be deleted */{ Itcl_ListElem *elemPtr; assert(listPtr->validate == ITCL_VALID_LIST); elemPtr = listPtr->head; while (elemPtr) { elemPtr = Itcl_DeleteListElem(elemPtr); } listPtr->validate = 0;}/* * ------------------------------------------------------------------------ * Itcl_CreateListElem() * * Low-level routined used by procedures like Itcl_InsertList() and * Itcl_AppendList() to create new list elements. If elements are * available, one is taken from the list element pool. Otherwise, * a new one is allocated. * ------------------------------------------------------------------------ */Itcl_ListElem*Itcl_CreateListElem(listPtr) Itcl_List *listPtr; /* list that will contain this new element */{ Itcl_ListElem *elemPtr; if (listPoolLen > 0) { elemPtr = listPool; listPool = elemPtr->next; --listPoolLen; } else { elemPtr = (Itcl_ListElem*)ckalloc((unsigned)sizeof(Itcl_ListElem)); } elemPtr->owner = listPtr; elemPtr->value = NULL; elemPtr->next = NULL; elemPtr->prev = NULL; return elemPtr;}/* * ------------------------------------------------------------------------ * Itcl_DeleteListElem() * * Destroys a single element in a linked list, returning it to a pool of * elements that can be later reused. Returns a pointer to the next * element in the list. * ------------------------------------------------------------------------ */Itcl_ListElem*Itcl_DeleteListElem(elemPtr) Itcl_ListElem *elemPtr; /* list element to be deleted */{ Itcl_List *listPtr; Itcl_ListElem *nextPtr; nextPtr = elemPtr->next; if (elemPtr->prev) { elemPtr->prev->next = elemPtr->next; } if (elemPtr->next) { elemPtr->next->prev = elemPtr->prev; } listPtr = elemPtr->owner; if (elemPtr == listPtr->head) listPtr->head = elemPtr->next; if (elemPtr == listPtr->tail) listPtr->tail = elemPtr->prev; --listPtr->num; if (listPoolLen < ITCL_LIST_POOL_SIZE) { elemPtr->next = listPool; listPool = elemPtr; ++listPoolLen; } else { ckfree((char*)elemPtr); } return nextPtr;}/* * ------------------------------------------------------------------------ * Itcl_InsertList() * * Creates a new list element containing the given value and returns * a pointer to it. The element is inserted at the beginning of the * specified list. * ------------------------------------------------------------------------ */Itcl_ListElem*Itcl_InsertList(listPtr,val) Itcl_List *listPtr; /* list being modified */ ClientData val; /* value associated with new element */{ Itcl_ListElem *elemPtr; assert(listPtr->validate == ITCL_VALID_LIST); elemPtr = Itcl_CreateListElem(listPtr); elemPtr->value = val; elemPtr->next = listPtr->head; elemPtr->prev = NULL; if (listPtr->head) { listPtr->head->prev = elemPtr; } listPtr->head = elemPtr; if (listPtr->tail == NULL) { listPtr->tail = elemPtr; } ++listPtr->num; return elemPtr;}/* * ------------------------------------------------------------------------ * Itcl_InsertListElem() * * Creates a new list element containing the given value and returns * a pointer to it. The element is inserted in the list just before * the specified element. * ------------------------------------------------------------------------ */Itcl_ListElem*Itcl_InsertListElem(pos,val) Itcl_ListElem *pos; /* insert just before this element */ ClientData val; /* value associated with new element */{ Itcl_List *listPtr; Itcl_ListElem *elemPtr; listPtr = pos->owner; assert(listPtr->validate == ITCL_VALID_LIST); assert(pos != NULL); elemPtr = Itcl_CreateListElem(listPtr); elemPtr->value = val; elemPtr->prev = pos->prev; if (elemPtr->prev) { elemPtr->prev->next = elemPtr; } elemPtr->next = pos; pos->prev = elemPtr; if (listPtr->head == pos) { listPtr->head = elemPtr; } if (listPtr->tail == NULL) { listPtr->tail = elemPtr; } ++listPtr->num; return elemPtr;}/* * ------------------------------------------------------------------------ * Itcl_AppendList() * * Creates a new list element containing the given value and returns * a pointer to it. The element is appended at the end of the * specified list. * ------------------------------------------------------------------------ */Itcl_ListElem*Itcl_AppendList(listPtr,val) Itcl_List *listPtr; /* list being modified */ ClientData val; /* value associated with new element */{ Itcl_ListElem *elemPtr; assert(listPtr->validate == ITCL_VALID_LIST); elemPtr = Itcl_CreateListElem(listPtr); elemPtr->value = val; elemPtr->prev = listPtr->tail; elemPtr->next = NULL; if (listPtr->tail) { listPtr->tail->next = elemPtr; } listPtr->tail = elemPtr; if (listPtr->head == NULL) { listPtr->head = elemPtr; } ++listPtr->num; return elemPtr;}/* * ------------------------------------------------------------------------ * Itcl_AppendListElem() * * Creates a new list element containing the given value and returns * a pointer to it. The element is inserted in the list just after * the specified element. * ------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -