summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2019-11-17 20:12:21 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2019-11-17 20:12:21 (GMT)
commit1b8114cd7186099f4c1d2d7a98a2dda31be3696b (patch)
treeb0c2fd1f42abef6ba767d004f841124b3a8a0483 /generic
parentbf1382a38f16c8a562dd89acb6c487739ba6d0fb (diff)
parent13ebaf6ca3645cf886c7fc686bdba2dcf339dbe6 (diff)
downloadtcl-1b8114cd7186099f4c1d2d7a98a2dda31be3696b.zip
tcl-1b8114cd7186099f4c1d2d7a98a2dda31be3696b.tar.gz
tcl-1b8114cd7186099f4c1d2d7a98a2dda31be3696b.tar.bz2
Merge 9.0
Diffstat (limited to 'generic')
-rw-r--r--generic/tcl.decls7
-rw-r--r--generic/tcl.h291
-rw-r--r--generic/tclBasic.c6
-rw-r--r--generic/tclBinary.c6
-rw-r--r--generic/tclCompile.c6
-rw-r--r--generic/tclDecls.h8
-rw-r--r--generic/tclEncoding.c174
-rw-r--r--generic/tclExecute.c16
-rw-r--r--generic/tclFileName.c5
-rw-r--r--generic/tclIOUtil.c2119
-rw-r--r--generic/tclInt.h13
-rw-r--r--generic/tclOO.c44
-rw-r--r--generic/tclOOInt.h14
-rw-r--r--generic/tclOOMethod.c8
-rw-r--r--generic/tclOOScript.h2
-rw-r--r--generic/tclOOScript.tcl456
-rw-r--r--generic/tclObj.c2
-rw-r--r--generic/tclPathObj.c198
-rw-r--r--generic/tclScan.c33
-rw-r--r--generic/tclStrToD.c72
-rw-r--r--generic/tclStubInit.c51
-rw-r--r--generic/tclTest.c2
-rw-r--r--generic/tclTestObj.c2
-rw-r--r--generic/tclTomMath.decls62
-rw-r--r--generic/tclTomMath.h100
-rw-r--r--generic/tclTomMathDecls.h176
-rw-r--r--generic/tclTomMathInterface.c60
-rw-r--r--generic/tclUtil.c6
28 files changed, 1644 insertions, 2295 deletions
diff --git a/generic/tcl.decls b/generic/tcl.decls
index 8b16a1b..2c72914 100644
--- a/generic/tcl.decls
+++ b/generic/tcl.decls
@@ -134,10 +134,9 @@ declare 28 {
declare 29 {
Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *objPtr)
}
-# Removed in 9.0
-#declare 30 {
-# void TclFreeObj(Tcl_Obj *objPtr)
-#}
+declare 30 {
+ void TclFreeObj(Tcl_Obj *objPtr)
+}
declare 31 {
int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *boolPtr)
}
diff --git a/generic/tcl.h b/generic/tcl.h
index d5c9d5f..5301b54 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -1483,7 +1483,7 @@ typedef struct Tcl_FSVersion_ *Tcl_FSVersion;
* struct Tcl_Filesystem:
*
* One such structure exists for each type (kind) of filesystem. It collects
- * together in one place all the functions that are part of the specific
+ * together the functions that form the interface for a particulr the
* filesystem. Tcl always accesses the filesystem through one of these
* structures.
*
@@ -1498,147 +1498,119 @@ typedef struct Tcl_Filesystem {
* compatibility can be assured. */
Tcl_FSVersion version; /* Version of the filesystem type. */
Tcl_FSPathInFilesystemProc *pathInFilesystemProc;
- /* Function to check whether a path is in this
+ /* Determines whether the pathname is in this
* filesystem. This is the most important
* filesystem function. */
Tcl_FSDupInternalRepProc *dupInternalRepProc;
- /* Function to duplicate internal fs rep. May
- * be NULL (but then fs is less efficient). */
+ /* Duplicates the internal handle of the node.
+ * If it is NULL, the filesystem is less
+ * performant. */
Tcl_FSFreeInternalRepProc *freeInternalRepProc;
- /* Function to free internal fs rep. Must be
- * implemented if internal representations
- * need freeing, otherwise it can be NULL. */
+ /* Frees the internal handle of the node. NULL
+ * only if there is no need to free resources
+ * used for the internal handle. */
Tcl_FSInternalToNormalizedProc *internalToNormalizedProc;
- /* Function to convert internal representation
- * to a normalized path. Only required if the
- * fs creates pure path objects with no
- * string/path representation. */
+ /* Converts the internal handle to a normalized
+ * path. NULL if the filesystem creates nodes
+ * having no pathname. */
Tcl_FSCreateInternalRepProc *createInternalRepProc;
- /* Function to create a filesystem-specific
- * internal representation. May be NULL if
- * paths have no internal representation, or
- * if the Tcl_FSPathInFilesystemProc for this
- * filesystem always immediately creates an
- * internal representation for paths it
- * accepts. */
+ /* Creates an internal handle for a pathname.
+ * May be NULL if pathnames have no internal
+ * handle or if pathInFilesystemProc always
+ * immediately creates an internal
+ * representation for pathnames in the
+ * filesystem. */
Tcl_FSNormalizePathProc *normalizePathProc;
- /* Function to normalize a path. Should be
- * implemented for all filesystems which can
- * have multiple string representations for
- * the same path object. */
+ /* Normalizes a path. Should be implemented if
+ * the filesystems supports multiple paths to
+ * the same node. */
Tcl_FSFilesystemPathTypeProc *filesystemPathTypeProc;
- /* Function to determine the type of a path in
- * this filesystem. May be NULL. */
+ /* Determines the type of a path in this
+ * filesystem. May be NULL. */
Tcl_FSFilesystemSeparatorProc *filesystemSeparatorProc;
- /* Function to return the separator
- * character(s) for this filesystem. Must be
- * implemented. */
- Tcl_FSStatProc *statProc; /* Function to process a 'Tcl_FSStat()' call.
- * Must be implemented for any reasonable
- * filesystem. */
- Tcl_FSAccessProc *accessProc;
- /* Function to process a 'Tcl_FSAccess()'
- * call. Must be implemented for any
+ /* Produces the separator character(s) for this
+ * filesystem. Must not be NULL. */
+ Tcl_FSStatProc *statProc; /* Called by 'Tcl_FSStat()'. Provided by any
* reasonable filesystem. */
+ Tcl_FSAccessProc *accessProc;
+ /* Called by 'Tcl_FSAccess()'. Implemented by
+ * any reasonable filesystem. */
Tcl_FSOpenFileChannelProc *openFileChannelProc;
- /* Function to process a
- * 'Tcl_FSOpenFileChannel()' call. Must be
- * implemented for any reasonable
- * filesystem. */
+ /* Called by 'Tcl_FSOpenFileChannel()'.
+ * Provided by any reasonable filesystem. */
Tcl_FSMatchInDirectoryProc *matchInDirectoryProc;
- /* Function to process a
- * 'Tcl_FSMatchInDirectory()'. If not
- * implemented, then glob and recursive copy
- * functionality will be lacking in the
- * filesystem. */
- Tcl_FSUtimeProc *utimeProc; /* Function to process a 'Tcl_FSUtime()' call.
- * Required to allow setting (not reading) of
- * times with 'file mtime', 'file atime' and
- * the open-r/open-w/fcopy implementation of
- * 'file copy'. */
- Tcl_FSLinkProc *linkProc; /* Function to process a 'Tcl_FSLink()' call.
- * Should be implemented only if the
- * filesystem supports links (reading or
- * creating). */
+ /* Called by 'Tcl_FSMatchInDirectory()'. NULL
+ * if the filesystem does not support glob or
+ * recursive copy. */
+ Tcl_FSUtimeProc *utimeProc; /* Called by 'Tcl_FSUtime()', by 'file
+ * mtime' to set (not read) times, 'file
+ * atime', and the open-r/open-w/fcopy variant
+ * of 'file copy'. */
+ Tcl_FSLinkProc *linkProc; /* Called by 'Tcl_FSLink()'. NULL if reading or
+ * creating links is not supported. */
Tcl_FSListVolumesProc *listVolumesProc;
- /* Function to list any filesystem volumes
- * added by this filesystem. Should be
- * implemented only if the filesystem adds
- * volumes at the head of the filesystem. */
+ /* Lists filesystem volumes added by this
+ * filesystem. NULL if the filesystem does not
+ * use volumes. */
Tcl_FSFileAttrStringsProc *fileAttrStringsProc;
- /* Function to list all attributes strings
- * which are valid for this filesystem. If not
- * implemented the filesystem will not support
- * the 'file attributes' command. This allows
- * arbitrary additional information to be
- * attached to files in the filesystem. */
+ /* List all valid attributes strings. NULL if
+ * the filesystem does not support the 'file
+ * attributes' command. Can be used to attach
+ * arbitrary additional data to files in a
+ * filesystem. */
Tcl_FSFileAttrsGetProc *fileAttrsGetProc;
- /* Function to process a
- * 'Tcl_FSFileAttrsGet()' call, used by 'file
- * attributes'. */
+ /* Called by 'Tcl_FSFileAttrsGet()' and by
+ * 'file attributes'. */
Tcl_FSFileAttrsSetProc *fileAttrsSetProc;
- /* Function to process a
- * 'Tcl_FSFileAttrsSet()' call, used by 'file
- * attributes'. */
+ /* Called by 'Tcl_FSFileAttrsSet()' and by
+ * 'file attributes'. */
Tcl_FSCreateDirectoryProc *createDirectoryProc;
- /* Function to process a
- * 'Tcl_FSCreateDirectory()' call. Should be
- * implemented unless the FS is read-only. */
+ /* Called by 'Tcl_FSCreateDirectory()'. May be
+ * NULL if the filesystem is read-only. */
Tcl_FSRemoveDirectoryProc *removeDirectoryProc;
- /* Function to process a
- * 'Tcl_FSRemoveDirectory()' call. Should be
- * implemented unless the FS is read-only. */
+ /* Called by 'Tcl_FSRemoveDirectory()'. May be
+ * NULL if the filesystem is read-only. */
Tcl_FSDeleteFileProc *deleteFileProc;
- /* Function to process a 'Tcl_FSDeleteFile()'
- * call. Should be implemented unless the FS
- * is read-only. */
+ /* Called by 'Tcl_FSDeleteFile()' May be NULL
+ * if the filesystem is is read-only. */
Tcl_FSCopyFileProc *copyFileProc;
- /* Function to process a 'Tcl_FSCopyFile()'
- * call. If not implemented Tcl will fall back
- * on open-r, open-w and fcopy as a copying
- * mechanism, for copying actions initiated in
- * Tcl (not C). */
+ /* Called by 'Tcl_FSCopyFile()'. If NULL, for
+ * a copy operation at the script level (not
+ * C) Tcl uses open-r, open-w and fcopy. */
Tcl_FSRenameFileProc *renameFileProc;
- /* Function to process a 'Tcl_FSRenameFile()'
- * call. If not implemented, Tcl will fall
- * back on a copy and delete mechanism, for
- * rename actions initiated in Tcl (not C). */
+ /* Called by 'Tcl_FSRenameFile()'. If NULL, for
+ * a rename operation at the script level (not
+ * C) Tcl performs a copy operation followed
+ * by a delete operation. */
Tcl_FSCopyDirectoryProc *copyDirectoryProc;
- /* Function to process a
- * 'Tcl_FSCopyDirectory()' call. If not
- * implemented, Tcl will fall back on a
- * recursive create-dir, file copy mechanism,
- * for copying actions initiated in Tcl (not
- * C). */
- Tcl_FSLstatProc *lstatProc; /* Function to process a 'Tcl_FSLstat()' call.
- * If not implemented, Tcl will attempt to use
- * the 'statProc' defined above instead. */
+ /* Called by 'Tcl_FSCopyDirectory()'. If NULL,
+ * for a copy operation at the script level
+ * (not C) Tcl recursively creates directories
+ * and copies files. */
+ Tcl_FSLstatProc *lstatProc; /* Called by 'Tcl_FSLstat()'. If NULL, Tcl
+ * attempts to use 'statProc' instead. */
Tcl_FSLoadFileProc *loadFileProc;
- /* Function to process a 'Tcl_FSLoadFile()'
- * call. If not implemented, Tcl will fall
- * back on a copy to native-temp followed by a
- * Tcl_FSLoadFile on that temporary copy. */
+ /* Called by 'Tcl_FSLoadFile()'. If NULL, Tcl
+ * performs a copy to a temporary file in the
+ * native filesystem and then calls
+ * Tcl_FSLoadFile() on that temporary copy. */
Tcl_FSGetCwdProc *getCwdProc;
- /* Function to process a 'Tcl_FSGetCwd()'
- * call. Most filesystems need not implement
- * this. It will usually only be called once,
- * if 'getcwd' is called before 'chdir'. May
- * be NULL. */
- Tcl_FSChdirProc *chdirProc; /* Function to process a 'Tcl_FSChdir()' call.
- * If filesystems do not implement this, it
- * will be emulated by a series of directory
- * access checks. Otherwise, virtual
- * filesystems which do implement it need only
- * respond with a positive return result if
- * the dirName is a valid directory in their
- * filesystem. They need not remember the
- * result, since that will be automatically
- * remembered for use by GetCwd. Real
- * filesystems should carry out the correct
- * action (i.e. call the correct system
- * 'chdir' api). If not implemented, then 'cd'
- * and 'pwd' will fail inside the
- * filesystem. */
+ /* Called by 'Tcl_FSGetCwd()'. Normally NULL.
+ * Usually only called once: If 'getcwd' is
+ * called before 'chdir' is ever called. */
+ Tcl_FSChdirProc *chdirProc; /* Called by 'Tcl_FSChdir()'. For a virtual
+ * filesystem, chdirProc just returns zero
+ * (success) if the pathname is a valid
+ * directory, and some other value otherwise.
+ * For A real filesystem, chdirProc performs
+ * the correct action, e.g. calls the system
+ * 'chdir' function. If not implemented, then
+ * 'cd' and 'pwd' fail for a pathname in this
+ * filesystem. On success Tcl stores the
+ * pathname for use by GetCwd. If NULL, Tcl
+ * performs records the pathname as the new
+ * current directory if it passes a series of
+ * directory access checks. */
} Tcl_Filesystem;
/*
@@ -1899,29 +1871,28 @@ typedef struct Tcl_EncodingType {
* reset to an initial state. If the source
* buffer contains the entire input stream to be
* converted, this flag should be set.
- * TCL_ENCODING_STOPONERROR - If set, then the converter will return
- * immediately upon encountering an invalid byte
- * sequence or a source character that has no
- * mapping in the target encoding. If clear, then
- * the converter will skip the problem,
- * substituting one or more "close" characters in
- * the destination buffer and then continue to
+ * TCL_ENCODING_STOPONERROR - If set, the converter returns immediately upon
+ * encountering an invalid byte sequence or a
+ * source character that has no mapping in the
+ * target encoding. If clear, the converter
+ * substitues the problematic character(s) with
+ * one or more "close" characters in the
+ * destination buffer and then continues to
* convert the source.
- * TCL_ENCODING_NO_TERMINATE - If set, Tcl_ExternalToUtf will not append a
- * terminating NUL byte. Knowing that it will
- * not need space to do so, it will fill all
- * dstLen bytes with encoded UTF-8 content, as
- * other circumstances permit. If clear, the
- * default behavior is to reserve a byte in
- * the dst space for NUL termination, and to
- * append the NUL byte.
+ * TCL_ENCODING_NO_TERMINATE - If set, Tcl_ExternalToUtf does not append a
+ * terminating NUL byte. Since it does not need
+ * an extra byte for a terminating NUL, it fills
+ * all dstLen bytes with encoded UTF-8 content if
+ * needed. If clear, a byte is reserved in the
+ * dst space for NUL termination, and a
+ * terminating NUL is appended.
* TCL_ENCODING_CHAR_LIMIT - If set and dstCharsPtr is not NULL, then
- * Tcl_ExternalToUtf takes the initial value
- * of *dstCharsPtr is taken as a limit of the
- * maximum number of chars to produce in the
- * encoded UTF-8 content. Otherwise, the
- * number of chars produced is controlled only
- * by other limiting factors.
+ * Tcl_ExternalToUtf takes the initial value of
+ * *dstCharsPtr as a limit of the maximum number
+ * of chars to produce in the encoded UTF-8
+ * content. Otherwise, the number of chars
+ * produced is controlled only by other limiting
+ * factors.
*/
#define TCL_ENCODING_START 0x01
@@ -2031,8 +2002,6 @@ typedef void (Tcl_LimitHandlerDeleteProc) (void *clientData);
typedef struct mp_int mp_int;
#define MP_INT_DECLARED
-typedef unsigned int mp_digit;
-#define MP_DIGIT_DECLARED
/*
*----------------------------------------------------------------------------
@@ -2264,14 +2233,23 @@ EXTERN int TclZipfs_AppHook(int *argc, char ***argv);
/*
*----------------------------------------------------------------------------
* The following declarations map ckalloc and ckfree to Tcl_Alloc and
- * Tcl_Free.
+ * Tcl_Free for use in Tcl-8.x-compatible extensions.
*/
-#define ckalloc Tcl_Alloc
-#define ckfree Tcl_Free
-#define ckrealloc Tcl_Realloc
-#define attemptckalloc Tcl_AttemptAlloc
-#define attemptckrealloc Tcl_AttemptRealloc
+#ifndef BUILD_tcl
+# define ckalloc Tcl_Alloc
+# define attemptckalloc Tcl_AttemptAlloc
+# ifdef _MSC_VER
+ /* Silence invalid C4090 warnings */
+# define ckfree(a) Tcl_Free((char *)(a))
+# define ckrealloc(a,b) Tcl_Realloc((char *)(a),(b))
+# define attemptckrealloc(a,b) Tcl_AttemptRealloc((char *)(a),(b))
+# else
+# define ckfree Tcl_Free
+# define ckrealloc Tcl_Realloc
+# define attemptckrealloc Tcl_AttemptRealloc
+# endif
+#endif
#ifndef TCL_MEM_DEBUG
@@ -2300,6 +2278,25 @@ EXTERN int TclZipfs_AppHook(int *argc, char ***argv);
# undef Tcl_IsShared
# define Tcl_IsShared(objPtr) \
Tcl_DbIsShared(objPtr, __FILE__, __LINE__)
+#else
+# undef Tcl_IncrRefCount
+# define Tcl_IncrRefCount(objPtr) \
+ ++(objPtr)->refCount
+ /*
+ * Use do/while0 idiom for optimum correctness without compiler warnings.
+ * http://c2.com/cgi/wiki?TrivialDoWhileLoop
+ */
+# undef Tcl_DecrRefCount
+# define Tcl_DecrRefCount(objPtr) \
+ do { \
+ Tcl_Obj *_objPtr = (objPtr); \
+ if ((_objPtr)->refCount-- <= 1) { \
+ TclFreeObj(_objPtr); \
+ } \
+ } while(0)
+# undef Tcl_IsShared
+# define Tcl_IsShared(objPtr) \
+ ((objPtr)->refCount > 1)
#endif
/*
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index b4f9d2b..4d42d58 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -6892,7 +6892,7 @@ ExprIsqrtFunc(
if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
return TCL_ERROR;
}
- if (big.sign != MP_ZPOS) {
+ if (mp_isneg(&big)) {
mp_clear(&big);
goto negarg;
}
@@ -7138,7 +7138,7 @@ ExprAbsFunc(
}
goto unChanged;
} else if (l == WIDE_MIN) {
- TclInitBignumFromWideInt(&big, l);
+ mp_init_ll(&big, l);
goto tooLarge;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l));
@@ -7166,7 +7166,7 @@ ExprAbsFunc(
}
if (type == TCL_NUMBER_BIG) {
- if (((const mp_int *) ptr)->sign != MP_ZPOS) {
+ if (mp_isneg((const mp_int *) ptr)) {
Tcl_GetBignumFromObj(NULL, objv[1], &big);
tooLarge:
mp_neg(&big, &big);
diff --git a/generic/tclBinary.c b/generic/tclBinary.c
index 83c323b..9d7d3d4 100644
--- a/generic/tclBinary.c
+++ b/generic/tclBinary.c
@@ -2336,8 +2336,10 @@ ScanNumber(
Tcl_Obj *bigObj = NULL;
mp_int big;
- TclInitBignumFromWideUInt(&big, uwvalue);
- bigObj = Tcl_NewBignumObj(&big);
+ if (mp_init(&big) == MP_OKAY) {
+ mp_set_ull(&big, uwvalue);
+ bigObj = Tcl_NewBignumObj(&big);
+ }
return bigObj;
}
return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue);
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 1c284df..59c5ba0 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -2169,7 +2169,7 @@ TclCompileScript(
* many nested compilations (body enclosed in body) can cause abnormal
* program termination with a stack overflow exception, bug [fec0c17d39].
*/
- Tcl_Parse *parsePtr = ckalloc(sizeof(Tcl_Parse));
+ Tcl_Parse *parsePtr = Tcl_Alloc(sizeof(Tcl_Parse));
do {
const char *next;
@@ -2182,7 +2182,7 @@ TclCompileScript(
Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
parsePtr->term + 1 - parsePtr->commandStart);
TclCompileSyntaxError(interp, envPtr);
- ckfree(parsePtr);
+ Tcl_Free(parsePtr);
return;
}
@@ -2258,7 +2258,7 @@ TclCompileScript(
Tcl_FreeParse(parsePtr);
} while (numBytes > 0);
- ckfree(parsePtr);
+ Tcl_Free(parsePtr);
}
if (lastCmdIdx == -1) {
diff --git a/generic/tclDecls.h b/generic/tclDecls.h
index 210a094..e525b26 100644
--- a/generic/tclDecls.h
+++ b/generic/tclDecls.h
@@ -136,7 +136,8 @@ EXTERN Tcl_Obj * Tcl_DbNewStringObj(const char *bytes, size_t length,
const char *file, int line);
/* 29 */
EXTERN Tcl_Obj * Tcl_DuplicateObj(Tcl_Obj *objPtr);
-/* Slot 30 is reserved */
+/* 30 */
+EXTERN void TclFreeObj(Tcl_Obj *objPtr);
/* 31 */
EXTERN int Tcl_GetBoolean(Tcl_Interp *interp, const char *src,
int *boolPtr);
@@ -1823,7 +1824,7 @@ typedef struct TclStubs {
Tcl_Obj * (*tcl_DbNewObj) (const char *file, int line); /* 27 */
Tcl_Obj * (*tcl_DbNewStringObj) (const char *bytes, size_t length, const char *file, int line); /* 28 */
Tcl_Obj * (*tcl_DuplicateObj) (Tcl_Obj *objPtr); /* 29 */
- void (*reserved30)(void);
+ void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */
int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *boolPtr); /* 31 */
int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr); /* 32 */
unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */
@@ -2534,7 +2535,8 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_DbNewStringObj) /* 28 */
#define Tcl_DuplicateObj \
(tclStubsPtr->tcl_DuplicateObj) /* 29 */
-/* Slot 30 is reserved */
+#define TclFreeObj \
+ (tclStubsPtr->tclFreeObj) /* 30 */
#define Tcl_GetBoolean \
(tclStubsPtr->tcl_GetBoolean) /* 31 */
#define Tcl_GetBooleanFromObj \
diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c
index 93c1c59..afba9aa 100644
--- a/generic/tclEncoding.c
+++ b/generic/tclEncoding.c
@@ -83,7 +83,7 @@ typedef struct {
} TableEncodingData;
/*
- * The following structures is the clientData for a dynamically-loaded,
+ * Each of the following structures is the clientData for a dynamically-loaded
* escape-driven encoding that is itself comprised of other simpler encodings.
* An example is "iso-2022-jp", which uses escape sequences to switch between
* ascii, jis0208, jis0212, gb2312, and ksc5601. Note that "escape-driven"
@@ -117,8 +117,8 @@ typedef struct {
* 0. */
int numSubTables; /* Length of following array. */
EscapeSubTable subTables[1];/* Information about each EscapeSubTable used
- * by this encoding type. The actual size will
- * be as large as necessary to hold all
+ * by this encoding type. The actual size is
+ * as large as necessary to hold all
* EscapeSubTables. */
} EscapeEncodingData;
@@ -156,7 +156,7 @@ static ProcessGlobalValue encodingFileMap = {
* A list of directories making up the "library path". Historically this
* search path has served many uses, but the only one remaining is a base for
* the encodingSearchPath above. If the application does not explicitly set
- * the encodingSearchPath, then it will be initialized by appending /encoding
+ * the encodingSearchPath, then it is initialized by appending /encoding
* to each directory in this "libraryPath".
*/
@@ -177,7 +177,7 @@ TCL_DECLARE_MUTEX(encodingMutex)
/*
* The following are used to hold the default and current system encodings.
* If NULL is passed to one of the conversion routines, the current setting of
- * the system encoding will be used to perform the conversion.
+ * the system encoding is used to perform the conversion.
*/
static Tcl_Encoding defaultEncoding = NULL;
@@ -451,9 +451,8 @@ TclGetLibraryPath(void)
* Keeps the per-thread copy of the library path current with changes to
* the global copy.
*
- * NOTE: this routine returns void, so there's no way to report the error
- * that searchPath is not a valid list. In that case, this routine will
- * silently do nothing.
+ * Since the result of this routine is void, if searchPath is not a valid
+ * list this routine silently does nothing.
*
*----------------------------------------------------------------------
*/
@@ -475,17 +474,16 @@ TclSetLibraryPath(
*
* FillEncodingFileMap --
*
- * Called to bring the encoding file map in sync with the current value
+ * Called to update the encoding file map with the current value
* of the encoding search path.
*
- * Scan the directories on the encoding search path, find the *.enc
- * files, and store the found pathnames in a map associated with the
- * encoding name.
+ * Finds *.end files in the directories on the encoding search path and
+ * stores the found pathnames in a map associated with the encoding name.
*
- * In particular, if $dir is on the encoding search path, and the file
- * $dir/foo.enc is found, then store a "foo" -> $dir entry in the map.
- * Later, any need for the "foo" encoding will quickly * be able to
- * construct the $dir/foo.enc pathname for reading the encoding data.
+ * If $dir is on the encoding search path and the file $dir/foo.enc is
+ * found, stores a "foo" -> $dir entry in the map. if the "foo" encoding
+ * is needed later, the $dir/foo.enc name can be quickly constructed in
+ * order to read the encoding data.
*
* Results:
* None.
@@ -584,9 +582,9 @@ TclInitEncodingSubsystem(void)
Tcl_MutexUnlock(&encodingMutex);
/*
- * Create a few initial encodings. Note that the UTF-8 to UTF-8
- * translation is not a no-op, because it will turn a stream of improperly
- * formed UTF-8 into a properly formed stream.
+ * Create a few initial encodings. UTF-8 to UTF-8 translation is not a
+ * no-op because it turns a stream of improperly formed UTF-8 into a
+ * properly formed stream.
*/
type.encodingName = NULL;
@@ -742,11 +740,7 @@ TclFinalizeEncodingSubsystem(void)
* interp was NULL.
*
* Side effects:
- * The new encoding type is entered into a table visible to all
- * interpreters, keyed off the encoding's name. For each call to this
- * function, there should eventually be a call to Tcl_FreeEncoding, so
- * that the database can be cleaned up when encodings aren't needed
- * anymore.
+ * LoadEncodingFile is called if necessary.
*
*-------------------------------------------------------------------------
*/
@@ -784,15 +778,15 @@ Tcl_GetEncoding(
*
* Tcl_FreeEncoding --
*
- * This function is called to release an encoding allocated by
- * Tcl_CreateEncoding() or Tcl_GetEncoding().
+ * Releases an encoding allocated by Tcl_CreateEncoding() or
+ * Tcl_GetEncoding().
*
* Results:
* None.
*
* Side effects:
* The reference count associated with the encoding is decremented and
- * the encoding may be deleted if nothing is using it anymore.
+ * the encoding is deleted if nothing is using it anymore.
*
*---------------------------------------------------------------------------
*/
@@ -811,13 +805,14 @@ Tcl_FreeEncoding(
*
* FreeEncoding --
*
- * This function is called to release an encoding by functions that
- * already have the encodingMutex.
+ * Decrements the reference count of an encoding. The caller must hold
+ * encodingMutes.
*
* Results:
* None.
*
* Side effects:
+ * Releases the resource for an encoding if it is now unused.
* The reference count associated with the encoding is decremented and
* the encoding may be deleted if nothing is using it anymore.
*
@@ -1005,23 +1000,22 @@ Tcl_SetSystemEncoding(
*
* Tcl_CreateEncoding --
*
- * This function is called to define a new encoding and the functions
- * that are used to convert between the specified encoding and Unicode.
+ * Defines a new encoding, along with the functions that are used to
+ * convert to and from Unicode.
*
* Results:
* Returns a token that represents the encoding. If an encoding with the
* same name already existed, the old encoding token remains valid and
- * continues to behave as it used to, and will eventually be garbage
- * collected when the last reference to it goes away. Any subsequent
- * calls to Tcl_GetEncoding with the specified name will retrieve the
- * most recent encoding token.
+ * continues to behave as it used to, and is eventually garbage collected
+ * when the last reference to it goes away. Any subsequent calls to
+ * Tcl_GetEncoding with the specified name retrieve the most recent
+ * encoding token.
*
* Side effects:
- * The new encoding type is entered into a table visible to all
- * interpreters, keyed off the encoding's name. For each call to this
- * function, there should eventually be a call to Tcl_FreeEncoding, so
- * that the database can be cleaned up when encodings aren't needed
- * anymore.
+ * A new record having the name of the encoding is entered into a table of
+ * encodings visible to all interpreters. For each call to this function,
+ * there should eventually be a call to Tcl_FreeEncoding, which cleans
+ * deletes the record in the table when an encoding is no longer needed.
*
*---------------------------------------------------------------------------
*/
@@ -1269,10 +1263,9 @@ Tcl_ExternalToUtf(
*
* Tcl_UtfToExternalDString --
*
- * Convert a source buffer from UTF-8 into the specified encoding. If any
+ * Convert a source buffer from UTF-8 to the specified encoding. If any
* of the bytes in the source buffer are invalid or cannot be represented
- * in the target encoding, a default fallback character will be
- * substituted.
+ * in the target encoding, a default fallback character is substituted.
*
* Results:
* The converted bytes are stored in the DString, which is then NULL
@@ -1584,13 +1577,13 @@ OpenEncodingFileChannel(
* the data.
*
* Results:
- * The return value is the newly loaded Encoding, or NULL if the file
- * didn't exist of was in the incorrect format. If NULL was returned, an
- * error message is left in interp's result object, unless interp was
- * NULL.
+ * The return value is the newly loaded Tcl_Encoding or NULL if the file
+ * didn't exist or could not be processed. If NULL is returned and interp
+ * is not NULL, an error message is left in interp's result object.
*
* Side effects:
- * File read from disk.
+ * A corresponding encoding file might be read from persistent storage, in
+ * which case LoadTableEncoding is called.
*
*---------------------------------------------------------------------------
*/
@@ -1598,8 +1591,8 @@ OpenEncodingFileChannel(
static Tcl_Encoding
LoadEncodingFile(
Tcl_Interp *interp, /* Interp for error reporting, if not NULL. */
- const char *name) /* The name of the encoding file on disk and
- * also the name for new encoding. */
+ const char *name) /* The name of both the encoding file
+ * and the new encoding. */
{
Tcl_Channel chan = NULL;
Tcl_Encoding encoding = NULL;
@@ -1653,27 +1646,27 @@ LoadEncodingFile(
*
* LoadTableEncoding --
*
- * Helper function for LoadEncodingTable(). Loads a table to that
- * converts between Unicode and some other encoding and creates an
- * encoding (using a TableEncoding structure) from that information.
+ * Helper function for LoadEncodingFile(). Creates a Tcl_EncodingType
+ * structure along with its corresponding TableEncodingData structure, and
+ * passes it to Tcl_Createncoding.
*
- * File contains binary data, but begins with a marker to indicate
- * byte-ordering, so that same binary file can be read on either endian
- * platforms.
+ * The file contains binary data but begins with a marker to indicate
+ * byte-ordering so a single binary file can be read on big or
+ * little-endian systems.
*
* Results:
- * The return value is the new encoding, or NULL if the encoding could
- * not be created (because the file contained invalid data).
+ * Returns the new Tcl_Encoding, or NULL if it could could
+ * not be created because the file contained invalid data.
*
* Side effects:
- * None.
+ * See Tcl_CreateEncoding().
*
*-------------------------------------------------------------------------
*/
static Tcl_Encoding
LoadTableEncoding(
- const char *name, /* Name for new encoding. */
+ const char *name, /* Name of the new encoding. */
int type, /* Type of encoding (ENCODING_?????). */
Tcl_Channel chan) /* File containing new encoding. */
{
@@ -1790,10 +1783,10 @@ LoadTableEncoding(
}
/*
- * Invert toUnicode array to produce the fromUnicode array. Performs a
+ * Invert the toUnicode array to produce the fromUnicode array. Performs a
* single malloc to get the memory for the array and all the pages needed
- * by the array. While reading in the toUnicode array, we remembered what
- * pages that would be needed for the fromUnicode array.
+ * by the array. While reading in the toUnicode array remember what
+ * pages are needed for the fromUnicode array.
*/
if (symbol) {
@@ -1832,8 +1825,8 @@ LoadTableEncoding(
if (type == ENCODING_MULTIBYTE) {
/*
* If multibyte encodings don't have a backslash character, define
- * one. Otherwise, on Windows, native file names won't work because
- * the backslash in the file name will map to the unknown character
+ * one. Otherwise, on Windows, native file names don't work because
+ * the backslash in the file name maps to the unknown character
* (question mark) when converting from UTF-8 to external encoding.
*/
@@ -1845,13 +1838,13 @@ LoadTableEncoding(
}
if (symbol) {
/*
- * Make a special symbol encoding that not only maps the symbol
- * characters from their Unicode code points down into page 0, but
- * also ensure that the characters on page 0 map to themselves. This
- * is so that a symbol font can be used to display a simple string
- * like "abcd" and have alpha, beta, chi, delta show up, rather than
- * have "unknown" chars show up because strictly speaking the symbol
- * font doesn't have glyphs for those low ASCII chars.
+ * Make a special symbol encoding that maps each symbol character from
+ * its Unicode code point down into page 0, and also ensure that each
+ * characters on page 0 maps to itself so that a symbol font can be
+ * used to display a simple string like "abcd" and have alpha, beta,
+ * chi, delta show up, rather than have "unknown" chars show up because
+ * strictly speaking the symbol font doesn't have glyphs for those low
+ * ASCII chars.
*/
page = dataPtr->fromUnicode[0];
@@ -1898,7 +1891,7 @@ LoadTableEncoding(
}
/*
- * Read lines from the encoding until EOF.
+ * Read lines until EOF.
*/
for (TclDStringClear(&lineString);
@@ -1975,7 +1968,7 @@ LoadTableEncoding(
static Tcl_Encoding
LoadEscapeEncoding(
- const char *name, /* Name for new encoding. */
+ const char *name, /* Name of the new encoding. */
Tcl_Channel chan) /* File containing new encoding. */
{
int i;
@@ -2147,7 +2140,7 @@ BinaryProc(
/*
*-------------------------------------------------------------------------
*
- * UtfExtToUtfIntProc --
+ * UtfIntToUtfExtProc --
*
* Convert from UTF-8 to UTF-8. While converting null-bytes from the
* Tcl's internal representation (0xc0, 0x80) to the official
@@ -2288,7 +2281,7 @@ UtfToUtfProc(
* output buffer. */
int pureNullMode) /* Convert embedded nulls from internal
* representation to real null-bytes or vice
- * versa. */
+ * versa. Also combine or separate surrogate pairs */
{
const char *srcStart, *srcEnd, *srcClose;
const char *dstStart, *dstEnd;
@@ -2304,7 +2297,7 @@ UtfToUtfProc(
srcEnd = src + srcLen;
srcClose = srcEnd;
if ((flags & TCL_ENCODING_END) == 0) {
- srcClose -= TCL_UTF_MAX;
+ srcClose -= 6;
}
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
@@ -2353,15 +2346,21 @@ UtfToUtfProc(
src += 1;
dst += Tcl_UniCharToUtf(*chPtr, dst);
} else {
- int len = TclUtfToUniChar(src, chPtr);
- src += len;
- dst += Tcl_UniCharToUtf(*chPtr, dst);
-#if TCL_UTF_MAX <= 4
- if ((*chPtr >= 0xD800) && (len < 3)) {
- src += TclUtfToUniChar(src + len, chPtr);
- dst += Tcl_UniCharToUtf(*chPtr, dst);
+ src += TclUtfToUniChar(src, chPtr);
+ if ((*chPtr & 0xFC00) == 0xD800) {
+ /* A high surrogate character is detected, handle especially */
+ Tcl_UniChar low = *chPtr;
+ if (src <= srcEnd-3) {
+ Tcl_UtfToUniChar(src, &low);
+ }
+ if ((low & 0xFC00) != 0xDC00) {
+ *dst++ = (char) (((*chPtr >> 12) | 0xE0) & 0xEF);
+ *dst++ = (char) (((*chPtr >> 6) | 0x80) & 0xBF);
+ *dst++ = (char) ((*chPtr | 0x80) & 0xBF);
+ continue;
+ }
}
-#endif
+ dst += Tcl_UniCharToUtf(*chPtr, dst);
}
}
@@ -3598,14 +3597,13 @@ EscapeFromUtfProc(
*
* EscapeFreeProc --
*
- * This function is invoked when an EscapeEncodingData encoding is
- * deleted. It deletes the memory used by the encoding.
+ * Frees resources used by the encoding.
*
* Results:
* None.
*
* Side effects:
- * Memory freed.
+ * Memory is freed.
*
*---------------------------------------------------------------------------
*/
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index d725140..8d13c6c 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -7697,12 +7697,12 @@ ExecuteExtendedBinaryMathOp(
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
/* TODO: internals intrusion */
- if ((w1 > ((Tcl_WideInt) 0)) ^ (big2.sign == MP_ZPOS)) {
+ if ((w1 > ((Tcl_WideInt) 0)) ^ !mp_isneg(&big2)) {
/*
* Arguments are opposite sign; remainder is sum.
*/
- TclInitBignumFromWideInt(&big1, w1);
+ mp_init_ll(&big1, w1);
mp_add(&big2, &big1, &big2);
mp_clear(&big1);
BIG_RESULT(&big2);
@@ -7746,7 +7746,7 @@ ExecuteExtendedBinaryMathOp(
break;
case TCL_NUMBER_BIG:
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
- invalid = big2.sign != MP_ZPOS;
+ invalid = mp_isneg(&big2);
mp_clear(&big2);
break;
default:
@@ -7825,7 +7825,7 @@ ExecuteExtendedBinaryMathOp(
break;
case TCL_NUMBER_BIG:
Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
- zero = (big1.sign == MP_ZPOS);
+ zero = !mp_isneg(&big1);
mp_clear(&big1);
break;
default:
@@ -7949,7 +7949,7 @@ ExecuteExtendedBinaryMathOp(
oddExponent = (int) (w2 & (Tcl_WideInt)1);
} else {
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
- negativeExponent = big2.sign != MP_ZPOS;
+ negativeExponent = mp_isneg(&big2);
mp_mod_2d(&big2, 1, &big2);
oddExponent = big2.used != 0;
mp_clear(&big2);
@@ -8331,7 +8331,7 @@ ExecuteExtendedUnaryMathOp(
if (w != WIDE_MIN) {
WIDE_RESULT(-w);
}
- TclInitBignumFromWideInt(&big, w);
+ mp_init_ll(&big, w);
break;
default:
Tcl_TakeBignumFromObj(NULL, valuePtr, &big);
@@ -8424,7 +8424,7 @@ TclCompareTwoNumbers(
goto wideCompare;
case TCL_NUMBER_BIG:
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
- if (big2.sign != MP_ZPOS) {
+ if (mp_isneg(&big2)) {
compare = MP_GT;
} else {
compare = MP_LT;
@@ -8461,7 +8461,7 @@ TclCompareTwoNumbers(
}
Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
if ((d1 < (double)WIDE_MAX) && (d1 > (double)WIDE_MIN)) {
- if (big2.sign != MP_ZPOS) {
+ if (mp_isneg(&big2)) {
compare = MP_GT;
} else {
compare = MP_LT;
diff --git a/generic/tclFileName.c b/generic/tclFileName.c
index 0f3f8b1..9ecb631 100644
--- a/generic/tclFileName.c
+++ b/generic/tclFileName.c
@@ -1683,9 +1683,8 @@ Tcl_GlobObjCmd(
*
* TclGlob --
*
- * This procedure prepares arguments for the DoGlob call. It sets the
- * separator string based on the platform, performs * tilde substitution,
- * and calls DoGlob.
+ * Sets the separator string based on the platform, performs tilde
+ * substitution, and calls DoGlob.
*
* The interpreter's result, on entry to this function, must be a valid
* Tcl list (e.g. it could be empty), since we will lappend any new
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index 21d7c67..91b4ab3 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(
size_t 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. */
{
size_t length;
int result = TCL_ERROR;
@@ -1781,15 +1719,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) {
@@ -1804,8 +1743,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) {
@@ -1818,8 +1756,8 @@ Tcl_FSEvalFileEx(
string = TclGetString(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,
@@ -1842,16 +1780,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) {
@@ -1863,7 +1801,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);
@@ -1883,11 +1821,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;
@@ -1916,15 +1855,16 @@ TclNREvalFile(
TclPkgFileSeen(interp, TclGetString(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) {
@@ -1939,8 +1879,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) {
@@ -1954,8 +1893,8 @@ TclNREvalFile(
string = TclGetString(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,
@@ -1979,7 +1918,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;
@@ -2000,9 +1939,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) {
@@ -2014,7 +1953,7 @@ EvalFileCallback(
result = TclUpdateReturnInfo(iPtr);
} else if (result == TCL_ERROR) {
/*
- * Record information telling where the error occurred.
+ * Record information about where the error occurred.
*/
size_t length;
@@ -2037,16 +1976,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.
*
*----------------------------------------------------------------------
*/
@@ -2055,8 +1993,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;
@@ -2067,15 +2005,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.
*
*----------------------------------------------------------------------
*/
@@ -2085,8 +2023,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;
@@ -2097,24 +2035,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;
@@ -2130,11 +2065,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.
@@ -2147,8 +2081,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);
@@ -2163,11 +2099,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.
@@ -2180,8 +2116,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);
@@ -2202,8 +2139,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.
@@ -2216,7 +2154,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);
@@ -2233,38 +2171,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;
}
@@ -2273,8 +2209,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);
@@ -2283,7 +2219,7 @@ Tcl_FSOpenFileChannel(
}
/*
- * Do the actual open() call.
+ * Open the file.
*/
retVal = fsPtr->openFileChannelProc(interp, pathPtr, mode,
@@ -2293,7 +2229,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)
@@ -2330,8 +2266,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.
@@ -2344,9 +2282,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);
@@ -2363,11 +2300,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
@@ -2391,16 +2327,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.
@@ -2412,8 +2350,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);
}
@@ -2423,13 +2361,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.
@@ -2441,8 +2379,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);
}
@@ -2452,18 +2390,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.
@@ -2490,11 +2426,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.
@@ -2504,10 +2442,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;
@@ -2567,15 +2504,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.
@@ -2586,9 +2524,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);
@@ -2604,12 +2542,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.
@@ -2620,9 +2560,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);
@@ -2638,33 +2578,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.
@@ -2683,9 +2615,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();
@@ -2710,7 +2643,7 @@ Tcl_FSGetCwd(
Tcl_Obj *norm;
/*
- * Looks like a new current directory.
+ * Found the pathname of the current directory.
*/
retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd);
@@ -2718,15 +2651,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);
@@ -2746,29 +2679,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);
@@ -2777,13 +2708,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 =
@@ -2791,16 +2728,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;
}
@@ -2832,28 +2764,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);
@@ -2861,11 +2790,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.
*/
size_t len1, len2;
@@ -2875,18 +2805,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);
}
@@ -2907,17 +2839,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.
*
*----------------------------------------------------------------------
*/
@@ -2942,70 +2876,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);
@@ -3017,45 +2927,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;
@@ -3066,25 +2991,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.
*
*----------------------------------------------------------------------
*/
@@ -3092,38 +3009,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];
@@ -3140,49 +3048,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
@@ -3190,21 +3089,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
@@ -3215,6 +3111,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;
@@ -3223,9 +3122,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(TclGetString(shlibFile), &fs) == 0)
@@ -3237,8 +3139,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 */
@@ -3247,16 +3149,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);
@@ -3294,10 +3195,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) {
@@ -3311,9 +3213,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:
*/
{
@@ -3329,7 +3231,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) {
@@ -3360,8 +3262,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);
@@ -3373,11 +3274,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) {
@@ -3388,10 +3293,6 @@ Tcl_LoadFile(
}
if (TclCrossFilesystemCopy(interp, pathPtr, copyToPtr) != TCL_OK) {
- /*
- * Cross-platform copy failed.
- */
-
Tcl_FSDeleteFile(copyToPtr);
Tcl_DecrRefCount(copyToPtr);
return TCL_ERROR;
@@ -3399,10 +3300,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:
*/
{
@@ -3419,8 +3319,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) {
@@ -3430,18 +3330,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) &&
@@ -3449,10 +3345,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;
@@ -3463,47 +3358,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 = Tcl_Alloc(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;
@@ -3526,8 +3415,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) {
@@ -3536,9 +3425,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);
@@ -3555,16 +3443,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;
@@ -3577,83 +3466,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);
@@ -3668,23 +3549,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);
}
@@ -3694,16 +3575,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) {
@@ -3724,52 +3604,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.
*/
@@ -3777,33 +3650,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);
@@ -3817,38 +3689,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);
@@ -3858,11 +3733,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
@@ -3878,16 +3752,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.
@@ -3905,10 +3772,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();
@@ -3919,6 +3785,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);
}
}
@@ -3934,22 +3804,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;
@@ -3957,10 +3826,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();
@@ -3986,34 +3853,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,
@@ -4025,9 +3889,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);
@@ -4040,9 +3902,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();
@@ -4052,7 +3914,7 @@ Tcl_FSSplitPath(
p += driveNameLength;
/*
- * Add the remaining path elements to the list.
+ * Add the remaining pathname elements to the list.
*/
for (;;) {
@@ -4079,10 +3941,6 @@ Tcl_FSSplitPath(
}
}
- /*
- * Compute the number of elements in the result.
- */
-
if (lenPtr != NULL) {
TclListObjLength(NULL, result, lenPtr);
}
@@ -4093,35 +3951,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. */
{
size_t pathLen;
const char *path = TclGetStringFromObj(pathPtr, &pathLen);
@@ -4145,14 +3999,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.
*
@@ -4164,49 +4018,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)
@@ -4219,12 +4069,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;
@@ -4258,7 +4107,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;
@@ -4276,12 +4125,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.
@@ -4291,10 +4141,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;
@@ -4317,27 +4166,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;
@@ -4359,15 +4208,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.
*
*---------------------------------------------------------------------------
*/
@@ -4375,8 +4223,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;
@@ -4387,7 +4235,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;
}
@@ -4395,7 +4243,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);
@@ -4403,8 +4251,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) {
@@ -4412,7 +4260,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);
@@ -4437,11 +4285,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.
@@ -4467,14 +4315,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.
*
*---------------------------------------------------------------------------
*/
@@ -4497,27 +4346,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;
@@ -4539,28 +4391,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);
@@ -4569,14 +4424,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;
size_t cwdLen, normLen;
@@ -4588,8 +4437,8 @@ Tcl_FSRemoveDirectory(
if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr,
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,
@@ -4610,16 +4459,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.
*
*---------------------------------------------------------------------------
*/
@@ -4636,41 +4483,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;
@@ -4679,10 +4523,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();
@@ -4699,26 +4543,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.
*
*---------------------------------------------------------------------------
*/
@@ -4735,7 +4560,7 @@ Tcl_FSGetNativePath(
*
* NativeFreeInternalRep --
*
- * Free a native internal representation, which will be non-NULL.
+ * Free a native internal representation.
*
* Results:
* None.
@@ -4757,16 +4582,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.
*
*---------------------------------------------------------------------------
*/
@@ -4802,16 +4628,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
*
*---------------------------------------------------------------------------
*/
@@ -4832,8 +4655,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, "/");
@@ -4845,11 +4668,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.
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 85a89e9..c75fd52 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -2806,18 +2806,14 @@ struct Tcl_LoadHandle_ {
/* Flags for conversion of doubles to digit strings */
-#define TCL_DD_SHORTEST 0x4
- /* Use the shortest possible string */
#define TCL_DD_E_FORMAT 0x2
/* Use a fixed-length string of digits,
* suitable for E format*/
#define TCL_DD_F_FORMAT 0x3
/* Use a fixed number of digits after the
* decimal point, suitable for F format */
-
-#define TCL_DD_SHORTEN_FLAG 0x4
- /* Allow return of a shorter digit string
- * if it converts losslessly */
+#define TCL_DD_SHORTEST 0x4
+ /* Use the shortest possible string */
#define TCL_DD_NO_QUICK 0x8
/* Debug flag: forbid quick FP conversion */
@@ -2991,8 +2987,6 @@ MODULE_SCOPE int TclInfoLocalsCmd(void *dummy, Tcl_Interp *interp,
MODULE_SCOPE int TclInfoVarsCmd(void *dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE void TclInitAlloc(void);
-MODULE_SCOPE void TclInitBignumFromWideInt(mp_int *, Tcl_WideInt);
-MODULE_SCOPE void TclInitBignumFromWideUInt(mp_int *, Tcl_WideUInt);
MODULE_SCOPE void TclInitDbCkalloc(void);
MODULE_SCOPE void TclInitDoubleConversion(void);
MODULE_SCOPE void TclInitEmbeddedConfigurationInformation(
@@ -4051,7 +4045,6 @@ MODULE_SCOPE int TclObjCallVarTraces(Interp *iPtr, Var *arrayPtr,
*/
MODULE_SCOPE int TclCompareObjKeys(void *keyPtr, Tcl_HashEntry *hPtr);
-MODULE_SCOPE void TclFreeObj(Tcl_Obj *objPtr);
MODULE_SCOPE void TclFreeObjEntry(Tcl_HashEntry *hPtr);
MODULE_SCOPE TCL_HASH_TYPE TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr);
@@ -4110,8 +4103,6 @@ MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr,
size_t before, size_t after, int *indexPtr);
MODULE_SCOPE size_t TclIndexDecode(int encoded, size_t endValue);
-MODULE_SCOPE void TclBN_s_mp_reverse(unsigned char *s, size_t len);
-
/* Constants used in index value encoding routines. */
#define TCL_INDEX_END ((size_t)-2)
#define TCL_INDEX_START ((size_t)0)
diff --git a/generic/tclOO.c b/generic/tclOO.c
index 3edca32..5ffe294 100644
--- a/generic/tclOO.c
+++ b/generic/tclOO.c
@@ -175,7 +175,7 @@ MODULE_SCOPE const TclOOStubs tclOOStubs;
* ROOT_CLASS respectively.
*/
-#define Deleted(oPtr) ((oPtr)->flags & OBJECT_DELETED)
+#define Destructing(oPtr) ((oPtr)->flags & OBJECT_DESTRUCTING)
#define IsRootObject(ocPtr) ((ocPtr)->flags & ROOT_OBJECT)
#define IsRootClass(ocPtr) ((ocPtr)->flags & ROOT_CLASS)
#define IsRoot(ocPtr) ((ocPtr)->flags & (ROOT_OBJECT|ROOT_CLASS))
@@ -840,7 +840,7 @@ ObjectRenamedTrace(
* 2950259].
*/
- if (!Deleted(oPtr)) {
+ if (!Destructing(oPtr)) {
Tcl_DeleteNamespace(oPtr->namespacePtr);
}
oPtr->command = NULL;
@@ -880,7 +880,7 @@ TclOODeleteDescendants(
* clsPtr
*/
- if (!Deleted(mixinSubclassPtr->thisPtr)
+ if (!Destructing(mixinSubclassPtr->thisPtr)
&& !(mixinSubclassPtr->thisPtr->flags & DONT_DELETE)) {
Tcl_DeleteCommandFromToken(interp,
mixinSubclassPtr->thisPtr->command);
@@ -900,7 +900,7 @@ TclOODeleteDescendants(
if (clsPtr->subclasses.num > 0) {
while (clsPtr->subclasses.num > 0) {
subclassPtr = clsPtr->subclasses.list[clsPtr->subclasses.num - 1];
- if (!Deleted(subclassPtr->thisPtr) && !IsRoot(subclassPtr)
+ if (!Destructing(subclassPtr->thisPtr) && !IsRoot(subclassPtr)
&& !(subclassPtr->thisPtr->flags & DONT_DELETE)) {
Tcl_DeleteCommandFromToken(interp,
subclassPtr->thisPtr->command);
@@ -926,7 +926,7 @@ TclOODeleteDescendants(
* This condition also covers the case where instancePtr == oPtr
*/
- if (!Deleted(instancePtr) && !IsRoot(instancePtr) &&
+ if (!Destructing(instancePtr) && !IsRoot(instancePtr) &&
!(instancePtr->flags & DONT_DELETE)) {
Tcl_DeleteCommandFromToken(interp, instancePtr->command);
}
@@ -968,7 +968,7 @@ TclOOReleaseClassContents(
* Sanity check!
*/
- if (!Deleted(oPtr)) {
+ if (!Destructing(oPtr)) {
if (IsRootClass(oPtr)) {
Tcl_Panic("deleting class structure for non-deleted %s",
"::oo::class");
@@ -1087,7 +1087,7 @@ TclOOReleaseClassContents(
Tcl_Free(clsPtr->privateVariables.list);
}
- if (IsRootClass(oPtr) && !Deleted(fPtr->objectCls->thisPtr)) {
+ if (IsRootClass(oPtr) && !Destructing(fPtr->objectCls->thisPtr)) {
Tcl_DeleteCommandFromToken(interp, fPtr->objectCls->thisPtr->command);
}
}
@@ -1120,7 +1120,7 @@ ObjectNamespaceDeleted(
Tcl_Interp *interp = oPtr->fPtr->interp;
int i;
- if (Deleted(oPtr)) {
+ if (Destructing(oPtr)) {
/*
* TODO: Can ObjectNamespaceDeleted ever be called twice? If not,
* this guard could be removed.
@@ -1135,7 +1135,7 @@ ObjectNamespaceDeleted(
* records. This is the flag that
*/
- oPtr->flags |= OBJECT_DELETED;
+ oPtr->flags |= OBJECT_DESTRUCTING;
/*
* Let the dominoes fall!
@@ -1280,7 +1280,7 @@ ObjectNamespaceDeleted(
* sometimes not go away automatically; we force it here. [Bug 2962664]
*/
- if (IsRootObject(oPtr) && !Deleted(fPtr->classCls->thisPtr)
+ if (IsRootObject(oPtr) && !Destructing(fPtr->classCls->thisPtr)
&& !Tcl_InterpDeleted(interp)) {
Tcl_DeleteCommandFromToken(interp, fPtr->classCls->thisPtr->command);
}
@@ -1331,6 +1331,20 @@ TclOODecrRefCount(
/*
* ----------------------------------------------------------------------
*
+ * TclOOObjectDestroyed --
+ *
+ * Returns TCL_OK if an object is entirely deleted, i.e. the destruction
+ * sequence has completed.
+ *
+ * ----------------------------------------------------------------------
+ */
+int TclOOObjectDestroyed(Object *oPtr) {
+ return (oPtr->namespacePtr == NULL);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
* TclOORemoveFromInstances --
*
* Utility function to remove an object from the list of instances within
@@ -1473,7 +1487,7 @@ TclOOAddToSubclasses(
* is assumed that the class is not already
* present as a subclass in the superclass. */
{
- if (Deleted(superPtr->thisPtr)) {
+ if (Destructing(superPtr->thisPtr)) {
return;
}
if (superPtr->subclasses.num >= superPtr->subclasses.size) {
@@ -1538,7 +1552,7 @@ TclOOAddToMixinSubs(
* is assumed that the class is not already
* present as a subclass in the superclass. */
{
- if (Deleted(superPtr->thisPtr)) {
+ if (Destructing(superPtr->thisPtr)) {
return;
}
if (superPtr->mixinSubs.num >= superPtr->mixinSubs.size) {
@@ -1847,7 +1861,7 @@ FinalizeAlloc(
* want to lose errors by accident. [Bug 2903011]
*/
- if (result != TCL_ERROR && Deleted(oPtr)) {
+ if (result != TCL_ERROR && Destructing(oPtr)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"object deleted in constructor", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "STILLBORN", NULL);
@@ -1862,7 +1876,7 @@ FinalizeAlloc(
* command before we delete it. [Bug 9dd1bd7a74]
*/
- if (!Deleted(oPtr)) {
+ if (!Destructing(oPtr)) {
(void) TclOOObjectName(interp, oPtr);
Tcl_DeleteCommandFromToken(interp, oPtr->command);
}
@@ -2007,7 +2021,7 @@ Tcl_CopyObjectInstance(
*/
o2Ptr->flags = oPtr->flags & ~(
- OBJECT_DELETED | ROOT_OBJECT | ROOT_CLASS | FILTER_HANDLING);
+ OBJECT_DESTRUCTING | ROOT_OBJECT | ROOT_CLASS | FILTER_HANDLING);
/*
* Copy the object's metadata.
diff --git a/generic/tclOOInt.h b/generic/tclOOInt.h
index fd1b051..54f4476 100644
--- a/generic/tclOOInt.h
+++ b/generic/tclOOInt.h
@@ -213,14 +213,11 @@ typedef struct Object {
* command. */
} Object;
-#define OBJECT_DELETED 1 /* Flag to say that an object has been
- * destroyed. */
-#define DESTRUCTOR_CALLED 2 /* Flag to say that the destructor has been
- * called. */
-#define CLASS_GONE 4 /* Obsolete. Indicates that the class of this
- * object has been deleted, and so the object
- * should not attempt to remove itself from its
- * class. */
+#define OBJECT_DESTRUCTING 1 /* Indicates that an object is being or has
+ * been destroyed */
+#define DESTRUCTOR_CALLED 2 /* Indicates that evaluation of destructor script for the
+ object has began */
+#define OO_UNUSED_4 4 /* No longer used. */
#define ROOT_OBJECT 0x1000 /* Flag to say that this object is the root of
* the class hierarchy and should be treated
* specially during teardown. */
@@ -587,6 +584,7 @@ MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp,
const char *nameStr,
const char *nsNameStr);
MODULE_SCOPE int TclOODecrRefCount(Object *oPtr);
+MODULE_SCOPE int TclOOObjectDestroyed(Object *oPtr);
MODULE_SCOPE int TclOODefineSlots(Foundation *fPtr);
MODULE_SCOPE void TclOODeleteChain(CallChain *callPtr);
MODULE_SCOPE void TclOODeleteChainCache(Tcl_HashTable *tablePtr);
diff --git a/generic/tclOOMethod.c b/generic/tclOOMethod.c
index 462da48..1797c6a 100644
--- a/generic/tclOOMethod.c
+++ b/generic/tclOOMethod.c
@@ -679,11 +679,13 @@ InvokeProcedureMethod(
* call frame's lifetime). */
/*
- * If the interpreter was deleted, we just skip to the next thing in the
- * chain.
+ * If the object namespace (or interpreter) were deleted, we just skip to
+ * the next thing in the chain.
*/
- if (Tcl_InterpDeleted(interp)) {
+ if (TclOOObjectDestroyed(((CallContext *)context)->oPtr) ||
+ Tcl_InterpDeleted(interp)
+ ) {
return TclNRObjectContextInvokeNext(interp, context, objc, objv,
Tcl_ObjectContextSkippedArgs(context));
}
diff --git a/generic/tclOOScript.h b/generic/tclOOScript.h
index ab637dd..a1e4624 100644
--- a/generic/tclOOScript.h
+++ b/generic/tclOOScript.h
@@ -110,7 +110,7 @@ static const char *tclOOSetupScript =
"\t\t\t&& ![info object isa class $targetDelegate]\n"
"\t\t} then {\n"
"\t\t\tcopy $originDelegate $targetDelegate\n"
-"\t\t\tobjdefine $targetObject mixin -set \\\n"
+"\t\t\tobjdefine $targetObject ::oo::objdefine::mixin -set \\\n"
"\t\t\t\t{*}[lmap c [info object mixin $targetObject] {\n"
"\t\t\t\t\tif {$c eq $originDelegate} {set targetDelegate} {set c}\n"
"\t\t\t\t}]\n"
diff --git a/generic/tclOOScript.tcl b/generic/tclOOScript.tcl
deleted file mode 100644
index 5e0145f..0000000
--- a/generic/tclOOScript.tcl
+++ /dev/null
@@ -1,456 +0,0 @@
-# tclOOScript.h --
-#
-# This file contains support scripts for TclOO. They are defined here so
-# that the code can be definitely run even in safe interpreters; TclOO's
-# core setup is safe.
-#
-# Copyright (c) 2012-2018 Donal K. Fellows
-# Copyright (c) 2013 Andreas Kupries
-# Copyright (c) 2017 Gerald Lester
-#
-# See the file "license.terms" for information on usage and redistribution of
-# this file, and for a DISCLAIMER OF ALL WARRANTIES.
-
-::namespace eval ::oo {
- ::namespace path {}
-
- #
- # Commands that are made available to objects by default.
- #
- namespace eval Helpers {
- ::namespace path {}
-
- # ------------------------------------------------------------------
- #
- # callback, mymethod --
- #
- # Create a script prefix that calls a method on the current
- # object. Same operation, two names.
- #
- # ------------------------------------------------------------------
-
- proc callback {method args} {
- list [uplevel 1 {::namespace which my}] $method {*}$args
- }
-
- # Make the [callback] command appear as [mymethod] too.
- namespace export callback
- namespace eval tmp {namespace import ::oo::Helpers::callback}
- namespace export -clear
- rename tmp::callback mymethod
- namespace delete tmp
-
- # ------------------------------------------------------------------
- #
- # classvariable --
- #
- # Link to a variable in the class of the current object.
- #
- # ------------------------------------------------------------------
-
- proc classvariable {name args} {
- # Get a reference to the class's namespace
- set ns [info object namespace [uplevel 1 {self class}]]
- # Double up the list of variable names
- foreach v [list $name {*}$args] {
- if {[string match *(*) $v]} {
- set reason "can't create a scalar variable that looks like an array element"
- return -code error -errorcode {TCL UPVAR LOCAL_ELEMENT} \
- [format {bad variable name "%s": %s} $v $reason]
- }
- if {[string match *::* $v]} {
- set reason "can't create a local variable with a namespace separator in it"
- return -code error -errorcode {TCL UPVAR INVERTED} \
- [format {bad variable name "%s": %s} $v $reason]
- }
- lappend vs $v $v
- }
- # Lastly, link the caller's local variables to the class's variables
- tailcall namespace upvar $ns {*}$vs
- }
-
- # ------------------------------------------------------------------
- #
- # link --
- #
- # Make a command that invokes a method on the current object.
- # The name of the command and the name of the method match by
- # default.
- #
- # ------------------------------------------------------------------
-
- proc link {args} {
- set ns [uplevel 1 {::namespace current}]
- foreach link $args {
- if {[llength $link] == 2} {
- lassign $link src dst
- } elseif {[llength $link] == 1} {
- lassign $link src
- set dst $src
- } else {
- return -code error -errorcode {TCLOO CMDLINK FORMAT} \
- "bad link description; must only have one or two elements"
- }
- if {![string match ::* $src]} {
- set src [string cat $ns :: $src]
- }
- interp alias {} $src {} ${ns}::my $dst
- trace add command ${ns}::my delete [list \
- ::oo::UnlinkLinkedCommand $src]
- }
- return
- }
- }
-
- # ----------------------------------------------------------------------
- #
- # UnlinkLinkedCommand --
- #
- # Callback used to remove linked command when the underlying mechanism
- # that supports it is deleted.
- #
- # ----------------------------------------------------------------------
-
- proc UnlinkLinkedCommand {cmd args} {
- if {[namespace which $cmd] ne {}} {
- rename $cmd {}
- }
- }
-
- # ----------------------------------------------------------------------
- #
- # DelegateName --
- #
- # Utility that gets the name of the class delegate for a class. It's
- # trivial, but makes working with them much easier as delegate names are
- # intentionally hard to create by accident.
- #
- # ----------------------------------------------------------------------
-
- proc DelegateName {class} {
- string cat [info object namespace $class] {:: oo ::delegate}
- }
-
- # ----------------------------------------------------------------------
- #
- # MixinClassDelegates --
- #
- # Support code called *after* [oo::define] inside the constructor of a
- # class that patches in the appropriate class delegates.
- #
- # ----------------------------------------------------------------------
-
- proc MixinClassDelegates {class} {
- if {![info object isa class $class]} {
- return
- }
- set delegate [DelegateName $class]
- if {![info object isa class $delegate]} {
- return
- }
- foreach c [info class superclass $class] {
- set d [DelegateName $c]
- if {![info object isa class $d]} {
- continue
- }
- define $delegate ::oo::define::superclass -append $d
- }
- objdefine $class ::oo::objdefine::mixin -append $delegate
- }
-
- # ----------------------------------------------------------------------
- #
- # UpdateClassDelegatesAfterClone --
- #
- # Support code that is like [MixinClassDelegates] except for when a
- # class is cloned.
- #
- # ----------------------------------------------------------------------
-
- proc UpdateClassDelegatesAfterClone {originObject targetObject} {
- # Rebuild the class inheritance delegation class
- set originDelegate [DelegateName $originObject]
- set targetDelegate [DelegateName $targetObject]
- if {
- [info object isa class $originDelegate]
- && ![info object isa class $targetDelegate]
- } then {
- copy $originDelegate $targetDelegate
- objdefine $targetObject ::oo::objdefine::mixin -set \
- {*}[lmap c [info object mixin $targetObject] {
- if {$c eq $originDelegate} {set targetDelegate} {set c}
- }]
- }
- }
-
- # ----------------------------------------------------------------------
- #
- # oo::define::classmethod --
- #
- # Defines a class method. See define(n) for details.
- #
- # Note that the ::oo::define namespace is semi-public and a bit weird
- # anyway, so we don't regard the namespace path as being under control:
- # fully qualified names are used for everything.
- #
- # ----------------------------------------------------------------------
-
- proc define::classmethod {name {args {}} {body {}}} {
- # Create the method on the class if the caller gave arguments and body
- ::set argc [::llength [::info level 0]]
- ::if {$argc == 3} {
- ::return -code error -errorcode {TCL WRONGARGS} [::format \
- {wrong # args: should be "%s name ?args body?"} \
- [::lindex [::info level 0] 0]]
- }
- ::set cls [::uplevel 1 self]
- ::if {$argc == 4} {
- ::oo::define [::oo::DelegateName $cls] method $name $args $body
- }
- # Make the connection by forwarding
- ::tailcall forward $name myclass $name
- }
-
- # ----------------------------------------------------------------------
- #
- # oo::define::initialise, oo::define::initialize --
- #
- # Do specific initialisation for a class. See define(n) for details.
- #
- # Note that the ::oo::define namespace is semi-public and a bit weird
- # anyway, so we don't regard the namespace path as being under control:
- # fully qualified names are used for everything.
- #
- # ----------------------------------------------------------------------
-
- proc define::initialise {body} {
- ::set clsns [::info object namespace [::uplevel 1 self]]
- ::tailcall apply [::list {} $body $clsns]
- }
-
- # Make the [initialise] definition appear as [initialize] too
- namespace eval define {
- ::namespace export initialise
- ::namespace eval tmp {::namespace import ::oo::define::initialise}
- ::namespace export -clear
- ::rename tmp::initialise initialize
- ::namespace delete tmp
- }
-
- # ----------------------------------------------------------------------
- #
- # Slot --
- #
- # The class of slot operations, which are basically lists at the low
- # level of TclOO; this provides a more consistent interface to them.
- #
- # ----------------------------------------------------------------------
-
- define Slot {
- # ------------------------------------------------------------------
- #
- # Slot Get --
- #
- # Basic slot getter. Retrieves the contents of the slot.
- # Particular slots must provide concrete non-erroring
- # implementation.
- #
- # ------------------------------------------------------------------
-
- method Get {} {
- return -code error -errorcode {TCLOO ABSTRACT_SLOT} "unimplemented"
- }
-
- # ------------------------------------------------------------------
- #
- # Slot Set --
- #
- # Basic slot setter. Sets the contents of the slot. Particular
- # slots must provide concrete non-erroring implementation.
- #
- # ------------------------------------------------------------------
-
- method Set list {
- return -code error -errorcode {TCLOO ABSTRACT_SLOT} "unimplemented"
- }
-
- # ------------------------------------------------------------------
- #
- # Slot Resolve --
- #
- # Helper that lets a slot convert a list of arguments of a
- # particular type to their canonical forms. Defaults to doing
- # nothing (suitable for simple strings).
- #
- # ------------------------------------------------------------------
-
- method Resolve list {
- return $list
- }
-
- # ------------------------------------------------------------------
- #
- # Slot -set, -append, -clear, --default-operation --
- #
- # Standard public slot operations. If a slot can't figure out
- # what method to call directly, it uses --default-operation.
- #
- # ------------------------------------------------------------------
-
- method -set args {
- set my [namespace which my]
- set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
- tailcall my Set $args
- }
- method -append args {
- set my [namespace which my]
- set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
- set current [uplevel 1 [list $my Get]]
- tailcall my Set [list {*}$current {*}$args]
- }
- method -clear {} {tailcall my Set {}}
- method -prepend args {
- set my [namespace which my]
- set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
- set current [uplevel 1 [list $my Get]]
- tailcall my Set [list {*}$args {*}$current]
- }
- method -remove args {
- set my [namespace which my]
- set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
- set current [uplevel 1 [list $my Get]]
- tailcall my Set [lmap val $current {
- if {$val in $args} continue else {set val}
- }]
- }
-
- # Default handling
- forward --default-operation my -append
- method unknown {args} {
- set def --default-operation
- if {[llength $args] == 0} {
- tailcall my $def
- } elseif {![string match -* [lindex $args 0]]} {
- tailcall my $def {*}$args
- }
- next {*}$args
- }
-
- # Set up what is exported and what isn't
- export -set -append -clear -prepend -remove
- unexport unknown destroy
- }
-
- # Set the default operation differently for these slots
- objdefine define::superclass forward --default-operation my -set
- objdefine define::mixin forward --default-operation my -set
- objdefine objdefine::mixin forward --default-operation my -set
-
- # ----------------------------------------------------------------------
- #
- # oo::object <cloned> --
- #
- # Handler for cloning objects that clones basic bits (only!) of the
- # object's namespace. Non-procedures, traces, sub-namespaces, etc. need
- # more complex (and class-specific) handling.
- #
- # ----------------------------------------------------------------------
-
- define object method <cloned> {originObject} {
- # Copy over the procedures from the original namespace
- foreach p [info procs [info object namespace $originObject]::*] {
- set args [info args $p]
- set idx -1
- foreach a $args {
- if {[info default $p $a d]} {
- lset args [incr idx] [list $a $d]
- } else {
- lset args [incr idx] [list $a]
- }
- }
- set b [info body $p]
- set p [namespace tail $p]
- proc $p $args $b
- }
- # Copy over the variables from the original namespace
- foreach v [info vars [info object namespace $originObject]::*] {
- upvar 0 $v vOrigin
- namespace upvar [namespace current] [namespace tail $v] vNew
- if {[info exists vOrigin]} {
- if {[array exists vOrigin]} {
- array set vNew [array get vOrigin]
- } else {
- set vNew $vOrigin
- }
- }
- }
- # General commands, sub-namespaces and advancd variable config (traces,
- # etc) are *not* copied over. Classes that want that should do it
- # themselves.
- }
-
- # ----------------------------------------------------------------------
- #
- # oo::class <cloned> --
- #
- # Handler for cloning classes, which fixes up the delegates.
- #
- # ----------------------------------------------------------------------
-
- define class method <cloned> {originObject} {
- next $originObject
- # Rebuild the class inheritance delegation class
- ::oo::UpdateClassDelegatesAfterClone $originObject [self]
- }
-
- # ----------------------------------------------------------------------
- #
- # oo::singleton --
- #
- # A metaclass that is used to make classes that only permit one instance
- # of them to exist. See singleton(n).
- #
- # ----------------------------------------------------------------------
-
- class create singleton {
- superclass class
- variable object
- unexport create createWithNamespace
- method new args {
- if {![info exists object] || ![info object isa object $object]} {
- set object [next {*}$args]
- ::oo::objdefine $object {
- method destroy {} {
- ::return -code error -errorcode {TCLOO SINGLETON} \
- "may not destroy a singleton object"
- }
- method <cloned> {originObject} {
- ::return -code error -errorcode {TCLOO SINGLETON} \
- "may not clone a singleton object"
- }
- }
- }
- return $object
- }
- }
-
- # ----------------------------------------------------------------------
- #
- # oo::abstract --
- #
- # A metaclass that is used to make classes that can't be directly
- # instantiated. See abstract(n).
- #
- # ----------------------------------------------------------------------
-
- class create abstract {
- superclass class
- unexport create createWithNamespace new
- }
-}
-
-# Local Variables:
-# mode: tcl
-# c-basic-offset: 4
-# fill-column: 78
-# End:
diff --git a/generic/tclObj.c b/generic/tclObj.c
index 89125cf..02203b0 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.c
@@ -3156,7 +3156,7 @@ GetBignumFromObj(
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType) {
- TclInitBignumFromWideInt(bignumValue,
+ mp_init_ll(bignumValue,
objPtr->internalRep.wideValue);
return TCL_OK;
}
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c
index 927ba35..b8fc428 100644
--- a/generic/tclPathObj.c
+++ b/generic/tclPathObj.c
@@ -47,37 +47,21 @@ static const Tcl_ObjType fsPathType = {
/*
* struct FsPath --
*
- * Internal representation of a Tcl_Obj of "path" type. This can be used to
- * represent relative or absolute paths, and has certain optimisations when
- * used to represent paths which are already normalized and absolute.
- *
- * There are two cases, with the first being the most common:
- *
- * (i) flags == 0, => Ordinary path.
- *
- * translatedPathPtr contains the translated path. If it is NULL then the path
- * is pure normalized. cwdPtr is null for an absolute path, and non-null for a
- * relative path (unless the cwd has never been set, in which case the cwdPtr
- * may also be null for a relative path).
- *
- * (ii) flags != 0, => Special path, see TclNewFSPathObj
- *
- * Now, this is a path like 'file join $dir $tail' where, cwdPtr is the $dir
- * and normPathPtr is the $tail.
- *
+ * Internal representation of a Tcl_Obj of fsPathType
*/
typedef struct {
- Tcl_Obj *translatedPathPtr; /* Name without any ~user sequences. If this
- * is NULL, then this is a pure normalized,
- * absolute path object, in which the parent
- * Tcl_Obj's string rep is already both
- * translated and normalized. */
- Tcl_Obj *normPathPtr; /* Normalized absolute path, without ., .. or
- * ~user sequences. */
- Tcl_Obj *cwdPtr; /* If null, path is absolute, else this points
- * to the cwd object used for this path. We
- * have a refCount on the object. */
+ Tcl_Obj *translatedPathPtr; /* If the path has been normalized (flags ==
+ * 0), this is NULL. Otherwise it is a path
+ * in which any ~user sequences have been
+ * translated away. */
+ Tcl_Obj *normPathPtr; /* If the path has been normalized (flags ==
+ * 0), this is an absolute path without ., ..
+ * or ~user components. Otherwise it is a
+ * path, possibly absolute, to normalize
+ * relative to cwdPtr. */
+ Tcl_Obj *cwdPtr; /* If NULL, either translatedPtr exists or
+ * normPathPtr exists and is absolute. */
int flags; /* Flags to describe interpretation - see
* below. */
ClientData nativePathPtr; /* Native representation of this path, which
@@ -131,17 +115,17 @@ typedef struct {
* pathPtr may have a refCount of zero, or may be a shared object.
*
* Results:
- * The result is returned in a Tcl_Obj with a refCount of 1, which is
- * therefore owned by the caller. It must be freed (with
- * Tcl_DecrRefCount) by the caller when no longer needed.
+ * The result is returned in a Tcl_Obj with a refCount already
+ * incremented, which gives the caller ownership of it. The caller must
+ * arrange for Tcl_DecRefCount to be called when the object is no-longer
+ * needed.
*
* Side effects:
* None (beyond the memory allocation for the result).
*
* Special note:
- * This code was originally based on code from Matt Newman and
- * Jean-Claude Wippler, but has since been totally rewritten by Vince
- * Darley to deal with symbolic links.
+ * Originally based on code from Matt Newman and Jean-Claude Wippler.
+ * Totally rewritten later by Vince Darley to handle symbolic links.
*
*---------------------------------------------------------------------------
*/
@@ -708,9 +692,8 @@ TclPathPart(
}
/*
- * The behaviour we want here is slightly different to the standard
* Tcl_FSSplitPath in the handling of home directories;
- * Tcl_FSSplitPath preserves the "~" while this code computes the
+ * Tcl_FSSplitPath preserves the "~", but this code computes the
* actual full path name, if we had just a single component.
*/
@@ -869,7 +852,7 @@ TclJoinPath(
* could expand that in the future.
*
* Bugfix [a47641a0]. TclNewFSPathObj requires first argument
- * to be an absolute path. Added a check for that elt is absolute.
+ * to be an absolute path. Added a check to ensure that elt is absolute.
*/
if ((eltIr)
@@ -1507,7 +1490,7 @@ MakePathFromNormalized(
*
* Tcl_FSNewNativePath --
*
- * This function performs the something like the reverse of the usual
+ * Performs the something like the reverse of the usual
* obj->path->nativerep conversions. If some code retrieves a path in
* native form (from, e.g. readlink or a native dialog), and that path is
* to be used at the Tcl level, then calling this function is an
@@ -1570,16 +1553,18 @@ Tcl_FSNewNativePath(
*
* Tcl_FSGetTranslatedPath --
*
- * This function attempts to extract the translated path from the given
+ * Attempts to extract the translated path from the given
* Tcl_Obj. If the translation succeeds (i.e. the object is a valid
- * path), then it is returned. Otherwise NULL will be returned, and an
- * error message may be left in the interpreter (if it is non-NULL)
+ * path), then it is returned. Otherwise NULL is returned and an
+ * error message may be left in the interpreter if it is not NULL.
*
* Results:
- * NULL or a valid Tcl_Obj pointer.
+ * A Tcl_Obj pointer or NULL.
*
* Side effects:
- * Only those of 'Tcl_FSConvertToPathType'
+ * pathPtr is converted to fsPathType if necessary.
+ *
+ * FsPath members are modified as needed.
*
*---------------------------------------------------------------------------
*/
@@ -1597,7 +1582,12 @@ Tcl_FSGetTranslatedPath(
}
srcFsPathPtr = PATHOBJ(pathPtr);
if (srcFsPathPtr->translatedPathPtr == NULL) {
- if (PATHFLAGS(pathPtr) != 0) {
+ if (PATHFLAGS(pathPtr) == 0) {
+ /*
+ * Path is already normalized
+ */
+ retObj = srcFsPathPtr->normPathPtr;
+ } else {
/*
* We lack a translated path result, but we have a directory
* (cwdPtr) and a tail (normPathPtr), and if we join the
@@ -1624,14 +1614,6 @@ Tcl_FSGetTranslatedPath(
srcFsPathPtr->filesystemEpoch = 0;
}
Tcl_DecrRefCount(translatedCwdPtr);
- } else {
- /*
- * It is a pure absolute, normalized path object. This is
- * something like being a 'pure list'. The object's string,
- * translatedPath and normalizedPath are all identical.
- */
-
- retObj = srcFsPathPtr->normPathPtr;
}
} else {
/*
@@ -1800,11 +1782,6 @@ Tcl_FSGetNormalizedPath(
TclDecrRefCount(fsPathPtr->normPathPtr);
fsPathPtr->normPathPtr = copy;
- /*
- * That's our reference to copy used.
- */
- copy = NULL;
-
TclDecrRefCount(dir);
TclDecrRefCount(origDir);
} else {
@@ -1813,10 +1790,6 @@ Tcl_FSGetNormalizedPath(
TclDecrRefCount(fsPathPtr->normPathPtr);
fsPathPtr->normPathPtr = copy;
- /*
- * That's our reference to copy used.
- */
- copy = NULL;
TclDecrRefCount(dir);
}
PATHFLAGS(pathPtr) = 0;
@@ -1857,7 +1830,7 @@ Tcl_FSGetNormalizedPath(
Tcl_Obj *useThisCwd = NULL;
/*
- * Since normPathPtr is NULL, but this is a valid path object, we know
+ * Since normPathPtr is NULL but this is a valid path object, we know
* that the translatedPathPtr cannot be NULL.
*/
@@ -1957,19 +1930,23 @@ Tcl_FSGetNormalizedPath(
*
* Tcl_FSGetInternalRep --
*
- * Extract the internal representation of a given path object, in the
- * given filesystem. If the path object belongs to a different
- * filesystem, we return NULL.
+ * Produces a native representation of a given path object in the given
+ * filesystem.
*
- * If the internal representation is currently NULL, we attempt to
- * generate it, by calling the filesystem's
- * 'Tcl_FSCreateInternalRepProc'.
+ * 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 internal representation.
+ *
+ * The native handle for the path, or NULL if the path is not handled by
+ * the given filesystem
*
* Side effects:
- * An attempt may be made to convert the object.
+ *
+ * Tcl_FSCreateInternalRepProc if needed to produce the native
+ * handle, which is then stored in the internal representation of pathPtr.
*
*---------------------------------------------------------------------------
*/
@@ -1987,49 +1964,36 @@ Tcl_FSGetInternalRep(
srcFsPathPtr = PATHOBJ(pathPtr);
/*
- * We will only return the native representation for the caller's
- * filesystem. Otherwise we will simply return NULL. This means that there
- * must be a unique bi-directional mapping between paths and filesystems,
- * and that this mapping will not allow 'remapped' files -- files which
- * are in one filesystem but mapped into another. Another way of putting
- * this is that 'stacked' filesystems are not allowed. We recognise that
- * this is a potentially useful feature for the future.
+ * Currently there must be a unique bi-directional mapping between a path
+ * and a filesystem, and therefore there is no way to "remap" a file, i.e.,
+ * to map a file in one filesystem into another. Another way of putting
+ * this is that 'stacked' filesystems are not allowed. It could be useful
+ * in the future to redesign the system to allow that.
*
* Even something simple like a 'pass through' filesystem which logs all
* activity and passes the calls onto the native system would be nice, but
- * not easily achievable with the current implementation.
+ * not currently easily achievable.
*/
if (srcFsPathPtr->fsPtr == NULL) {
- /*
- * This only usually happens in wrappers like TclpStat which create a
- * string object and pass it to TclpObjStat. Code which calls the
- * Tcl_FS.. functions should always have a filesystem already set.
- * Whether this code path is legal or not depends on whether we decide
- * to allow external code to call the native filesystem directly. It
- * is at least safer to allow this sub-optimal routing.
- */
-
Tcl_FSGetFileSystemForPath(pathPtr);
- /*
- * If we fail through here, then the path is probably not a valid path
- * in the filesystsem, and is most likely to be a use of the empty
- * path "" via a direct call to one of the objectified interfaces
- * (e.g. from the Tcl testsuite).
- */
-
srcFsPathPtr = PATHOBJ(pathPtr);
if (srcFsPathPtr->fsPtr == NULL) {
+ /*
+ * The path is probably not a valid path in the filesystsem, and is
+ * most likely to be a use of the empty path "" via a direct call
+ * to one of the objectified interfaces (e.g. from the Tcl
+ * testsuite).
+ */
return NULL;
}
}
/*
- * There is still one possibility we should consider; if the file belongs
- * to a different filesystem, perhaps it is actually linked through to a
- * file in our own filesystem which we do care about. The way we can check
- * for this is we ask what filesystem this path belongs to.
+ * If the file belongs to a different filesystem, perhaps it is actually
+ * linked through to a file in the given filesystem. Check this by
+ * inspecting the filesystem associated with the given path.
*/
if (fsPtr != srcFsPathPtr->fsPtr) {
@@ -2053,6 +2017,7 @@ Tcl_FSGetInternalRep(
nativePathPtr = proc(pathPtr);
srcFsPathPtr = PATHOBJ(pathPtr);
srcFsPathPtr->nativePathPtr = nativePathPtr;
+ srcFsPathPtr->filesystemEpoch = TclFSEpoch();
}
return srcFsPathPtr->nativePathPtr;
@@ -2063,15 +2028,15 @@ Tcl_FSGetInternalRep(
*
* TclFSEnsureEpochOk --
*
- * This will ensure the pathPtr is up to date and can be converted into a
- * "path" type, and that we are able to generate a complete normalized
- * path which is used to determine the filesystem match.
+ * Ensure that the path is a valid path, and that it has a
+ * fsPathType internal representation that is not stale.
*
* Results:
- * Standard Tcl return code.
+ * A standard Tcl return code.
*
* Side effects:
- * An attempt may be made to convert the object.
+ * The internal representation of fsPtrPtr is converted to fsPathType if
+ * possible.
*
*---------------------------------------------------------------------------
*/
@@ -2089,14 +2054,11 @@ TclFSEnsureEpochOk(
srcFsPathPtr = PATHOBJ(pathPtr);
- /*
- * Check if the filesystem has changed in some way since this object's
- * internal representation was calculated.
- */
-
if (!TclFSEpochOk(srcFsPathPtr->filesystemEpoch)) {
/*
- * We have to discard the stale representation and recalculate it.
+ * The filesystem has changed in some way since the internal
+ * representation for this object was calculated. Discard the stale
+ * representation and recalculate it.
*/
TclGetString(pathPtr);
@@ -2107,11 +2069,10 @@ TclFSEnsureEpochOk(
srcFsPathPtr = PATHOBJ(pathPtr);
}
- /*
- * Check whether the object is already assigned to a fs.
- */
-
if (srcFsPathPtr->fsPtr != NULL) {
+ /*
+ * There is already a filesystem assigned to this path.
+ */
*fsPtrPtr = srcFsPathPtr->fsPtr;
}
return TCL_OK;
@@ -2220,11 +2181,12 @@ Tcl_FSEqualPaths(
*
* SetFsPathFromAny --
*
- * This function tries to convert the given Tcl_Obj to a valid Tcl path
- * type.
+ * Attempt to convert the internal representation of pathPtr to
+ * fsPathType.
*
- * The filename may begin with "~" (to indicate current user's home
- * directory) or "~<user>" (to indicate any user's home directory).
+ * A tilde ("~") character at the beginnig of the filename indicates the
+ * current user's home directory, and "~<user>" indicates a particular
+ * user's directory.
*
* Results:
* Standard Tcl error code.
@@ -2308,7 +2270,7 @@ SetFsPathFromAny(
Tcl_DStringFree(&dirString);
} else {
/*
- * We have a user name '~user'
+ * There is a '~user'
*/
const char *expandedUser;
diff --git a/generic/tclScan.c b/generic/tclScan.c
index ba9ccbe..6f9515b 100644
--- a/generic/tclScan.c
+++ b/generic/tclScan.c
@@ -579,9 +579,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,
@@ -931,8 +928,16 @@ Tcl_ScanObjCmd(
}
}
if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) {
- sprintf(buf, "%" TCL_LL_MODIFIER "u", wideValue);
- Tcl_SetStringObj(objPtr, buf, -1);
+ mp_int big;
+ if (mp_init(&big) != MP_OKAY) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "insufficient memory to create bignum", -1));
+ Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
+ return TCL_ERROR;
+ } else {
+ mp_set_ull(&big, (Tcl_WideUInt)wideValue);
+ Tcl_SetBignumObj(objPtr, &big);
+ }
} else {
TclSetIntObj(objPtr, wideValue);
}
@@ -942,7 +947,7 @@ Tcl_ScanObjCmd(
int code = Tcl_GetBignumFromObj(interp, objPtr, &big);
if (code == TCL_OK) {
- if (big.sign != MP_ZPOS) {
+ if (mp_isneg(&big)) {
code = TCL_ERROR;
}
mp_clear(&big);
@@ -969,8 +974,20 @@ 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;
+ if (mp_init(&big) != MP_OKAY) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "insufficient memory to create bignum", -1));
+ Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
+ return TCL_ERROR;
+ } else {
+ mp_set_ull(&big, (unsigned long)value);
+ Tcl_SetBignumObj(objPtr, &big);
+ }
+#else
+ Tcl_SetWideIntObj(objPtr, (unsigned long)value);
+#endif
} else {
TclSetIntObj(objPtr, value);
}
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c
index 4739eee..d624f87 100644
--- a/generic/tclStrToD.c
+++ b/generic/tclStrToD.c
@@ -706,7 +706,7 @@ TclParseNumber(
|| (octalSignificandWide >
((Tcl_WideUInt)-1 >> shift)))) {
octalSignificandOverflow = 1;
- TclInitBignumFromWideUInt(&octalSignificandBig,
+ mp_init_ull(&octalSignificandBig,
octalSignificandWide);
}
}
@@ -771,7 +771,7 @@ TclParseNumber(
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > ((Tcl_WideUInt)-1 >> shift))) {
significandOverflow = 1;
- TclInitBignumFromWideUInt(&significandBig,
+ mp_init_ull(&significandBig,
significandWide);
}
}
@@ -812,7 +812,7 @@ TclParseNumber(
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > ((Tcl_WideUInt)-1 >> shift))) {
significandOverflow = 1;
- TclInitBignumFromWideUInt(&significandBig,
+ mp_init_ull(&significandBig,
significandWide);
}
}
@@ -1154,7 +1154,7 @@ TclParseNumber(
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > (MOST_BITS + signum) >> shift)) {
significandOverflow = 1;
- TclInitBignumFromWideUInt(&significandBig, significandWide);
+ mp_init_ull(&significandBig, significandWide);
}
if (shift) {
if (!significandOverflow) {
@@ -1175,7 +1175,7 @@ TclParseNumber(
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
significandWide > (MOST_BITS + signum) >> shift)) {
significandOverflow = 1;
- TclInitBignumFromWideUInt(&significandBig, significandWide);
+ mp_init_ull(&significandBig, significandWide);
}
if (shift) {
if (!significandOverflow) {
@@ -1196,7 +1196,7 @@ TclParseNumber(
((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
octalSignificandWide > (MOST_BITS + signum) >> shift)) {
octalSignificandOverflow = 1;
- TclInitBignumFromWideUInt(&octalSignificandBig,
+ mp_init_ull(&octalSignificandBig,
octalSignificandWide);
}
if (shift) {
@@ -1209,7 +1209,7 @@ TclParseNumber(
}
if (!octalSignificandOverflow) {
if (octalSignificandWide > (MOST_BITS + signum)) {
- TclInitBignumFromWideUInt(&octalSignificandBig,
+ mp_init_ull(&octalSignificandBig,
octalSignificandWide);
octalSignificandOverflow = 1;
} else {
@@ -1237,12 +1237,12 @@ TclParseNumber(
&significandWide, &significandBig, significandOverflow);
if (!significandOverflow && (significandWide > MOST_BITS+signum)){
significandOverflow = 1;
- TclInitBignumFromWideUInt(&significandBig, significandWide);
+ mp_init_ull(&significandBig, significandWide);
}
returnInteger:
if (!significandOverflow) {
if (significandWide > MOST_BITS+signum) {
- TclInitBignumFromWideUInt(&significandBig,
+ mp_init_ull(&significandBig,
significandWide);
significandOverflow = 1;
} else {
@@ -1394,7 +1394,7 @@ AccumulateDecimalDigit(
* bignum and fall through into the bignum case.
*/
- TclInitBignumFromWideUInt(bignumRepPtr, w);
+ mp_init_ull(bignumRepPtr, w);
} else {
/*
* Wide multiplication.
@@ -1537,7 +1537,7 @@ MakeLowPrecisionDouble(
* call MakeHighPrecisionDouble to do it the hard way.
*/
- TclInitBignumFromWideUInt(&significandBig, significand);
+ mp_init_ull(&significandBig, significand);
retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs,
exponent);
mp_clear(&significandBig);
@@ -2661,7 +2661,7 @@ QuickConversion(
int k, /* floor(log10(d)), approximately. */
int k_check, /* 0 if k is exact, 1 if it may be too high */
int flags, /* Flags passed to dtoa:
- * TCL_DD_SHORTEN_FLAG */
+ * TCL_DD_SHORTEST */
int len, /* Length of the return value. */
int ilim, /* Number of digits to store. */
int ilim1, /* Number of digits to store if we misguessed
@@ -2732,7 +2732,7 @@ QuickConversion(
* Format the digit string.
*/
- if (flags & TCL_DD_SHORTEN_FLAG) {
+ if (flags & TCL_DD_SHORTEST) {
end = ShorteningQuickFormat(d, k, ilim, eps.d, retval, decpt);
} else {
end = StrictQuickFormat(d, k, ilim, eps.d, retval, decpt);
@@ -3204,7 +3204,7 @@ ShorteningBignumConversionPowD(
* mminus = 5**m5
*/
- TclInitBignumFromWideUInt(&b, bw);
+ mp_init_ull(&b, bw);
mp_init_set(&mminus, 1);
MulPow5(&b, b5, &b);
mp_mul_2d(&b, b2, &b);
@@ -3388,7 +3388,7 @@ StrictBignumConversionPowD(
* b = bw * 2**b2 * 5**b5
*/
- TclInitBignumFromWideUInt(&b, bw);
+ mp_init_ull(&b, bw);
MulPow5(&b, b5, &b);
mp_mul_2d(&b, b2, &b);
@@ -3588,7 +3588,7 @@ ShorteningBignumConversion(
* S = 2**s2 * 5*s5
*/
- TclInitBignumFromWideUInt(&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);
@@ -3797,7 +3797,7 @@ StrictBignumConversion(
*/
mp_init_multi(&dig, NULL);
- TclInitBignumFromWideUInt(&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);
@@ -3944,7 +3944,7 @@ StrictBignumConversion(
* choosing the one that is closest to the given number (and
* resolving ties with 'round to even'). It is allowed to return
* fewer than 'ndigits' if the number converts exactly; if the
- * TCL_DD_E_FORMAT|TCL_DD_SHORTEN_FLAG is supplied instead, it
+ * TCL_DD_E_FORMAT|TCL_DD_SHORTEST is supplied instead, it
* also returns fewer digits if the shorter string will still
* reconvert without loss to the given input number. In any case,
* strings of trailing zeroes are suppressed.
@@ -3955,7 +3955,7 @@ StrictBignumConversion(
* string if the number is sufficiently small. Again, it is
* permissible for TCL_DD_F_FORMAT to return fewer digits for a
* number that converts exactly, and changing the argument to
- * TCL_DD_F_FORMAT|TCL_DD_SHORTEN_FLAG will allow the routine
+ * TCL_DD_F_FORMAT|TCL_DD_SHORTEST will allow the routine
* also to return fewer digits if the shorter string will still
* reconvert without loss to the given input number. Strings of
* trailing zeroes are suppressed.
@@ -4092,7 +4092,7 @@ TclDoubleDigits(
* denominator.
*/
- if (flags & TCL_DD_SHORTEN_FLAG) {
+ if (flags & TCL_DD_SHORTEST) {
int m2minus = b2;
int m2plus;
int m5 = b5;
@@ -4439,7 +4439,7 @@ Tcl_InitBignumFromDouble(
Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits);
int shift = expt - mantBits;
- TclInitBignumFromWideInt(b, w);
+ mp_init_ll(b, w);
if (shift < 0) {
mp_div_2d(b, -shift, b, NULL);
} else if (shift > 0) {
@@ -4481,10 +4481,10 @@ TclBignumToDouble(
bits = mp_count_bits(a);
if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
errno = ERANGE;
- if (a->sign == MP_ZPOS) {
- return HUGE_VAL;
- } else {
+ if (mp_isneg(a)) {
return -HUGE_VAL;
+ } else {
+ return HUGE_VAL;
}
}
shift = mantBits - bits;
@@ -4514,10 +4514,10 @@ TclBignumToDouble(
mp_div_2d(a, -shift, &b, NULL);
if (mp_isodd(&b)) {
- if (b.sign == MP_ZPOS) {
- mp_add_d(&b, 1, &b);
- } else {
+ if (mp_isneg(&b)) {
mp_sub_d(&b, 1, &b);
+ } else {
+ mp_add_d(&b, 1, &b);
}
}
} else {
@@ -4527,10 +4527,10 @@ TclBignumToDouble(
*/
mp_div_2d(a, -1-shift, &b, NULL);
- if (b.sign == MP_ZPOS) {
- mp_add_d(&b, 1, &b);
- } else {
+ if (mp_isneg(&b)) {
mp_sub_d(&b, 1, &b);
+ } else {
+ mp_add_d(&b, 1, &b);
}
mp_div_2d(&b, 1, &b, NULL);
}
@@ -4556,10 +4556,10 @@ TclBignumToDouble(
* Return the result with the appropriate sign.
*/
- if (a->sign == MP_ZPOS) {
- return r;
- } else {
+ if (mp_isneg(a)) {
return -r;
+ } else {
+ return r;
}
}
@@ -4585,7 +4585,7 @@ TclCeil(
mp_int b;
mp_init(&b);
- if (a->sign != MP_ZPOS) {
+ if (mp_isneg(a)) {
mp_neg(a, &b);
r = -TclFloor(&b);
} else {
@@ -4642,7 +4642,7 @@ TclFloor(
mp_int b;
mp_init(&b);
- if (a->sign != MP_ZPOS) {
+ if (mp_isneg(a)) {
mp_neg(a, &b);
r = -TclCeil(&b);
} else {
@@ -4732,7 +4732,7 @@ BignumToBiasedFrExp(
*/
*machexp = bits - mantBits + 2;
- return ((a->sign == MP_ZPOS) ? r : -r);
+ return (mp_isneg(a) ? -r : r);
}
/*
diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c
index ee6c67b..6c11147 100644
--- a/generic/tclStubInit.c
+++ b/generic/tclStubInit.c
@@ -60,6 +60,7 @@
#endif
MP_SET_UNSIGNED(mp_set_ull, Tcl_WideUInt)
+MP_SET_SIGNED(mp_set_ll, mp_set_ull, Tcl_WideInt, Tcl_WideUInt)
MP_GET_MAG(mp_get_mag_ull, Tcl_WideUInt)
mp_err TclBN_mp_set_int(mp_int *a, unsigned long i)
@@ -76,6 +77,40 @@ static mp_err TclBN_mp_set_long(mp_int *a, unsigned long i)
#define TclBN_mp_set_ul (void (*)(mp_int *a, unsigned long i))TclBN_mp_set_long
+mp_err MP_WUR TclBN_mp_expt_u32(const mp_int *a, unsigned int b, mp_int *c) {
+ return TclBN_s_mp_expt_u32(a, b, c);
+}
+
+mp_err TclBN_mp_add_d(const mp_int *a, unsigned int b, mp_int *c) {
+ return TclBN_s_mp_add_d(a, b, c);
+}
+mp_err TclBN_mp_cmp_d(const mp_int *a, unsigned int b) {
+ return TclBN_s_mp_cmp_d(a, b);
+}
+mp_err TclBN_mp_sub_d(const mp_int *a, unsigned int b, mp_int *c) {
+ return TclBN_s_mp_sub_d(a, b, c);
+}
+
+mp_err TclBN_mp_div_d(const mp_int *a, unsigned int b, mp_int *c, unsigned int *d) {
+ mp_digit d2;
+ mp_err result = TclBN_s_mp_div_d(a, b, c, (d ? &d2 : NULL));
+ if (d) {
+ *d = d2;
+ }
+ return result;
+}
+mp_err TclBN_mp_init_set(mp_int *a, unsigned int b) {
+ return TclBN_s_mp_init_set(a, b);
+}
+mp_err TclBN_mp_mul_d(const mp_int *a, unsigned int b, mp_int *c) {
+ return TclBN_s_mp_mul_d(a, b, c);
+}
+void TclBN_mp_set(mp_int *a, unsigned int b) {
+ TclBN_s_mp_set(a, b);
+}
+
+
+
#ifdef _WIN32
# define TclUnixWaitForFile 0
# define TclUnixCopyFile 0
@@ -583,7 +618,7 @@ const TclTomMathStubs tclTomMathStubs = {
TclBN_mp_div_d, /* 14 */
TclBN_mp_div_2, /* 15 */
TclBN_mp_div_2d, /* 16 */
- TclBN_mp_div_3, /* 17 */
+ 0, /* 17 */
TclBN_mp_exch, /* 18 */
TclBN_mp_expt_u32, /* 19 */
TclBN_mp_grow, /* 20 */
@@ -606,7 +641,7 @@ const TclTomMathStubs tclTomMathStubs = {
TclBN_mp_rshd, /* 37 */
TclBN_mp_shrink, /* 38 */
TclBN_mp_set, /* 39 */
- TclBN_mp_sqr, /* 40 */
+ 0, /* 40 */
TclBN_mp_sqrt, /* 41 */
TclBN_mp_sub, /* 42 */
TclBN_mp_sub_d, /* 43 */
@@ -630,15 +665,15 @@ const TclTomMathStubs tclTomMathStubs = {
TclBN_mp_init_ul, /* 61 */
TclBN_mp_set_ul, /* 62 */
TclBN_mp_cnt_lsb, /* 63 */
- 0, /* 64 */
- 0, /* 65 */
- 0, /* 66 */
+ TclBNInitBignumFromLong, /* 64 */
+ TclBNInitBignumFromWideInt, /* 65 */
+ TclBNInitBignumFromWideUInt, /* 66 */
0, /* 67 */
TclBN_mp_set_ull, /* 68 */
TclBN_mp_get_mag_ull, /* 69 */
- 0, /* 70 */
+ TclBN_mp_set_ll, /* 70 */
TclBN_mp_get_mag_ul, /* 71 */
- TclBN_mp_isodd, /* 72 */
+ TclBN_mp_set_l, /* 72 */
0, /* 73 */
0, /* 74 */
0, /* 75 */
@@ -704,7 +739,7 @@ const TclStubs tclStubs = {
Tcl_DbNewObj, /* 27 */
Tcl_DbNewStringObj, /* 28 */
Tcl_DuplicateObj, /* 29 */
- 0, /* 30 */
+ TclFreeObj, /* 30 */
Tcl_GetBoolean, /* 31 */
Tcl_GetBooleanFromObj, /* 32 */
Tcl_GetByteArrayFromObj, /* 33 */
diff --git a/generic/tclTest.c b/generic/tclTest.c
index f0b7637..f49a7cd 100644
--- a/generic/tclTest.c
+++ b/generic/tclTest.c
@@ -1804,7 +1804,7 @@ TestdoubledigitsObjCmd(void *unused,
Tcl_SetObjResult(interp, Tcl_NewStringObj("bad flag", -1));
return TCL_ERROR;
}
- type |= TCL_DD_SHORTEN_FLAG;
+ type |= TCL_DD_SHORTEST;
}
str = TclDoubleDigits(d, ndigits, type, &decpt, &signum, &endPtr);
strObj = Tcl_NewStringObj(str, endPtr-str);
diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c
index 9c609c9..f7bfcc4 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 49d6fca..3dbe18c 100644
--- a/generic/tclTomMath.decls
+++ b/generic/tclTomMath.decls
@@ -33,7 +33,7 @@ declare 2 {
mp_err MP_WUR TclBN_mp_add(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 3 {
- mp_err MP_WUR TclBN_mp_add_d(const mp_int *a, mp_digit b, mp_int *c)
+ mp_err MP_WUR TclBN_mp_add_d(const mp_int *a, unsigned int b, mp_int *c)
}
declare 4 {
mp_err MP_WUR TclBN_mp_and(const mp_int *a, const mp_int *b, mp_int *c)
@@ -51,7 +51,7 @@ declare 8 {
mp_ord MP_WUR TclBN_mp_cmp(const mp_int *a, const mp_int *b)
}
declare 9 {
- mp_ord MP_WUR TclBN_mp_cmp_d(const mp_int *a, mp_digit b)
+ mp_ord MP_WUR TclBN_mp_cmp_d(const mp_int *a, unsigned int b)
}
declare 10 {
mp_ord MP_WUR TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b)
@@ -66,7 +66,7 @@ declare 13 {
mp_err MP_WUR TclBN_mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r)
}
declare 14 {
- mp_err MP_WUR TclBN_mp_div_d(const mp_int *a, mp_digit b, mp_int *q, mp_digit *r)
+ mp_err MP_WUR TclBN_mp_div_d(const mp_int *a, unsigned int b, mp_int *q, unsigned int *r)
}
declare 15 {
mp_err MP_WUR TclBN_mp_div_2(const mp_int *a, mp_int *q)
@@ -74,9 +74,10 @@ declare 15 {
declare 16 {
mp_err MP_WUR TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r)
}
-declare 17 {
- mp_err MP_WUR TclBN_mp_div_3(const mp_int *a, mp_int *q, mp_digit *r)
-}
+# Removed in 9.0
+#declare 17 {deprecated {is private function in libtommath}} {
+# mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, unsigned int *r)
+#}
declare 18 {
void TclBN_mp_exch(mp_int *a, mp_int *b)
}
@@ -96,7 +97,7 @@ declare 23 {
mp_err MP_WUR TclBN_mp_init_multi(mp_int *a, ...)
}
declare 24 {
- mp_err MP_WUR TclBN_mp_init_set(mp_int *a, mp_digit b)
+ mp_err MP_WUR TclBN_mp_init_set(mp_int *a, unsigned int b)
}
declare 25 {
mp_err MP_WUR TclBN_mp_init_size(mp_int *a, int size)
@@ -114,7 +115,7 @@ declare 29 {
mp_err MP_WUR TclBN_mp_mul(const mp_int *a, const mp_int *b, mp_int *p)
}
declare 30 {
- mp_err MP_WUR TclBN_mp_mul_d(const mp_int *a, mp_digit b, mp_int *p)
+ mp_err MP_WUR TclBN_mp_mul_d(const mp_int *a, unsigned int b, mp_int *p)
}
declare 31 {
mp_err MP_WUR TclBN_mp_mul_2(const mp_int *a, mp_int *p)
@@ -141,11 +142,12 @@ declare 38 {
mp_err MP_WUR TclBN_mp_shrink(mp_int *a)
}
declare 39 {
- void TclBN_mp_set(mp_int *a, mp_digit b)
-}
-declare 40 {
- mp_err MP_WUR TclBN_mp_sqr(const mp_int *a, mp_int *b)
+ void TclBN_mp_set(mp_int *a, unsigned int b)
}
+# Removed in 9.0
+#declare 40 {nostub {is private function in libtommath}} {
+# mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b)
+#}
declare 41 {
mp_err MP_WUR TclBN_mp_sqrt(const mp_int *a, mp_int *b)
}
@@ -153,7 +155,7 @@ declare 42 {
mp_err MP_WUR TclBN_mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 43 {
- mp_err MP_WUR TclBN_mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
+ mp_err MP_WUR TclBN_mp_sub_d(const mp_int *a, unsigned int b, mp_int *c)
}
# Removed in 9.0
#declare 44 {
@@ -189,22 +191,19 @@ declare 63 {
# Formerly internal API to allow initialisation of bignums without knowing the
# typedefs of how a bignum works internally.
-# Removed in 9.0
-#declare 64 {
-# void TclBNInitBignumFromLong(mp_int *bignum, long initVal)
-#}
-# Removed in 9.0
-#declare 65 {
-# void TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal)
-#}
-# Removed in 9.0
-#declare 66 {
-# void TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal)
-#}
+declare 64 {
+ int TclBNInitBignumFromLong(mp_int *bignum, long initVal)
+}
+declare 65 {
+ int TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal)
+}
+declare 66 {
+ int TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal)
+}
# Removed in 9.0
#declare 67 {
-# mp_err TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
+# mp_err TclBN_mp_expt_d_ex(const mp_int *a, unsigned int b, mp_int *c, int fast)
#}
# Added in libtommath 1.0.1
declare 68 {
@@ -213,11 +212,14 @@ declare 68 {
declare 69 {
Tcl_WideUInt MP_WUR TclBN_mp_get_mag_ull(const mp_int *a)
}
+declare 70 {
+ void TclBN_mp_set_ll(mp_int *a, Tcl_WideInt i)
+}
declare 71 {
- unsigned long TclBN_mp_get_mag_ul(const mp_int *a)
+ unsigned long MP_WUR TclBN_mp_get_mag_ul(const mp_int *a)
}
declare 72 {
- mp_bool MP_WUR TclBN_mp_isodd(const mp_int *a)
+ void TclBN_mp_set_l(mp_int *a, long i)
}
# Added in libtommath 1.1.0
@@ -236,10 +238,6 @@ declare 72 {
declare 76 {
mp_err MP_WUR TclBN_mp_signed_rsh(const mp_int *a, int b, mp_int *c)
}
-# Removed in 9.0
-#declare 77 {
-# mp_bool TclBN_mp_get_bit(const mp_int *a, unsigned int b)
-#}
# Added in libtommath 1.2.0
declare 78 {
diff --git a/generic/tclTomMath.h b/generic/tclTomMath.h
index 618e555..1ecd5be 100644
--- a/generic/tclTomMath.h
+++ b/generic/tclTomMath.h
@@ -7,24 +7,48 @@
#ifndef MP_NO_STDINT
# include <stdint.h>
#endif
+#include <stddef.h>
+#include <limits.h>
#ifndef MODULE_SCOPE
#define MODULE_SCOPE extern
#endif
+#ifdef LTM_NO_FILE
+# warning LTM_NO_FILE has been deprecated, use MP_NO_FILE.
+# define MP_NO_FILE
+#endif
+
+#ifndef MP_NO_FILE
+# include <stdio.h>
+#endif
+
+#ifdef MP_8BIT
+# ifdef _MSC_VER
+# pragma message("8-bit (MP_8BIT) support is deprecated and will be dropped completely in the next version.")
+# else
+# warning "8-bit (MP_8BIT) support is deprecated and will be dropped completely in the next version."
+# endif
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */
-#if (defined(_WIN32) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)) && !defined(MP_64BIT)
+#if (defined(_WIN32) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)) && !defined(MP_32BIT) && !defined(MP_64BIT)
# define MP_32BIT
#endif
/* detect 64-bit mode if possible */
-#if defined(NEVER)
-# if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT))
-# if defined(__GNUC__)
+#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \
+ defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \
+ defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \
+ defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \
+ defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \
+ defined(__LP64__) || defined(_LP64) || defined(__64BIT__)
+# if !(defined(MP_64BIT) || defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT))
+# if defined(__GNUC__) && !defined(__hppa)
/* we support 128bit integers only via: __attribute__((mode(TI))) */
# define MP_64BIT
# else
@@ -47,39 +71,17 @@ extern "C" {
*/
#ifdef MP_8BIT
-#ifndef MP_DIGIT_DECLARED
typedef unsigned char mp_digit;
-#define MP_DIGIT_DECLARED
-#endif
-# define MP_SIZEOF_MP_DIGIT 1
-# ifdef MP_DIGIT_BIT
-# error You must not define MP_DIGIT_BIT when using MP_8BIT
-# endif
+# define MP_DIGIT_BIT 7
#elif defined(MP_16BIT)
-#ifndef MP_DIGIT_DECLARED
typedef unsigned short mp_digit;
-#define MP_DIGIT_DECLARED
-#endif
-# define MP_SIZEOF_MP_DIGIT 2
-# ifdef MP_DIGIT_BIT
-# error You must not define MP_DIGIT_BIT when using MP_16BIT
-# endif
+# define MP_DIGIT_BIT 15
#elif defined(MP_64BIT)
/* for GCC only on supported platforms */
-#ifndef MP_DIGIT_DECLARED
typedef unsigned long long mp_digit;
-#define MP_DIGIT_DECLARED
-#endif
# define MP_DIGIT_BIT 60
#else
-/* this is the default case, 28-bit digits */
-
-/* this is to make porting into LibTomCrypt easier :-) */
-#ifndef MP_DIGIT_DECLARED
typedef unsigned int mp_digit;
-#define MP_DIGIT_DECLARED
-#endif
-
# ifdef MP_31BIT
/*
* This is an extension that uses 31-bit digits.
@@ -108,10 +110,6 @@ typedef unsigned int mp_digit;
#define MP_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
#define MP_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
-#define LTM_PRIME_BBS (MP_DEPRECATED_PRAGMA("LTM_PRIME_BBS has been deprecated, use MP_PRIME_BBS") MP_PRIME_BBS)
-#define LTM_PRIME_SAFE (MP_DEPRECATED_PRAGMA("LTM_PRIME_SAFE has been deprecated, use MP_PRIME_SAFE") MP_PRIME_SAFE)
-#define LTM_PRIME_2MSB_ON (MP_DEPRECATED_PRAGMA("LTM_PRIME_2MSB_ON has been deprecated, use MP_PRIME_2MSB_ON") MP_PRIME_2MSB_ON)
-
#ifdef MP_USE_ENUMS
typedef enum {
MP_ZPOS = 0, /* positive */
@@ -236,10 +234,10 @@ TOOM_SQR_CUTOFF;
# define MP_DEPRECATED_PRAGMA(s)
#endif
-#define DIGIT_BIT MP_DIGIT_BIT
-#define USED(m) ((m)->used)
-#define DIGIT(m,k) ((m)->dp[(k)])
-#define SIGN(m) ((m)->sign)
+#define DIGIT_BIT (MP_DEPRECATED_PRAGMA("DIGIT_BIT macro is deprecated, MP_DIGIT_BIT instead") MP_DIGIT_BIT)
+#define USED(m) (MP_DEPRECATED_PRAGMA("USED macro is deprecated, use z->used instead") (m)->used)
+#define DIGIT(m, k) (MP_DEPRECATED_PRAGMA("DIGIT macro is deprecated, use z->dp instead") (m)->dp[(k)])
+#define SIGN(m) (MP_DEPRECATED_PRAGMA("SIGN macro is deprecated, use z->sign instead") (m)->sign)
/* the infamous mp_int structure */
#ifndef MP_INT_DECLARED
@@ -300,12 +298,8 @@ mp_err mp_init_size(mp_int *a, int size) MP_WUR;
/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
-/*
-mp_bool mp_iseven(const mp_int *a) MP_WUR;
-*/
-/*
-mp_bool mp_isodd(const mp_int *a) MP_WUR;
-*/
+#define mp_isodd(a) (((a)->used != 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)
/* set to zero */
@@ -374,7 +368,7 @@ uint64_t mp_get_mag_u64(const mp_int *a) MP_WUR;
unsigned long mp_get_mag_ul(const mp_int *a) MP_WUR;
*/
/*
-Tcl_WideUInt mp_get_mag_ull(const mp_int *a) MP_WUR;
+unsigned long long mp_get_mag_ull(const mp_int *a) MP_WUR;
*/
/* get integer, set integer (long) */
@@ -397,24 +391,24 @@ void mp_set_ul(mp_int *a, unsigned long b);
mp_err mp_init_ul(mp_int *a, unsigned long b) MP_WUR;
*/
-/* get integer, set integer (Tcl_WideInt) */
+/* get integer, set integer (long long) */
/*
-Tcl_WideInt mp_get_ll(const mp_int *a) MP_WUR;
+long long mp_get_ll(const mp_int *a) MP_WUR;
*/
/*
-void mp_set_ll(mp_int *a, Tcl_WideInt b);
+void mp_set_ll(mp_int *a, long long b);
*/
/*
-mp_err mp_init_ll(mp_int *a, Tcl_WideInt b) MP_WUR;
+mp_err mp_init_ll(mp_int *a, long long b) MP_WUR;
*/
-/* get integer, set integer (Tcl_WideUInt) */
+/* get integer, set integer (unsigned long long) */
#define mp_get_ull(a) ((Tcl_WideUInt)mp_get_ll(a))
/*
-void mp_set_ull(mp_int *a, Tcl_WideUInt b);
+void mp_set_ull(mp_int *a, unsigned long long b);
*/
/*
-mp_err mp_init_ull(mp_int *a, Tcl_WideUInt b) MP_WUR;
+mp_err mp_init_ull(mp_int *a, unsigned long long b) MP_WUR;
*/
/* set to single unsigned digit, up to MP_DIGIT_MAX */
@@ -433,7 +427,7 @@ MP_DEPRECATED(mp_get_mag_u32/mp_get_u32) unsigned long mp_get_int(const mp_int *
MP_DEPRECATED(mp_get_mag_ul/mp_get_ul) unsigned long mp_get_long(const mp_int *a) MP_WUR;
*/
/*
-MP_DEPRECATED(mp_get_mag_ull/mp_get_ull) Tcl_WideUInt mp_get_long_long(const mp_int *a) MP_WUR;
+MP_DEPRECATED(mp_get_mag_ull/mp_get_ull) unsigned long long mp_get_long_long(const mp_int *a) MP_WUR;
*/
/*
MP_DEPRECATED(mp_set_ul) mp_err mp_set_int(mp_int *a, unsigned long b);
@@ -442,7 +436,7 @@ MP_DEPRECATED(mp_set_ul) mp_err mp_set_int(mp_int *a, unsigned long b);
MP_DEPRECATED(mp_set_ul) mp_err mp_set_long(mp_int *a, unsigned long b);
*/
/*
-MP_DEPRECATED(mp_set_ull) mp_err mp_set_long_long(mp_int *a, Tcl_WideUInt b);
+MP_DEPRECATED(mp_set_ull) mp_err mp_set_long_long(mp_int *a, unsigned long long b);
*/
/*
MP_DEPRECATED(mp_init_ul) mp_err mp_init_set_int(mp_int *a, unsigned long b) MP_WUR;
@@ -463,6 +457,7 @@ mp_err mp_init_copy(mp_int *a, const mp_int *b) MP_WUR;
void mp_clamp(mp_int *a);
*/
+
/* export binary data */
/*
MP_DEPRECATED(mp_pack) mp_err mp_export(void *rop, size_t *countp, int order, size_t size,
@@ -559,6 +554,7 @@ void mp_rand_source(mp_err(*source)(void *out, size_t size));
*/
#ifdef MP_PRNG_ENABLE_LTM_RNG
+# warning MP_PRNG_ENABLE_LTM_RNG has been deprecated, use mp_rand_source instead.
/* A last resort to provide random data on systems without any of the other
* implemented ways to gather entropy.
* It is compatible with `rng_get_bytes()` from libtomcrypt so you could
diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h
index 9be7e12..e90b572 100644
--- a/generic/tclTomMathDecls.h
+++ b/generic/tclTomMathDecls.h
@@ -34,75 +34,76 @@
/* Define custom memory allocation for libtommath */
-/* MODULE_SCOPE void* TclBNAlloc( size_t ); */
-#define TclBNAlloc(s) ((void*)Tcl_Alloc((size_t)(s)))
-/* MODULE_SCOPE void* TclBNCalloc( size_t, size_t ); */
-#define TclBNCalloc(m,s) memset(ckalloc((size_t)(m)*(size_t)(s)),0,(size_t)(m)*(size_t)(s))
-/* MODULE_SCOPE void* TclBNRealloc( void*, size_t ); */
-#define TclBNRealloc(x,s) ((void*)Tcl_Realloc((char*)(x),(size_t)(s)))
-/* MODULE_SCOPE void TclBNFree( void* ); */
-#define TclBNFree(x) (Tcl_Free((char*)(x)))
+#define MP_MALLOC(size) Tcl_Alloc(size)
+#define MP_CALLOC(nmemb, size) memset(Tcl_Alloc((nmemb)*(size_t)(size)),0,(nmemb)*(size_t)(size))
+#define MP_REALLOC(mem, oldsize, newsize) Tcl_Realloc(mem, newsize)
+#define MP_FREE(mem, size) Tcl_Free(mem)
+
+
+MODULE_SCOPE void TclBN_s_mp_reverse(unsigned char *s, size_t len);
+MODULE_SCOPE mp_err TclBN_s_mp_add_d(const mp_int *a, mp_digit b, mp_int *c);
+MODULE_SCOPE mp_ord TclBN_s_mp_cmp_d(const mp_int *a, mp_digit b);
+MODULE_SCOPE mp_err TclBN_s_mp_sub_d(const mp_int *a, mp_digit b, mp_int *c);
+MODULE_SCOPE mp_err TclBN_s_mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+MODULE_SCOPE mp_err TclBN_s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d);
+MODULE_SCOPE mp_err TclBN_s_mp_init_set(mp_int *a, mp_digit b);
+MODULE_SCOPE mp_err TclBN_s_mp_mul_d(const mp_int *a, mp_digit b, mp_int *c);
+MODULE_SCOPE void TclBN_s_mp_set(mp_int *a, mp_digit b);
+MODULE_SCOPE mp_err TclBN_s_mp_expt_u32(const mp_int *a, unsigned int b, mp_int *c);
+MODULE_SCOPE mp_err TclBN_s_mp_sqr(const mp_int *a, mp_int *c);
+MODULE_SCOPE mp_err TclBN_mp_sqr(const mp_int *a, mp_int *c);
+
-#define MP_MALLOC(size) TclBNAlloc(size)
-#define MP_CALLOC(nmemb, size) TclBNCalloc(nmemb, size)
-#define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc(mem, newsize)
-#define MP_FREE(mem, size) TclBNFree(mem)
/* Rename the global symbols in libtommath to avoid linkage conflicts */
#define mp_add TclBN_mp_add
-#define mp_add_d TclBN_mp_add_d
#define mp_and TclBN_mp_and
#define mp_clamp TclBN_mp_clamp
#define mp_clear TclBN_mp_clear
#define mp_clear_multi TclBN_mp_clear_multi
#define mp_cmp TclBN_mp_cmp
-#define mp_cmp_d TclBN_mp_cmp_d
#define mp_cmp_mag TclBN_mp_cmp_mag
#define mp_cnt_lsb TclBN_mp_cnt_lsb
#define mp_copy TclBN_mp_copy
#define mp_count_bits TclBN_mp_count_bits
#define mp_div TclBN_mp_div
#define mp_div_2 TclBN_mp_div_2
+#define mp_div_3 TclBN_s_mp_div_3
#define mp_div_2d TclBN_mp_div_2d
-#define mp_div_3 TclBN_mp_div_3
-#define mp_div_d TclBN_mp_div_d
#define mp_exch TclBN_mp_exch
#define mp_expt_d TclBN_mp_expt_u32
#define mp_expt_d_ex TclBN_mp_expt_d_ex
-#define mp_expt_u32 TclBN_mp_expt_u32
-#define mp_get_bit TclBN_mp_get_bit
#define mp_get_mag_ul TclBN_mp_get_mag_ul
#define mp_get_mag_ull TclBN_mp_get_mag_ull
#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 TclBN_mp_init_set
#define mp_init_size TclBN_mp_init_size
#define mp_init_ul TclBN_mp_init_ul
-#define mp_isodd TclBN_mp_isodd
+#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
#define mp_mul TclBN_mp_mul
#define mp_mul_2 TclBN_mp_mul_2
#define mp_mul_2d TclBN_mp_mul_2d
-#define mp_mul_d TclBN_mp_mul_d
#define mp_neg TclBN_mp_neg
#define mp_or TclBN_mp_or
#define mp_radix_size TclBN_mp_radix_size
#define mp_read_radix TclBN_mp_read_radix
#define mp_rshd TclBN_mp_rshd
-#define mp_set TclBN_mp_set
+#define mp_set_l TclBN_mp_set_l
+#define mp_set_ll TclBN_mp_set_ll
#define mp_set_ul TclBN_mp_set_ul
#define mp_set_ull TclBN_mp_set_ull
#define mp_shrink TclBN_mp_shrink
-#define mp_sqr TclBN_mp_sqr
#define mp_sqrt TclBN_mp_sqrt
#define mp_sub TclBN_mp_sub
-#define mp_sub_d TclBN_mp_sub_d
#define mp_signed_rsh TclBN_mp_signed_rsh
#define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin
#define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n
@@ -113,7 +114,7 @@
#define mp_zero TclBN_mp_zero
#define s_mp_add TclBN_s_mp_add
#define s_mp_balance_mul TclBN_mp_balance_mul
-#define s_mp_get_bit TclBN_mp_get_bit
+#define s_mp_div_3 TclBN_s_mp_div_3
#define s_mp_karatsuba_mul TclBN_mp_karatsuba_mul
#define s_mp_karatsuba_sqr TclBN_mp_karatsuba_sqr
#define s_mp_mul_digs TclBN_s_mp_mul_digs
@@ -160,7 +161,7 @@ EXTERN int TclBN_revision(void) MP_WUR;
EXTERN mp_err TclBN_mp_add(const mp_int *a, const mp_int *b,
mp_int *c) MP_WUR;
/* 3 */
-EXTERN mp_err TclBN_mp_add_d(const mp_int *a, mp_digit b,
+EXTERN mp_err TclBN_mp_add_d(const mp_int *a, unsigned int b,
mp_int *c) MP_WUR;
/* 4 */
EXTERN mp_err TclBN_mp_and(const mp_int *a, const mp_int *b,
@@ -174,7 +175,7 @@ EXTERN void TclBN_mp_clear_multi(mp_int *a, ...);
/* 8 */
EXTERN mp_ord TclBN_mp_cmp(const mp_int *a, const mp_int *b) MP_WUR;
/* 9 */
-EXTERN mp_ord TclBN_mp_cmp_d(const mp_int *a, mp_digit b) MP_WUR;
+EXTERN mp_ord TclBN_mp_cmp_d(const mp_int *a, unsigned int b) MP_WUR;
/* 10 */
EXTERN mp_ord TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b) MP_WUR;
/* 11 */
@@ -185,16 +186,14 @@ EXTERN int TclBN_mp_count_bits(const mp_int *a) MP_WUR;
EXTERN mp_err TclBN_mp_div(const mp_int *a, const mp_int *b,
mp_int *q, mp_int *r) MP_WUR;
/* 14 */
-EXTERN mp_err TclBN_mp_div_d(const mp_int *a, mp_digit b,
- mp_int *q, mp_digit *r) MP_WUR;
+EXTERN mp_err TclBN_mp_div_d(const mp_int *a, unsigned int b,
+ mp_int *q, unsigned int *r) MP_WUR;
/* 15 */
EXTERN mp_err TclBN_mp_div_2(const mp_int *a, mp_int *q) MP_WUR;
/* 16 */
EXTERN mp_err TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q,
mp_int *r) MP_WUR;
-/* 17 */
-EXTERN mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q,
- mp_digit *r) MP_WUR;
+/* Slot 17 is reserved */
/* 18 */
EXTERN void TclBN_mp_exch(mp_int *a, mp_int *b);
/* 19 */
@@ -209,7 +208,7 @@ EXTERN mp_err TclBN_mp_init_copy(mp_int *a, const mp_int *b) MP_WUR;
/* 23 */
EXTERN mp_err TclBN_mp_init_multi(mp_int *a, ...) MP_WUR;
/* 24 */
-EXTERN mp_err TclBN_mp_init_set(mp_int *a, mp_digit b) MP_WUR;
+EXTERN mp_err TclBN_mp_init_set(mp_int *a, unsigned int b) MP_WUR;
/* 25 */
EXTERN mp_err TclBN_mp_init_size(mp_int *a, int size) MP_WUR;
/* 26 */
@@ -223,7 +222,7 @@ EXTERN mp_err TclBN_mp_mod_2d(const mp_int *a, int b, mp_int *r) MP_WUR;
EXTERN mp_err TclBN_mp_mul(const mp_int *a, const mp_int *b,
mp_int *p) MP_WUR;
/* 30 */
-EXTERN mp_err TclBN_mp_mul_d(const mp_int *a, mp_digit b,
+EXTERN mp_err TclBN_mp_mul_d(const mp_int *a, unsigned int b,
mp_int *p) MP_WUR;
/* 31 */
EXTERN mp_err TclBN_mp_mul_2(const mp_int *a, mp_int *p) MP_WUR;
@@ -245,16 +244,15 @@ EXTERN void TclBN_mp_rshd(mp_int *a, int shift);
/* 38 */
EXTERN mp_err TclBN_mp_shrink(mp_int *a) MP_WUR;
/* 39 */
-EXTERN void TclBN_mp_set(mp_int *a, mp_digit b);
-/* 40 */
-EXTERN mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b) MP_WUR;
+EXTERN void TclBN_mp_set(mp_int *a, unsigned int b);
+/* Slot 40 is reserved */
/* 41 */
EXTERN mp_err TclBN_mp_sqrt(const mp_int *a, mp_int *b) MP_WUR;
/* 42 */
EXTERN mp_err TclBN_mp_sub(const mp_int *a, const mp_int *b,
mp_int *c) MP_WUR;
/* 43 */
-EXTERN mp_err TclBN_mp_sub_d(const mp_int *a, mp_digit b,
+EXTERN mp_err TclBN_mp_sub_d(const mp_int *a, unsigned int b,
mp_int *c) MP_WUR;
/* Slot 44 is reserved */
/* Slot 45 is reserved */
@@ -283,19 +281,25 @@ EXTERN mp_err TclBN_mp_init_ul(mp_int *a, unsigned long i) MP_WUR;
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;
-/* Slot 64 is reserved */
-/* Slot 65 is reserved */
-/* Slot 66 is reserved */
+/* 64 */
+EXTERN int TclBNInitBignumFromLong(mp_int *bignum, long initVal);
+/* 65 */
+EXTERN int TclBNInitBignumFromWideInt(mp_int *bignum,
+ Tcl_WideInt initVal);
+/* 66 */
+EXTERN int TclBNInitBignumFromWideUInt(mp_int *bignum,
+ Tcl_WideUInt initVal);
/* Slot 67 is reserved */
/* 68 */
EXTERN void TclBN_mp_set_ull(mp_int *a, Tcl_WideUInt i);
/* 69 */
EXTERN Tcl_WideUInt TclBN_mp_get_mag_ull(const mp_int *a) MP_WUR;
-/* Slot 70 is reserved */
+/* 70 */
+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);
+EXTERN unsigned long TclBN_mp_get_mag_ul(const mp_int *a) MP_WUR;
/* 72 */
-EXTERN mp_bool TclBN_mp_isodd(const mp_int *a) MP_WUR;
+EXTERN void TclBN_mp_set_l(mp_int *a, long i);
/* Slot 73 is reserved */
/* Slot 74 is reserved */
/* Slot 75 is reserved */
@@ -318,34 +322,34 @@ typedef struct TclTomMathStubs {
int (*tclBN_epoch) (void) MP_WUR; /* 0 */
int (*tclBN_revision) (void) MP_WUR; /* 1 */
mp_err (*tclBN_mp_add) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 2 */
- mp_err (*tclBN_mp_add_d) (const mp_int *a, mp_digit b, mp_int *c) MP_WUR; /* 3 */
+ mp_err (*tclBN_mp_add_d) (const mp_int *a, unsigned int b, mp_int *c) MP_WUR; /* 3 */
mp_err (*tclBN_mp_and) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 4 */
void (*tclBN_mp_clamp) (mp_int *a); /* 5 */
void (*tclBN_mp_clear) (mp_int *a); /* 6 */
void (*tclBN_mp_clear_multi) (mp_int *a, ...); /* 7 */
mp_ord (*tclBN_mp_cmp) (const mp_int *a, const mp_int *b) MP_WUR; /* 8 */
- mp_ord (*tclBN_mp_cmp_d) (const mp_int *a, mp_digit b) MP_WUR; /* 9 */
+ mp_ord (*tclBN_mp_cmp_d) (const mp_int *a, unsigned int b) MP_WUR; /* 9 */
mp_ord (*tclBN_mp_cmp_mag) (const mp_int *a, const mp_int *b) MP_WUR; /* 10 */
mp_err (*tclBN_mp_copy) (const mp_int *a, mp_int *b) MP_WUR; /* 11 */
int (*tclBN_mp_count_bits) (const mp_int *a) MP_WUR; /* 12 */
mp_err (*tclBN_mp_div) (const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) MP_WUR; /* 13 */
- mp_err (*tclBN_mp_div_d) (const mp_int *a, mp_digit b, mp_int *q, mp_digit *r) MP_WUR; /* 14 */
+ mp_err (*tclBN_mp_div_d) (const mp_int *a, unsigned int b, mp_int *q, unsigned int *r) MP_WUR; /* 14 */
mp_err (*tclBN_mp_div_2) (const mp_int *a, mp_int *q) MP_WUR; /* 15 */
mp_err (*tclBN_mp_div_2d) (const mp_int *a, int b, mp_int *q, mp_int *r) MP_WUR; /* 16 */
- mp_err (*tclBN_mp_div_3) (const mp_int *a, mp_int *q, mp_digit *r) MP_WUR; /* 17 */
+ void (*reserved17)(void);
void (*tclBN_mp_exch) (mp_int *a, mp_int *b); /* 18 */
mp_err (*tclBN_mp_expt_u32) (const mp_int *a, unsigned int b, mp_int *c) MP_WUR; /* 19 */
mp_err (*tclBN_mp_grow) (mp_int *a, int size) MP_WUR; /* 20 */
mp_err (*tclBN_mp_init) (mp_int *a) MP_WUR; /* 21 */
mp_err (*tclBN_mp_init_copy) (mp_int *a, const mp_int *b) MP_WUR; /* 22 */
mp_err (*tclBN_mp_init_multi) (mp_int *a, ...) MP_WUR; /* 23 */
- mp_err (*tclBN_mp_init_set) (mp_int *a, mp_digit b) MP_WUR; /* 24 */
+ mp_err (*tclBN_mp_init_set) (mp_int *a, unsigned int b) MP_WUR; /* 24 */
mp_err (*tclBN_mp_init_size) (mp_int *a, int size) MP_WUR; /* 25 */
mp_err (*tclBN_mp_lshd) (mp_int *a, int shift) MP_WUR; /* 26 */
mp_err (*tclBN_mp_mod) (const mp_int *a, const mp_int *b, mp_int *r) MP_WUR; /* 27 */
mp_err (*tclBN_mp_mod_2d) (const mp_int *a, int b, mp_int *r) MP_WUR; /* 28 */
mp_err (*tclBN_mp_mul) (const mp_int *a, const mp_int *b, mp_int *p) MP_WUR; /* 29 */
- mp_err (*tclBN_mp_mul_d) (const mp_int *a, mp_digit b, mp_int *p) MP_WUR; /* 30 */
+ mp_err (*tclBN_mp_mul_d) (const mp_int *a, unsigned int b, mp_int *p) MP_WUR; /* 30 */
mp_err (*tclBN_mp_mul_2) (const mp_int *a, mp_int *p) MP_WUR; /* 31 */
mp_err (*tclBN_mp_mul_2d) (const mp_int *a, int d, mp_int *p) MP_WUR; /* 32 */
mp_err (*tclBN_mp_neg) (const mp_int *a, mp_int *b) MP_WUR; /* 33 */
@@ -354,11 +358,11 @@ typedef struct TclTomMathStubs {
mp_err (*tclBN_mp_read_radix) (mp_int *a, const char *str, int radix) MP_WUR; /* 36 */
void (*tclBN_mp_rshd) (mp_int *a, int shift); /* 37 */
mp_err (*tclBN_mp_shrink) (mp_int *a) MP_WUR; /* 38 */
- void (*tclBN_mp_set) (mp_int *a, mp_digit b); /* 39 */
- mp_err (*tclBN_mp_sqr) (const mp_int *a, mp_int *b) MP_WUR; /* 40 */
+ void (*tclBN_mp_set) (mp_int *a, unsigned int b); /* 39 */
+ void (*reserved40)(void);
mp_err (*tclBN_mp_sqrt) (const mp_int *a, mp_int *b) MP_WUR; /* 41 */
mp_err (*tclBN_mp_sub) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 42 */
- mp_err (*tclBN_mp_sub_d) (const mp_int *a, mp_digit b, mp_int *c) MP_WUR; /* 43 */
+ mp_err (*tclBN_mp_sub_d) (const mp_int *a, unsigned int b, mp_int *c) MP_WUR; /* 43 */
void (*reserved44)(void);
void (*reserved45)(void);
void (*reserved46)(void);
@@ -379,15 +383,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 */
- void (*reserved64)(void);
- void (*reserved65)(void);
- void (*reserved66)(void);
+ 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 */
void (*reserved67)(void);
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 (*reserved70)(void);
- unsigned long (*tclBN_mp_get_mag_ul) (const mp_int *a); /* 71 */
- mp_bool (*tclBN_mp_isodd) (const mp_int *a) MP_WUR; /* 72 */
+ 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 (*tclBN_mp_set_l) (mp_int *a, long i); /* 72 */
void (*reserved73)(void);
void (*reserved74)(void);
void (*reserved75)(void);
@@ -444,8 +448,7 @@ extern const TclTomMathStubs *tclTomMathStubsPtr;
(tclTomMathStubsPtr->tclBN_mp_div_2) /* 15 */
#define TclBN_mp_div_2d \
(tclTomMathStubsPtr->tclBN_mp_div_2d) /* 16 */
-#define TclBN_mp_div_3 \
- (tclTomMathStubsPtr->tclBN_mp_div_3) /* 17 */
+/* Slot 17 is reserved */
#define TclBN_mp_exch \
(tclTomMathStubsPtr->tclBN_mp_exch) /* 18 */
#define TclBN_mp_expt_u32 \
@@ -490,8 +493,7 @@ extern const TclTomMathStubs *tclTomMathStubsPtr;
(tclTomMathStubsPtr->tclBN_mp_shrink) /* 38 */
#define TclBN_mp_set \
(tclTomMathStubsPtr->tclBN_mp_set) /* 39 */
-#define TclBN_mp_sqr \
- (tclTomMathStubsPtr->tclBN_mp_sqr) /* 40 */
+/* Slot 40 is reserved */
#define TclBN_mp_sqrt \
(tclTomMathStubsPtr->tclBN_mp_sqrt) /* 41 */
#define TclBN_mp_sub \
@@ -524,19 +526,23 @@ extern const TclTomMathStubs *tclTomMathStubsPtr;
(tclTomMathStubsPtr->tclBN_mp_set_ul) /* 62 */
#define TclBN_mp_cnt_lsb \
(tclTomMathStubsPtr->tclBN_mp_cnt_lsb) /* 63 */
-/* Slot 64 is reserved */
-/* Slot 65 is reserved */
-/* Slot 66 is reserved */
+#define TclBNInitBignumFromLong \
+ (tclTomMathStubsPtr->tclBNInitBignumFromLong) /* 64 */
+#define TclBNInitBignumFromWideInt \
+ (tclTomMathStubsPtr->tclBNInitBignumFromWideInt) /* 65 */
+#define TclBNInitBignumFromWideUInt \
+ (tclTomMathStubsPtr->tclBNInitBignumFromWideUInt) /* 66 */
/* Slot 67 is reserved */
#define TclBN_mp_set_ull \
(tclTomMathStubsPtr->tclBN_mp_set_ull) /* 68 */
#define TclBN_mp_get_mag_ull \
(tclTomMathStubsPtr->tclBN_mp_get_mag_ull) /* 69 */
-/* Slot 70 is reserved */
+#define TclBN_mp_set_ll \
+ (tclTomMathStubsPtr->tclBN_mp_set_ll) /* 70 */
#define TclBN_mp_get_mag_ul \
(tclTomMathStubsPtr->tclBN_mp_get_mag_ul) /* 71 */
-#define TclBN_mp_isodd \
- (tclTomMathStubsPtr->tclBN_mp_isodd) /* 72 */
+#define TclBN_mp_set_l \
+ (tclTomMathStubsPtr->tclBN_mp_set_l) /* 72 */
/* Slot 73 is reserved */
/* Slot 74 is reserved */
/* Slot 75 is reserved */
@@ -553,11 +559,37 @@ extern const TclTomMathStubs *tclTomMathStubsPtr;
/* !END!: Do not edit above this line. */
-#undef mp_isodd
-#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
-#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#if defined(USE_TCL_STUBS)
+#define mp_add_d TclBN_mp_add_d
+#define mp_cmp_d TclBN_mp_cmp_d
+#define mp_div_d TclBN_mp_div_d
+#define mp_sub_d TclBN_mp_sub_d
+#define mp_init_set TclBN_mp_init_set
+#define mp_mul_d TclBN_mp_mul_d
+#define mp_set TclBN_mp_set
+#define mp_expt_u32 TclBN_mp_expt_u32
+#else
+#define mp_add_d TclBN_s_mp_add_d
+#define mp_cmp_d TclBN_s_mp_cmp_d
+#define mp_div_d TclBN_s_mp_div_d
+#define mp_sub_d TclBN_s_mp_sub_d
+#define mp_init_set TclBN_s_mp_init_set
+#define mp_mul_d TclBN_s_mp_mul_d
+#define mp_set TclBN_s_mp_set
+#define mp_expt_u32 TclBN_s_mp_expt_u32
+#endif /* !BUILD_tcl */
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
+#if defined(USE_TCL_STUBS)
+# define mp_sqr(a,b) mp_mul(a,a,b)
+#else
+# define mp_sqr TclBN_mp_sqr
+#endif
+
+#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 eb012e4..576929c 100644
--- a/generic/tclTomMathInterface.c
+++ b/generic/tclTomMathInterface.c
@@ -91,66 +91,6 @@ TclBN_revision(void)
}
/*
- *----------------------------------------------------------------------
- *
- * TclInitBignumFromWideInt --
- *
- * Allocate and initialize a 'bignum' from a Tcl_WideInt
- *
- * Results:
- * None.
- *
- * Side effects:
- * The 'bignum' is constructed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclInitBignumFromWideInt(
- mp_int *a, /* Bignum to initialize */
- Tcl_WideInt v) /* Initial value */
-{
- if (mp_init(a) != MP_OKAY) {
- wipanic:
- Tcl_Panic("initialization failure in TclInitBignumFromWideInt");
- }
- if (v < (Tcl_WideInt)0) {
- mp_set_ull(a, (Tcl_WideUInt)(-v));
- if (mp_neg(a, a) != MP_OKAY) goto wipanic;
- } else {
- mp_set_ull(a, (Tcl_WideUInt)v);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclInitBignumFromWideUInt --
- *
- * Allocate and initialize a 'bignum' from a Tcl_WideUInt
- *
- * Results:
- * None.
- *
- * Side effects:
- * The 'bignum' is constructed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclInitBignumFromWideUInt(
- mp_int *a, /* Bignum to initialize */
- Tcl_WideUInt v) /* Initial value */
-{
- if (mp_init(a) != MP_OKAY) {
- Tcl_Panic("initialization failure in TclInitBignumFromWideUInt");
- }
- mp_set_ull(a, v);
-}
-
-/*
* Local Variables:
* mode: c
* c-basic-offset: 4
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index c9d7003..200e319 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -3419,7 +3419,7 @@ GetWideForIndex(
/* objPtr holds an integer outside the signed wide range */
/* Truncate to the signed wide range. */
- *widePtr = (((mp_int *)cd)->sign != MP_ZPOS) ? WIDE_MIN : WIDE_MAX;
+ *widePtr = ((mp_isneg((mp_int *)cd)) ? WIDE_MIN : WIDE_MAX);
return TCL_OK;
}
@@ -3532,7 +3532,7 @@ GetWideForIndex(
} else {
/* sum holds an integer outside the signed wide range */
/* Truncate to the signed wide range. */
- if (((mp_int *)cd)->sign != MP_ZPOS) {
+ if (mp_isneg((mp_int *)cd)) {
*widePtr = WIDE_MIN;
} else {
*widePtr = WIDE_MAX;
@@ -3685,7 +3685,7 @@ GetEndOffsetFromObj(
if (t == TCL_NUMBER_BIG) {
/* Truncate to the signed wide range. */
- if (((mp_int *)cd)->sign != MP_ZPOS) {
+ if (mp_isneg((mp_int *)cd)) {
offset = (bytes[3] == '-') ? WIDE_MAX : WIDE_MIN;
} else {
offset = (bytes[3] == '-') ? WIDE_MIN : WIDE_MAX;