📄 tcl_internal.c
字号:
if (flag & DB_MULTIPLE_KEY) { if (type == DB_RECNO || type == DB_QUEUE) DB_MULTIPLE_RECNO_NEXT(pointer, data, recno, dp, dlen); else DB_MULTIPLE_KEY_NEXT(pointer, data, kp, klen, dp, dlen); } else DB_MULTIPLE_NEXT(pointer, data, dp, dlen); if (pointer == NULL) break; if (type == DB_RECNO || type == DB_QUEUE) { result = _SetListRecnoElem(interp, list, recno, dp, dlen); recno++; } else result = _SetListElem(interp, list, kp, klen, dp, dlen); } while (result == TCL_OK); return (result);}/* * PUBLIC: int _GetGlobPrefix __P((char *, char **)); */int_GetGlobPrefix(pattern, prefix) char *pattern; char **prefix;{ int i, j; char *p; /* * Duplicate it, we get enough space and most of the work is done. */ if (__os_strdup(NULL, pattern, prefix) != 0) return (1); p = *prefix; for (i = 0, j = 0; p[i] && !GLOB_CHAR(p[i]); i++, j++) /* * Check for an escaped character and adjust */ if (p[i] == '\\' && p[i+1]) { p[j] = p[i+1]; i++; } else p[j] = p[i]; p[j] = 0; return (0);}/* * PUBLIC: int _ReturnSetup __P((Tcl_Interp *, int, int, char *)); */int_ReturnSetup(interp, ret, ok, errmsg) Tcl_Interp *interp; int ret, ok; char *errmsg;{ char *msg; if (ret > 0) return (_ErrorSetup(interp, ret, errmsg)); /* * We either have success or a DB error. If a DB error, set up the * string. We return an error if not one of the errors we catch. * If anyone wants to reset the result to return anything different, * then the calling function is responsible for doing so via * Tcl_ResetResult or another Tcl_SetObjResult. */ if (ret == 0) { Tcl_SetResult(interp, "0", TCL_STATIC); return (TCL_OK); } msg = db_strerror(ret); Tcl_AppendResult(interp, msg, NULL); if (ok) return (TCL_OK); else { Tcl_SetErrorCode(interp, "BerkeleyDB", msg, NULL); return (TCL_ERROR); }}/* * PUBLIC: int _ErrorSetup __P((Tcl_Interp *, int, char *)); */int_ErrorSetup(interp, ret, errmsg) Tcl_Interp *interp; int ret; char *errmsg;{ Tcl_SetErrno(ret); Tcl_AppendResult(interp, errmsg, ":", Tcl_PosixError(interp), NULL); return (TCL_ERROR);}/* * PUBLIC: void _ErrorFunc __P((CONST char *, char *)); */void_ErrorFunc(pfx, msg) CONST char *pfx; char *msg;{ DBTCL_INFO *p; Tcl_Interp *interp; int size; char *err; p = _NameToInfo(pfx); if (p == NULL) return; interp = p->i_interp; size = strlen(pfx) + strlen(msg) + 4; /* * If we cannot allocate enough to put together the prefix * and message then give them just the message. */ if (__os_malloc(NULL, size, &err) != 0) { Tcl_AddErrorInfo(interp, msg); Tcl_AppendResult(interp, msg, "\n", NULL); return; } snprintf(err, size, "%s: %s", pfx, msg); Tcl_AddErrorInfo(interp, err); Tcl_AppendResult(interp, err, "\n", NULL); __os_free(NULL, err); return;}#define INVALID_LSNMSG "Invalid LSN with %d parts. Should have 2.\n"/* * PUBLIC: int _GetLsn __P((Tcl_Interp *, Tcl_Obj *, DB_LSN *)); */int_GetLsn(interp, obj, lsn) Tcl_Interp *interp; Tcl_Obj *obj; DB_LSN *lsn;{ Tcl_Obj **myobjv; char msg[MSG_SIZE]; int myobjc, result; u_int32_t tmp; result = Tcl_ListObjGetElements(interp, obj, &myobjc, &myobjv); if (result == TCL_ERROR) return (result); if (myobjc != 2) { result = TCL_ERROR; snprintf(msg, MSG_SIZE, INVALID_LSNMSG, myobjc); Tcl_SetResult(interp, msg, TCL_VOLATILE); return (result); } result = _GetUInt32(interp, myobjv[0], &tmp); if (result == TCL_ERROR) return (result); lsn->file = tmp; result = _GetUInt32(interp, myobjv[1], &tmp); lsn->offset = tmp; return (result);}/* * _GetUInt32 -- * Get a u_int32_t from a Tcl object. Tcl_GetIntFromObj does the * right thing most of the time, but on machines where a long is 8 bytes * and an int is 4 bytes, it errors on integers between the maximum * int32_t and the maximum u_int32_t. This is correct, but we generally * want a u_int32_t in the end anyway, so we use Tcl_GetLongFromObj and do * the bounds checking ourselves. * * This code looks much like Tcl_GetIntFromObj, only with a different * bounds check. It's essentially Tcl_GetUnsignedIntFromObj, which * unfortunately doesn't exist. * * PUBLIC: int _GetUInt32 __P((Tcl_Interp *, Tcl_Obj *, u_int32_t *)); */int_GetUInt32(interp, obj, resp) Tcl_Interp *interp; Tcl_Obj *obj; u_int32_t *resp;{ int result; long ltmp; result = Tcl_GetLongFromObj(interp, obj, <mp); if (result != TCL_OK) return (result); if ((unsigned long)ltmp != (u_int32_t)ltmp) { if (interp != NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "integer value too large for u_int32_t", -1); } return (TCL_ERROR); } *resp = (u_int32_t)ltmp; return (TCL_OK);}/* * tcl_flag_callback -- * Callback for db_pr.c functions that contain the FN struct mapping * flag values to meaningful strings. This function appends a Tcl_Obj * containing each pertinent flag string to the specified Tcl list. */static voidtcl_flag_callback(flags, fn, vtcbp) u_int32_t flags; const FN *fn; void *vtcbp;{ const FN *fnp; Tcl_Interp *interp; Tcl_Obj *newobj, *listobj; int result; struct __tcl_callback_bundle *tcbp; tcbp = (struct __tcl_callback_bundle *)vtcbp; interp = tcbp->interp; listobj = tcbp->obj; for (fnp = fn; fnp->mask != 0; ++fnp) if (LF_ISSET(fnp->mask)) { newobj = Tcl_NewStringObj(fnp->name, strlen(fnp->name)); result = Tcl_ListObjAppendElement(interp, listobj, newobj); /* * Tcl_ListObjAppendElement is defined to return TCL_OK * unless listobj isn't actually a list (or convertible * into one). If this is the case, we screwed up badly * somehow. */ DB_ASSERT(result == TCL_OK); }}/* * _GetFlagsList -- * Get a new Tcl object, containing a list of the string values * associated with a particular set of flag values, given a function * that can extract the right names for the right flags. * * PUBLIC: Tcl_Obj *_GetFlagsList __P((Tcl_Interp *, u_int32_t, * PUBLIC: void (*)(u_int32_t, void *, * PUBLIC: void (*)(u_int32_t, const FN *, void *)))); */Tcl_Obj *_GetFlagsList(interp, flags, func) Tcl_Interp *interp; u_int32_t flags; void (*func) __P((u_int32_t, void *, void (*)(u_int32_t, const FN *, void *)));{ Tcl_Obj *newlist; struct __tcl_callback_bundle tcb; newlist = Tcl_NewObj(); memset(&tcb, 0, sizeof(tcb)); tcb.interp = interp; tcb.obj = newlist; func(flags, &tcb, tcl_flag_callback); return (newlist);}int __debug_stop, __debug_on, __debug_print, __debug_test;/* * PUBLIC: void _debug_check __P((void)); */void_debug_check(){ if (__debug_on == 0) return; if (__debug_print != 0) { printf("\r%7d:", __debug_on); fflush(stdout); } if (__debug_on++ == __debug_test || __debug_stop) __db_loadme();}/* * XXX * Tcl 8.1+ Tcl_GetByteArrayFromObj/Tcl_GetIntFromObj bug. * * There is a bug in Tcl 8.1+ and byte arrays in that if it happens * to use an object as both a byte array and something else like * an int, and you've done a Tcl_GetByteArrayFromObj, then you * do a Tcl_GetIntFromObj, your memory is deleted. * * Workaround is for all byte arrays we want to use, if it can be * represented as an integer, we copy it so that we don't lose the * memory. *//* * PUBLIC: int _CopyObjBytes __P((Tcl_Interp *, Tcl_Obj *obj, void **, * PUBLIC: u_int32_t *, int *)); */int_CopyObjBytes(interp, obj, newp, sizep, freep) Tcl_Interp *interp; Tcl_Obj *obj; void **newp; u_int32_t *sizep; int *freep;{ void *tmp, *new; int i, len, ret; /* * If the object is not an int, then just return the byte * array because it won't be transformed out from under us. * If it is a number, we need to copy it. */ *freep = 0; ret = Tcl_GetIntFromObj(interp, obj, &i); tmp = Tcl_GetByteArrayFromObj(obj, &len); *sizep = len; if (ret == TCL_ERROR) { Tcl_ResetResult(interp); *newp = tmp; return (0); } /* * If we get here, we have an integer that might be reused * at some other point so we cannot count on GetByteArray * keeping our pointer valid. */ if ((ret = __os_malloc(NULL, len, &new)) != 0) return (ret); memcpy(new, tmp, len); *newp = new; *freep = 1; return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -