From ae33d6bbf676b0bdd074ee8a295a1c35a6107459 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 6 Nov 2019 13:25:09 +0000 Subject: Fix tclScan.c, not generating a string representation any more with unsigned wideints and unsigned longs. --- generic/tclScan.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/generic/tclScan.c b/generic/tclScan.c index b0669ab..4b9298d 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -585,9 +585,6 @@ Tcl_ScanObjCmd( Tcl_UniChar ch = 0, sch = 0; Tcl_Obj **objs = NULL, *objPtr = NULL; int flags; - char buf[513]; /* Temporary buffer to hold scanned number - * strings before they are passed to - * strtoul. */ if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, @@ -937,9 +934,9 @@ Tcl_ScanObjCmd( } } if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) { - sprintf(buf, "%" TCL_LL_MODIFIER "u", - (Tcl_WideUInt)wideValue); - Tcl_SetStringObj(objPtr, buf, -1); + mp_int big; + TclBNInitBignumFromWideUInt(&big, (Tcl_WideUInt)wideValue); + Tcl_SetBignumObj(objPtr, &big); } else { Tcl_SetWideIntObj(objPtr, wideValue); } @@ -952,8 +949,13 @@ Tcl_ScanObjCmd( } } if ((flags & SCAN_UNSIGNED) && (value < 0)) { - sprintf(buf, "%lu", value); /* INTL: ISO digit */ - Tcl_SetStringObj(objPtr, buf, -1); +#ifdef TCL_WIDE_INT_IS_LONG + mp_int big; + TclBNInitBignumFromWideUInt(&big, (unsigned long)value); + Tcl_SetBignumObj(objPtr, &big); +#else + Tcl_SetWideIntObj(objPtr, (unsigned long)value); +#endif } else { Tcl_SetLongObj(objPtr, value); } -- cgit v0.12 From 52e0f14369c4c32549d39a45bd1cb9b8736ca20e Mon Sep 17 00:00:00 2001 From: pooryorick Date: Thu, 7 Nov 2019 16:40:09 +0000 Subject: Rewrite comments in tclIOUtil.c --- generic/tclIOUtil.c | 2119 +++++++++++++++++++++++---------------------------- 1 file changed, 971 insertions(+), 1148 deletions(-) diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 3773159..ceee36e 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -1,14 +1,11 @@ /* * tclIOUtil.c -- * - * This file contains the implementation of Tcl's generic filesystem - * code, which supports a pluggable filesystem architecture allowing both - * platform specific filesystems and 'virtual filesystems'. All - * filesystem access should go through the functions defined in this - * file. Most of this code was contributed by Vince Darley. - * - * Parts of this file are based on code contributed by Karl Lehenbauer, - * Mark Diekhans and Peter da Silva. + * Provides an interface for managing filesystems in Tcl, and also for + * creating a filesystem interface in Tcl arbitrary facilities. All + * filesystem operations are performed via this interface. Vince Darley + * is the primary author. Other signifiant contributors are Karl + * Lehenbauer, Mark Diekhans and Peter da Silva. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. @@ -33,42 +30,41 @@ /* * struct FilesystemRecord -- * - * A filesystem record is used to keep track of each filesystem currently - * registered with the core, in a linked list. + * An item in a linked list of registered filesystems */ typedef struct FilesystemRecord { - ClientData clientData; /* Client specific data for the new filesystem + ClientData clientData; /* Client-specific data for the filesystem * (can be NULL) */ const Tcl_Filesystem *fsPtr;/* Pointer to filesystem dispatch table. */ struct FilesystemRecord *nextPtr; - /* The next filesystem registered to Tcl, or - * NULL if no more. */ + /* The next registered filesystem, or NULL to + * indicate the end of the list. */ struct FilesystemRecord *prevPtr; - /* The previous filesystem registered to Tcl, - * or NULL if no more. */ + /* The previous filesystem, or NULL to indicate + * the ned of the list */ } FilesystemRecord; /* - * This structure holds per-thread private copy of the current directory - * maintained by the global cwdPathPtr. This structure holds per-thread - * private copies of some global data. This way we avoid most of the - * synchronization calls which boosts performance, at cost of having to update - * this information each time the corresponding epoch counter changes. */ typedef struct { int initialized; - size_t cwdPathEpoch; + size_t cwdPathEpoch; /* Compared with the global cwdPathEpoch to + * determine whether cwdPathPtr is stale. + */ size_t filesystemEpoch; - Tcl_Obj *cwdPathPtr; + Tcl_Obj *cwdPathPtr; /* A private copy of cwdPathPtr. Updated when + * the value is accessed and cwdPathEpoch has + * changed. + */ ClientData cwdClientData; FilesystemRecord *filesystemList; size_t claims; } ThreadSpecificData; /* - * Prototypes for functions defined later in this file. + * Forward declarations. */ static Tcl_NRPostProc EvalFileCallback; @@ -87,28 +83,12 @@ static void * DivertFindSymbol(Tcl_Interp *interp, Tcl_LoadHandle loadHandle, const char *symbol); static void DivertUnloadFile(Tcl_LoadHandle loadHandle); -/* - * These form part of the native filesystem support. They are needed here - * because we have a few native filesystem functions (which are the same for - * win/unix) in this file. There is no need to place them in tclInt.h, because - * they are not (and should not be) used anywhere else. - */ - -MODULE_SCOPE const char *const tclpFileAttrStrings[]; -MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[]; /* - * Declare the native filesystem support. These functions should be considered - * private to Tcl, and should really not be called directly by any code other - * than this file (i.e. neither by Tcl's core nor by extensions). Similarly, - * the old string-based Tclp... native filesystem functions should not be - * called. - * - * The correct API to use now is the Tcl_FS... set of functions, which ensure - * correct and complete virtual filesystem support. - * - * We cannot make all of these static, since some of them are implemented in - * the platform-specific directories. + * Functions that provide native filesystem support. They are private and + * should be used only here. They should be called instead of calling Tclp... + * native filesystem functions. Others should use the Tcl_FS... functions + * which ensure correct and complete virtual filesystem support. */ static Tcl_FSFilesystemSeparatorProc NativeFilesystemSeparator; @@ -118,12 +98,21 @@ static Tcl_FSFileAttrsGetProc NativeFileAttrsGet; static Tcl_FSFileAttrsSetProc NativeFileAttrsSet; /* - * The only reason these functions are not static is that they are either - * called by code in the native (win/unix) directories or they are actually - * implemented in those directories. They should simply not be called by code - * outside Tcl's native filesystem core i.e. they should be considered - * 'static' to Tcl's filesystem code (if we ever built the native filesystem - * support into a separate code library, this could actually be enforced). + * Functions that support the native filesystem functions listed above. They + * are the same for win/unix, and not in tclInt.h because they are and should + * be used only here. + */ + +MODULE_SCOPE const char *const tclpFileAttrStrings[]; +MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[]; + + +/* + * These these functions are not static either because routines in the native + * (win/unix) directories call them or they are actually implemented in those + * directories. They should be called from outside Tcl's native filesystem + * routines. If we ever built the native filesystem support into a separate + * code library, this could actually be enforced. */ Tcl_FSFilesystemPathTypeProc TclpFilesystemPathType; @@ -143,11 +132,9 @@ Tcl_FSLinkProc TclpObjLink; Tcl_FSListVolumesProc TclpObjListVolumes; /* - * Define the native filesystem dispatch table. If necessary, it is ok to make - * this non-static, but it should only be accessed by the functions actually - * listed within it (or perhaps other helper functions of them). Anything - * which is not part of this 'native filesystem implementation' should not be - * delving inside here! + * The native filesystem dispatch table. This could me made public but it + * should only be accessed by the functions it points to, or perhaps + * subordinate helper functions. */ const Tcl_Filesystem tclNativeFilesystem = { @@ -190,13 +177,10 @@ const Tcl_Filesystem tclNativeFilesystem = { }; /* - * Define the tail of the linked list. Note that for unconventional uses of - * Tcl without a native filesystem, we may in the future wish to modify the - * current approach of hard-coding the native filesystem in the lookup list - * 'filesystemList' below. - * - * We initialize the record so that it thinks one file uses it. This means it - * will never be freed. + * An initial record in the linked list for the native filesystem. Remains at + * the tail of the list and is never freed. Currently the native filesystem is + * hard-coded. It may make sense to modify this to accomodate unconventional + * uses of Tcl that provide no native filesystem. */ static FilesystemRecord nativeFilesystemRecord = { @@ -207,41 +191,39 @@ static FilesystemRecord nativeFilesystemRecord = { }; /* - * This is incremented each time we modify the linked list of filesystems. Any - * time it changes, all cached filesystem representations are suspect and must - * be freed. For multithreading builds, change of the filesystem epoch will - * trigger cache cleanup in all threads. + * Incremented each time the linked list of filesystems is modified. For + * multithreaded builds, invalidates all cached filesystem internal + * representations. */ static size_t theFilesystemEpoch = 1; /* - * Stores the linked list of filesystems. A 1:1 copy of this list is also - * maintained in the TSD for each thread. This is to avoid synchronization - * issues. + * The linked list of filesystems. To minimize locking each thread maintains a + * local copy of this list. + * */ static FilesystemRecord *filesystemList = &nativeFilesystemRecord; TCL_DECLARE_MUTEX(filesystemMutex) /* - * Used to implement Tcl_FSGetCwd in a file-system independent way. + * A files-system indepent sense of the current directory. */ static Tcl_Obj *cwdPathPtr = NULL; -static size_t cwdPathEpoch = 0; +static size_t cwdPathEpoch = 0; /* The pathname of the current directory */ static ClientData cwdClientData = NULL; TCL_DECLARE_MUTEX(cwdMutex) static Tcl_ThreadDataKey fsDataKey; /* - * One of these structures is used each time we successfully load a file from - * a file system by way of making a temporary copy of the file on the native - * filesystem. We need to store both the actual unloadProc/clientData - * combination which was used, and the original and modified filenames, so - * that we can correctly undo the entire operation when we want to unload the - * code. + * When a temporary copy of a file is created on the native filesystem in order + * to load the file, an FsDivertLoad structure is created to track both the + * actual unloadProc/clientData combination which was used, and the original and + * modified filenames. This makes it possible to correctly undo the entire + * operation in order to unload the library. */ typedef struct { @@ -253,14 +235,14 @@ typedef struct { } FsDivertLoad; /* - * The following functions are obsolete string based APIs, and should be - * removed in a future release (Tcl 9 would be a good time). + * Obsolete string-based APIs that should be removed in a future release, + * perhaps in Tcl 9. */ /* Obsolete */ int Tcl_Stat( - const char *path, /* Path of file to stat (in current CP). */ + const char *path, /* Pathname of file to stat (in current CP). */ struct stat *oldStyleBuf) /* Filled with results of stat call. */ { int ret; @@ -347,7 +329,8 @@ Tcl_Stat( /* Obsolete */ int Tcl_Access( - const char *path, /* Path of file to access (in current CP). */ + const char *path, /* Pathname of file to access (in current CP). + */ int mode) /* Permission setting. */ { int ret; @@ -363,13 +346,12 @@ Tcl_Access( /* Obsolete */ Tcl_Channel Tcl_OpenFileChannel( - Tcl_Interp *interp, /* Interpreter for error reporting; can be + Tcl_Interp *interp, /* Interpreter for error reporting. May be * NULL. */ - const char *path, /* Name of file to open. */ + const char *path, /* Pathname of file to open. */ const char *modeString, /* A list of POSIX open modes or a string such * as "rw". */ - int permissions) /* If the open involves creating a file, with - * what modes to create it? */ + int permissions) /* The modes to use if creating a new file. */ { Tcl_Channel ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1); @@ -413,9 +395,10 @@ Tcl_GetCwd( int Tcl_EvalFile( - Tcl_Interp *interp, /* Interpreter in which to process file. */ - const char *fileName) /* Name of file to process. Tilde-substitution - * will be performed on this name. */ + Tcl_Interp *interp, /* Interpreter in which to evaluate the script. */ + const char *fileName) /* Pathname of the file containing the script. + * Performs Tilde-substitution on this + * pathaname. */ { int ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(fileName,-1); @@ -427,7 +410,7 @@ Tcl_EvalFile( } /* - * Now move on to the basic filesystem implementation. + * The basic filesystem implementation. */ static void @@ -438,7 +421,7 @@ FsThrExitProc( FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL; /* - * Trash the cwd copy. + * Discard the cwd copy. */ if (tsdPtr->cwdPathPtr != NULL) { @@ -450,7 +433,7 @@ FsThrExitProc( } /* - * Trash the filesystems cache. + * Discard the filesystems cache. */ fsRecPtr = tsdPtr->filesystemList; @@ -480,20 +463,20 @@ TclFSCwdIsNative(void) *---------------------------------------------------------------------- * * TclFSCwdPointerEquals -- - * - * Check whether the current working directory is equal to the path - * given. + * Determine whether the given pathname is equal to the current working + * directory. * * Results: - * 1 (equal) or 0 (un-equal) as appropriate. + * 1 if equal, 0 otherwise. * * Side effects: - * If the paths are equal, but are not the same object, this method will - * modify the given pathPtrPtr to refer to the same object. In this case - * the object pointed to by pathPtrPtr will have its refCount - * decremented, and it will be adjusted to point to the cwd (with a new - * refCount). + * Updates TSD if needed. + * + * Stores a pointer to the current directory in *pathPtrPtr if it is not + * already there and the current directory is not NULL. * + * If *pathPtrPtr is not null its reference count is decremented + * before it is replaced. *---------------------------------------------------------------------- */ @@ -546,8 +529,8 @@ TclFSCwdPointerEquals( str2 = TclGetStringFromObj(*pathPtrPtr, &len2); if ((len1 == len2) && !memcmp(str1, str2, len1)) { /* - * They are equal, but different objects. Update so they will be - * the same object in the future. + * The values are equal but the objects are different. Cache the + * current structure in place of the old one. */ Tcl_DecrRefCount(*pathPtrPtr); @@ -590,7 +573,7 @@ FsRecacheFilesystemList(void) } /* - * Refill the cache honouring the order. + * Refill the cache, honouring the order. */ list = NULL; @@ -637,8 +620,8 @@ FsGetFirstFilesystem(void) } /* - * The epoch can be changed by filesystems being added or removed, by changing - * the "system encoding" and by env(HOME) changing. + * The epoch can is changed when a filesystems is added or removed, when + * "system encoding" changes, and when env(HOME) changes. */ int @@ -673,7 +656,7 @@ TclFSEpoch(void) } /* - * If non-NULL, clientData is owned by us and must be freed later. + * If non-NULL, take posession of clientData and free it later. */ static void @@ -702,7 +685,7 @@ FsUpdateCwd( cwdClientData = NULL; } else { /* - * This must be stored as string obj! + * This must be stored as a string obj! */ cwdPathPtr = Tcl_NewStringObj(str, len); @@ -738,17 +721,17 @@ FsUpdateCwd( * * TclFinalizeFilesystem -- * - * Clean up the filesystem. After this, calls to all Tcl_FS... functions - * will fail. + * Clean up the filesystem. After this, any call to a Tcl_FS... function + * fails. * - * We will later call TclResetFilesystem to restore the FS to a pristine - * state. + * If TclResetFilesystem is called later, it restores the filesystem to a + * pristine state. * * Results: * None. * * Side effects: - * Frees any memory allocated by the filesystem. + * Frees memory allocated for the filesystem. * *---------------------------------------------------------------------- */ @@ -759,8 +742,9 @@ TclFinalizeFilesystem(void) FilesystemRecord *fsRecPtr; /* - * Assumption that only one thread is active now. Otherwise we would need - * to put various mutexes around this code. + * Assume that only one thread is active. Otherwise mutexes would be needed + * around this code. + * TO DO: This assumption is false, isn't it? */ if (cwdPathPtr != NULL) { @@ -783,7 +767,7 @@ TclFinalizeFilesystem(void) FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr; /* - * The native filesystem is static, so we don't free it. + * The native filesystem is static, so don't free it. */ if (fsRecPtr != &nativeFilesystemRecord) { @@ -797,8 +781,8 @@ TclFinalizeFilesystem(void) filesystemList = NULL; /* - * Now filesystemList is NULL. This means that any attempt to use the - * filesystem is likely to fail. + * filesystemList is now NULL. Any attempt to use the filesystem is likely + * to fail. */ #ifdef _WIN32 @@ -836,34 +820,31 @@ TclResetFilesystem(void) * * Tcl_FSRegister -- * - * Insert the filesystem function table at the head of the list of - * functions which are used during calls to all file-system operations. - * The filesystem will be added even if it is already in the list. (You - * can use Tcl_FSData to check if it is in the list, provided the - * ClientData used was not NULL). + * Prepends to the list of registered fileystems a new FilesystemRecord + * for the given Tcl_Filesystem, which is added even if it is already in + * the list. To determine whether the filesystem is already in the list, + * use Tcl_FSData(). * - * Note that the filesystem handling is head-to-tail of the list. Each - * filesystem is asked in turn whether it can handle a particular - * request, until one of them says 'yes'. At that point no further - * filesystems are asked. - * - * In particular this means if you want to add a diagnostic filesystem - * (which simply reports all fs activity), it must be at the head of the - * list: i.e. it must be the last registered. + * Functions that use the list generally process it from head to tail and + * use the first filesystem that is suitable. Therefore, when adding a + * diagnostic filsystem (one which simply reports all fs activity), it + * must be at the head of the list. I.e. it must be the last one + * registered. * * Results: - * Normally TCL_OK; TCL_ERROR if memory for a new node in the list could + * TCL_OK, or TCL_ERROR if memory for a new node in the list could * not be allocated. * * Side effects: - * Memory allocated and modifies the link list for filesystems. + * Allocates memory for a filesystem record and modifies the list of + * registered filesystems. * *---------------------------------------------------------------------- */ int Tcl_FSRegister( - ClientData clientData, /* Client specific data for this fs. */ + ClientData clientData, /* Client-specific data for this filesystem. */ const Tcl_Filesystem *fsPtr)/* The filesystem record for the new fs. */ { FilesystemRecord *newFilesystemPtr; @@ -877,19 +858,6 @@ Tcl_FSRegister( newFilesystemPtr->clientData = clientData; newFilesystemPtr->fsPtr = fsPtr; - /* - * Is this lock and wait strictly speaking necessary? Since any iterators - * out there will have grabbed a copy of the head of the list and be - * iterating away from that, if we add a new element to the head of the - * list, it can't possibly have any effect on any of their loops. In fact - * it could be better not to wait, since we are adjusting the filesystem - * epoch, any cached representations calculated by existing iterators are - * going to have to be thrown away anyway. - * - * However, since registering and unregistering filesystems is a very rare - * action, this is not a very important point. - */ - Tcl_MutexLock(&filesystemMutex); newFilesystemPtr->nextPtr = filesystemList; @@ -900,7 +868,7 @@ Tcl_FSRegister( filesystemList = newFilesystemPtr; /* - * Increment the filesystem epoch counter, since existing paths might + * Increment the filesystem epoch counter since existing pathnames might * conceivably now belong to different filesystems. */ @@ -917,21 +885,19 @@ Tcl_FSRegister( * * Tcl_FSUnregister -- * - * Remove the passed filesystem from the list of filesystem function - * tables. It also ensures that the built-in (native) filesystem is not - * removable, although we may wish to change that decision in the future - * to allow a smaller Tcl core, in which the native filesystem is not - * used at all (we could, say, initialise Tcl completely over a network - * connection). + * Removes the record for given filesystem from the list of registered + * filesystems. Refuses to remove the built-in (native) filesystem. This + * might be changed in the future to allow a smaller Tcl core in which the + * native filesystem is not used at all, e.g. initializing Tcl over a + * network connection. * * Results: - * TCL_OK if the function pointer was successfully removed, TCL_ERROR + * TCL_OK if the function pointer was successfully removed, or TCL_ERROR * otherwise. * * Side effects: - * Memory may be deallocated (or will be later, once no "path" objects - * refer to this filesystem), but the list of registered filesystems is - * updated immediately. + * The list of registered filesystems is updated. Memory for the + * corresponding FilesystemRecord is eventually freed. * *---------------------------------------------------------------------- */ @@ -946,9 +912,9 @@ Tcl_FSUnregister( Tcl_MutexLock(&filesystemMutex); /* - * Traverse the 'filesystemList' looking for the particular node whose - * 'fsPtr' member matches 'fsPtr' and remove that one from the list. - * Ensure that the "default" node cannot be removed. + * Traverse filesystemList in search of the record whose + * 'fsPtr' member matches 'fsPtr' and remove that record from the list. + * Do not revmoe the record for the native filesystem. */ fsRecPtr = filesystemList; @@ -964,11 +930,9 @@ Tcl_FSUnregister( } /* - * Increment the filesystem epoch counter, since existing paths - * might conceivably now belong to different filesystems. This - * should also ensure that paths which have cached the filesystem - * which is about to be deleted do not reference that filesystem - * (which would of course lead to memory exceptions). + * Each cached pathname could now belong to a different filesystem, + * so increment the filesystem epoch counter to ensure that cached + * information about the removed filesystem is not used. */ if (++theFilesystemEpoch == 0) { @@ -992,52 +956,37 @@ Tcl_FSUnregister( * * Tcl_FSMatchInDirectory -- * - * This routine is used by the globbing code to search a directory for - * all files which match a given pattern. The appropriate function for - * the filesystem to which pathPtr belongs will be called. If pathPtr - * does not belong to any filesystem and if it is NULL or the empty - * string, then we assume the pattern is to be matched in the current - * working directory. To avoid have the Tcl_FSMatchInDirectoryProc for - * each filesystem from having to deal with this issue, we create a - * pathPtr on the fly (equal to the cwd), and then remove it from the - * results returned. This makes filesystems easy to write, since they can - * assume the pathPtr passed to them is an ordinary path. In fact this - * means we could remove such special case handling from Tcl's native - * filesystems. - * - * If 'pattern' is NULL, then pathPtr is assumed to be a fully specified - * path of a single file/directory which must be checked for existence - * and correct type. + * Search in the given pathname for files matching the given pattern. + * Used by [glob]. Processes just one pattern for one directory. Callers + * such as TclGlob and DoGlob implement manage the searching of multiple + * directories in cases such as + * glob -dir $dir -join * pkgIndex.tcl * * Results: * - * The return value is a standard Tcl result indicating whether an error - * occurred in globbing. Error messages are placed in interp, but good - * results are placed in the resultPtr given. - * - * Recursive searches, e.g. - * glob -dir $dir -join * pkgIndex.tcl - * which must recurse through each directory matching '*' are handled - * internally by Tcl, by passing specific flags in a modified 'types' - * parameter. This means the actual filesystem only ever sees patterns - * which match in a single directory. + * TCL_OK, or TCL_ERROR * * Side effects: - * The interpreter may have an error message inserted into it. + * resultPtr is populated, or in the case of an TCL_ERROR, an error message is + * set in the interpreter. * *---------------------------------------------------------------------- */ int Tcl_FSMatchInDirectory( - Tcl_Interp *interp, /* Interpreter to receive error messages, but - * may be NULL. */ - Tcl_Obj *resultPtr, /* List object to receive results. */ - Tcl_Obj *pathPtr, /* Contains path to directory to search. */ - const char *pattern, /* Pattern to match against. */ - Tcl_GlobTypeData *types) /* Object containing list of acceptable types. - * May be NULL. In particular the directory - * flag is very important. */ + Tcl_Interp *interp, /* Interpreter to receive error messages, or + * NULL */ + Tcl_Obj *resultPtr, /* List that results are added to. */ + Tcl_Obj *pathPtr, /* Pathname of directory to search. If NULL, + * the current working directory is used. */ + const char *pattern, /* Pattern to match. If NULL, pathPtr must be + * a fully-specified pathname of a single + * file/directory which already exists and is + * of the correct type. */ + Tcl_GlobTypeData *types) /* Specifies acceptable types. + * May be NULL. The directory flag is + * particularly significant. */ { const Tcl_Filesystem *fsPtr; Tcl_Obj *cwd, *tmpResultPtr, **elemsPtr; @@ -1045,10 +994,10 @@ Tcl_FSMatchInDirectory( if (types != NULL && (types->type & TCL_GLOB_TYPE_MOUNT)) { /* - * We don't currently allow querying of mounts by external code (a - * valuable future step), so since we're the only function that - * actually knows about mounts, this means we're being called - * recursively by ourself. Return no matches. + * Currently external callers may not query mounts, which would be a + * valuable future step. This is the only routine that knows about + * mounts, so we're being called recursively by ourself. Return no + * matches. */ return TCL_OK; @@ -1060,12 +1009,11 @@ Tcl_FSMatchInDirectory( fsPtr = NULL; } - /* - * Check if we've successfully mapped the path to a filesystem within - * which to search. - */ - if (fsPtr != NULL) { + /* + * A corresponding filesystem was found. Search within it. + */ + if (fsPtr->matchInDirectoryProc == NULL) { Tcl_SetErrno(ENOENT); return -1; @@ -1078,24 +1026,21 @@ Tcl_FSMatchInDirectory( return ret; } - /* - * If the path isn't empty, we have no idea how to match files in a - * directory which belongs to no known filesystem. - */ - if (pathPtr != NULL && TclGetString(pathPtr)[0] != '\0') { + /* + * There is a pathname but it belongs to no known filesystem. Mayday! + */ + Tcl_SetErrno(ENOENT); return -1; } /* - * We have an empty or NULL path. This is defined to mean we must search - * for files within the current 'cwd'. We therefore use that, but then - * since the proc we call will return results which include the cwd we - * must then trim it off the front of each path in the result. We choose - * to deal with this here (in the generic code), since if we don't, every - * single filesystem's implementation of Tcl_FSMatchInDirectory will have - * to deal with it for us. + * The pathname is empty or NULL so search in the current working + * directory. matchInDirectoryProc prefixes each result with this + * directory, so trim it from each result. Deal with this here in the + * generic code because otherwise every filesystem implementation of + * Tcl_FSMatchInDirectory has to do it. */ cwd = Tcl_FSGetCwd(NULL); @@ -1118,7 +1063,7 @@ Tcl_FSMatchInDirectory( FsAddMountsToGlobResult(tmpResultPtr, cwd, pattern, types); /* - * Note that we know resultPtr and tmpResultPtr are distinct. + * resultPtr and tmpResultPtr are guaranteed to be distinct. */ ret = Tcl_ListObjGetElements(interp, tmpResultPtr, @@ -1138,30 +1083,28 @@ Tcl_FSMatchInDirectory( *---------------------------------------------------------------------- * * FsAddMountsToGlobResult -- - * - * This routine is used by the globbing code to take the results of a - * directory listing and add any mounted paths to that listing. This is - * required so that simple things like 'glob *' merge mounts and listings - * correctly. + * Adds any mounted pathnames to a set of results so that simple things + * like 'glob *' merge mounts and listings correctly. Used by the + * Tcl_FSMatchInDirectory. * * Results: * None. * * Side effects: - * Modifies the resultPtr. + * Stores a result in resultPtr. * *---------------------------------------------------------------------- */ static void FsAddMountsToGlobResult( - Tcl_Obj *resultPtr, /* The current list of matching paths; must - * not be shared! */ - Tcl_Obj *pathPtr, /* The directory in question. */ - const char *pattern, /* Pattern to match against. */ - Tcl_GlobTypeData *types) /* Object containing list of acceptable types. - * May be NULL. In particular the directory - * flag is very important. */ + Tcl_Obj *resultPtr, /* The current list of matching pathnames. Must + * not be shared. */ + Tcl_Obj *pathPtr, /* The directory that was searched. */ + const char *pattern, /* Pattern to match mounts against. */ + Tcl_GlobTypeData *types) /* Acceptable types. May be NULL. The + * directory flag is particularly significant. + */ { int mLength, gLength, i; int dir = (types == NULL || (types->type & TCL_GLOB_TYPE_DIR)); @@ -1206,9 +1149,9 @@ FsAddMountsToGlobResult( int len, mlen; /* - * We know mElt is absolute normalized and lies inside pathPtr, so - * now we must add to the result the right representation of mElt, - * i.e. the representation which is relative to pathPtr. + * mElt is normalized and lies inside pathPtr so + * add to the result the right representation of mElt, + * i.e. the representation relative to pathPtr. */ norm = Tcl_FSGetNormalizedPath(NULL, pathPtr); @@ -1225,12 +1168,13 @@ FsAddMountsToGlobResult( len--; } len++; /* account for '/' in the mElt [Bug 1602539] */ + + mElt = TclNewFSPathObj(pathPtr, mount + len, mlen - len); Tcl_ListObjAppendElement(NULL, resultPtr, mElt); } /* - * No need to increment gLength, since we don't want to compare - * mounts against mounts. + * Not comparing mounts to mounts, so no need to increment gLength */ } } @@ -1244,44 +1188,41 @@ FsAddMountsToGlobResult( * * Tcl_FSMountsChanged -- * - * Notify the filesystem that the available mounted filesystems (or - * within any one filesystem type, the number or location of mount - * points) have changed. + * Announecs that mount points have changed or that the system encoding + * has changed. * * Results: * None. * * Side effects: - * The global filesystem variable 'theFilesystemEpoch' is incremented. - * The effect of this is to make all cached path representations invalid. - * Clearly it should only therefore be called when it is really required! - * There are a few circumstances when it should be called: + * The shared 'theFilesystemEpoch' is incremented, invalidating every + * exising cached internal representation of a pathname. Avoid calling + * Tcl_FSMountsChanged whenever possible. It must be called when: * - * (1) when a new filesystem is registered or unregistered. Strictly - * speaking this is only necessary if the new filesystem accepts file - * paths as is (normally the filesystem itself is really a shell which - * hasn't yet had any mount points established and so its - * 'pathInFilesystem' proc will always fail). However, for safety, Tcl - * always calls this for you in these circumstances. + * (1) A filesystem is registered or unregistered. This is only necessary + * if the new filesystem accepts file pathnames as-is. Normally the + * filesystem is really a shell which doesn't yet have any mount points + * established and so its 'pathInFilesystem' routine always fails. + * However, for safety, Tcl calls 'Tcl_FSMountsChanged' each time a + * filesystem is registered or unregistered. * - * (2) when additional mount points are established inside any existing - * filesystem (except the native fs) + * (2) An additional mount point is established inside an existing + * filesystem (except for the native file system; see note below). * - * (3) when any filesystem (except the native fs) changes the list of - * available volumes. + * (3) A filesystem changes the list of available volumes (except for the + * native file system; see note below). * - * (4) when the mapping from a string representation of a file to a full, - * normalized path changes. For example, if 'env(HOME)' is modified, then - * any path containing '~' will map to a different filesystem location. - * Therefore all such paths need to have their internal representation - * invalidated. + * (4) The mapping from a string representation of a file to a full, + * normalized pathname changes. For example, if 'env(HOME)' is modified, + * then any pathname containing '~' maps to a different item, possibly in + * a different filesystem. * - * Tcl has no control over (2) and (3), so any registered filesystem must - * make sure it calls this function when those situations occur. + * Tcl has no control over (2) and (3), so each registered filesystem must + * call Tcl_FSMountsChnaged in each of those circumstances. * - * (Note: the reason for the exception in 2,3 for the native filesystem - * is that the native filesystem by default claims all unknown files even - * if it really doesn't understand them or if they don't exist). + * The reason for the exception in 2,3 for the native filesystem is that + * the native filesystem claims every file without determining whether + * whether the file exists, or even whether the pathname makes sense. * *---------------------------------------------------------------------- */ @@ -1291,16 +1232,15 @@ Tcl_FSMountsChanged( const Tcl_Filesystem *fsPtr) { /* - * We currently don't do anything with this parameter. We could in the - * future only invalidate files for this filesystem or otherwise take more - * advanced action. + * fsPtr is currently unused. In the future it might invalidate files for + * a particular filesystem, or take some other more advanced action. */ (void)fsPtr; /* - * Increment the filesystem epoch counter, since existing paths might now - * belong to different filesystems. + * Increment the filesystem epoch to invalidate every existing cached + * internal representation. */ Tcl_MutexLock(&filesystemMutex); @@ -1315,13 +1255,11 @@ Tcl_FSMountsChanged( * * Tcl_FSData -- * - * Retrieve the clientData field for the filesystem given, or NULL if - * that filesystem is not registered. + * Retrieves the clientData member of the given filesystem. * * Results: - * A clientData value, or NULL. Note that if the filesystem was - * registered with a NULL clientData field, this function will return - * that NULL value. + * A clientData value, or NULL if the given filesystem is not registered. + * The clientData value itself may also be NULL. * * Side effects: * None. @@ -1331,15 +1269,14 @@ Tcl_FSMountsChanged( ClientData Tcl_FSData( - const Tcl_Filesystem *fsPtr) /* The filesystem record to query. */ + const Tcl_Filesystem *fsPtr) /* The filesystem to find in the list of + * registered filesystems. */ { ClientData retVal = NULL; FilesystemRecord *fsRecPtr = FsGetFirstFilesystem(); /* - * Traverse the list of filesystems look for a particular one. If found, - * return that filesystem's clientData (originally provided when calling - * Tcl_FSRegister). + * Find the filesystem in and retrieve its clientData. */ while ((retVal == NULL) && (fsRecPtr != NULL)) { @@ -1357,27 +1294,24 @@ Tcl_FSData( * * TclFSNormalizeToUniquePath -- * - * Takes a path specification containing no ../, ./ sequences, and - * converts it into a unique path for the given platform. On Unix, this - * means the path must be free of symbolic links/aliases, and on Windows - * it means we want the long form, with that long form's case-dependence - * (which gives us a unique, case-dependent path). + * Converts the given pathname, containing no ../, ./ components, into a + * unique pathname for the given platform. On Unix the resulting pathname + * is free of symbolic links/aliases, and on Windows it is the long + * case-preserving form. + * * * Results: - * The pathPtr is modified in place. The return value is the last byte - * offset which was recognised in the path string. + * Stores the resulting pathname in pathPtr and returns the offset of the + * last byte processed in pathPtr. * * Side effects: * None (beyond the memory allocation for the result). * * Special notes: * If the filesystem-specific normalizePathProcs can re-introduce ../, ./ - * sequences into the path, then this function will not return the - * correct result. This may be possible with symbolic links on unix. + * components into the pathname, this function does not return the correct + * result. This may be possible with symbolic links on unix. * - * Important assumption: if startAt is non-zero, it must point to a - * directory separator that we know exists and is already normalized (so - * it is important not to point to the char just after the separator). * *--------------------------------------------------------------------------- */ @@ -1385,8 +1319,13 @@ Tcl_FSData( int TclFSNormalizeToUniquePath( Tcl_Interp *interp, /* Used for error messages. */ - Tcl_Obj *pathPtr, /* The path to normalize in place. */ - int startAt) /* Start at this char-offset. */ + Tcl_Obj *pathPtr, /* An Pathname to normalize in-place. Must be + * unshared. */ + int startAt) /* Offset the string of pathPtr to start at. + * Must either be 0 or offset of a directory + * separator at the end of a pathname part that + * is already normalized, I.e. not the index of + * the byte just after the separator. */ { FilesystemRecord *fsRecPtr, *firstFsRecPtr; @@ -1395,10 +1334,10 @@ TclFSNormalizeToUniquePath( const char *path; /* - * Paths starting with a UNC prefix whose final character is a colon - * are reserved for VFS use. These names can not conflict with real - * UNC paths per https://msdn.microsoft.com/en-us/library/gg465305.aspx - * and rfc3986's definition of reg-name. + * Pathnames starting with a UNC prefix and ending with a colon character + * are reserved for VFS use. These names can not conflict with real UNC + * pathnames per https://msdn.microsoft.com/en-us/library/gg465305.aspx and + * rfc3986's definition of reg-name. * * We check these first to avoid useless calls to the native filesystem's * normalizePathProc. @@ -1416,7 +1355,7 @@ TclFSNormalizeToUniquePath( } /* - * Call each of the "normalise path" functions in succession. + * Call the the normalizePathProc routine of each registered filesystem. */ firstFsRecPtr = FsGetFirstFilesystem(); @@ -1425,7 +1364,7 @@ TclFSNormalizeToUniquePath( if (!isVfsPath) { /* - * If we have a native filesystem handler, we call it first. This is + * Find and call the native filesystem handler first if there is one * because the root of Tcl's filesystem is always a native filesystem * (i.e., '/' on unix is native). */ @@ -1436,8 +1375,8 @@ TclFSNormalizeToUniquePath( } /* - * TODO: Assume that we always find the native file system; it should - * always be there... + * TODO: Always call the normalizePathProc here because it should + * always exist. */ if (fsRecPtr->fsPtr->normalizePathProc != NULL) { @@ -1449,11 +1388,10 @@ TclFSNormalizeToUniquePath( } for (fsRecPtr=firstFsRecPtr; fsRecPtr!=NULL; fsRecPtr=fsRecPtr->nextPtr) { - /* - * Skip the native system next time through. - */ - if (fsRecPtr->fsPtr == &tclNativeFilesystem) { + /* + * Skip the native system this time through. + */ continue; } @@ -1463,7 +1401,7 @@ TclFSNormalizeToUniquePath( } /* - * We could add an efficiency check like this: + * This efficiency check could be added: * if (retVal == length-of(pathPtr)) {break;} * but there's not much benefit. */ @@ -1478,26 +1416,27 @@ TclFSNormalizeToUniquePath( * * TclGetOpenMode -- * - * This routine is an obsolete, limited version of TclGetOpenModeEx() - * below. It exists only to satisfy any extensions imprudently using it - * via Tcl's internal stubs table. + * Obsolete. A limited version of TclGetOpenModeEx() which exists only to + * satisfy any extensions imprudently using it via Tcl's internal stubs + * table. * * Results: - * Same as TclGetOpenModeEx(). + * See TclGetOpenModeEx(). * * Side effects: - * Same as TclGetOpenModeEx(). + * See TclGetOpenModeEx(). * *--------------------------------------------------------------------------- */ int TclGetOpenMode( - Tcl_Interp *interp, /* Interpreter to use for error reporting - - * may be NULL. */ - const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */ - int *seekFlagPtr) /* Set this to 1 if the caller should seek to - * EOF during the opening of the file. */ + Tcl_Interp *interp, /* Interpreter to use for error reporting. May + * be NULL. */ + const char *modeString, /* e.g. "r+" or "RDONLY CREAT". */ + int *seekFlagPtr) /* Sets this to 1 to tell the caller to seek to + EOF after opening the file, and + * 0 otherwise. */ { int binary = 0; return TclGetOpenModeEx(interp, modeString, seekFlagPtr, &binary); @@ -1508,46 +1447,44 @@ TclGetOpenMode( * * TclGetOpenModeEx -- * - * Computes a POSIX mode mask for opening a file, from a given string, - * and also sets flags to indicate whether the caller should seek to EOF - * after opening the file, and whether the caller should configure the - * channel for binary data. + * Computes a POSIX mode mask for opening a file. * * Results: - * On success, returns mode to pass to "open". If an error occurs, the - * return value is -1 and if interp is not NULL, sets interp's result - * object to an error message. + * The mode to pass to "open", or -1 if an error occurs. * * Side effects: - * Sets the integer referenced by seekFlagPtr to 1 to tell the caller to - * seek to EOF after opening the file, or to 0 otherwise. Sets the - * integer referenced by binaryPtr to 1 to tell the caller to seek to - * configure the channel for binary data, or to 0 otherwise. + * Sets *seekFlagPtr to 1 to tell the caller to + * seek to EOF after opening the file, or to 0 otherwise. + * + * Sets *binaryPtr to 1 to tell the caller to configure the channel as a + * binary channel, or to 0 otherwise. + * + * If there is an error and interp is not NULL, sets interpreter result to + * an error message. * * Special note: - * This code is based on a prototype implementation contributed by Mark - * Diekhans. + * Based on a prototype implementation contributed by Mark Diekhans. * *--------------------------------------------------------------------------- */ int TclGetOpenModeEx( - Tcl_Interp *interp, /* Interpreter to use for error reporting - - * may be NULL. */ + Tcl_Interp *interp, /* Interpreter, possibly NULL, to use for + * error reporting. */ const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */ - int *seekFlagPtr, /* Set this to 1 if the caller should seek to - * EOF during the opening of the file. */ - int *binaryPtr) /* Set this to 1 if the caller should - * configure the opened channel for binary - * operations. */ + int *seekFlagPtr, /* Sets this to 1 to tell the the caller to seek to + * EOF after opening the file, and 0 otherwise. */ + int *binaryPtr) /* Sets this to 1 to tell the caller to + * configure the channel for binary + * operations after opening the file. */ { int mode, modeArgc, c, i, gotRW; const char **modeArgv, *flag; #define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR) /* - * Check for the simpler fopen-like access modes (e.g., "r"). They are + * Check for the simpler fopen-like access modes like "r" which are * distinguished from the POSIX access modes by the presence of a * lower-case first letter. */ @@ -1557,8 +1494,7 @@ TclGetOpenModeEx( mode = 0; /* - * Guard against international characters before using byte oriented - * routines. + * Guard against wide characters before using byte-oriented routines. */ if (!(modeString[0] & 0x80) @@ -1572,7 +1508,7 @@ TclGetOpenModeEx( break; case 'a': /* - * Added O_APPEND for proper automatic seek-to-end-on-write by the + * Add O_APPEND for proper automatic seek-to-end-on-write by the * OS. [Bug 680143] */ @@ -1590,8 +1526,8 @@ TclGetOpenModeEx( switch (modeString[i++]) { case '+': /* - * Must remove the O_APPEND flag so that the seek command - * works. [Bug 1773127] + * Remove O_APPEND so that the seek command works. [Bug + * 1773127] */ mode &= ~(O_RDONLY|O_WRONLY|O_APPEND); @@ -1620,11 +1556,9 @@ TclGetOpenModeEx( } /* - * The access modes are specified using a list of POSIX modes such as - * O_CREAT. + * The access modes are specified as a list of POSIX modes like O_CREAT. * - * IMPORTANT NOTE: We rely on Tcl_SplitList working correctly when a NULL - * interpreter is passed in. + * Tcl_SplitList must work correctly when interp is NULL. */ if (Tcl_SplitList(interp, modeString, &modeArgc, &modeArgv) != TCL_OK) { @@ -1719,8 +1653,10 @@ TclGetOpenModeEx( * * Tcl_FSEvalFile, Tcl_FSEvalFileEx, TclNREvalFile -- * - * Read in a file and process the entire file as one gigantic Tcl - * command. Tcl_FSEvalFile is Tcl_FSEvalFileEx without encoding argument. + * Reads a file and evaluates it as a script. + * + * Tcl_FSEvalFile is Tcl_FSEvalFileEx without the encoding argument. + * * TclNREvalFile is an NRE-enabled version of Tcl_FSEvalFileEx. * * Results: @@ -1728,29 +1664,31 @@ TclGetOpenModeEx( * file or an error indicating why the file couldn't be read. * * Side effects: - * Depends on the commands in the file. During the evaluation of the - * contents of the file, iPtr->scriptFile is made to point to pathPtr - * (the old value is cached and replaced when this function returns). + * Arbitrary, depending on the contents of the script. While the script + * is evaluated iPtr->scriptFile is a reference to pathPtr, and after the + * evaluation completes, has its original value restored again. * *---------------------------------------------------------------------- */ int Tcl_FSEvalFile( - Tcl_Interp *interp, /* Interpreter in which to process file. */ - Tcl_Obj *pathPtr) /* Path of file to process. Tilde-substitution - * will be performed on this name. */ + Tcl_Interp *interp, /* Interpreter that evaluates the script. */ + Tcl_Obj *pathPtr) /* Pathname of file containing the script. + * Tilde-substitution is performed on this + * pathname. */ { return Tcl_FSEvalFileEx(interp, pathPtr, NULL); } int Tcl_FSEvalFileEx( - Tcl_Interp *interp, /* Interpreter in which to process file. */ - Tcl_Obj *pathPtr, /* Path of file to process. Tilde-substitution - * will be performed on this name. */ - const char *encodingName) /* If non-NULL, then use this encoding for the - * file. NULL means use the system encoding. */ + Tcl_Interp *interp, /* Interpreter that evaluates the script. */ + Tcl_Obj *pathPtr, /* Pathname of the file to process. + * Tilde-substitution is performed on this + * pathname. */ + const char *encodingName) /* Either the name of an encoding or NULL to + use the system encoding. */ { int length, result = TCL_ERROR; Tcl_StatBuf statBuf; @@ -1780,15 +1718,16 @@ Tcl_FSEvalFileEx( } /* - * The eofchar is \32 (^Z). This is the usual on Windows, but we effect - * this cross-platform to allow for scripted documents. [Bug: 2040] + * The eof character is \32 (^Z). This is standard on Windows, and Tcl + * uses it on every platform to allow for scripted documents. [Bug: 2040] */ Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}"); /* - * If the encoding is specified, set it for the channel. Else don't touch - * it (and use the system encoding) Report error on unknown encoding. + * If the encoding is specified, set the channel to that encoding. + * Otherwise don't touch it, leaving things up to the system encoding. If + * the encoding is unknown report an error. */ if (encodingName != NULL) { @@ -1803,8 +1742,7 @@ Tcl_FSEvalFileEx( Tcl_IncrRefCount(objPtr); /* - * Try to read first character of stream, so we can check for utf-8 BOM to - * be handled especially. + * Read first character of stream to check for utf-8 BOM */ if (Tcl_ReadChars(chan, objPtr, 1, 0) == TCL_IO_FAILURE) { @@ -1817,8 +1755,8 @@ Tcl_FSEvalFileEx( string = Tcl_GetString(objPtr); /* - * If first character is not a BOM, append the remaining characters, - * otherwise replace them. [Bug 3466099] + * If first character is not a BOM, append the remaining characters. + * Otherwise, replace them. [Bug 3466099] */ if (Tcl_ReadChars(chan, objPtr, -1, @@ -1841,16 +1779,16 @@ Tcl_FSEvalFileEx( string = TclGetStringFromObj(objPtr, &length); /* - * TIP #280 Force the evaluator to open a frame for a sourced file. + * TIP #280: Open a frame for the evaluated script. */ iPtr->evalFlags |= TCL_EVAL_FILE; result = TclEvalEx(interp, string, length, 0, 1, NULL, string); /* - * Now we have to be careful; the script may have changed the - * iPtr->scriptFile value, so we must reset it without assuming it still - * points to 'pathPtr'. + * Restore the original iPtr->scriptFile value, but because the value may + * have hanged during evaluation, don't assume it currently points to + * pathPtr. */ if (iPtr->scriptFile != NULL) { @@ -1862,7 +1800,7 @@ Tcl_FSEvalFileEx( result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { /* - * Record information telling where the error occurred. + * Record information about where the error occurred. */ const char *pathString = TclGetStringFromObj(pathPtr, &length); @@ -1882,11 +1820,12 @@ Tcl_FSEvalFileEx( int TclNREvalFile( - Tcl_Interp *interp, /* Interpreter in which to process file. */ - Tcl_Obj *pathPtr, /* Path of file to process. Tilde-substitution - * will be performed on this name. */ - const char *encodingName) /* If non-NULL, then use this encoding for the - * file. NULL means use the system encoding. */ + Tcl_Interp *interp, /* Interpreter in which to evaluate the script. */ + Tcl_Obj *pathPtr, /* Pathname of a file containing the script to + * evaluate. Tilde-substitution is performed on + * this pathname. */ + const char *encodingName) /* The name of an encoding to use, or NULL to + * use the system encoding. */ { Tcl_StatBuf statBuf; Tcl_Obj *oldScriptFile, *objPtr; @@ -1915,15 +1854,16 @@ TclNREvalFile( TclPkgFileSeen(interp, Tcl_GetString(pathPtr)); /* - * The eofchar is \32 (^Z). This is the usual on Windows, but we effect - * this cross-platform to allow for scripted documents. [Bug: 2040] + * The eof character is \32 (^Z). This is standard on Windows, and Tcl + * uses it on every platform to allow for scripted documents. [Bug: 2040] */ Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}"); /* - * If the encoding is specified, set it for the channel. Else don't touch - * it (and use the system encoding) Report error on unknown encoding. + * If the encoding is specified, set the channel to that encoding. + * Otherwise don't touch it, leaving things up to the system encoding. If + * the encoding is unknown report an error. */ if (encodingName != NULL) { @@ -1938,8 +1878,7 @@ TclNREvalFile( Tcl_IncrRefCount(objPtr); /* - * Try to read first character of stream, so we can check for utf-8 BOM to - * be handled especially. + * Read first character of stream to check for utf-8 BOM */ if (Tcl_ReadChars(chan, objPtr, 1, 0) == TCL_IO_FAILURE) { @@ -1953,8 +1892,8 @@ TclNREvalFile( string = Tcl_GetString(objPtr); /* - * If first character is not a BOM, append the remaining characters, - * otherwise replace them. [Bug 3466099] + * If first character is not a BOM, append the remaining characters. + * Otherwise, replace them. [Bug 3466099] */ if (Tcl_ReadChars(chan, objPtr, -1, @@ -1978,7 +1917,7 @@ TclNREvalFile( Tcl_IncrRefCount(iPtr->scriptFile); /* - * TIP #280: Force the evaluator to open a frame for a sourced file. + * TIP #280: Open a frame for the evaluated script. */ iPtr->evalFlags |= TCL_EVAL_FILE; @@ -1999,9 +1938,9 @@ EvalFileCallback( Tcl_Obj *objPtr = data[2]; /* - * Now we have to be careful; the script may have changed the - * iPtr->scriptFile value, so we must reset it without assuming it still - * points to 'pathPtr'. + * Restore the original iPtr->scriptFile value, but because the value may + * have hanged during evaluation, don't assume it currently points to + * pathPtr. */ if (iPtr->scriptFile != NULL) { @@ -2013,7 +1952,7 @@ EvalFileCallback( result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { /* - * Record information telling where the error occurred. + * Record information about where the error occurred. */ int length; @@ -2036,16 +1975,15 @@ EvalFileCallback( * * Tcl_GetErrno -- * - * Gets the current value of the Tcl error code variable. This is - * currently the global variable "errno" but could in the future change + * Currently the global variable "errno", but could in the future change * to something else. * * Results: - * The value of the Tcl error code variable. + * The current Tcl error number. * * Side effects: - * None. Note that the value of the Tcl error code variable is UNDEFINED - * if a call to Tcl_SetErrno did not precede this call. + * None. The value of the Tcl error code variable is only defined if it + * was set by a previous call to Tcl_SetErrno. * *---------------------------------------------------------------------- */ @@ -2054,8 +1992,8 @@ int Tcl_GetErrno(void) { /* - * On some platforms, errno is really a thread local (implemented by the C - * library). + * On some platforms errno is thread-local, as implemented by the C + * library. */ return errno; @@ -2066,15 +2004,15 @@ Tcl_GetErrno(void) * * Tcl_SetErrno -- * - * Sets the Tcl error code variable to the supplied value. On some saner - * platforms this is actually a thread-local (this is implemented in the - * C library) but this is *really* unsafe to assume! + * Sets the Tcl error code to the given value. On some saner platforms + * this is implemented in the C library as a thread-local value , but this + * is *really* unsafe to assume! * * Results: * None. * * Side effects: - * Modifies the value of the Tcl error code variable. + * Modifies the the Tcl error code value. * *---------------------------------------------------------------------- */ @@ -2084,8 +2022,8 @@ Tcl_SetErrno( int err) /* The new value. */ { /* - * On some platforms, errno is really a thread local (implemented by the C - * library). + * On some platforms, errno is implemented by the C library as a thread + * local value */ errno = err; @@ -2096,24 +2034,21 @@ Tcl_SetErrno( * * Tcl_PosixError -- * - * This function is typically called after UNIX kernel calls return - * errors. It stores machine-readable information about the error in - * errorCode field of interp and returns an information string for the - * caller's use. + * Typically called after a UNIX kernel call returns an error. Sets the + * interpreter errorCode to machine-parsable information about the error. * * Results: - * The return value is a human-readable string describing the error. + * A human-readable sring describing the error. * * Side effects: - * The errorCode field of the interp is set. + * Sets the errorCode value of the interpreter. * *---------------------------------------------------------------------- */ const char * Tcl_PosixError( - Tcl_Interp *interp) /* Interpreter whose errorCode field is to be - * set. */ + Tcl_Interp *interp) /* Interpreter to set the errorCode of */ { const char *id, *msg; @@ -2129,11 +2064,10 @@ Tcl_PosixError( *---------------------------------------------------------------------- * * Tcl_FSStat -- + * Calls 'statProc' of the filesystem corresponding to pathPtr. * - * This function replaces the library version of stat and lsat. + * Replaces the standard library routines stat. * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. * * Results: * See stat documentation. @@ -2146,8 +2080,10 @@ Tcl_PosixError( int Tcl_FSStat( - Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */ - Tcl_StatBuf *buf) /* Filled with results of stat call. */ + Tcl_Obj *pathPtr, /* Pathname of the file to call stat on (in + * current CP). */ + Tcl_StatBuf *buf) /* A buffer to hold the results of the call to + * stat. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2162,11 +2098,11 @@ Tcl_FSStat( *---------------------------------------------------------------------- * * Tcl_FSLstat -- + * Calls the 'lstatProc' of the filesystem corresponding to pathPtr. * - * This function replaces the library version of lstat. The appropriate - * function for the filesystem to which pathPtr belongs will be called. - * If no 'lstat' function is listed, but a 'stat' function is, then Tcl - * will fall back on the stat function. + * Replaces the library version of lstat. If the filesystem doesn't + * provide lstatProc but does provide statProc, Tcl falls back to + * statProc. * * Results: * See lstat documentation. @@ -2179,8 +2115,9 @@ Tcl_FSStat( int Tcl_FSLstat( - Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */ - Tcl_StatBuf *buf) /* Filled with results of stat call. */ + Tcl_Obj *pathPtr, /* Pathname of the file to call stat on (in + current CP). */ + Tcl_StatBuf *buf) /* Filled with results of that call to stat. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2201,8 +2138,9 @@ Tcl_FSLstat( * * Tcl_FSAccess -- * - * This function replaces the library version of access. The appropriate - * function for the filesystem to which pathPtr belongs will be called. + * Calls 'accessProc' of the filesystem corresponding to pathPtr. + * + * Replaces the library version of access. * * Results: * See access documentation. @@ -2215,7 +2153,7 @@ Tcl_FSLstat( int Tcl_FSAccess( - Tcl_Obj *pathPtr, /* Path of file to access (in current CP). */ + Tcl_Obj *pathPtr, /* Pathname of file to access (in current CP). */ int mode) /* Permission setting. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2232,38 +2170,36 @@ Tcl_FSAccess( * * Tcl_FSOpenFileChannel -- * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. + * Calls 'openfileChannelProc' of the filesystem corresponding to + * pathPtr. * * Results: - * The new channel or NULL, if the named file could not be opened. + * The new channel, or NULL if the named file could not be opened. * * Side effects: - * May open the channel and may cause creation of a file on the file - * system. + * Opens a channel, possibly creating the corresponding the file on the + * filesystem. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_FSOpenFileChannel( - Tcl_Interp *interp, /* Interpreter for error reporting; can be - * NULL. */ - Tcl_Obj *pathPtr, /* Name of file to open. */ + Tcl_Interp *interp, /* Interpreter for error reporting, or NULL */ + Tcl_Obj *pathPtr, /* Pathname of file to open. */ const char *modeString, /* A list of POSIX open modes or a string such * as "rw". */ - int permissions) /* If the open involves creating a file, with - * what modes to create it? */ + int permissions) /* What modes to use if opening the file + involves creating it. */ { const Tcl_Filesystem *fsPtr; Tcl_Channel retVal = NULL; - /* - * We need this just to ensure we return the correct error messages under - * some circumstances. - */ if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) { + /* + * Return the correct error message. + */ return NULL; } @@ -2272,8 +2208,8 @@ Tcl_FSOpenFileChannel( int mode, seekFlag, binary; /* - * Parse the mode, picking up whether we want to seek to start with - * and/or set the channel automatically into binary mode. + * Parse the mode to determine whether to seek at the outset + * and/or set the channel into binary mode. */ mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary); @@ -2282,7 +2218,7 @@ Tcl_FSOpenFileChannel( } /* - * Do the actual open() call. + * Open the file. */ retVal = fsPtr->openFileChannelProc(interp, pathPtr, mode, @@ -2292,7 +2228,7 @@ Tcl_FSOpenFileChannel( } /* - * Apply appropriate flags parsed out above. + * Seek and/or set binary mode as determined above. */ if (seekFlag && Tcl_Seek(retVal, (Tcl_WideInt) 0, SEEK_END) @@ -2329,8 +2265,10 @@ Tcl_FSOpenFileChannel( * * Tcl_FSUtime -- * - * This function replaces the library version of utime. The appropriate - * function for the filesystem to which pathPtr belongs will be called. + * Calls 'uTimeProc' of the filesystem corresponding to the given + * pathname. + * + * Replaces the library version of utime. * * Results: * See utime documentation. @@ -2343,9 +2281,8 @@ Tcl_FSOpenFileChannel( int Tcl_FSUtime( - Tcl_Obj *pathPtr, /* File to change access/modification - * times. */ - struct utimbuf *tval) /* Structure containing access/modification + Tcl_Obj *pathPtr, /* Pathaname of file to call uTimeProc on */ + struct utimbuf *tval) /* Specifies the access/modification * times to use. Should not be modified. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2362,11 +2299,10 @@ Tcl_FSUtime( * * NativeFileAttrStrings -- * - * This function implements the platform dependent 'file attributes' - * subcommand, for the native filesystem, for listing the set of possible - * attribute strings. This function is part of Tcl's native filesystem - * support, and is placed here because it is shared by Unix and Windows - * code. + * Implements the platform-dependent 'file attributes' subcommand for the + * native filesystem, for listing the set of possible attribute strings. + * Part of Tcl's native filesystem support. Placed here because it is used + * under both Unix and Windows. * * Results: * An array of strings @@ -2390,16 +2326,18 @@ NativeFileAttrStrings( * * NativeFileAttrsGet -- * - * This function implements the platform dependent 'file attributes' - * subcommand, for the native filesystem, for 'get' operations. This - * function is part of Tcl's native filesystem support, and is placed - * here because it is shared by Unix and Windows code. + * Implements the platform-dependent 'file attributes' subcommand for the + * native filesystem for 'get' operations. Part of Tcl's native + * filesystem support. Defined here because it is used under both Unix + * and Windows. * * Results: - * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK - * was returned) is likely to have a refCount of zero. Either way we must - * either store it somewhere (e.g. the Tcl result), or Incr/Decr its - * refCount to ensure it is properly freed. + * Standard Tcl return code. + * + * If there was no error, stores in objPtrRef a pointer to a new object + * having a refCount of zero and holding the result. The caller should + * store it somewhere, e.g. as the Tcl result, or decrement its refCount + * to free it. * * Side effects: * None. @@ -2411,8 +2349,8 @@ static int NativeFileAttrsGet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ - Tcl_Obj *pathPtr, /* path of file we are operating on. */ - Tcl_Obj **objPtrRef) /* for output. */ + Tcl_Obj *pathPtr, /* Pathname of the file */ + Tcl_Obj **objPtrRef) /* Where to store the a pointer to the result. */ { return tclpFileAttrProcs[index].getProc(interp, index, pathPtr,objPtrRef); } @@ -2422,13 +2360,13 @@ NativeFileAttrsGet( * * NativeFileAttrsSet -- * - * This function implements the platform dependent 'file attributes' - * subcommand, for the native filesystem, for 'set' operations. This - * function is part of Tcl's native filesystem support, and is placed - * here because it is shared by Unix and Windows code. + * Implements the platform-dependent 'file attributes' subcommand for the + * native filesystem for 'set' operations. A part of Tcl's native + * filesystem support, it is defined here because it is used under both + * Unix and Windows. * * Results: - * Standard Tcl return code. + * A standard Tcl return code. * * Side effects: * None. @@ -2440,8 +2378,8 @@ static int NativeFileAttrsSet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ - Tcl_Obj *pathPtr, /* path of file we are operating on. */ - Tcl_Obj *objPtr) /* set to this value. */ + Tcl_Obj *pathPtr, /* Pathname of the file */ + Tcl_Obj *objPtr) /* The value to set. */ { return tclpFileAttrProcs[index].setProc(interp, index, pathPtr, objPtr); } @@ -2451,18 +2389,16 @@ NativeFileAttrsSet( * * Tcl_FSFileAttrStrings -- * - * This function implements part of the hookable 'file attributes' - * subcommand. The appropriate function for the filesystem to which - * pathPtr belongs will be called. + * Implements part of the hookable 'file attributes' + * subcommand. + * + * Calls 'fileAttrStringsProc' of the filesystem corresponding to the + * given pathname. * * Results: - * The called function may either return an array of strings, or may - * instead return NULL and place a Tcl list into the given objPtrRef. - * Tcl will take that list and first increment its refCount before using - * it. On completion of that use, Tcl will decrement its refCount. Hence - * if the list should be disposed of by Tcl when done, it should have a - * refCount of zero, and if the list should not be disposed of, the - * filesystem should ensure it retains a refCount on the object. + * Returns an array of strings, or returns NULL and stores in objPtrRef + * a pointer to a new Tcl list having a refCount of zero, and containing + * the file attribute strings. * * Side effects: * None. @@ -2489,11 +2425,13 @@ Tcl_FSFileAttrStrings( * * TclFSFileAttrIndex -- * - * Helper function for converting an attribute name to an index into the + * Given an attribute name, determines the index of the attribute in the * attribute table. * * Results: - * Tcl result code, index written to *indexPtr on result==TCL_OK + * A standard Tcl result code. + * + * If there is no error, stores the index in *indexPtr. * * Side effects: * None. @@ -2503,10 +2441,9 @@ Tcl_FSFileAttrStrings( int TclFSFileAttrIndex( - Tcl_Obj *pathPtr, /* File whose attributes are to be indexed - * into. */ - const char *attributeName, /* The attribute being looked for. */ - int *indexPtr) /* Where to write the found index. */ + Tcl_Obj *pathPtr, /* Pathname of the file. */ + const char *attributeName, /* The name of the attribute. */ + int *indexPtr) /* A place to store the result. */ { Tcl_Obj *listObj = NULL; const char *const *attrTable; @@ -2566,15 +2503,16 @@ TclFSFileAttrIndex( * * Tcl_FSFileAttrsGet -- * - * This function implements read access for the hookable 'file - * attributes' subcommand. The appropriate function for the filesystem to - * which pathPtr belongs will be called. + * Implements read access for the hookable 'file attributes' subcommand. + * + * Calls 'fileAttrsGetProc' of the filesystem corresponding to the given + * pathname. * * Results: - * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK - * was returned) is likely to have a refCount of zero. Either way we must - * either store it somewhere (e.g. the Tcl result), or Incr/Decr its - * refCount to ensure it is properly freed. + * A standard Tcl return code. + * + * On success, stores in objPtrRef a pointer to a new Tcl_Obj having a + * refCount of zero, and containing the result. * * Side effects: * None. @@ -2585,9 +2523,9 @@ TclFSFileAttrIndex( int Tcl_FSFileAttrsGet( Tcl_Interp *interp, /* The interpreter for error reporting. */ - int index, /* index of the attribute command. */ - Tcl_Obj *pathPtr, /* filename we are operating on. */ - Tcl_Obj **objPtrRef) /* for output. */ + int index, /* The index of the attribute command. */ + Tcl_Obj *pathPtr, /* The pathname of the file. */ + Tcl_Obj **objPtrRef) /* A place to store the result. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2603,12 +2541,14 @@ Tcl_FSFileAttrsGet( * * Tcl_FSFileAttrsSet -- * - * This function implements write access for the hookable 'file - * attributes' subcommand. The appropriate function for the filesystem to - * which pathPtr belongs will be called. + * Implements write access for the hookable 'file + * attributes' subcommand. + * + * Calls 'fileAttrsSetProc' for the filesystem corresponding to the given + * pathname. * * Results: - * Standard Tcl return code. + * A standard Tcl return code. * * Side effects: * None. @@ -2619,9 +2559,9 @@ Tcl_FSFileAttrsGet( int Tcl_FSFileAttrsSet( Tcl_Interp *interp, /* The interpreter for error reporting. */ - int index, /* index of the attribute command. */ - Tcl_Obj *pathPtr, /* filename we are operating on. */ - Tcl_Obj *objPtr) /* Input value. */ + int index, /* The index of the attribute command. */ + Tcl_Obj *pathPtr, /* The pathname of the file. */ + Tcl_Obj *objPtr) /* A place to store the result. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2637,33 +2577,25 @@ Tcl_FSFileAttrsSet( * * Tcl_FSGetCwd -- * - * This function replaces the library version of getcwd(). + * Replaces the library version of getcwd(). * - * Most VFS's will *not* implement a 'cwdProc'. Tcl now maintains its own - * record (in a Tcl_Obj) of the cwd, and an attempt is made to synch this - * with the cwd's containing filesystem, if that filesystem provides a - * cwdProc (e.g. the native filesystem). + * Most virtual filesystems do not implement cwdProc. Tcl maintains its + * own record of the current directory which it keeps synchronized with + * the filesystem corresponding to the pathname of the current directory + * if the filesystem provides a cwdProc (the native filesystem does). * - * Note that if Tcl's cwd is not in the native filesystem, then of course - * Tcl's cwd and the native cwd are different: extensions should - * therefore ensure they only access the cwd through this function to - * avoid confusion. - * - * If a global cwdPathPtr already exists, it is cached in the thread's - * private data structures and reference to the cached copy is returned, - * subject to a synchronisation attempt in that cwdPathPtr's fs. - * - * Otherwise, the chain of functions that have been "inserted" into the - * filesystem will be called in succession until either a value other - * than NULL is returned, or the entire list is visited. + * If Tcl's current directory is not in the native filesystem, Tcl's + * current directory and the current directory of the process are + * different. To avoid confusion, extensions should call Tcl_FSGetCwd to + * obtain the current directory from Tcl rather than from the operating + * system. * * Results: - * The result is a pointer to a Tcl_Obj specifying the current directory, - * or NULL if the current directory could not be determined. If NULL is - * returned, an error message is left in the interp's result. + * Returns a pointer to a Tcl_Obj having a refCount of 1 and containing + * the current thread's local copy of the global cwdPathPtr value. * - * The result already has its refCount incremented for the caller. When - * it is no longer needed, that refCount should be decremented. + * Returns NULL if the current directory could not be determined, and + * leaves an error message in the interpreter's result. * * Side effects: * Various objects may be freed and allocated. @@ -2682,9 +2614,10 @@ Tcl_FSGetCwd( Tcl_Obj *retVal = NULL; /* - * We've never been called before, try to find a cwd. Call each of the - * "Tcl_GetCwd" function in succession. A non-NULL return value - * indicates the particular function has succeeded. + * This is the first time this routine has been called. Call + * 'getCwdProc' for each registered filsystems until one returns + * something other than NULL, which is a pointer to the pathname of the + * current directory. */ fsRecPtr = FsGetFirstFilesystem(); @@ -2709,7 +2642,7 @@ Tcl_FSGetCwd( Tcl_Obj *norm; /* - * Looks like a new current directory. + * Found the pathname of the current directory. */ retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd); @@ -2717,15 +2650,15 @@ Tcl_FSGetCwd( norm = TclFSNormalizeAbsolutePath(interp,retVal); if (norm != NULL) { /* - * We found a cwd, which is now in our global storage. We - * must make a copy. Norm already has a refCount of 1. + * Assign to global storage the pathname of the current directory + * and copy it into thread-local storage as well. * - * Threading issue: note that multiple threads at system - * startup could in principle call this function - * simultaneously. They will therefore each set the - * cwdPathPtr independently. That behaviour is a bit - * peculiar, but should be fine. Once we have a cwd, we'll - * always be in the 'else' branch below which is simpler. + * At system startup multiple threads could in principle + * call this function simultaneously, which is a little + * peculiar, but should be fine given the mutex locks in + * FSUPdateCWD. Once some value is assigned to the global + * variable the 'else' branch below is always taken, which + * is simpler. */ FsUpdateCwd(norm, retCd); @@ -2745,29 +2678,27 @@ Tcl_FSGetCwd( } Disclaim(); - /* - * Now the 'cwd' may NOT be normalized, at least on some platforms. - * For the sake of efficiency, we want a completely normalized cwd at - * all times. - * - * Finally, if retVal is NULL, we do not have a cwd, which could be - * problematic. - */ - if (retVal != NULL) { + /* + * On some platforms the pathname of the current directory might + * not be normalized. For efficiency, ensure that it is + * normalized. For the sake of efficiency, we want a completely + * normalized current working directory at all times. + */ + Tcl_Obj *norm = TclFSNormalizeAbsolutePath(interp, retVal); if (norm != NULL) { /* - * We found a cwd, which is now in our global storage. We must - * make a copy. Norm already has a refCount of 1. + * We found a current working directory, which is now in our + * global storage. We must make a copy. Norm already has a + * refCount of 1. * - * Threading issue: note that multiple threads at system - * startup could in principle call this function - * simultaneously. They will therefore each set the cwdPathPtr - * independently. That behaviour is a bit peculiar, but should - * be fine. Once we have a cwd, we'll always be in the 'else' - * branch below which is simpler. + * Threading issue: Multiple threads at system startup could in + * principle call this function simultaneously. They will + * therefore each set the cwdPathPtr independently, which is a + * bit peculiar, but should be fine. Once we have a cwd, we'll + * always be in the 'else' branch below which is simpler. */ ClientData cd = (ClientData) Tcl_FSGetNativePath(norm); @@ -2776,13 +2707,19 @@ Tcl_FSGetCwd( Tcl_DecrRefCount(norm); } Tcl_DecrRefCount(retVal); + } else { + /* + * retVal is NULL. There is no current directory, which could be + * problematic. + */ } } else { /* - * We already have a cwd cached, but we want to give the filesystem it - * is in a chance to check whether that cwd has changed, or is perhaps - * no longer accessible. This allows an error to be thrown if, say, - * the permissions on that directory have changed. + * There is a thread-local value for the pathname of the current + * directory. Give corresponding filesystem a chance update the value + * if it is out-of-date. This allows an error to be thrown if, for + * example, the permissions on the current working directory have + * changed. */ const Tcl_Filesystem *fsPtr = @@ -2790,16 +2727,11 @@ Tcl_FSGetCwd( ClientData retCd = NULL; Tcl_Obj *retVal, *norm; - /* - * If the filesystem couldn't be found, or if no cwd function exists - * for this filesystem, then we simply assume the cached cwd is ok. - * If we do call a cwd, we must watch for errors (if the cwd returns - * NULL). This ensures that, say, on Unix if the permissions of the - * cwd change, 'pwd' does actually throw the correct error in Tcl. - * (This is tested for in the test suite on unix). - */ - if (fsPtr == NULL || fsPtr->getCwdProc == NULL) { + /* + * There is no corresponding filesystem or the filesystem does not + * have a getCwd routine. Just assume current local value is ok. + */ goto cdDidNotChange; } @@ -2831,28 +2763,25 @@ Tcl_FSGetCwd( Tcl_IncrRefCount(retVal); } - /* - * Check if the 'cwd' function returned an error; if so, reset the - * cwd. - */ - if (retVal == NULL) { + /* + * The current directory could not not determined. Reset the + * current direcory to ensure, for example, that 'pwd' does actually + * throw the correct error in Tcl. This is tested for in the test + * suite on unix. + */ + FsUpdateCwd(NULL, NULL); goto cdDidNotChange; } - /* - * Normalize the path. - */ - norm = TclFSNormalizeAbsolutePath(interp, retVal); - /* - * Check whether cwd has changed from the value previously stored in - * cwdPathPtr. Really 'norm' shouldn't be NULL, but we are careful. - */ - if (norm == NULL) { + /* + * 'norm' shouldn't ever be NULL, but we are careful. + */ + /* Do nothing */ if (retCd != NULL) { fsPtr->freeInternalRepProc(retCd); @@ -2860,11 +2789,12 @@ Tcl_FSGetCwd( } else if (norm == tsdPtr->cwdPathPtr) { goto cdEqual; } else { - /* - * Note that both 'norm' and 'tsdPtr->cwdPathPtr' are normalized - * paths. Therefore we can be more efficient than calling - * 'Tcl_FSEqualPaths', and in addition avoid a nasty infinite loop - * bug when trying to normalize tsdPtr->cwdPathPtr. + /* + * Determine whether the filesystem's answer is the same as the + * cached local value. Since both 'norm' and 'tsdPtr->cwdPathPtr' + * are normalized pathnames, do something more efficient than + * calling 'Tcl_FSEqualPaths', and in addition avoid a nasty + * infinite loop bug when trying to normalize tsdPtr->cwdPathPtr. */ int len1, len2; @@ -2874,18 +2804,20 @@ Tcl_FSGetCwd( str2 = TclGetStringFromObj(norm, &len2); if ((len1 == len2) && (strcmp(str1, str2) == 0)) { /* - * If the paths were equal, we can be more efficient and - * retain the old path object which will probably already be - * shared. In this case we can simply free the normalized path - * we just calculated. + * The pathname values are equal so retain the old pathname + * object which is probably already shared and free the + * normalized pathname that was just produced. */ - cdEqual: Tcl_DecrRefCount(norm); if (retCd != NULL) { fsPtr->freeInternalRepProc(retCd); } } else { + /* + * The pathname of the current directory is not the same as + * this thread's local cached value. Replace the local value. + */ FsUpdateCwd(norm, retCd); Tcl_DecrRefCount(norm); } @@ -2906,17 +2838,19 @@ Tcl_FSGetCwd( * * Tcl_FSChdir -- * - * This function replaces the library version of chdir(). + * Replaces the library version of chdir(). * - * The path is normalized and then passed to the filesystem which claims - * it. + * Calls 'chdirProc' of the filesystem that corresponds to the given + * pathname. * * Results: - * See chdir() documentation. If successful, we keep a record of the - * successful path in cwdPathPtr for subsequent calls to getcwd. + * See chdir() documentation. * * Side effects: - * See chdir() documentation. The global cwdPathPtr may change value. + * See chdir() documentation. + * + * On success stores in cwdPathPtr the pathname of the new current + * directory. * *---------------------------------------------------------------------- */ @@ -2941,70 +2875,46 @@ Tcl_FSChdir( if (fsPtr != NULL) { if (fsPtr->chdirProc != NULL) { /* - * If this fails, an appropriate errno will have been stored using - * 'Tcl_SetErrno()'. + * If this fails Tcl_SetErrno() has already been called. */ retVal = fsPtr->chdirProc(pathPtr); } else { /* - * Fallback on stat-based implementation. + * Fallback to stat-based implementation. */ Tcl_StatBuf buf; - /* - * If the file can be stat'ed and is a directory and is readable, - * then we can chdir. If any of these actions fail, then - * 'Tcl_SetErrno()' should automatically have been called to set - * an appropriate error code. - */ - if ((Tcl_FSStat(pathPtr, &buf) == 0) && (S_ISDIR(buf.st_mode)) && (Tcl_FSAccess(pathPtr, R_OK) == 0)) { /* - * We allow the chdir. + * stat was successful, and the file is a directory and is + * readable. Can proceed to change the current directory. */ retVal = 0; + } else { + /* + * 'Tcl_SetErrno()' has already been called. + */ } } } else { Tcl_SetErrno(ENOENT); } - /* - * The cwd changed, or an error was thrown. If an error was thrown, we can - * just continue (and that will report the error to the user). If there - * was no error we must assume that the cwd was actually changed to the - * normalized value we calculated above, and we must therefore cache that - * information. - * - * If the filesystem in question has a getCwdProc, then the correct logic - * which performs the part below is already part of the Tcl_FSGetCwd() - * call, so no need to replicate it again. This will have a side effect - * though. The private authoritative representation of the current working - * directory stored in cwdPathPtr in static memory will be out-of-sync - * with the real OS-maintained value. The first call to Tcl_FSGetCwd will - * however recalculate the private copy to match the OS-value so - * everything will work right. - * - * However, if there is no getCwdProc, then we _must_ update our private - * storage of the cwd, since this is the only opportunity to do that! - * - * Note: We currently call this block of code irrespective of whether - * there was a getCwdProc or not, but the code should all in principle - * work if we only call this block if fsPtr->getCwdProc == NULL. - */ - if (retVal == 0) { + + /* Assume that the cwd was actually changed to the normalized value + * just calculated, and cache that information. */ + /* - * Note that this normalized path may be different to what we found - * above (or at least a different object), if the filesystem epoch - * changed recently. This can actually happen with scripted documents - * very easily. Therefore we ask for the normalized path again (the - * correct value will have been cached as a result of the - * Tcl_FSGetFileSystemForPath call above anyway). + * If the filesystem epoch changed recently, the normalized pathname or + * its internal handle may be different from what was found above. + * This can easily be the case with scripted documents . Therefore get + * the normalized pathname again. The correct value will have been + * cached as a result of the Tcl_FSGetFileSystemForPath call, above. */ Tcl_Obj *normDirName = Tcl_FSGetNormalizedPath(NULL, pathPtr); @@ -3016,45 +2926,60 @@ Tcl_FSChdir( } if (fsPtr == &tclNativeFilesystem) { - /* - * For the native filesystem, we keep a cache of the native - * representation of the cwd. But, we want to do that for the - * exact format that is returned by 'getcwd' (so that we can later - * compare the two representations for equality), which might not - * be exactly the same char-string as the native representation of - * the fully normalized path (e.g. on Windows there's a - * forward-slash vs backslash difference). Hence we ask for this - * again here. On Unix it might actually be true that we always - * have the correct form in the native rep in which case we could - * simply use: - * cd = Tcl_FSGetNativePath(pathPtr); - * instead. This should be examined by someone on Unix. - */ - ClientData cd; ClientData oldcd = tsdPtr->cwdClientData; /* - * Assumption we are using a filesystem version 2. + * Assume that the native filesystem has a getCwdProc and that it + * is at version 2. */ TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2 *) fsPtr->getCwdProc; cd = proc2(oldcd); if (cd != oldcd) { + /* + * Call getCwdProc() and store the resulting internal handle to + * compare things with it later. This might might not be + * exactly the same string as that of the fully normalized + * pathname. For example, for the Windows internal handle the + * separator is the backslash character. On Unix it might well + * be true that the internal handle is the fully normalized + * pathname and one could simply use: + * cd = Tcl_FSGetNativePath(pathPtr); + * but this can't be guaranteed in the general case. In fact, + * the internal handle could be any value the filesystem + * decides to use to identify a node. + */ + FsUpdateCwd(normDirName, cd); - } + } } else { + /* + * Tcl_FSGetCwd() synchronizes the file-global cwdPathPtr if + * needed. However, if there is no 'getCwdProc', cwdPathPtr must be + * updated right now because there won't be another chance. This + * block of code is currently executed whether or not the + * filesystem provides a getCwdProc, but it should in principle + * work to only call this block if fsPtr->getCwdProc == NULL. + */ + FsUpdateCwd(normDirName, NULL); } - /* - * If the filesystem changed between old and new cwd - * force filesystem refresh on path objects. - */ if (oldFsPtr != NULL && fsPtr != oldFsPtr) { + /* + * The filesystem of the current directory is not the same as the + * filesystem of the previous current directory. Invalidate All + * FsPath objects. + */ Tcl_FSMountsChanged(NULL); } + } else { + /* + * The current directory is now changed or an error occurred and an + * error message is now set. Just continue. + */ } return retVal; @@ -3065,25 +2990,17 @@ Tcl_FSChdir( * * Tcl_FSLoadFile -- * - * Dynamically loads a binary code file into memory and returns the - * addresses of two functions within that file, if they are defined. The - * appropriate function for the filesystem to which pathPtr belongs will - * be called. - * - * Note that the native filesystem doesn't actually assume 'pathPtr' is a - * path. Rather it assumes pathPtr is either a path or just the name - * (tail) of a file which can be found somewhere in the environment's - * loadable path. This behaviour is not very compatible with virtual - * filesystems (and has other problems documented in the load man-page), - * so it is advised that full paths are always used. + * Loads a dynamic shared object by passing the given pathname unmodified + * to Tcl_LoadFile, and provides pointers to the functions named by 'sym1' + * and 'sym2', and another pointer to a function that unloads the object. * * Results: - * A standard Tcl completion code. If an error occurs, an error message - * is left in the interp's result. + * A standard Tcl completion code. If an error occurs, sets the + * interpreter's result to an error message. * * Side effects: - * New code suddenly appears in memory. This may later be unloaded by - * passing the clientData to the unloadProc. + * A dynamic shared object is loaded into memory. This may later be + * unloaded by passing the handlePtr to *unloadProcPtr. * *---------------------------------------------------------------------- */ @@ -3091,38 +3008,29 @@ Tcl_FSChdir( int Tcl_FSLoadFile( Tcl_Interp *interp, /* Used for error reporting. */ - Tcl_Obj *pathPtr, /* Name of the file containing the desired - * code. */ + Tcl_Obj *pathPtr, /* Pathname of the file containing the dynamic shared object. + */ const char *sym1, const char *sym2, - /* Names of two functions to look up in the - * file's symbol table. */ + /* Names of two functions to find in the + * dynamic shared object. */ Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - Tcl_LoadHandle *handlePtr, /* Filled with token for dynamically loaded - * file which will be passed back to + /* Places to store pointers to the functions + * named by sym1 and sym2. */ + Tcl_LoadHandle *handlePtr, /* A place to store the token for the loaded + * object. Can be passed to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) - /* Filled with address of Tcl_FSUnloadFileProc - * function which should be used for this - * file. */ + /* A place to store a pointer to the function + * that unloads the object. */ { const char *symbols[3]; void *procPtrs[2]; int res; - /* - * Initialize the arrays. - */ - symbols[0] = sym1; symbols[1] = sym2; symbols[2] = NULL; - /* - * Perform the load. - */ - res = Tcl_LoadFile(interp, pathPtr, symbols, 0, procPtrs, handlePtr); if (res == TCL_OK) { *proc1Ptr = (Tcl_PackageInitProc *) procPtrs[0]; @@ -3139,49 +3047,40 @@ Tcl_FSLoadFile( * * Tcl_LoadFile -- * - * Dynamically loads a binary code file into memory and returns the - * addresses of a number of given functions within that file, if they are - * defined. The appropriate function for the filesystem to which pathPtr - * belongs will be called. + * Load a dynamic shared object by calling 'loadFileProc' of the + * filesystem corresponding to the given pathname, and then finds within + * the loaded object the functions named in symbols[]. * - * Note that the native filesystem doesn't actually assume 'pathPtr' is a - * path. Rather it assumes pathPtr is either a path or just the name - * (tail) of a file which can be found somewhere in the environment's - * loadable path. This behaviour is not very compatible with virtual - * filesystems (and has other problems documented in the load man-page), - * so it is advised that full paths are always used. + * The given pathname is passed unmodified to `loadFileProc`, which + * decides how to resolve it. On POSIX systems the native filesystem + * passes the given pathname to dlopen(), which resolves the filename + * according to its own set of rules. This behaviour is not very + * compatible with virtual filesystems, and has other problems as + * documented for [load], so it is recommended to use an absolute + * pathname. * * Results: - * A standard Tcl completion code. If an error occurs, an error message - * is left in the interp's result. + * A standard Tcl completion code. If an error occurs, sets the + * interpreter result to an error message. * * Side effects: - * New code suddenly appears in memory. This may later be unloaded by - * calling TclFS_UnloadFile. + * Memory is allocated for the new object. May be freed by calling + * TclFS_UnloadFile. * *---------------------------------------------------------------------- */ /* - * Workaround for issue with modern HPUX which do allow the unlink (no ETXTBSY - * error) yet somehow trash some internal data structures which prevents the - * second and further shared libraries from getting properly loaded. Only the - * first is ok. We try to get around the issue by not unlinking, i.e., - * emulating the behaviour of the older HPUX which denied removal. + * Modern HPUX allows the unlink (no ETXTBSY error) yet somehow trashes some + * internal data structures, preventing any additional dynamic shared objects + * from getting properly loaded. Only the first is ok. Work around the issue + * by not unlinking, i.e., emulating the behaviour of the older HPUX which + * denied removal. * * Doing the unlink is also an issue within docker containers, whose AUFS * bungles this as well, see * https://github.com/dotcloud/docker/issues/1911 * - * For these situations the change below makes the execution of the unlink - * semi-controllable at runtime. - * - * An AUFS filesystem (if it can be detected) will force avoidance of - * unlink. The env variable TCL_TEMPLOAD_NO_UNLINK allows detection of a - * users general request (unlink and not. - * - * By default the unlink is done (if not in AUFS). However if the variable is - * present and set to true (any integer > 0) then the unlink is skipped. */ static int @@ -3189,21 +3088,18 @@ skipUnlink( Tcl_Obj *shlibFile) { /* - * Order of testing: - * 1. On hpux we generally want to skip unlink in general + * Unlinking is not performed in the following cases: * - * Outside of hpux then: - * 2. For a general user request (TCL_TEMPLOAD_NO_UNLINK present, - * non-empty, => int) - * 3. For general AUFS environment (statfs, if available). + * 1. The operating system is HPUX. * - * Ad 2: This variable can disable/override the AUFS detection, i.e. for - * testing if a newer AUFS does not have the bug any more. + * 2. If the environment variable TCL_TEMPLOAD_NO_UNLINK is present and + * set to true (an integer > 0) + * + * 3. TCL_TEMPLOAD_NO_UNLINK is not true (an integer > 0) and AUFS filesystem can be detected (using statfs, if available). * - * Ad 3: This is conditionally compiled in. Condition currently must be - * set manually. This part needs proper tests in the configure(.in). */ + #ifdef hpux return 1; #else @@ -3214,6 +3110,9 @@ skipUnlink( } #ifdef TCL_TEMPLOAD_NO_UNLINK +/* At built time TCL_TEMPLOAD_NO_UNLINK can be set manually to control whether + * this automatic overriding of unlink is included. + */ #ifndef NO_FSTATFS { struct statfs fs; @@ -3222,9 +3121,12 @@ skipUnlink( * box is too old to have it directly in the headers. Define taken from * http://mooon.googlecode.com/svn/trunk/linux_include/linux/aufs_type.h * http://aufs.sourceforge.net/ - * Better reference will be gladly taken. + * Better reference will be gladly accepted. */ #ifndef AUFS_SUPER_MAGIC +/* AUFS_SUPER_MAGIC can disable/override the AUFS detection, i.e. for + * testing if a newer AUFS does not have the bug any more. +*/ #define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') #endif /* AUFS_SUPER_MAGIC */ if ((statfs(Tcl_GetString(shlibFile), &fs) == 0) @@ -3236,8 +3138,8 @@ skipUnlink( #endif /* ... TCL_TEMPLOAD_NO_UNLINK */ /* - * Fallback: !hpux, no EV override, no AUFS (detection, nor detected): - * Don't skip + * No HPUX, environment variable override, or AUFS detected. Perform + * unlink. */ return 0; #endif /* hpux */ @@ -3246,16 +3148,15 @@ skipUnlink( int Tcl_LoadFile( Tcl_Interp *interp, /* Used for error reporting. */ - Tcl_Obj *pathPtr, /* Name of the file containing the desired - * code. */ - const char *const symbols[],/* Names of functions to look up in the file's - * symbol table. */ + Tcl_Obj *pathPtr, /* Pathname of the file containing the dynamic + * shared object. */ + const char *const symbols[],/* A null-terminated array of names of + * functions to find in the loaded object. */ int flags, /* Flags */ - void *procVPtrs, /* Where to return the addresses corresponding - * to symbols[]. */ - Tcl_LoadHandle *handlePtr) /* Filled with token for shared library - * information which can be used in - * TclpFindSymbol. */ + void *procVPtrs, /* A place to store pointers to the functions + * named by symbols[]. */ + Tcl_LoadHandle *handlePtr) /* A place to hold a token for the loaded object. + * Can be used by TclpFindSymbol. */ { void **procPtrs = (void **) procVPtrs; const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -3293,10 +3194,11 @@ Tcl_LoadFile( } /* - * The filesystem doesn't support 'load', so we fall back on the following - * technique: - * - * First check if it is readable -- and exists! + * The filesystem doesn't support 'load'. Fall to the following: + */ + + /* + * Make sure the file is accessible. */ if (Tcl_FSAccess(pathPtr, R_OK) != 0) { @@ -3310,9 +3212,9 @@ Tcl_LoadFile( #ifdef TCL_LOAD_FROM_MEMORY /* - * The platform supports loading code from memory, so ask for a buffer of - * the appropriate size, read the file into it and load the code from the - * buffer: + * The platform supports loading a dynamic shared object from memory. + * Create a sufficiently large buffer, read the file into it, and then load + * the dynamic shared object from the buffer: */ { @@ -3328,7 +3230,7 @@ Tcl_LoadFile( size = (int) statBuf.st_size; /* - * Tcl_Read takes an int: check that file size isn't wide. + * Tcl_Read takes an int: Determine whether the file size is wide. */ if (size != (Tcl_WideInt) statBuf.st_size) { @@ -3359,8 +3261,7 @@ Tcl_LoadFile( #endif /* TCL_LOAD_FROM_MEMORY */ /* - * Get a temporary filename to use, first to copy the file into, and then - * to load. + * Get a temporary filename, first to copy the file into, and then to load. */ copyToPtr = TclpTempFileNameForLibrary(interp, pathPtr); @@ -3372,11 +3273,15 @@ Tcl_LoadFile( copyFsPtr = Tcl_FSGetFileSystemForPath(copyToPtr); if ((copyFsPtr == NULL) || (copyFsPtr == fsPtr)) { /* - * We already know we can't use Tcl_FSLoadFile from this filesystem, - * and we must avoid a possible infinite loop. Try to delete the file - * we probably created, and then exit. + * Tcl_FSLoadFile isn't available for the filesystem of the temporary + * file. In order to avoid a possible infinite loop, do not attempt to + * load further. */ + /* + * Try to delete the file we probably created and then exit. + */ + Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); if (interp) { @@ -3387,10 +3292,6 @@ Tcl_LoadFile( } if (TclCrossFilesystemCopy(interp, pathPtr, copyToPtr) != TCL_OK) { - /* - * Cross-platform copy failed. - */ - Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); return TCL_ERROR; @@ -3398,10 +3299,9 @@ Tcl_LoadFile( #ifndef _WIN32 /* - * Do we need to set appropriate permissions on the file? This may be - * required on some systems. On Unix we could loop over the file - * attributes, and set any that are called "-permissions" to 0700. However - * we just do this directly, like this: + * It might be necessary on some systems to set the appropriate permissions + * on the file. On Unix we could loop over the file attributes and set any + * that are called "-permissions" to 0700, but just do it directly instead: */ { @@ -3418,8 +3318,8 @@ Tcl_LoadFile( #endif /* - * We need to reset the result now, because the cross-filesystem copy may - * have stored the number of bytes in the result. + * The cross-filesystem copy may have stored the number of bytes in the + * result, so reset the result now. */ if (interp) { @@ -3429,18 +3329,14 @@ Tcl_LoadFile( retVal = Tcl_LoadFile(interp, copyToPtr, symbols, flags, procPtrs, &newLoadHandle); if (retVal != TCL_OK) { - /* - * The file didn't load successfully. - */ - Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); return retVal; } /* - * Try to delete the file immediately - this is possible in some OSes, and - * avoids any worries about leaving the copy laying around on exit. + * Try to delete the file immediately. Some operatings systems allow this, + * and it avoids leaving the copy laying around after exit. */ if (!skipUnlink(copyToPtr) && @@ -3448,10 +3344,9 @@ Tcl_LoadFile( Tcl_DecrRefCount(copyToPtr); /* - * We tell our caller about the real shared library which was loaded. - * Note that this does mean that the package list maintained by 'load' - * will store the original (vfs) path alongside the temporary load - * handle and unload proc ptr. + * Tell the caller all the details: The package list maintained by + * 'load' stores the original (vfs) pathname, the handle of object + * loaded from the temporary file, and the unloadProcPtr. */ *handlePtr = newLoadHandle; @@ -3462,47 +3357,41 @@ Tcl_LoadFile( } /* - * When we unload this file, we need to divert the unloading so we can - * unload and cleanup the temporary file correctly. + * Divert the unloading in order to unload and cleanup the temporary file. */ tvdlPtr = ckalloc(sizeof(FsDivertLoad)); /* - * Remember three pieces of information. This allows us to cleanup the - * diverted load completely, on platforms which allow proper unloading of - * code. + * Remember three pieces of information in order to clean up the diverted + * load completely on platforms which allow proper unloading of code. */ tvdlPtr->loadHandle = newLoadHandle; tvdlPtr->unloadProcPtr = newUnloadProcPtr; if (copyFsPtr != &tclNativeFilesystem) { - /* - * copyToPtr is already incremented for this reference. - */ - + /* refCount of copyToPtr is already incremented. */ tvdlPtr->divertedFile = copyToPtr; /* - * This is the filesystem we loaded it into. Since we have a reference - * to 'copyToPtr', we already have a refCount on this filesystem, so - * we don't need to worry about it disappearing on us. + * This is the filesystem for the temporary file the object was loaded + * from. A reference to copyToPtr is already stored in + * tvdlPtr->divertedFile, so need need to increment the refCount again. */ tvdlPtr->divertedFilesystem = copyFsPtr; tvdlPtr->divertedFileNativeRep = NULL; } else { /* - * We need the native rep. + * Grab the native representation. */ tvdlPtr->divertedFileNativeRep = TclNativeDupInternalRep( Tcl_FSGetInternalRep(copyToPtr, copyFsPtr)); /* - * We don't need or want references to the copied Tcl_Obj or the - * filesystem if it is the native one. + * Don't keeep a reference to the Tcl_Obj or the native filesystem. */ tvdlPtr->divertedFile = NULL; @@ -3525,8 +3414,8 @@ Tcl_LoadFile( resolveSymbols: /* - * At this point, *handlePtr is already set up to the handle for the - * loaded library. We now try to resolve the symbols. + * handlePtr now contains a token for the loaded object. + * Resolve the symbols. */ if (symbols != NULL) { @@ -3535,9 +3424,8 @@ Tcl_LoadFile( if (procPtrs[i] == NULL) { /* * At least one symbol in the list was not found. Unload the - * file, and report the problem back to the caller. - * (Tcl_FindSymbol should already have left an appropriate - * error message.) + * file and return an error code. Tcl_FindSymbol should have + * already left an appropriate error message. */ (*handlePtr)->unloadFileProcPtr(*handlePtr); @@ -3554,16 +3442,17 @@ Tcl_LoadFile( * * DivertFindSymbol -- * - * Find a symbol in a shared library loaded by copy-from-VFS. + * Find a symbol in a shared library loaded by making a copying a file + * from the virtual filesystem to a native filesystem. * *---------------------------------------------------------------------- */ static void * DivertFindSymbol( - Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_LoadHandle loadHandle, /* Handle to the diverted module */ - const char *symbol) /* Symbol to resolve */ + Tcl_Interp *interp, /* The relevant interpreter. */ + Tcl_LoadHandle loadHandle, /* A handle to the diverted module. */ + const char *symbol) /* The name of symbol to resolve. */ { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle->clientData; Tcl_LoadHandle originalHandle = tvdlPtr->loadHandle; @@ -3576,83 +3465,75 @@ DivertFindSymbol( * * DivertUnloadFile -- * - * Unloads a file that has been loaded by copying from VFS to the native - * filesystem. - * - * Parameters: - * loadHandle -- Handle of the file to unload + * Unloads an object that was loaded from a temporary file copied from the + * virtual filesystem the native filesystem. * *---------------------------------------------------------------------- */ static void DivertUnloadFile( - Tcl_LoadHandle loadHandle) + Tcl_LoadHandle loadHandle) /* A handle for the loaded object. */ { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle->clientData; Tcl_LoadHandle originalHandle; - /* - * This test should never trigger, since we give the client data in the - * function above. - */ - if (tvdlPtr == NULL) { + /* + * tvdlPtr was provided by Tcl_LoadFile so it should not be NULL here. + */ + return; } originalHandle = tvdlPtr->loadHandle; /* - * Call the real 'unloadfile' proc we actually used. It is very important - * that we call this first, so that the shared library is actually - * unloaded by the OS. Otherwise, the following 'delete' may well fail - * because the shared library is still in use. + * Call the real 'unloadfile' proc. This must be called first so that the + * shared library is actually unloaded by the OS. Otherwise, the following + * 'delete' may fail because the shared library is still in use. */ originalHandle->unloadFileProcPtr(originalHandle); /* - * What filesystem contains the temp copy of the library? + * Determine which filesystem contains the temporary copy of the file. */ if (tvdlPtr->divertedFilesystem == NULL) { /* - * It was the native filesystem, and we have a special function - * available just for this purpose, which we know works even at this - * late stage. + * Use the function for the native filsystem, which works works even at + * this late stage. */ TclpDeleteFile(tvdlPtr->divertedFileNativeRep); NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep); } else { /* - * Remove the temporary file we created. Note, we may crash here - * because encodings have been taken down already. + * Remove the temporary file. If encodings have been cleaned up + * already, this may crash. */ if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile) != TCL_OK) { /* - * The above may have failed because the filesystem, or something - * it depends upon (e.g. encodings) have been taken down because - * Tcl is exiting. + * This may have happened because Tcl is exiting, and encodings may + * have already been deleted or something else the filesystem + * depends on may be gone. * - * We may need to work out how to delete this file more robustly - * (or give the filesystem the information it needs to delete the - * file more robustly). - * - * In particular, one problem might be that the filesystem cannot - * extract the information it needs from the above path object + * TO DO: Figure out how to delete this file more robustly, or + * give the filesystem the information it needs to delete the file + * more robustly. One problem might be that the filesystem cannot + * extract the information it needs from the above pathname object * because Tcl's entire filesystem apparatus (the code in this - * file) has been finalized, and it refuses to pass the internal - * representation to the filesystem. + * file) has been finalized and there is no way to get the native + * handle of the file. */ } /* - * And free up the allocations. This will also of course remove a - * refCount from the Tcl_Filesystem to which this file belongs, which - * could then free up the filesystem if we are exiting. + * This also decrements the refCount of the Tcl_Filesystem + * corresponding to this file. which might cause the filesystem to be + * deallocated if Tcl is exiting. */ Tcl_DecrRefCount(tvdlPtr->divertedFile); @@ -3667,23 +3548,23 @@ DivertUnloadFile( * * Tcl_FindSymbol -- * - * Find a symbol in a loaded library + * Find a symbol in a loaded object. * - * Results: - * Returns a pointer to the symbol if found. If not found, returns NULL - * and leaves an error message in the interpreter result. + * Previously filesystem-specific, but has been made portable by having + * TclpDlopen return a structure that includes procedure pointers. * - * This function was once filesystem-specific, but has been made portable by - * having TclpDlopen return a structure that includes procedure pointers. + * Results: + * Returns a pointer to the symbol if found. Otherwise, sets + * an error message in the interpreter result and returns NULL. * *---------------------------------------------------------------------- */ void * Tcl_FindSymbol( - Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_LoadHandle loadHandle, /* Handle to the loaded library */ - const char *symbol) /* Name of the symbol to resolve */ + Tcl_Interp *interp, /* The relevant interpreter. */ + Tcl_LoadHandle loadHandle, /* A handle for the loaded object. */ + const char *symbol) /* The name name of the symbol to resolve. */ { return loadHandle->findSymbolProcPtr(interp, loadHandle, symbol); } @@ -3693,16 +3574,15 @@ Tcl_FindSymbol( * * Tcl_FSUnloadFile -- * - * Unloads a library given its handle. Checks first that the library - * supports unloading. + * Unloads a loaded object if unloading is supported for the object. * *---------------------------------------------------------------------- */ int Tcl_FSUnloadFile( - Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_LoadHandle handle) /* Handle of the file to unload */ + Tcl_Interp *interp, /* The relevant interpreter. */ + Tcl_LoadHandle handle) /* A handle for the object to unload. */ { if (handle->unloadFileProcPtr == NULL) { if (interp != NULL) { @@ -3723,52 +3603,45 @@ Tcl_FSUnloadFile( * * TclFSUnloadTempFile -- * - * This function is called when we loaded a library of code via an - * intermediate temporary file. This function ensures the library is - * correctly unloaded and the temporary file is correctly deleted. + * Unloads an object loaded via temporary file from a virtual filesystem + * to a native filesystem. * * Results: * None. * * Side effects: - * The effects of the 'unload' function called, and of course the - * temporary file will be deleted. + * Frees resources for the loaded object and deletes the temporary file. * *---------------------------------------------------------------------- */ void TclFSUnloadTempFile( - Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to - * Tcl_FSLoadFile(). The loadHandle is a token - * that represents the loaded file. */ + Tcl_LoadHandle loadHandle) /* A handle for the object, as provided by a + * previous call to Tcl_FSLoadFile(). */ { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle; - /* - * This test should never trigger, since we give the client data in the - * function above. - */ - if (tvdlPtr == NULL) { + /* + * tvdlPtr was provided by Tcl_LoadFile so it should not be NULL here. + */ return; } - /* - * Call the real 'unloadfile' proc we actually used. It is very important - * that we call this first, so that the shared library is actually - * unloaded by the OS. Otherwise, the following 'delete' may well fail - * because the shared library is still in use. - */ - if (tvdlPtr->unloadProcPtr != NULL) { + /* + * 'unloadProcPtr' must be called first so that the shared library is + * actually unloaded by the OS. Otherwise, the following 'delete' may + * well fail because the shared library is still in use. + */ + tvdlPtr->unloadProcPtr(tvdlPtr->loadHandle); } if (tvdlPtr->divertedFilesystem == NULL) { /* - * It was the native filesystem, and we have a special function - * available just for this purpose, which we know works even at this + * Call the function for the native fileystem, which works even at this * late stage. */ @@ -3776,33 +3649,32 @@ TclFSUnloadTempFile( NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep); } else { /* - * Remove the temporary file we created. Note, we may crash here - * because encodings have been taken down already. + * Remove the temporary file that was created. If encodings have + * already been freed because the interpreter is exiting this may + * crash. */ if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile) != TCL_OK) { /* - * The above may have failed because the filesystem, or something - * it depends upon (e.g. encodings) have been taken down because - * Tcl is exiting. - * - * We may need to work out how to delete this file more robustly - * (or give the filesystem the information it needs to delete the - * file more robustly). + * This may have happened because Tcl is exiting and encodings may + * have already been deleted, or something else the filesystem + * depends on may be gone. * - * In particular, one problem might be that the filesystem cannot - * extract the information it needs from the above path object + * TO DO: Figure out how to delete this file more robustly, or + * give the filesystem the information it needs to delete the file + * more robustly. One problem might be that the filesystem cannot + * extract the information it needs from the above pathname object * because Tcl's entire filesystem apparatus (the code in this - * file) has been finalized, and it refuses to pass the internal - * representation to the filesystem. + * file) has been finalized and there is no way to get the native + * handle of the file. */ } /* - * And free up the allocations. This will also of course remove a - * refCount from the Tcl_Filesystem to which this file belongs, which - * could then free up the filesystem if we are exiting. + * This also decrements the refCount of the Tcl_Filesystem + * corresponding to this file. which might case filesystem to be freed + * if Tcl is exiting. */ Tcl_DecrRefCount(tvdlPtr->divertedFile); @@ -3816,38 +3688,41 @@ TclFSUnloadTempFile( * * Tcl_FSLink -- * - * This function replaces the library version of readlink() and can also - * be used to make links. The appropriate function for the filesystem to - * which pathPtr belongs will be called. + * Creates or inspects a link by calling 'linkProc' of the filesystem + * corresponding to the given pathname. Replaces the library version of + * readlink(). * * Results: - * If toPtr is NULL, then the result is a Tcl_Obj specifying the contents - * of the symbolic link given by 'pathPtr', or NULL if the symbolic link - * could not be read. The result is owned by the caller, which should - * call Tcl_DecrRefCount when the result is no longer needed. + * If toPtr is NULL, a Tcl_Obj containing the value the symbolic link for + * 'pathPtr', or NULL if a symbolic link was not accessible. The caller + * should Tcl_DecrRefCount on the result to release it. Otherwise NULL. * - * If toPtr is non-NULL, then the result is toPtr if the link action was - * successful, or NULL if not. In this case the result has no additional - * reference count, and need not be freed. The actual action to perform - * is given by the 'linkAction' flags, which is an or'd combination of: + * In this case the result has no additional reference count and need not + * be freed. The actual action to perform is given by the 'linkAction' + * flags, which is a combination of: * * TCL_CREATE_SYMBOLIC_LINK * TCL_CREATE_HARD_LINK * - * Note that most filesystems will not support linking across to - * different filesystems, so this function will usually fail unless toPtr - * is in the same FS as pathPtr. + * Most filesystems do not support linking across to different + * filesystems, so this function usually fails if the filesystem + * corresponding to toPtr is not the same as the filesystem corresponding + * to pathPtr. * * Side effects: - * See readlink() documentation. A new filesystem link object may appear. + * Creates or sets a link if toPtr is not NULL. + * + * See readlink(). * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSLink( - Tcl_Obj *pathPtr, /* Path of file to readlink or link. */ - Tcl_Obj *toPtr, /* NULL or path to be linked to. */ + Tcl_Obj *pathPtr, /* Pathaname of file. */ + Tcl_Obj *toPtr, /* + * NULL or the pathname of a file to link to. + */ int linkAction) /* Action to perform. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -3857,11 +3732,10 @@ Tcl_FSLink( } /* - * If S_IFLNK isn't defined it means that the machine doesn't support - * symbolic links, so the file can't possibly be a symbolic link. Generate - * an EINVAL error, which is what happens on machines that do support - * symbolic links when you invoke readlink on a file that isn't a symbolic - * link. + * If S_IFLNK isn't defined the machine doesn't support symbolic links, so + * the file can't possibly be a symbolic link. Generate an EINVAL error, + * which is what happens on machines that do support symbolic links when + * readlink is called for a file that isn't a symbolic link. */ #ifndef S_IFLNK @@ -3877,16 +3751,9 @@ Tcl_FSLink( * * Tcl_FSListVolumes -- * - * Lists the currently mounted volumes. The chain of functions that have - * been "inserted" into the filesystem will be called in succession; each - * may return a list of volumes, all of which are added to the result - * until all mounted file systems are listed. - * - * Notice that we assume the lists returned by each filesystem (if non - * NULL) have been given a refCount for us already. However, we are NOT - * allowed to hang on to the list itself (it belongs to the filesystem we - * called). Therefore we quite naturally add its contents to the result - * we are building, and then decrement the refCount. + * Lists the currently mounted volumes by calling `listVolumesProc` of + * each registered filesystem, and combining the results to form a list of + * volumes. * * Results: * The list of volumes, in an object which has refCount 0. @@ -3904,10 +3771,9 @@ Tcl_FSListVolumes(void) Tcl_Obj *resultPtr = Tcl_NewObj(); /* - * Call each of the "listVolumes" function in succession. A non-NULL - * return value indicates the particular function has succeeded. We call - * all the functions registered, since we want a list of all drives from - * all filesystems. + * Call each "listVolumes" function of each registered filesystem in + * succession. A non-NULL return value indicates the particular function + * has succeeded. */ fsRecPtr = FsGetFirstFilesystem(); @@ -3918,6 +3784,10 @@ Tcl_FSListVolumes(void) if (thisFsVolumes != NULL) { Tcl_ListObjAppendList(NULL, resultPtr, thisFsVolumes); + /* The refCount of each list returned by a `listVolumesProc` is + * already incremented. Do not hang onto the list, though. It + * belongs to the filesystem. Add its contents to * the result + * we are building, and then decrement the refCount. */ Tcl_DecrRefCount(thisFsVolumes); } } @@ -3933,22 +3803,21 @@ Tcl_FSListVolumes(void) * * FsListMounts -- * - * List all mounts within the given directory, which match the given - * pattern. + * Lists the mounts mathing the given pattern in the given directory. * * Results: - * The list of mounts, in a list object which has refCount 0, or NULL if - * we didn't even find any filesystems to try to list mounts. + * A list, having a refCount of 0, of the matching mounts, or NULL if no + * search was performed because no filesystem provided a search routine. * * Side effects: - * None + * None. * *--------------------------------------------------------------------------- */ static Tcl_Obj * FsListMounts( - Tcl_Obj *pathPtr, /* Contains path to directory to search. */ + Tcl_Obj *pathPtr, /* Pathname of directory to search. */ const char *pattern) /* Pattern to match against. */ { FilesystemRecord *fsRecPtr; @@ -3956,10 +3825,8 @@ FsListMounts( Tcl_Obj *resultPtr = NULL; /* - * Call each of the "matchInDirectory" functions in succession, with the - * specific type information 'mountsOnly'. A non-NULL return value - * indicates the particular function has succeeded. We call all the - * functions registered, since we want a list from each filesystems. + * Call the matchInDirectory function of each registered filesystem, + * passing it 'mountsOnly'. Results accumulate in resultPtr. */ fsRecPtr = FsGetFirstFilesystem(); @@ -3985,34 +3852,31 @@ FsListMounts( * * Tcl_FSSplitPath -- * - * This function takes the given Tcl_Obj, which should be a valid path, - * and returns a Tcl List object containing each segment of that path as - * an element. + * Splits a pathname into its components. * * Results: - * Returns list object with refCount of zero. If the passed in lenPtr is - * non-NULL, we use it to return the number of elements in the returned - * list. + * A list with refCount of zero. * * Side effects: - * None. + * If lenPtr is not null, sets it to the number of elements in the result. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSSplitPath( - Tcl_Obj *pathPtr, /* Path to split. */ - int *lenPtr) /* int to store number of path elements. */ + Tcl_Obj *pathPtr, /* The pathname to split. */ + int *lenPtr) /* A place to hold the number of pathname + * elements. */ { - Tcl_Obj *result = NULL; /* Needed only to prevent gcc warnings. */ + Tcl_Obj *result = NULL; /* Just to squelch gcc warnings. */ const Tcl_Filesystem *fsPtr; char separator = '/'; int driveNameLength; const char *p; /* - * Perform platform specific splitting. + * Perform platform-specific splitting. */ if (TclFSGetPathType(pathPtr, &fsPtr, @@ -4024,9 +3888,7 @@ Tcl_FSSplitPath( return TclpNativeSplitPath(pathPtr, lenPtr); } - /* - * We assume separators are single characters. - */ + /* Assume each separator is a single character. */ if (fsPtr->filesystemSeparatorProc != NULL) { Tcl_Obj *sep = fsPtr->filesystemSeparatorProc(pathPtr); @@ -4039,9 +3901,9 @@ Tcl_FSSplitPath( } /* - * Place the drive name as first element of the result list. The drive - * name may contain strange characters, like colons and multiple forward - * slashes (for example 'ftp://' is a valid vfs drive name) + * Add the drive name as first element of the result. The drive name may + * contain strange characters like colons and sequences of forward slashes + * For example, 'ftp://' is a valid drive name. */ result = Tcl_NewObj(); @@ -4051,7 +3913,7 @@ Tcl_FSSplitPath( p += driveNameLength; /* - * Add the remaining path elements to the list. + * Add the remaining pathname elements to the list. */ for (;;) { @@ -4078,10 +3940,6 @@ Tcl_FSSplitPath( } } - /* - * Compute the number of elements in the result. - */ - if (lenPtr != NULL) { TclListObjLength(NULL, result, lenPtr); } @@ -4092,35 +3950,31 @@ Tcl_FSSplitPath( * * TclGetPathType -- * - * Helper function used by FSGetPathType. + * Helper function used by TclFSGetPathType and TclJoinPath. * * Results: - * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or - * TCL_PATH_VOLUME_RELATIVE. The filesystem reference will be set if and - * only if it is non-NULL and the function's return value is - * TCL_PATH_ABSOLUTE. + * One of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or + * TCL_PATH_VOLUME_RELATIVE. * * Side effects: - * None. + * See **filesystemPtrptr, *driveNameLengthPtr and **driveNameRef, * *---------------------------------------------------------------------- */ Tcl_PathType TclGetPathType( - Tcl_Obj *pathPtr, /* Path to determine type for. */ + Tcl_Obj *pathPtr, /* Pathname to determine type of. */ const Tcl_Filesystem **filesystemPtrPtr, - /* If absolute path and this is not NULL, then - * set to the filesystem which claims this - * path. */ - int *driveNameLengthPtr, /* If the path is absolute, and this is - * non-NULL, then set to the length of the - * driveName. */ - Tcl_Obj **driveNameRef) /* If the path is absolute, and this is - * non-NULL, then set to the name of the - * drive, network-volume which contains the - * path, already with a refCount for the - * caller. */ + /* If not NULL, a place in which to store a + * pointer to the filesystem for this pathname + * if it is absolute. */ + int *driveNameLengthPtr, /* If not NULL, a place in which to store the + * length of the volume name. */ + Tcl_Obj **driveNameRef) /* If not NULL, for an absolute pathname, a + * place to store a pointer to an object with a + * refCount of 1, and whose value is the name + * of the volume. */ { int pathLen; const char *path = TclGetStringFromObj(pathPtr, &pathLen); @@ -4144,14 +3998,14 @@ TclGetPathType( * * TclFSNonnativePathType -- * - * Helper function used by TclGetPathType. Its purpose is to check - * whether the given path starts with a string which corresponds to a - * file volume in any registered filesystem except the native one. For - * speed and historical reasons the native filesystem has special - * hard-coded checks dotted here and there in the filesystem code. + * Helper function used by TclGetPathType. Checks whether the given + * pathname starts with a string which corresponds to a file volume in + * some registered filesystem other than the native one. For speed and + * historical reasons the native filesystem has special hard-coded checks + * dotted here and there in the filesystem code. * * Results: - * Returns one of TCL_PATH_ABSOLUTE or TCL_PATH_RELATIVE. The filesystem + * One of TCL_PATH_ABSOLUTE or TCL_PATH_RELATIVE. The filesystem * reference will be set if and only if it is non-NULL and the function's * return value is TCL_PATH_ABSOLUTE. * @@ -4163,49 +4017,45 @@ TclGetPathType( Tcl_PathType TclFSNonnativePathType( - const char *path, /* Path to determine type for. */ - int pathLen, /* Length of the path. */ + const char *path, /* Pathname to determine the type of. */ + int pathLen, /* Length of the pathname. */ const Tcl_Filesystem **filesystemPtrPtr, - /* If absolute path and this is not NULL, then - * set to the filesystem which claims this - * path. */ - int *driveNameLengthPtr, /* If the path is absolute, and this is - * non-NULL, then set to the length of the - * driveName. */ - Tcl_Obj **driveNameRef) /* If the path is absolute, and this is - * non-NULL, then set to the name of the - * drive, network-volume which contains the - * path, already with a refCount for the - * caller. */ + /* If not NULL, a place to store a pointer to + * the filesystem for this pathname when it is + * an absolute pathname. */ + int *driveNameLengthPtr, /* If not NULL, a place to store the length of + * the volume name if the pathname is absolute. + */ + Tcl_Obj **driveNameRef) /* If not NULL, a place to store a pointer to + * an object having its its refCount already + * incremented, and contining the name of the + * volume if the pathname is absolute. */ { FilesystemRecord *fsRecPtr; Tcl_PathType type = TCL_PATH_RELATIVE; /* - * Call each of the "listVolumes" function in succession, checking whether - * the given path is an absolute path on any of the volumes returned (this - * is done by checking whether the path's prefix matches). + * Determine whether the given pathname is an absolute pathname on some + * filesystem other than the native filesystem. */ fsRecPtr = FsGetFirstFilesystem(); Claim(); while (fsRecPtr != NULL) { /* - * We want to skip the native filesystem in this loop because - * otherwise we won't necessarily pass all the Tcl testsuite - this is - * because some of the tests artificially change the current platform - * (between win, unix) but the list of volumes we get by calling - * fsRecPtr->fsPtr->listVolumesProc will reflect the current (real) - * platform only and this may cause some tests to fail. In particular, - * on Unix '/' will match the beginning of certain absolute Windows - * paths starting '//' and those tests will go wrong. + * Skip the the native filesystem because otherwise some of the tests + * in the Tcl testsuite might fail because some of the tests + * artificially change the current platform (between win, unix) but the + * list of volumes obtained by calling fsRecPtr->fsPtr->listVolumesProc + * reflects the current (real) platform only. In particular, on Unix + * '/' matchs the beginning of certain absolute Windows pathnames + * starting '//' and those tests go wrong. * - * Besides these test-suite issues, there is one other reason to skip - * the native filesystem - since the tclFilename.c code has nice fast - * 'absolute path' checkers, we don't want to waste time repeating - * that effort here, and this function is actually called quite often, - * so if we can save the overhead of the native filesystem returning - * us a list of volumes all the time, it is better. + * There is another reason to skip the native filesystem: Since the + * tclFilename.c code has nice fast 'absolute path' checkers, there is + * no reason to waste time doing that in this frequently-called + * function. It is better to save the overhead of the native + * filesystem continuously returning a list of volumes. */ if ((fsRecPtr->fsPtr != &tclNativeFilesystem) @@ -4218,12 +4068,11 @@ TclFSNonnativePathType( != TCL_OK) { /* * This is VERY bad; the listVolumesProc didn't return a - * valid list. Set numVolumes to -1 so that we skip the - * while loop below and just return with the current value - * of 'type'. + * valid list. Set numVolumes to -1 to skip the loop below + * and just return with the current value of 'type'. * - * It would be better if we could signal an error here - * (but Tcl_Panic seems a bit excessive). + * It would be better to signal an error here, but + * Tcl_Panic seems a bit excessive. */ numVolumes = -1; @@ -4257,7 +4106,7 @@ TclFSNonnativePathType( Tcl_DecrRefCount(thisFsVolumes); if (type == TCL_PATH_ABSOLUTE) { /* - * We don't need to examine any more filesystems. + * No need to to examine additional filesystems. */ break; @@ -4275,12 +4124,13 @@ TclFSNonnativePathType( * * Tcl_FSRenameFile -- * - * If the two paths given belong to the same filesystem, we call that - * filesystems rename function. Otherwise we simply return the POSIX - * error 'EXDEV', and -1. + * If the two pathnames correspond to the same filesystem, call + * 'renameFileProc' of that filesystem. Otherwise return the POSIX error + * 'EXDEV', and -1. * * Results: - * Standard Tcl error code if a function was called. + * A standard Tcl error code if a rename function was called, or -1 + * otherwise. * * Side effects: * A file may be renamed. @@ -4290,10 +4140,9 @@ TclFSNonnativePathType( int Tcl_FSRenameFile( - Tcl_Obj *srcPathPtr, /* Pathname of file or dir to be renamed - * (UTF-8). */ - Tcl_Obj *destPathPtr) /* New pathname of file or directory - * (UTF-8). */ + Tcl_Obj *srcPathPtr, /* The pathname of a file or directory to be + renamed. */ + Tcl_Obj *destPathPtr) /* The new pathname for the file. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; @@ -4316,27 +4165,27 @@ Tcl_FSRenameFile( * * Tcl_FSCopyFile -- * - * If the two paths given belong to the same filesystem, we call that - * filesystem's copy function. Otherwise we simply return the POSIX error - * 'EXDEV', and -1. + * If both pathnames correspond to the same filesystem, calls + * 'copyFileProc' of that filesystem. * - * Note that in the native filesystems, 'copyFileProc' is defined to copy - * soft links (i.e. it copies the links themselves, not the things they - * point to). + * In the native filesystems, 'copyFileProc' copies a link itself, not the + * thing the link points to. * * Results: - * Standard Tcl error code if a function was called. + * A standard Tcl return code if a copyFileProc was called, or -1 + * otherwise. * * Side effects: - * A file may be copied. + * A file might be copied. The POSIX error 'EXDEV' is set if a copy + * function was not called. * *--------------------------------------------------------------------------- */ int Tcl_FSCopyFile( - Tcl_Obj *srcPathPtr, /* Pathname of file to be copied (UTF-8). */ - Tcl_Obj *destPathPtr) /* Pathname of file to copy to (UTF-8). */ + Tcl_Obj *srcPathPtr, /* The pathname of file to be copied. */ + Tcl_Obj *destPathPtr) /* The new pathname to copy the file to. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; @@ -4358,15 +4207,14 @@ Tcl_FSCopyFile( * * TclCrossFilesystemCopy -- * - * Helper for above function, and for Tcl_FSLoadFile, to copy files from - * one filesystem to another. This function will overwrite the target - * file if it already exists. + * Helper for Tcl_FSCopyFile and Tcl_FSLoadFile. Copies a file from one + * filesystem to another, overwiting any file that already exists. * * Results: - * Standard Tcl error code. + * A standard Tcl return code. * * Side effects: - * A file may be created. + * A file may be copied. * *--------------------------------------------------------------------------- */ @@ -4374,8 +4222,8 @@ Tcl_FSCopyFile( int TclCrossFilesystemCopy( Tcl_Interp *interp, /* For error messages. */ - Tcl_Obj *source, /* Pathname of file to be copied (UTF-8). */ - Tcl_Obj *target) /* Pathname of file to copy to (UTF-8). */ + Tcl_Obj *source, /* Pathname of file to be copied. */ + Tcl_Obj *target) /* Pathname to copy the file to. */ { int result = TCL_ERROR; int prot = 0666; @@ -4386,7 +4234,7 @@ TclCrossFilesystemCopy( out = Tcl_FSOpenFileChannel(interp, target, "wb", prot); if (out == NULL) { /* - * It looks like we cannot copy it over. Bail out... + * Failed to open an output channel. Bail out. */ goto done; } @@ -4394,7 +4242,7 @@ TclCrossFilesystemCopy( in = Tcl_FSOpenFileChannel(interp, source, "rb", prot); if (in == NULL) { /* - * This is very strange, caller should have checked this... + * Could not open an input channel. Why didn't the caller check this? */ Tcl_Close(interp, out); @@ -4402,8 +4250,8 @@ TclCrossFilesystemCopy( } /* - * Copy it synchronously. We might wish to add an asynchronous option to - * support vfs's which are slow (e.g. network sockets). + * Copy the file synchronously. TO DO: Maybe add an asynchronous option + * to support virtual filesystems that are slow (e.g. network sockets). */ if (TclCopyChannel(interp, in, out, -1, NULL) == TCL_OK) { @@ -4411,7 +4259,7 @@ TclCrossFilesystemCopy( } /* - * If the copy failed, assume that copy channel left a good error message. + * If the copy failed, assume that copy channel left an error message. */ Tcl_Close(interp, in); @@ -4436,11 +4284,11 @@ TclCrossFilesystemCopy( * * Tcl_FSDeleteFile -- * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. + * Calls 'deleteFileProc' of the filesystem corresponding to the given + * pathname. * * Results: - * Standard Tcl error code. + * A standard Tcl return code. * * Side effects: * A file may be deleted. @@ -4466,14 +4314,15 @@ Tcl_FSDeleteFile( * * Tcl_FSCreateDirectory -- * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. + * Calls 'createDirectoryProc' of the filesystem corresponding to the + * given pathname. * * Results: - * Standard Tcl error code. + * A standard Tcl return code, or -1 if no createDirectoryProc is found. * * Side effects: - * A directory may be created. + * A directory may be created. POSIX error 'ENOENT' is set if no + * createDirectoryProc is found. * *--------------------------------------------------------------------------- */ @@ -4496,27 +4345,30 @@ Tcl_FSCreateDirectory( * * Tcl_FSCopyDirectory -- * - * If the two paths given belong to the same filesystem, we call that - * filesystems copy-directory function. Otherwise we simply return the - * POSIX error 'EXDEV', and -1. + * If both pathnames correspond to the the same filesystem, calls + * 'copyDirectoryProc' of that filesystem. * * Results: - * Standard Tcl error code if a function was called. + * A standard Tcl return code, or -1 if no 'copyDirectoryProc' is found. * * Side effects: - * A directory may be copied. + * A directory may be copied. POSIX error 'EXDEV' is set if no + * copyDirectoryProc is found. * *--------------------------------------------------------------------------- */ int Tcl_FSCopyDirectory( - Tcl_Obj *srcPathPtr, /* Pathname of directory to be copied - * (UTF-8). */ - Tcl_Obj *destPathPtr, /* Pathname of target directory (UTF-8). */ - Tcl_Obj **errorPtr) /* If non-NULL, then will be set to a new - * object containing name of file causing - * error, with refCount 1. */ + Tcl_Obj *srcPathPtr, /* + * The pathname of the directory to be copied. + */ + Tcl_Obj *destPathPtr, /* The pathname of the target directory. */ + Tcl_Obj **errorPtr) /* If not NULL, and there is an error, a place + * to store a pointer to a new object, with + * its refCount already incremented, and + * containing the pathname name of file + * causing the error. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; @@ -4538,28 +4390,31 @@ Tcl_FSCopyDirectory( * * Tcl_FSRemoveDirectory -- * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. + * Calls 'removeDirectoryProc' of the filesystem corresponding to remove + * pathPtr. * * Results: - * Standard Tcl error code. + * A standard Tcl return code, or -1 if no removeDirectoryProc is found. * * Side effects: - * A directory may be deleted. + * A directory may be removed. POSIX error 'ENOENT' is set if no + * removeDirectoryProc is found. * *--------------------------------------------------------------------------- */ int Tcl_FSRemoveDirectory( - Tcl_Obj *pathPtr, /* Pathname of directory to be removed - * (UTF-8). */ - int recursive, /* If non-zero, removes directories that are - * nonempty. Otherwise, will only remove empty - * directories. */ - Tcl_Obj **errorPtr) /* If non-NULL, then will be set to a new - * object containing name of file causing - * error, with refCount 1. */ + Tcl_Obj *pathPtr, /* The pathname of the directory to be removed. + */ + int recursive, /* If zero, removes only an empty directory. + * Otherwise, removes the directory and all its + * contents. */ + Tcl_Obj **errorPtr) /* If not NULL and an error occurs, stores a + * place to store a a pointer to a new + * object having a refCount of 1 and containing + * the name of the file that produced an error. + * */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -4568,14 +4423,8 @@ Tcl_FSRemoveDirectory( return -1; } - /* - * When working recursively, we check whether the cwd lies inside this - * directory and move it if it does. - */ - if (recursive) { Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL); - if (cwdPtr != NULL) { const char *cwdStr, *normPathStr; int cwdLen, normLen; @@ -4587,8 +4436,8 @@ Tcl_FSRemoveDirectory( if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr, (size_t) normLen) == 0)) { /* - * The cwd is inside the directory, so we perform a 'cd - * [file dirname $path]'. + * The cwd is inside the directory to be removed. Change + * the cwd to [file dirname $path]. */ Tcl_Obj *dirPtr = TclPathPart(NULL, pathPtr, @@ -4609,16 +4458,14 @@ Tcl_FSRemoveDirectory( * * Tcl_FSGetFileSystemForPath -- * - * This function determines which filesystem to use for a particular path - * object, and returns the filesystem which accepts this file. If no - * filesystem will accept this object as a valid file path, then NULL is - * returned. + * Produces the filesystem that corresponds to the given pathname. * * Results: - * NULL or a filesystem which will accept this path. + * The corresponding Tcl_Filesystem, or NULL if the pathname is invalid. * * Side effects: - * The object may be converted to a path type. + * The internal representation of fsPtrPtr is converted to fsPathType if + * needed, and that internal representation is updated as needed. * *--------------------------------------------------------------------------- */ @@ -4635,41 +4482,38 @@ Tcl_FSGetFileSystemForPath( return NULL; } - /* - * If the object has a refCount of zero, we reject it. This is to avoid - * possible segfaults or nondeterministic memory leaks (i.e. the user - * doesn't know if they should decrement the ref count on return or not). - */ - if (pathPtr->refCount == 0) { + /* + * Avoid possible segfaults or nondeterministic memory leaks where the + * reference count has been incorreclty managed. + */ Tcl_Panic("Tcl_FSGetFileSystemForPath called with object with refCount == 0"); return NULL; } - /* - * Check if the filesystem has changed in some way since this object's - * internal representation was calculated. Before doing that, assure we - * have the most up-to-date copy of the master filesystem. This is - * accomplished by the FsGetFirstFilesystem() call. - */ - + /* Start with an up-to-date copy of the master filesystem. */ fsRecPtr = FsGetFirstFilesystem(); Claim(); + /* + * Ensure that pathPtr is a valid pathname. + */ if (TclFSEnsureEpochOk(pathPtr, &retVal) != TCL_OK) { + /* not a valid pathname */ Disclaim(); return NULL; } else if (retVal != NULL) { - /* TODO: Can this happen? */ + /* + * Found the filesystem in the internal representation of pathPtr. + */ Disclaim(); return retVal; } /* - * Call each of the "pathInFilesystem" functions in succession. A - * non-return value of -1 indicates the particular function has succeeded. - */ - + * Call each of the "pathInFilesystem" functions in succession until the + * corresponding filesystem is found. + */ for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) { ClientData clientData = NULL; @@ -4678,10 +4522,10 @@ Tcl_FSGetFileSystemForPath( } if (fsRecPtr->fsPtr->pathInFilesystemProc(pathPtr, &clientData)!=-1) { - /* - * We assume the type of pathPtr hasn't been changed by the above - * call to the pathInFilesystemProc. - */ + /* This is the filesystem for pathPtr. Assume the type of pathPtr + * hasn't been changed by the above call to the + * pathInFilesystemProc, and cache this result in the internal + * representation of pathPtr. */ TclFSSetPathDetails(pathPtr, fsRecPtr->fsPtr, clientData); Disclaim(); @@ -4698,26 +4542,7 @@ Tcl_FSGetFileSystemForPath( * * Tcl_FSGetNativePath -- * - * This function is for use by the Win/Unix native filesystems, so that - * they can easily retrieve the native (char* or WCHAR*) representation - * of a path. Other filesystems will probably want to implement similar - * functions. They basically act as a safety net around - * Tcl_FSGetInternalRep. Normally your file-system functions will always - * be called with path objects already converted to the correct - * filesystem, but if for some reason they are called directly (i.e. by - * functions not in this file), then one cannot necessarily guarantee - * that the path object pointer is from the correct filesystem. - * - * Note: in the future it might be desirable to have separate versions - * of this function with different signatures, for example - * Tcl_FSGetNativeWinPath, Tcl_FSGetNativeUnixPath etc. Right now, since - * native paths are all string based, we use just one function. - * - * Results: - * NULL or a valid native path. - * - * Side effects: - * See Tcl_FSGetInternalRep. + * See Tcl_FSGetInternalRep. * *--------------------------------------------------------------------------- */ @@ -4734,7 +4559,7 @@ Tcl_FSGetNativePath( * * NativeFreeInternalRep -- * - * Free a native internal representation, which will be non-NULL. + * Free a native internal representation. * * Results: * None. @@ -4756,16 +4581,17 @@ NativeFreeInternalRep( *--------------------------------------------------------------------------- * * Tcl_FSFileSystemInfo -- + * Produce the type of a pathname and the type of its filesystem. * - * This function returns a list of two elements. The first element is the - * name of the filesystem (e.g. "native" or "vfs"), and the second is the - * particular type of the given path within that filesystem. * * Results: - * A list of two elements. + * A list where the first item is the name of the filesystem (e.g. + * "native" or "vfs"), and the second item is the type of the given + * pathname within that filesystem. * * Side effects: - * The object may be converted to a path type. + * The internal representation of pathPtr may be converted to a + * fsPathType. * *--------------------------------------------------------------------------- */ @@ -4801,16 +4627,13 @@ Tcl_FSFileSystemInfo( * * Tcl_FSPathSeparator -- * - * This function returns the separator to be used for a given path. The - * object returned should have a refCount of zero + * Produces the separator for given pathname. * * Results: - * A Tcl object, with a refCount of zero. If the caller needs to retain a - * reference to the object, it should call Tcl_IncrRefCount, and should - * otherwise free the object. + * A Tcl object having a refCount of zero. * * Side effects: - * The path object may be converted to a path type. + * The internal representation of pathPtr may be converted to a fsPathType * *--------------------------------------------------------------------------- */ @@ -4831,8 +4654,8 @@ Tcl_FSPathSeparator( } /* - * Allow filesystems not to provide a filesystemSeparatorProc if they wish - * to use the standard forward slash. + * Use the standard forward slash character if filesystem does not to + * provide a filesystemSeparatorProc. */ TclNewLiteralStringObj(resultObj, "/"); @@ -4844,11 +4667,11 @@ Tcl_FSPathSeparator( * * NativeFilesystemSeparator -- * - * This function is part of the native filesystem support, and returns - * the separator for the given path. + * This function, part of the native filesystem support, returns the + * separator for the given pathname. * * Results: - * String object containing the separator character. + * The separator character. * * Side effects: * None. -- cgit v0.12 From 2325ddede0d49a1700d83457e8e36da87e548ccf Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 7 Nov 2019 18:36:57 +0000 Subject: added removal of timeout-event in cleanup of io-44.6 (can bother followed tests), removed unneeded constraint --- tests/io.test | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/io.test b/tests/io.test index 9bd87ef..519191f 100644 --- a/tests/io.test +++ b/tests/io.test @@ -5965,8 +5965,8 @@ test io-44.5 {FileEventProc procedure: end of file} {stdio unixExecs openpipe fi close $f -test chan-io-44.6 {FileEventProc procedure: write-only non-blocking channel} -setup { -} -constraints {stdio unixExecs fileevent openpipe} -body { +test io-44.6 {FileEventProc procedure: write-only non-blocking channel} -setup { +} -constraints {stdio fileevent openpipe} -body { namespace eval refchan { namespace ensemble create @@ -6017,12 +6017,13 @@ test chan-io-44.6 {FileEventProc procedure: write-only non-blocking channel} -se set x done } }] - after 10000 [namespace code { + set token [after 10000 [namespace code { set x timeout - }] + }]] vwait [namespace which -variable x] return $x } -cleanup { + after cancel $token catch {chan close $f} } -result done -- cgit v0.12 From c1f8c0290006c19eba948b7aaec6ae6ae0e0099c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 8 Nov 2019 15:32:33 +0000 Subject: Add support for mp_init_i32/mp_init_i64/mp_init_l/mp_init_ll/mp_init_u32/mp_init_u64/mp_init_ul/mp_init_ull/mp_set_ull, the main functions in libtommath 1.2.0 for setting values directly in mp_int's. One new stub entry (mp_set_ull), the others make use of already existing stub entries. This is 100% fully upwards compatible. --- generic/tclStubInit.c | 8 ++--- generic/tclTestObj.c | 2 +- generic/tclTomMath.decls | 11 ++++--- generic/tclTomMathDecls.h | 68 +++++++++++++++++++++++++++++++++++++------ generic/tclTomMathInterface.c | 9 ++++-- 5 files changed, 77 insertions(+), 21 deletions(-) diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 0618f00..09c975d 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -70,12 +70,12 @@ static int TclSockMinimumBuffersOld(int sock, int size) } #endif -static MP_SET_UNSIGNED(bn_mp_set_ull, Tcl_WideUInt) +MP_SET_UNSIGNED(mp_set_ull, Tcl_WideUInt) mp_err TclBN_mp_set_int(mp_int *a, unsigned long i) { - bn_mp_set_ull(a, i); + mp_set_ull(a, i); return MP_OKAY; } @@ -83,7 +83,7 @@ mp_err TclBN_mp_init_set_int(mp_int *a, unsigned long i) { mp_err result = mp_init(a); if (result == MP_OKAY) { - bn_mp_set_ull(a, i); + mp_set_ull(a, i); } return result; } @@ -916,7 +916,7 @@ const TclTomMathStubs tclTomMathStubs = { TclBNInitBignumFromWideInt, /* 65 */ TclBNInitBignumFromWideUInt, /* 66 */ TclBN_mp_expt_d_ex, /* 67 */ - 0, /* 68 */ + TclBN_mp_set_ull, /* 68 */ 0, /* 69 */ 0, /* 70 */ 0, /* 71 */ diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index 7f9b561..f741714 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -131,7 +131,7 @@ TclObjTest_Init( * * TestbignumobjCmd -- * - * This function implmenets the "testbignumobj" command. It is used + * This function implements the "testbignumobj" command. It is used * to exercise the bignum Tcl object type implementation. * * Results: diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index 8325922..c5645a4 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -224,20 +224,23 @@ declare 63 { # Formerly internal API to allow initialisation of bignums without knowing the # typedefs of how a bignum works internally. declare 64 { - void TclBNInitBignumFromLong(mp_int *bignum, long initVal) + int TclBNInitBignumFromLong(mp_int *bignum, long initVal) } declare 65 { - void TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal) + int TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal) } declare 66 { - void TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal) + int TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal) } # Added in libtommath 1.0 declare 67 { mp_err TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) } - +# Added in libtommath 1.0.1 +declare 68 { + void TclBN_mp_set_ull(mp_int *a, Tcl_WideUInt i) +} # Added in libtommath 1.1.0 declare 73 { mp_err TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index 9131041..a1da2c9 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -96,6 +96,8 @@ #define mp_set_int(a,b) (TclBN_mp_set_int(a,(unsigned int)(b)),MP_OKAY) #define mp_set_long(a,b) (TclBN_mp_set_int(a,b),MP_OKAY) #define mp_set_ul(a,b) (void)TclBN_mp_set_int(a,b) +#define mp_set_ull TclBN_mp_set_ull +#define mp_set_u64 TclBN_mp_set_ull #define mp_shrink TclBN_mp_shrink #define mp_sqr TclBN_mp_sqr #define mp_sqrt TclBN_mp_sqrt @@ -311,17 +313,18 @@ EXTERN mp_err TclBN_mp_set_int(mp_int *a, unsigned long i); /* 63 */ EXTERN int TclBN_mp_cnt_lsb(const mp_int *a); /* 64 */ -EXTERN void TclBNInitBignumFromLong(mp_int *bignum, long initVal); +EXTERN int TclBNInitBignumFromLong(mp_int *bignum, long initVal); /* 65 */ -EXTERN void TclBNInitBignumFromWideInt(mp_int *bignum, +EXTERN int TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal); /* 66 */ -EXTERN void TclBNInitBignumFromWideUInt(mp_int *bignum, +EXTERN int TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal); /* 67 */ EXTERN mp_err TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast); -/* Slot 68 is reserved */ +/* 68 */ +EXTERN void TclBN_mp_set_ull(mp_int *a, Tcl_WideUInt i); /* Slot 69 is reserved */ /* Slot 70 is reserved */ /* Slot 71 is reserved */ @@ -416,11 +419,11 @@ typedef struct TclTomMathStubs { mp_err (*tclBN_mp_init_set_int) (mp_int *a, unsigned long i); /* 61 */ mp_err (*tclBN_mp_set_int) (mp_int *a, unsigned long i); /* 62 */ int (*tclBN_mp_cnt_lsb) (const mp_int *a); /* 63 */ - void (*tclBNInitBignumFromLong) (mp_int *bignum, long initVal); /* 64 */ - void (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ - void (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ + int (*tclBNInitBignumFromLong) (mp_int *bignum, long initVal); /* 64 */ + int (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ + int (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ mp_err (*tclBN_mp_expt_d_ex) (const mp_int *a, mp_digit b, mp_int *c, int fast); /* 67 */ - void (*reserved68)(void); + void (*tclBN_mp_set_ull) (mp_int *a, Tcl_WideUInt i); /* 68 */ void (*reserved69)(void); void (*reserved70)(void); void (*reserved71)(void); @@ -583,7 +586,8 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBNInitBignumFromWideUInt) /* 66 */ #define TclBN_mp_expt_d_ex \ (tclTomMathStubsPtr->tclBN_mp_expt_d_ex) /* 67 */ -/* Slot 68 is reserved */ +#define TclBN_mp_set_ull \ + (tclTomMathStubsPtr->tclBN_mp_set_ull) /* 68 */ /* Slot 69 is reserved */ /* Slot 70 is reserved */ /* Slot 71 is reserved */ @@ -611,4 +615,50 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT +#ifdef USE_TCL_STUBS +#undef TclBNInitBignumFromLong +#define TclBNInitBignumFromLong(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)tclTomMathStubsPtr->tclBNInitBignumFromLong((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromLong"); \ + } \ + } while (0) +#undef TclBNInitBignumFromWideInt +#define TclBNInitBignumFromWideInt(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)tclTomMathStubsPtr->tclBNInitBignumFromWideInt((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromWideInt"); \ + } \ + } while (0) +#undef TclBNInitBignumFromWideUInt +#define TclBNInitBignumFromWideUInt(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)tclTomMathStubsPtr->tclBNInitBignumFromWideUInt((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt"); \ + } \ + } while (0) +#define mp_init_i32(a,b) (((a)->dp=NULL,tclTomMathStubsPtr->tclBNInitBignumFromLong((a),(int32_t)(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_l(a,b) (((a)->dp=NULL,tclTomMathStubsPtr->tclBNInitBignumFromLong((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_ll(a,b) (((a)->dp=NULL,tclTomMathStubsPtr->tclBNInitBignumFromWideInt((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_i64(a,b) (((a)->dp=NULL,tclTomMathStubsPtr->tclBNInitBignumFromWideInt((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_u32(a,b) (((a)->dp=NULL,tclTomMathStubsPtr->tclBNInitBignumFromWideUInt((a),(uint32_t)(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_ul(a,b) (((a)->dp=NULL,tclTomMathStubsPtr->tclBNInitBignumFromWideUInt((a),(unsigned long)(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_ull(a,b) (((a)->dp=NULL,tclTomMathStubsPtr->tclBNInitBignumFromWideUInt((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_u64(a,b) (((a)->dp=NULL,tclTomMathStubsPtr->tclBNInitBignumFromWideUInt((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#else +#define mp_init_i32(a,b) (((a)->dp=NULL,(TclBNInitBignumFromLong)((a),(int32_t)(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_l(a,b) (((a)->dp=NULL,(TclBNInitBignumFromLong)((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_ll(a,b) (((a)->dp=NULL,(TclBNInitBignumFromWideInt)((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_i64(a,b) (((a)->dp=NULL,(TclBNInitBignumFromWideInt)((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_u32(a,b) (((a)->dp=NULL,(TclBNInitBignumFromWideUInt)((a),(uint32_t)(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_ul(a,b) (((a)->dp=NULL,(TclBNInitBignumFromWideUInt)((a),(unsigned long)(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_ull(a,b) (((a)->dp=NULL,(TclBNInitBignumFromWideUInt)((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#define mp_init_u64(a,b) (((a)->dp=NULL,(TclBNInitBignumFromWideUInt)((a),(b)),(a)->dp)?MP_OKAY:MP_ERR) +#endif /* USE_TCL_STUBS */ #endif /* _TCLINTDECLS */ diff --git a/generic/tclTomMathInterface.c b/generic/tclTomMathInterface.c index c28b3b1..2dc8c2d 100644 --- a/generic/tclTomMathInterface.c +++ b/generic/tclTomMathInterface.c @@ -106,7 +106,7 @@ TclBN_revision(void) *---------------------------------------------------------------------- */ -void +int TclBNInitBignumFromLong( mp_int *a, long initVal) @@ -146,6 +146,7 @@ TclBNInitBignumFromLong( v >>= MP_DIGIT_BIT; } a->used = p - a->dp; + return MP_OKAY; } /* @@ -164,7 +165,7 @@ TclBNInitBignumFromLong( *---------------------------------------------------------------------- */ -void +int TclBNInitBignumFromWideInt( mp_int *a, /* Bignum to initialize */ Tcl_WideInt v) /* Initial value */ @@ -175,6 +176,7 @@ TclBNInitBignumFromWideInt( } else { TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)v); } + return MP_OKAY; } /* @@ -193,7 +195,7 @@ TclBNInitBignumFromWideInt( *---------------------------------------------------------------------- */ -void +int TclBNInitBignumFromWideUInt( mp_int *a, /* Bignum to initialize */ Tcl_WideUInt v) /* Initial value */ @@ -222,6 +224,7 @@ TclBNInitBignumFromWideUInt( v >>= MP_DIGIT_BIT; } a->used = p - a->dp; + return MP_OKAY; } /* -- cgit v0.12 From 3160edd84157a0015c5a24607b70561077dbb55a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 8 Nov 2019 21:56:52 +0000 Subject: Now that libtommath has mp_init_l/mp_init_ll/mp_init_ull, use those instead of the legacy TclBNInitBignumFromLong/TclBNInitBignumFromWideInt/TclBNInitBignumFromWideUInt --- generic/tclBasic.c | 2 +- generic/tclExecute.c | 4 +-- generic/tclObj.c | 2 +- generic/tclStrToD.c | 32 +++++++++++------------ generic/tclStubInit.c | 11 +------- generic/tclTomMath.decls | 15 ++++++----- generic/tclTomMathDecls.h | 61 ++++++++++++++++++++++++++++++++++--------- generic/tclTomMathInterface.c | 54 -------------------------------------- libtommath/bn_mp_init_ll.c | 2 +- libtommath/bn_mp_init_ull.c | 2 +- unix/Makefile.in | 15 ++++++++++- win/Makefile.in | 4 +++ win/makefile.vc | 4 +++ 13 files changed, 103 insertions(+), 105 deletions(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 59f656a..e67b25a 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -7891,7 +7891,7 @@ ExprAbsFunc( } goto unChanged; } else if (l == WIDE_MIN) { - TclBNInitBignumFromWideInt(&big, l); + mp_init_ll(&big, l); goto tooLarge; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l)); diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 1bcedff..bd73270 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -8072,7 +8072,7 @@ ExecuteExtendedBinaryMathOp( * Arguments are opposite sign; remainder is sum. */ - TclBNInitBignumFromWideInt(&big1, w1); + mp_init_ll(&big1, w1); mp_add(&big2, &big1, &big2); mp_clear(&big1); BIG_RESULT(&big2); @@ -8701,7 +8701,7 @@ ExecuteExtendedUnaryMathOp( if (w != WIDE_MIN) { WIDE_RESULT(-w); } - TclBNInitBignumFromWideInt(&big, w); + mp_init_ll(&big, w); break; default: Tcl_TakeBignumFromObj(NULL, valuePtr, &big); diff --git a/generic/tclObj.c b/generic/tclObj.c index 954c648..645b798 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -3604,7 +3604,7 @@ GetBignumFromObj( return TCL_OK; } if (objPtr->typePtr == &tclIntType) { - TclBNInitBignumFromWideInt(bignumValue, + mp_init_ll(bignumValue, objPtr->internalRep.wideValue); return TCL_OK; } diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 866ee10..0e35dbf 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -711,7 +711,7 @@ TclParseNumber( || (octalSignificandWide > ((Tcl_WideUInt)-1 >> shift)))) { octalSignificandOverflow = 1; - TclBNInitBignumFromWideUInt(&octalSignificandBig, + mp_init_ull(&octalSignificandBig, octalSignificandWide); } } @@ -828,7 +828,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, + mp_init_ull(&significandBig, significandWide); } } @@ -869,7 +869,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, + mp_init_ull(&significandBig, significandWide); } } @@ -1214,7 +1214,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_ull(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { @@ -1235,7 +1235,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_ull(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { @@ -1256,7 +1256,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || octalSignificandWide > (MOST_BITS + signum) >> shift)) { octalSignificandOverflow = 1; - TclBNInitBignumFromWideUInt(&octalSignificandBig, + mp_init_ull(&octalSignificandBig, octalSignificandWide); } if (shift) { @@ -1269,7 +1269,7 @@ TclParseNumber( } if (!octalSignificandOverflow) { if (octalSignificandWide > (MOST_BITS + signum)) { - TclBNInitBignumFromWideUInt(&octalSignificandBig, + mp_init_ull(&octalSignificandBig, octalSignificandWide); octalSignificandOverflow = 1; } else { @@ -1297,12 +1297,12 @@ TclParseNumber( &significandWide, &significandBig, significandOverflow); if (!significandOverflow && (significandWide > MOST_BITS+signum)){ significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_ull(&significandBig, significandWide); } returnInteger: if (!significandOverflow) { if (significandWide > MOST_BITS+signum) { - TclBNInitBignumFromWideUInt(&significandBig, + mp_init_ull(&significandBig, significandWide); significandOverflow = 1; } else { @@ -1457,7 +1457,7 @@ AccumulateDecimalDigit( * bignum and fall through into the bignum case. */ - TclBNInitBignumFromWideUInt(bignumRepPtr, w); + mp_init_ull(bignumRepPtr, w); } else { /* * Wide multiplication. @@ -1600,7 +1600,7 @@ MakeLowPrecisionDouble( * call MakeHighPrecisionDouble to do it the hard way. */ - TclBNInitBignumFromWideUInt(&significandBig, significand); + mp_init_ull(&significandBig, significand); retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs, exponent); mp_clear(&significandBig); @@ -3267,7 +3267,7 @@ ShorteningBignumConversionPowD( * mminus = 5**m5 */ - TclBNInitBignumFromWideUInt(&b, bw); + mp_init_ull(&b, bw); mp_init_set(&mminus, 1); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); @@ -3451,7 +3451,7 @@ StrictBignumConversionPowD( * b = bw * 2**b2 * 5**b5 */ - TclBNInitBignumFromWideUInt(&b, bw); + mp_init_ull(&b, bw); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); @@ -3651,7 +3651,7 @@ ShorteningBignumConversion( * S = 2**s2 * 5*s5 */ - TclBNInitBignumFromWideUInt(&b, bw); + mp_init_ull(&b, bw); mp_mul_2d(&b, b2, &b); mp_init_set(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); @@ -3860,7 +3860,7 @@ StrictBignumConversion( */ mp_init_multi(&dig, NULL); - TclBNInitBignumFromWideUInt(&b, bw); + mp_init_ull(&b, bw); mp_mul_2d(&b, b2, &b); mp_init_set(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); @@ -4503,7 +4503,7 @@ Tcl_InitBignumFromDouble( Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits); int shift = expt - mantBits; - TclBNInitBignumFromWideInt(b, w); + mp_init_ll(b, w); if (shift < 0) { mp_div_2d(b, -shift, b, NULL); } else if (shift > 0) { diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 6f3b2e9..511c4a6 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -57,7 +57,6 @@ #undef TclWinSetSockOpt #undef TclWinNToHS #undef TclStaticPackage -#undef TclBNInitBignumFromLong #undef Tcl_BackgroundError #define TclStaticPackage Tcl_StaticPackage #undef Tcl_UniCharToUtfDString @@ -155,9 +154,6 @@ void TclBN_mp_set(mp_int *a, unsigned int b) { # define TclWinResetInterfaces 0 # define TclWinSetInterfaces 0 # define TclWinGetPlatformId 0 -# define TclBNInitBignumFromWideUInt 0 -# define TclBNInitBignumFromWideInt 0 -# define TclBNInitBignumFromLong 0 # define Tcl_Backslash 0 # define Tcl_GetDefaultEncodingDir 0 # define Tcl_SetDefaultEncodingDir 0 @@ -217,11 +213,6 @@ mp_err mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) return mp_to_radix(a, str, (size_t)maxlen, NULL, radix); } -#define TclBNInitBignumFromLong initBignumFromLong -static void TclBNInitBignumFromLong(mp_int *a, long b) -{ - TclBNInitBignumFromWideInt(a, b); -} #define TclSetStartupScriptPath setStartupScriptPath static void TclSetStartupScriptPath(Tcl_Obj *path) { @@ -1056,7 +1047,7 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_mp_get_mag_ull, /* 69 */ TclBN_mp_set_ll, /* 70 */ TclBN_mp_get_mag_ul, /* 71 */ - 0, /* 72 */ + TclBN_mp_set_l, /* 72 */ TclBN_mp_tc_and, /* 73 */ TclBN_mp_tc_or, /* 74 */ TclBN_mp_tc_xor, /* 75 */ diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index b83059e..964b5a7 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -223,14 +223,14 @@ declare 63 { # Formerly internal API to allow initialisation of bignums without knowing the # typedefs of how a bignum works internally. -declare 64 {deprecated {Use mp_init() + mp_set_l()}} { - void TclBNInitBignumFromLong(mp_int *bignum, long initVal) +declare 64 { + int TclBNInitBignumFromLong(mp_int *bignum, long initVal) } -declare 65 {deprecated {Use mp_init() + mp_set_ll()}} { - void TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal) +declare 65 { + int TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal) } -declare 66 {deprecated {Use mp_init() + mp_set_ull()}} { - void TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal) +declare 66 { + int TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal) } # Added in libtommath 1.0 @@ -250,6 +250,9 @@ declare 70 { declare 71 { unsigned long MP_WUR TclBN_mp_get_mag_ul(const mp_int *a) } +declare 72 { + void TclBN_mp_set_l(mp_int *a, long i) +} # Added in libtommath 1.1.0 declare 73 { diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index a7b8dcd..7588d96 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -85,10 +85,13 @@ MODULE_SCOPE mp_err TclBN_s_mp_expt_u32(const mp_int *a, unsigned int b, mp_int #define mp_grow TclBN_mp_grow #define mp_init TclBN_mp_init #define mp_init_copy TclBN_mp_init_copy +#define mp_init_l TclBNInitBignumFromLong +#define mp_init_ll TclBNInitBignumFromWideInt #define mp_init_multi TclBN_mp_init_multi #define mp_init_set_int(a,i) (MP_DEPRECATED_PRAGMA("replaced by mp_init_ul") TclBN_mp_init_ul(a,(unsigned int)(i))) #define mp_init_size TclBN_mp_init_size #define mp_init_ul TclBN_mp_init_ul +#define mp_init_ull TclBNInitBignumFromWideUInt #define mp_lshd TclBN_mp_lshd #define mp_mod TclBN_mp_mod #define mp_mod_2d TclBN_mp_mod_2d @@ -101,6 +104,7 @@ MODULE_SCOPE mp_err TclBN_s_mp_expt_u32(const mp_int *a, unsigned int b, mp_int #define mp_read_radix TclBN_mp_read_radix #define mp_rshd TclBN_mp_rshd #define mp_set_int(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_ul") (TclBN_mp_set_ul((a),((unsigned int)(b))),MP_OKAY)) +#define mp_set_l TclBN_mp_set_l #define mp_set_ll TclBN_mp_set_ll #define mp_set_long(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_ul") (TclBN_mp_set_ul((a),(b)),MP_OKAY)) #define mp_set_long_long(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_ull") (TclBN_mp_set_ull((a),(b)),MP_OKAY)) @@ -334,15 +338,12 @@ EXTERN void TclBN_mp_set_ul(mp_int *a, unsigned long i); /* 63 */ EXTERN int TclBN_mp_cnt_lsb(const mp_int *a) MP_WUR; /* 64 */ -TCL_DEPRECATED("Use mp_init() + mp_set_l()") -void TclBNInitBignumFromLong(mp_int *bignum, long initVal); +EXTERN int TclBNInitBignumFromLong(mp_int *bignum, long initVal); /* 65 */ -TCL_DEPRECATED("Use mp_init() + mp_set_ll()") -void TclBNInitBignumFromWideInt(mp_int *bignum, +EXTERN int TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal); /* 66 */ -TCL_DEPRECATED("Use mp_init() + mp_set_ull()") -void TclBNInitBignumFromWideUInt(mp_int *bignum, +EXTERN int TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal); /* 67 */ TCL_DEPRECATED("Use mp_expt_u32") @@ -356,7 +357,8 @@ EXTERN Tcl_WideUInt TclBN_mp_get_mag_ull(const mp_int *a) MP_WUR; EXTERN void TclBN_mp_set_ll(mp_int *a, Tcl_WideInt i); /* 71 */ EXTERN unsigned long TclBN_mp_get_mag_ul(const mp_int *a) MP_WUR; -/* Slot 72 is reserved */ +/* 72 */ +EXTERN void TclBN_mp_set_l(mp_int *a, long i); /* 73 */ EXTERN mp_err TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; @@ -448,15 +450,15 @@ typedef struct TclTomMathStubs { mp_err (*tclBN_mp_init_ul) (mp_int *a, unsigned long i) MP_WUR; /* 61 */ void (*tclBN_mp_set_ul) (mp_int *a, unsigned long i); /* 62 */ int (*tclBN_mp_cnt_lsb) (const mp_int *a) MP_WUR; /* 63 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_l()") void (*tclBNInitBignumFromLong) (mp_int *bignum, long initVal); /* 64 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_ll()") void (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_ull()") void (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ + int (*tclBNInitBignumFromLong) (mp_int *bignum, long initVal); /* 64 */ + int (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ + int (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ TCL_DEPRECATED_API("Use mp_expt_u32") mp_err (*tclBN_mp_expt_d_ex) (const mp_int *a, unsigned int b, mp_int *c, int fast); /* 67 */ void (*tclBN_mp_set_ull) (mp_int *a, Tcl_WideUInt i); /* 68 */ Tcl_WideUInt (*tclBN_mp_get_mag_ull) (const mp_int *a) MP_WUR; /* 69 */ void (*tclBN_mp_set_ll) (mp_int *a, Tcl_WideInt i); /* 70 */ unsigned long (*tclBN_mp_get_mag_ul) (const mp_int *a) MP_WUR; /* 71 */ - void (*reserved72)(void); + void (*tclBN_mp_set_l) (mp_int *a, long i); /* 72 */ mp_err (*tclBN_mp_tc_and) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 73 */ mp_err (*tclBN_mp_tc_or) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 74 */ mp_err (*tclBN_mp_tc_xor) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 75 */ @@ -623,7 +625,8 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_mp_set_ll) /* 70 */ #define TclBN_mp_get_mag_ul \ (tclTomMathStubsPtr->tclBN_mp_get_mag_ul) /* 71 */ -/* Slot 72 is reserved */ +#define TclBN_mp_set_l \ + (tclTomMathStubsPtr->tclBN_mp_set_l) /* 72 */ #define TclBN_mp_tc_and \ (tclTomMathStubsPtr->tclBN_mp_tc_and) /* 73 */ #define TclBN_mp_tc_or \ @@ -675,4 +678,38 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; # define mp_sqr TclBN_mp_sqr #endif +#ifdef USE_TCL_STUBS +#undef TclBNInitBignumFromLong +#define TclBNInitBignumFromLong(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)tclTomMathStubsPtr->tclBNInitBignumFromLong((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromLong"); \ + } \ + } while (0) +#undef TclBNInitBignumFromWideInt +#define TclBNInitBignumFromWideInt(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)tclTomMathStubsPtr->tclBNInitBignumFromWideInt((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromWideInt"); \ + } \ + } while (0) +#undef TclBNInitBignumFromWideUInt +#define TclBNInitBignumFromWideUInt(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)tclTomMathStubsPtr->tclBNInitBignumFromWideUInt((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt"); \ + } \ + } while (0) +#else +#endif /* USE_TCL_STUBS */ +#define mp_init_i32(a,b) mp_init_l((a),(int32_t)(b)) +#define mp_init_i64(a,b) mp_init_ll((a),(b)) +#define mp_init_u32(a,b) mp_init_ull((a),(uint32_t)(b)) +#define mp_init_u64(a,b) mp_init_ull((a),(b)) #endif /* _TCLINTDECLS */ diff --git a/generic/tclTomMathInterface.c b/generic/tclTomMathInterface.c index 9cb5c37..576929c 100644 --- a/generic/tclTomMathInterface.c +++ b/generic/tclTomMathInterface.c @@ -91,60 +91,6 @@ TclBN_revision(void) } /* - *---------------------------------------------------------------------- - * - * TclBNInitBignumFromWideInt -- - * - * Allocate and initialize a 'bignum' from a Tcl_WideInt - * - * Results: - * None. - * - * Side effects: - * The 'bignum' is constructed. - * - *---------------------------------------------------------------------- - */ - -void -TclBNInitBignumFromWideInt( - mp_int *a, /* Bignum to initialize */ - Tcl_WideInt v) /* Initial value */ -{ - if (mp_init(a) != MP_OKAY) { - Tcl_Panic("insufficient memory to create bignum"); - } - mp_set_ll(a, v); -} - -/* - *---------------------------------------------------------------------- - * - * TclBNInitBignumFromWideUInt -- - * - * Allocate and initialize a 'bignum' from a Tcl_WideUInt - * - * Results: - * None. - * - * Side effects: - * The 'bignum' is constructed. - * - *---------------------------------------------------------------------- - */ - -void -TclBNInitBignumFromWideUInt( - mp_int *a, /* Bignum to initialize */ - Tcl_WideUInt v) /* Initial value */ -{ - if (mp_init(a) != MP_OKAY) { - Tcl_Panic("insufficient memory to create bignum"); - } - mp_set_ull(a, v); -} - -/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/libtommath/bn_mp_init_ll.c b/libtommath/bn_mp_init_ll.c index dc7c4a4..484d51c 100644 --- a/libtommath/bn_mp_init_ll.c +++ b/libtommath/bn_mp_init_ll.c @@ -3,5 +3,5 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ -MP_INIT_INT(mp_init_ll, mp_set_ll, long long) +MP_INIT_INT(mp_init_ll, mp_set_ll, Tcl_WideInt) #endif diff --git a/libtommath/bn_mp_init_ull.c b/libtommath/bn_mp_init_ull.c index 84110c0..92ad9f9 100644 --- a/libtommath/bn_mp_init_ull.c +++ b/libtommath/bn_mp_init_ull.c @@ -3,5 +3,5 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ -MP_INIT_INT(mp_init_ull, mp_set_ull, unsigned long long) +MP_INIT_INT(mp_init_ull, mp_set_ull, Tcl_WideUInt) #endif diff --git a/unix/Makefile.in b/unix/Makefile.in index b26faf9..218d48d 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -331,12 +331,13 @@ TOMMATH_OBJS = bn_s_mp_reverse.o bn_s_mp_mul_digs_fast.o \ bn_s_mp_get_bit.o bn_mp_get_mag_ul.o bn_mp_grow.o bn_mp_init.o \ bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \ bn_mp_init_size.o bn_mp_init_ul.o bn_s_mp_karatsuba_mul.o \ + bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_ull.o \ bn_s_mp_karatsuba_sqr.o bn_s_mp_balance_mul.o \ bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mul.o bn_mp_mul_2.o \ bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_neg.o bn_mp_or.o \ bn_mp_radix_size.o bn_mp_radix_smap.o \ bn_mp_read_radix.o bn_mp_rshd.o bn_mp_set.o bn_mp_set_ul.o \ - bn_mp_shrink.o \ + bn_mp_shrink.o bn_mp_set_l.o \ bn_mp_sqr.o bn_mp_sqrt.o bn_mp_sub.o bn_mp_sub_d.o \ bn_mp_signed_rsh.o \ bn_mp_to_ubin.o \ @@ -1625,6 +1626,12 @@ bn_mp_init.o: $(TOMMATH_DIR)/bn_mp_init.c $(MATHHDRS) bn_mp_init_copy.o: $(TOMMATH_DIR)/bn_mp_init_copy.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_copy.c +bn_mp_init_l.o:$(TOMMATH_DIR)/bn_mp_init_l.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_l.c + +bn_mp_init_ll.o:$(TOMMATH_DIR)/bn_mp_init_ll.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_ll.c + bn_mp_init_multi.o: $(TOMMATH_DIR)/bn_mp_init_multi.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_multi.c @@ -1637,6 +1644,9 @@ bn_mp_init_size.o:$(TOMMATH_DIR)/bn_mp_init_size.c $(MATHHDRS) bn_mp_init_ul.o:$(TOMMATH_DIR)/bn_mp_init_ul.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_ul.c +bn_mp_init_ull.o:$(TOMMATH_DIR)/bn_mp_init_ull.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_ull.c + bn_s_mp_karatsuba_mul.o: $(TOMMATH_DIR)/bn_s_mp_karatsuba_mul.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_karatsuba_mul.c @@ -1688,6 +1698,9 @@ bn_mp_rshd.o: $(TOMMATH_DIR)/bn_mp_rshd.c $(MATHHDRS) bn_mp_set.o: $(TOMMATH_DIR)/bn_mp_set.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set.c +bn_mp_set_l.o: $(TOMMATH_DIR)/bn_mp_set_l.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set_l.c + bn_mp_set_ul.o: $(TOMMATH_DIR)/bn_mp_set_ul.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set_ul.c diff --git a/win/Makefile.in b/win/Makefile.in index 8c8ed44..55744eb 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -384,10 +384,13 @@ TOMMATH_OBJS = \ bn_mp_grow.${OBJEXT} \ bn_mp_init.${OBJEXT} \ bn_mp_init_copy.${OBJEXT} \ + bn_mp_init_l.${OBJEXT} \ + bn_mp_init_ll.${OBJEXT} \ bn_mp_init_multi.${OBJEXT} \ bn_mp_init_set.${OBJEXT} \ bn_mp_init_size.${OBJEXT} \ bn_mp_init_ul.${OBJEXT} \ + bn_mp_init_ull.${OBJEXT} \ bn_mp_lshd.${OBJEXT} \ bn_mp_mod.${OBJEXT} \ bn_mp_mod_2d.${OBJEXT} \ @@ -402,6 +405,7 @@ TOMMATH_OBJS = \ bn_mp_read_radix.${OBJEXT} \ bn_mp_rshd.${OBJEXT} \ bn_mp_set.${OBJEXT} \ + bn_mp_set_l.${OBJEXT} \ bn_mp_set_ul.${OBJEXT} \ bn_mp_shrink.${OBJEXT} \ bn_mp_sqr.${OBJEXT} \ diff --git a/win/makefile.vc b/win/makefile.vc index 19911fd..216d5d9 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -340,10 +340,13 @@ TOMMATHOBJS = \ $(TMP_DIR)\bn_mp_grow.obj \ $(TMP_DIR)\bn_mp_init.obj \ $(TMP_DIR)\bn_mp_init_copy.obj \ + $(TMP_DIR)\bn_mp_init_l.obj \ + $(TMP_DIR)\bn_mp_init_ll.obj \ $(TMP_DIR)\bn_mp_init_multi.obj \ $(TMP_DIR)\bn_mp_init_set.obj \ $(TMP_DIR)\bn_mp_init_size.obj \ $(TMP_DIR)\bn_mp_init_ul.obj \ + $(TMP_DIR)\bn_mp_init_ull.obj \ $(TMP_DIR)\bn_mp_lshd.obj \ $(TMP_DIR)\bn_mp_mod.obj \ $(TMP_DIR)\bn_mp_mod_2d.obj \ @@ -358,6 +361,7 @@ TOMMATHOBJS = \ $(TMP_DIR)\bn_mp_read_radix.obj \ $(TMP_DIR)\bn_mp_rshd.obj \ $(TMP_DIR)\bn_mp_set.obj \ + $(TMP_DIR)\bn_mp_set_l.obj \ $(TMP_DIR)\bn_mp_set_ul.obj \ $(TMP_DIR)\bn_mp_shrink.obj \ $(TMP_DIR)\bn_mp_sqr.obj \ -- cgit v0.12 From e85c33074d52d9b69f1c521915615e8660f07d33 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 11 Nov 2019 16:32:42 +0000 Subject: On win32, include if available, just as on UNIX. Disable compiler warning C4244 on all Microsoft compiler versions, not just the latest ones. --- win/tclWinPort.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/win/tclWinPort.h b/win/tclWinPort.h index c30d346..e9ae9dc 100644 --- a/win/tclWinPort.h +++ b/win/tclWinPort.h @@ -14,6 +14,7 @@ #ifndef _TCLWINPORT #define _TCLWINPORT + #if !defined(_WIN64) && !defined(__MINGW_USE_VC2005_COMPAT) /* See [Bug 3354324]: file mtime sets wrong time */ # define __MINGW_USE_VC2005_COMPAT @@ -62,6 +63,9 @@ typedef DWORD_PTR * PDWORD_PTR; #include #include #include +#if HAVE_INTTYPES_H +# include +#endif #include #ifndef __GNUC__ @@ -379,12 +383,14 @@ typedef DWORD_PTR * PDWORD_PTR; * including the *printf family and others. Tell it to shut up. * (_MSC_VER is 1200 for VC6, 1300 or 1310 for vc7.net, 1400 for 8.0) */ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#if defined(_MSC_VER) # pragma warning(disable:4244) -# pragma warning(disable:4267) -# pragma warning(disable:4311) -# pragma warning(disable:4312) -# pragma warning(disable:4996) +# if _MSC_VER >= 1400 +# pragma warning(disable:4267) +# pragma warning(disable:4311) +# pragma warning(disable:4312) +# pragma warning(disable:4996) +# endif #endif -- cgit v0.12 From de04d595faa9eff7914a831e767b11a2d5116b44 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Nov 2019 08:16:51 +0000 Subject: Fix compiler warning when compiling with -DTCL_UTF_MAX=4 or 6 --- win/tclWinDde.c | 4 ++-- win/tclWinReg.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/win/tclWinDde.c b/win/tclWinDde.c index cbbcdae..267ee6e 100644 --- a/win/tclWinDde.c +++ b/win/tclWinDde.c @@ -119,8 +119,8 @@ static int DdeObjCmd(void *clientData, #if (TCL_MAJOR_VERSION < 9) && (TCL_MINOR_VERSION < 7) # if TCL_UTF_MAX > 3 -# define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf(a,(b)*sizeof(WCHAR),c) -# define Tcl_UtfToWCharDString(a,b,c) Tcl_WinUtfToTChar(a,b,c) +# define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf((TCHAR *)(a),(b)*sizeof(WCHAR),c) +# define Tcl_UtfToWCharDString(a,b,c) (WCHAR *)Tcl_WinUtfToTChar(a,b,c) # else # define Tcl_WCharToUtfDString Tcl_UniCharToUtfDString # define Tcl_UtfToWCharDString Tcl_UtfToUniCharDString diff --git a/win/tclWinReg.c b/win/tclWinReg.c index b66282a..2c1b8a5 100644 --- a/win/tclWinReg.c +++ b/win/tclWinReg.c @@ -126,8 +126,8 @@ static int SetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj, #if (TCL_MAJOR_VERSION < 9) && (TCL_MINOR_VERSION < 7) # if TCL_UTF_MAX > 3 -# define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf(a,(b)*sizeof(WCHAR),c) -# define Tcl_UtfToWCharDString(a,b,c) Tcl_WinUtfToTChar(a,b,c) +# define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf((TCHAR *)(a),(b)*sizeof(WCHAR),c) +# define Tcl_UtfToWCharDString(a,b,c) (WCHAR *)Tcl_WinUtfToTChar(a,b,c) # else # define Tcl_WCharToUtfDString Tcl_UniCharToUtfDString # define Tcl_UtfToWCharDString Tcl_UtfToUniCharDString -- cgit v0.12 From 3181ee9123bf2402abeba55ca2b9469d74382ed1 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Nov 2019 09:07:08 +0000 Subject: Fix TIP #389 implementation, bug [d433c0e0ad]: TCL_UTF_MAX == 4 problems. Thanks to Christian Werner for the report. --- generic/tclEncoding.c | 2 +- generic/tclInt.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 002c765..1c1f94c 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -2366,7 +2366,7 @@ UtfToUtfProc( dst += Tcl_UniCharToUtf(*chPtr, dst); #if TCL_UTF_MAX == 4 if ((*chPtr >= 0xD800) && (len < 3)) { - src += TclUtfToUniChar(src + len, chPtr); + src += Tcl_UtfToUniChar(src + len, chPtr); dst += Tcl_UniCharToUtf(*chPtr, dst); } #endif diff --git a/generic/tclInt.h b/generic/tclInt.h index 9038a56..39fb740 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4429,7 +4429,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, */ #define TclUtfToUniChar(str, chPtr) \ - ((((unsigned char) *(str)) < 0xC0) ? \ + ((((unsigned char) *(str)) < 0x80) ? \ ((*(chPtr) = (unsigned char) *(str)), 1) \ : Tcl_UtfToUniChar(str, chPtr)) -- cgit v0.12 From d3315530e8ae5a6b4dd6fce55c2bea70f4798131 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Nov 2019 12:37:24 +0000 Subject: Part 2 of bugfix [d433c0e0ad]: TCL_UTF_MAX == 4 problems --- generic/tclEncoding.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 1c1f94c..f159b32 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -2366,7 +2366,7 @@ UtfToUtfProc( dst += Tcl_UniCharToUtf(*chPtr, dst); #if TCL_UTF_MAX == 4 if ((*chPtr >= 0xD800) && (len < 3)) { - src += Tcl_UtfToUniChar(src + len, chPtr); + src += Tcl_UtfToUniChar(src, chPtr); dst += Tcl_UniCharToUtf(*chPtr, dst); } #endif -- cgit v0.12 From db160493def9e4d6ec6cb55fe788a5784447f1c5 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Nov 2019 15:59:11 +0000 Subject: Don't install tommath_class.h and tommath_superclass.h on Windows any more by makefile.vc. Those are purely internal, not needed by extensions. --- win/makefile.vc | 2 -- 1 file changed, 2 deletions(-) diff --git a/win/makefile.vc b/win/makefile.vc index 01cdb1f..6a428aa 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -893,8 +893,6 @@ install-libraries: tclConfig tcl-nmake install-msgs install-tzdata @$(CPY) "$(GENERICDIR)\tclPlatDecls.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclTomMath.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclTomMathDecls.h" "$(INCLUDE_INSTALL_DIR)\" - @$(CPY) "$(TOMMATHDIR)\tommath_class.h" "$(INCLUDE_INSTALL_DIR)\" - @$(CPY) "$(TOMMATHDIR)\tommath_superclass.h" "$(INCLUDE_INSTALL_DIR)\" @echo Installing library files to $(SCRIPT_INSTALL_DIR) @$(CPY) "$(ROOT)\library\history.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\init.tcl" "$(SCRIPT_INSTALL_DIR)\" -- cgit v0.12 From ed907ec2d18048ab42baa3a8a6b4436894dc8912 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Nov 2019 16:01:35 +0000 Subject: Make tclWinFile compile warningless using -DTCL_UTF_MAX=6 (not officially supported, but used by Androwish) --- win/tclWinFile.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 20cd6d4..e050862 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -1472,14 +1472,14 @@ TclpGetUserHome( Tcl_DStringFree(&ds); } else { Tcl_DStringInit(&ds); - wName = Tcl_UtfToUniCharDString(domain + 1, -1, &ds); + wName = (WCHAR *)Tcl_WinUtfToTChar(domain + 1, -1, &ds); rc = NetGetDCName(NULL, wName, (LPBYTE *) &wDomain); Tcl_DStringFree(&ds); nameLen = domain - name; } if (rc == 0) { Tcl_DStringInit(&ds); - wName = Tcl_UtfToUniCharDString(name, nameLen, &ds); + wName = (WCHAR *)Tcl_WinUtfToTChar(name, nameLen, &ds); while (NetUserGetInfo(wDomain, wName, 1, (LPBYTE *) &uiPtr) != 0) { /* * User does not exist; if domain was not specified, try again @@ -1507,7 +1507,7 @@ TclpGetUserHome( wHomeDir = uiPtr->usri1_home_dir; if ((wHomeDir != NULL) && (wHomeDir[0] != L'\0')) { size = lstrlenW(wHomeDir); - Tcl_UniCharToUtfDString(wHomeDir, size, bufferPtr); + Tcl_WinTCharToUtf((TCHAR *)wHomeDir, size*sizeof(WCHAR), bufferPtr); } else { /* * User exists but has no home dir. Return @@ -1515,7 +1515,7 @@ TclpGetUserHome( */ GetProfilesDirectoryW(buf, &size); - Tcl_UniCharToUtfDString(buf, size-1, bufferPtr); + Tcl_WinTCharToUtf((TCHAR *)buf, (size-1)*sizeof(WCHAR), bufferPtr); Tcl_DStringAppend(bufferPtr, "/", 1); Tcl_DStringAppend(bufferPtr, name, nameLen); } -- cgit v0.12