📄 tclutil.c
字号:
if (length < 0) { length = strlen(string); } newSize = length + dsPtr->length; /* * Allocate a larger buffer for the string if the current one isn't * large enough. Allocate extra space in the new buffer so that there * will be room to grow before we have to allocate again. */ if (newSize >= dsPtr->spaceAvl) { dsPtr->spaceAvl = newSize * 2; if (dsPtr->string == dsPtr->staticSpace) { char *newString; newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); memcpy((VOID *) newString, (VOID *) dsPtr->string, (size_t) dsPtr->length); dsPtr->string = newString; } else { dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string, (size_t) dsPtr->spaceAvl); } } /* * Copy the new string into the buffer at the end of the old * one. */ for (dst = dsPtr->string + dsPtr->length, end = string+length; string < end; string++, dst++) { *dst = *string; } *dst = '\0'; dsPtr->length += length; return dsPtr->string;}/* *---------------------------------------------------------------------- * * Tcl_DStringAppendElement -- * * Append a list element to the current value of a dynamic string. * * Results: * The return value is a pointer to the dynamic string's new value. * * Side effects: * String is reformatted as a list element and added to the current * value of the string. Memory gets reallocated if needed to * accomodate the string's new size. * *---------------------------------------------------------------------- */char *Tcl_DStringAppendElement(dsPtr, string) Tcl_DString *dsPtr; /* Structure describing dynamic string. */ CONST char *string; /* String to append. Must be * null-terminated. */{ int newSize, flags, strSize; char *dst; strSize = ((string == NULL) ? 0 : strlen(string)); newSize = Tcl_ScanCountedElement(string, strSize, &flags) + dsPtr->length + 1; /* * Allocate a larger buffer for the string if the current one isn't * large enough. Allocate extra space in the new buffer so that there * will be room to grow before we have to allocate again. * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string * to a larger buffer, since there may be embedded NULLs in the * string in some cases. */ if (newSize >= dsPtr->spaceAvl) { dsPtr->spaceAvl = newSize * 2; if (dsPtr->string == dsPtr->staticSpace) { char *newString; newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); memcpy((VOID *) newString, (VOID *) dsPtr->string, (size_t) dsPtr->length); dsPtr->string = newString; } else { dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string, (size_t) dsPtr->spaceAvl); } } /* * Convert the new string to a list element and copy it into the * buffer at the end, with a space, if needed. */ dst = dsPtr->string + dsPtr->length; if (TclNeedSpace(dsPtr->string, dst)) { *dst = ' '; dst++; dsPtr->length++; } dsPtr->length += Tcl_ConvertCountedElement(string, strSize, dst, flags); return dsPtr->string;}/* *---------------------------------------------------------------------- * * Tcl_DStringSetLength -- * * Change the length of a dynamic string. This can cause the * string to either grow or shrink, depending on the value of * length. * * Results: * None. * * Side effects: * The length of dsPtr is changed to length and a null byte is * stored at that position in the string. If length is larger * than the space allocated for dsPtr, then a panic occurs. * *---------------------------------------------------------------------- */voidTcl_DStringSetLength(dsPtr, length) Tcl_DString *dsPtr; /* Structure describing dynamic string. */ int length; /* New length for dynamic string. */{ int newsize; if (length < 0) { length = 0; } if (length >= dsPtr->spaceAvl) { /* * There are two interesting cases here. In the first case, the user * may be trying to allocate a large buffer of a specific size. It * would be wasteful to overallocate that buffer, so we just allocate * enough for the requested size plus the trailing null byte. In the * second case, we are growing the buffer incrementally, so we need * behavior similar to Tcl_DStringAppend. The requested length will * usually be a small delta above the current spaceAvl, so we'll end up * doubling the old size. This won't grow the buffer quite as quickly, * but it should be close enough. */ newsize = dsPtr->spaceAvl * 2; if (length < newsize) { dsPtr->spaceAvl = newsize; } else { dsPtr->spaceAvl = length + 1; } if (dsPtr->string == dsPtr->staticSpace) { char *newString; newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl); memcpy((VOID *) newString, (VOID *) dsPtr->string, (size_t) dsPtr->length); dsPtr->string = newString; } else { dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string, (size_t) dsPtr->spaceAvl); } } dsPtr->length = length; dsPtr->string[length] = 0;}/* *---------------------------------------------------------------------- * * Tcl_DStringFree -- * * Frees up any memory allocated for the dynamic string and * reinitializes the string to an empty state. * * Results: * None. * * Side effects: * The previous contents of the dynamic string are lost, and * the new value is an empty string. * *---------------------------------------------------------------------- */voidTcl_DStringFree(dsPtr) Tcl_DString *dsPtr; /* Structure describing dynamic string. */{ if (dsPtr->string != dsPtr->staticSpace) { ckfree(dsPtr->string); } dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; dsPtr->staticSpace[0] = '\0';}/* *---------------------------------------------------------------------- * * Tcl_DStringResult -- * * This procedure moves the value of a dynamic string into an * interpreter as its string result. Afterwards, the dynamic string * is reset to an empty string. * * Results: * None. * * Side effects: * The string is "moved" to interp's result, and any existing * string result for interp is freed. dsPtr is reinitialized to * an empty string. * *---------------------------------------------------------------------- */voidTcl_DStringResult(interp, dsPtr) Tcl_Interp *interp; /* Interpreter whose result is to be reset. */ Tcl_DString *dsPtr; /* Dynamic string that is to become the * result of interp. */{ Tcl_ResetResult(interp); if (dsPtr->string != dsPtr->staticSpace) { interp->result = dsPtr->string; interp->freeProc = TCL_DYNAMIC; } else if (dsPtr->length < TCL_RESULT_SIZE) { interp->result = ((Interp *) interp)->resultSpace; strcpy(interp->result, dsPtr->string); } else { Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE); } dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; dsPtr->staticSpace[0] = '\0';}/* *---------------------------------------------------------------------- * * Tcl_DStringGetResult -- * * This procedure moves an interpreter's result into a dynamic string. * * Results: * None. * * Side effects: * The interpreter's string result is cleared, and the previous * contents of dsPtr are freed. * * If the string result is empty, the object result is moved to the * string result, then the object result is reset. * *---------------------------------------------------------------------- */voidTcl_DStringGetResult(interp, dsPtr) Tcl_Interp *interp; /* Interpreter whose result is to be reset. */ Tcl_DString *dsPtr; /* Dynamic string that is to become the * result of interp. */{ Interp *iPtr = (Interp *) interp; if (dsPtr->string != dsPtr->staticSpace) { ckfree(dsPtr->string); } /* * If the string result is empty, move the object result to the * string result, then reset the object result. */ if (*(iPtr->result) == 0) { Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); } dsPtr->length = strlen(iPtr->result); if (iPtr->freeProc != NULL) { if ((iPtr->freeProc == TCL_DYNAMIC) || (iPtr->freeProc == (Tcl_FreeProc *) free)) { dsPtr->string = iPtr->result; dsPtr->spaceAvl = dsPtr->length+1; } else { dsPtr->string = (char *) ckalloc((unsigned) (dsPtr->length+1)); strcpy(dsPtr->string, iPtr->result); (*iPtr->freeProc)(iPtr->result); } dsPtr->spaceAvl = dsPtr->length+1; iPtr->freeProc = NULL; } else { if (dsPtr->length < TCL_DSTRING_STATIC_SIZE) { dsPtr->string = dsPtr->staticSpace; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; } else { dsPtr->string = (char *) ckalloc((unsigned) (dsPtr->length + 1)); dsPtr->spaceAvl = dsPtr->length + 1; } strcpy(dsPtr->string, iPtr->result); } iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0;}/* *---------------------------------------------------------------------- * * Tcl_DStringStartSublist -- * * This procedure adds the necessary information to a dynamic * string (e.g. " {" to start a sublist. Future element * appends will be in the sublist rather than the main list. * * Results: * None. * * Side effects: * Characters get added to the dynamic string. * *---------------------------------------------------------------------- */voidTcl_DStringStartSublist(dsPtr) Tcl_DString *dsPtr; /* Dynamic string. */{ if (TclNeedSpace(dsPtr->string, dsPtr->string + dsPtr->length)) { Tcl_DStringAppend(dsPtr, " {", -1); } else { Tcl_DStringAppend(dsPtr, "{", -1); }}/* *---------------------------------------------------------------------- * * Tcl_DStringEndSublist -- * * This procedure adds the necessary characters to a dynamic * string to end a sublist (e.g. "}"). Future element appends * will be in the enclosing (sub)list rather than the current * sublist. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */voidTcl_DStringEndSublist(dsPtr) Tcl_DString *dsPtr; /* Dynamic string. */{ Tcl_DStringAppend(dsPtr, "}", -1);}/* *---------------------------------------------------------------------- * * Tcl_PrintDouble -- * * Given a floating-point value, this procedure converts it to * an ASCII string using. * * Results: * The ASCII equivalent of "value" is written at "dst". It is * written using the current precision, and it is guaranteed to * contain a decimal point or exponent, so that it looks like * a floating-point value and not an integer. * * Side effects: * None. * *---------------------------------------------------------------------- */voidTcl_PrintDouble(interp, value, dst) Tcl_Interp *interp; /* Interpreter whose tcl_precision * variable used to be used to control * printing. It's ignored now. */ double value; /* Value to print as string. */ char *dst; /* Where to store converted value; * must have at least TCL_DOUBLE_SPACE * characters. */{ char *p, c; Tcl_UniChar ch; Tcl_MutexLock(&precisionMutex); sprintf(dst, precisionFormat, value); Tcl_MutexUnlock(&precisionMutex); /* * If the ASCII result looks like an integer, add ".0" so that it * doesn't look like an integer anymore. This prevents floating-point * values from being converted to integers unintentionally. * Check for ASCII specifically to speed up the function. */ for (p = dst; *p != 0; ) { if (UCHAR(*p) < 0x80) { c = *p++; } else { p += Tcl_UtfToUniChar(p, &ch); c = UCHAR(ch); } if ((c == '.') || isalpha(UCHAR(c))) { /* INTL: ISO only. */ return; } } p[0] = '.'; p[1] = '0'; p[2] = 0;}/* *---------------------------------------------------------------------- * * TclPrecTraceProc -- * * This procedure is invoked whenever the variable "tcl_precision" * is written. * * Results: * Returns NULL if all went well, or an error message if the * new value for the variable doesn't make sense. * * Side effects: * If the new value doesn't make sense then this procedure * undoes the effect of the variable modification. Otherwise * it modifies the format string that's used by Tcl_PrintDouble. * *---------------------------------------------------------------------- */ /* ARGSUSED */char *TclPrecTraceProc(clientData, interp, name1, name2, flags) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Interpreter containing variable. */ CONST char *name1; /* Name of variable. */ CONST char *name2; /* Second part of variable name. */ int flags; /* Information about what happened. */{ CONST char *value; char *end; int prec; /* * If the variable is unset, then recreate the trace. */ if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { Tcl_TraceVar2(interp, name1, name2, TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES |TCL_TRACE_UNSETS, TclPrecTraceProc, clientData); } return (char *) NULL; } /* * When the variable is read, reset its value from our shared * value. This is needed in case the variable was modified in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -