diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2019-11-11 14:26:50 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2019-11-11 14:26:50 (GMT) |
commit | e512564f360551e1821bc646ce75314246b9a0ee (patch) | |
tree | 855d2542e38d1f5c55cb823745749f8ec7f3148c /generic | |
parent | 99cce0ea110b9e0d8eec550f8bcc125b75940031 (diff) | |
parent | ac7ef03d8e108d7c755c1f560808429d0f4a0ce2 (diff) | |
download | tcl-e512564f360551e1821bc646ce75314246b9a0ee.zip tcl-e512564f360551e1821bc646ce75314246b9a0ee.tar.gz tcl-e512564f360551e1821bc646ce75314246b9a0ee.tar.bz2 |
Merge 8.7
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tcl.h | 249 | ||||
-rw-r--r-- | generic/tclBasic.c | 2 | ||||
-rw-r--r-- | generic/tclBinary.c | 6 | ||||
-rw-r--r-- | generic/tclEncoding.c | 146 | ||||
-rw-r--r-- | generic/tclExecute.c | 4 | ||||
-rw-r--r-- | generic/tclFileName.c | 5 | ||||
-rw-r--r-- | generic/tclIOUtil.c | 2119 | ||||
-rw-r--r-- | generic/tclOOScript.h | 2 | ||||
-rw-r--r-- | generic/tclOOScript.tcl | 456 | ||||
-rw-r--r-- | generic/tclObj.c | 2 | ||||
-rw-r--r-- | generic/tclPathObj.c | 197 | ||||
-rw-r--r-- | generic/tclScan.c | 31 | ||||
-rw-r--r-- | generic/tclStrToD.c | 32 | ||||
-rw-r--r-- | generic/tclStubInit.c | 75 | ||||
-rw-r--r-- | generic/tclTestObj.c | 2 | ||||
-rw-r--r-- | generic/tclTomMath.decls | 26 | ||||
-rw-r--r-- | generic/tclTomMath.h | 1 | ||||
-rw-r--r-- | generic/tclTomMathDecls.h | 233 | ||||
-rw-r--r-- | generic/tclTomMathInterface.c | 60 |
19 files changed, 1472 insertions, 2176 deletions
diff --git a/generic/tcl.h b/generic/tcl.h index 571a9b9..c1187c6 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -1653,7 +1653,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. * @@ -1668,147 +1668,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; /* @@ -2069,29 +2041,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 diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 05999c6..d8fc01f 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -7891,7 +7891,7 @@ ExprAbsFunc( } goto unChanged; } else if (l == WIDE_MIN) { - TclBNInitBignumFromWideInt(&big, l); + mp_init_ll(&big, l); goto tooLarge; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l)); diff --git a/generic/tclBinary.c b/generic/tclBinary.c index ea8e204..34e8fa6 100644 --- a/generic/tclBinary.c +++ b/generic/tclBinary.c @@ -2349,8 +2349,10 @@ ScanNumber( Tcl_Obj *bigObj = NULL; mp_int big; - TclBNInitBignumFromWideUInt(&big, uwvalue); - bigObj = Tcl_NewBignumObj(&big); + if (mp_init(&big) == MP_OKAY) { + mp_set_u64(&big, uwvalue); + bigObj = Tcl_NewBignumObj(&big); + } return bigObj; } return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue); diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 0ec0649..430f705 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; @@ -806,11 +804,7 @@ Tcl_SetDefaultEncodingDir( * 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. * *------------------------------------------------------------------------- */ @@ -848,15 +842,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. * *--------------------------------------------------------------------------- */ @@ -875,13 +869,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. * @@ -1069,23 +1064,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. * *--------------------------------------------------------------------------- */ @@ -1332,10 +1326,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 @@ -1646,13 +1639,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. * *--------------------------------------------------------------------------- */ @@ -1660,8 +1653,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; @@ -1715,27 +1708,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. */ { @@ -1852,10 +1845,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) { @@ -1894,8 +1887,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. */ @@ -1907,13 +1900,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]; @@ -1960,7 +1953,7 @@ LoadTableEncoding( } /* - * Read lines from the encoding until EOF. + * Read lines until EOF. */ for (TclDStringClear(&lineString); @@ -2037,7 +2030,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; @@ -3661,14 +3654,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 a2e9401..5f2ae4c 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -8072,7 +8072,7 @@ ExecuteExtendedBinaryMathOp( * Arguments are opposite sign; remainder is sum. */ - TclBNInitBignumFromWideInt(&big1, w1); + mp_init_ll(&big1, w1); mp_add(&big2, &big1, &big2); mp_clear(&big1); BIG_RESULT(&big2); @@ -8701,7 +8701,7 @@ ExecuteExtendedUnaryMathOp( if (w != WIDE_MIN) { WIDE_RESULT(-w); } - TclBNInitBignumFromWideInt(&big, w); + mp_init_ll(&big, w); break; default: Tcl_TakeBignumFromObj(NULL, valuePtr, &big); diff --git a/generic/tclFileName.c b/generic/tclFileName.c index 3419d7c..834eef7 100644 --- a/generic/tclFileName.c +++ b/generic/tclFileName.c @@ -1680,9 +1680,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 3773159..ceee36e 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -1,14 +1,11 @@ /* * tclIOUtil.c -- * - * This file contains the implementation of Tcl's generic filesystem - * code, which supports a pluggable filesystem architecture allowing both - * platform specific filesystems and 'virtual filesystems'. All - * filesystem access should go through the functions defined in this - * file. Most of this code was contributed by Vince Darley. - * - * Parts of this file are based on code contributed by Karl Lehenbauer, - * Mark Diekhans and Peter da Silva. + * Provides an interface for managing filesystems in Tcl, and also for + * creating a filesystem interface in Tcl arbitrary facilities. All + * filesystem operations are performed via this interface. Vince Darley + * is the primary author. Other signifiant contributors are Karl + * Lehenbauer, Mark Diekhans and Peter da Silva. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. @@ -33,42 +30,41 @@ /* * struct FilesystemRecord -- * - * A filesystem record is used to keep track of each filesystem currently - * registered with the core, in a linked list. + * An item in a linked list of registered filesystems */ typedef struct FilesystemRecord { - ClientData clientData; /* Client specific data for the new filesystem + ClientData clientData; /* Client-specific data for the filesystem * (can be NULL) */ const Tcl_Filesystem *fsPtr;/* Pointer to filesystem dispatch table. */ struct FilesystemRecord *nextPtr; - /* The next filesystem registered to Tcl, or - * NULL if no more. */ + /* The next registered filesystem, or NULL to + * indicate the end of the list. */ struct FilesystemRecord *prevPtr; - /* The previous filesystem registered to Tcl, - * or NULL if no more. */ + /* The previous filesystem, or NULL to indicate + * the ned of the list */ } FilesystemRecord; /* - * This structure holds per-thread private copy of the current directory - * maintained by the global cwdPathPtr. This structure holds per-thread - * private copies of some global data. This way we avoid most of the - * synchronization calls which boosts performance, at cost of having to update - * this information each time the corresponding epoch counter changes. */ typedef struct { int initialized; - size_t cwdPathEpoch; + size_t cwdPathEpoch; /* Compared with the global cwdPathEpoch to + * determine whether cwdPathPtr is stale. + */ size_t filesystemEpoch; - Tcl_Obj *cwdPathPtr; + Tcl_Obj *cwdPathPtr; /* A private copy of cwdPathPtr. Updated when + * the value is accessed and cwdPathEpoch has + * changed. + */ ClientData cwdClientData; FilesystemRecord *filesystemList; size_t claims; } ThreadSpecificData; /* - * Prototypes for functions defined later in this file. + * Forward declarations. */ static Tcl_NRPostProc EvalFileCallback; @@ -87,28 +83,12 @@ static void * DivertFindSymbol(Tcl_Interp *interp, Tcl_LoadHandle loadHandle, const char *symbol); static void DivertUnloadFile(Tcl_LoadHandle loadHandle); -/* - * These form part of the native filesystem support. They are needed here - * because we have a few native filesystem functions (which are the same for - * win/unix) in this file. There is no need to place them in tclInt.h, because - * they are not (and should not be) used anywhere else. - */ - -MODULE_SCOPE const char *const tclpFileAttrStrings[]; -MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[]; /* - * Declare the native filesystem support. These functions should be considered - * private to Tcl, and should really not be called directly by any code other - * than this file (i.e. neither by Tcl's core nor by extensions). Similarly, - * the old string-based Tclp... native filesystem functions should not be - * called. - * - * The correct API to use now is the Tcl_FS... set of functions, which ensure - * correct and complete virtual filesystem support. - * - * We cannot make all of these static, since some of them are implemented in - * the platform-specific directories. + * Functions that provide native filesystem support. They are private and + * should be used only here. They should be called instead of calling Tclp... + * native filesystem functions. Others should use the Tcl_FS... functions + * which ensure correct and complete virtual filesystem support. */ static Tcl_FSFilesystemSeparatorProc NativeFilesystemSeparator; @@ -118,12 +98,21 @@ static Tcl_FSFileAttrsGetProc NativeFileAttrsGet; static Tcl_FSFileAttrsSetProc NativeFileAttrsSet; /* - * The only reason these functions are not static is that they are either - * called by code in the native (win/unix) directories or they are actually - * implemented in those directories. They should simply not be called by code - * outside Tcl's native filesystem core i.e. they should be considered - * 'static' to Tcl's filesystem code (if we ever built the native filesystem - * support into a separate code library, this could actually be enforced). + * Functions that support the native filesystem functions listed above. They + * are the same for win/unix, and not in tclInt.h because they are and should + * be used only here. + */ + +MODULE_SCOPE const char *const tclpFileAttrStrings[]; +MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[]; + + +/* + * These these functions are not static either because routines in the native + * (win/unix) directories call them or they are actually implemented in those + * directories. They should be called from outside Tcl's native filesystem + * routines. If we ever built the native filesystem support into a separate + * code library, this could actually be enforced. */ Tcl_FSFilesystemPathTypeProc TclpFilesystemPathType; @@ -143,11 +132,9 @@ Tcl_FSLinkProc TclpObjLink; Tcl_FSListVolumesProc TclpObjListVolumes; /* - * Define the native filesystem dispatch table. If necessary, it is ok to make - * this non-static, but it should only be accessed by the functions actually - * listed within it (or perhaps other helper functions of them). Anything - * which is not part of this 'native filesystem implementation' should not be - * delving inside here! + * The native filesystem dispatch table. This could me made public but it + * should only be accessed by the functions it points to, or perhaps + * subordinate helper functions. */ const Tcl_Filesystem tclNativeFilesystem = { @@ -190,13 +177,10 @@ const Tcl_Filesystem tclNativeFilesystem = { }; /* - * Define the tail of the linked list. Note that for unconventional uses of - * Tcl without a native filesystem, we may in the future wish to modify the - * current approach of hard-coding the native filesystem in the lookup list - * 'filesystemList' below. - * - * We initialize the record so that it thinks one file uses it. This means it - * will never be freed. + * An initial record in the linked list for the native filesystem. Remains at + * the tail of the list and is never freed. Currently the native filesystem is + * hard-coded. It may make sense to modify this to accomodate unconventional + * uses of Tcl that provide no native filesystem. */ static FilesystemRecord nativeFilesystemRecord = { @@ -207,41 +191,39 @@ static FilesystemRecord nativeFilesystemRecord = { }; /* - * This is incremented each time we modify the linked list of filesystems. Any - * time it changes, all cached filesystem representations are suspect and must - * be freed. For multithreading builds, change of the filesystem epoch will - * trigger cache cleanup in all threads. + * Incremented each time the linked list of filesystems is modified. For + * multithreaded builds, invalidates all cached filesystem internal + * representations. */ static size_t theFilesystemEpoch = 1; /* - * Stores the linked list of filesystems. A 1:1 copy of this list is also - * maintained in the TSD for each thread. This is to avoid synchronization - * issues. + * The linked list of filesystems. To minimize locking each thread maintains a + * local copy of this list. + * */ static FilesystemRecord *filesystemList = &nativeFilesystemRecord; TCL_DECLARE_MUTEX(filesystemMutex) /* - * Used to implement Tcl_FSGetCwd in a file-system independent way. + * A files-system indepent sense of the current directory. */ static Tcl_Obj *cwdPathPtr = NULL; -static size_t cwdPathEpoch = 0; +static size_t cwdPathEpoch = 0; /* The pathname of the current directory */ static ClientData cwdClientData = NULL; TCL_DECLARE_MUTEX(cwdMutex) static Tcl_ThreadDataKey fsDataKey; /* - * One of these structures is used each time we successfully load a file from - * a file system by way of making a temporary copy of the file on the native - * filesystem. We need to store both the actual unloadProc/clientData - * combination which was used, and the original and modified filenames, so - * that we can correctly undo the entire operation when we want to unload the - * code. + * When a temporary copy of a file is created on the native filesystem in order + * to load the file, an FsDivertLoad structure is created to track both the + * actual unloadProc/clientData combination which was used, and the original and + * modified filenames. This makes it possible to correctly undo the entire + * operation in order to unload the library. */ typedef struct { @@ -253,14 +235,14 @@ typedef struct { } FsDivertLoad; /* - * The following functions are obsolete string based APIs, and should be - * removed in a future release (Tcl 9 would be a good time). + * Obsolete string-based APIs that should be removed in a future release, + * perhaps in Tcl 9. */ /* Obsolete */ int Tcl_Stat( - const char *path, /* Path of file to stat (in current CP). */ + const char *path, /* Pathname of file to stat (in current CP). */ struct stat *oldStyleBuf) /* Filled with results of stat call. */ { int ret; @@ -347,7 +329,8 @@ Tcl_Stat( /* Obsolete */ int Tcl_Access( - const char *path, /* Path of file to access (in current CP). */ + const char *path, /* Pathname of file to access (in current CP). + */ int mode) /* Permission setting. */ { int ret; @@ -363,13 +346,12 @@ Tcl_Access( /* Obsolete */ Tcl_Channel Tcl_OpenFileChannel( - Tcl_Interp *interp, /* Interpreter for error reporting; can be + Tcl_Interp *interp, /* Interpreter for error reporting. May be * NULL. */ - const char *path, /* Name of file to open. */ + const char *path, /* Pathname of file to open. */ const char *modeString, /* A list of POSIX open modes or a string such * as "rw". */ - int permissions) /* If the open involves creating a file, with - * what modes to create it? */ + int permissions) /* The modes to use if creating a new file. */ { Tcl_Channel ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1); @@ -413,9 +395,10 @@ Tcl_GetCwd( int Tcl_EvalFile( - Tcl_Interp *interp, /* Interpreter in which to process file. */ - const char *fileName) /* Name of file to process. Tilde-substitution - * will be performed on this name. */ + Tcl_Interp *interp, /* Interpreter in which to evaluate the script. */ + const char *fileName) /* Pathname of the file containing the script. + * Performs Tilde-substitution on this + * pathaname. */ { int ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(fileName,-1); @@ -427,7 +410,7 @@ Tcl_EvalFile( } /* - * Now move on to the basic filesystem implementation. + * The basic filesystem implementation. */ static void @@ -438,7 +421,7 @@ FsThrExitProc( FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL; /* - * Trash the cwd copy. + * Discard the cwd copy. */ if (tsdPtr->cwdPathPtr != NULL) { @@ -450,7 +433,7 @@ FsThrExitProc( } /* - * Trash the filesystems cache. + * Discard the filesystems cache. */ fsRecPtr = tsdPtr->filesystemList; @@ -480,20 +463,20 @@ TclFSCwdIsNative(void) *---------------------------------------------------------------------- * * TclFSCwdPointerEquals -- - * - * Check whether the current working directory is equal to the path - * given. + * Determine whether the given pathname is equal to the current working + * directory. * * Results: - * 1 (equal) or 0 (un-equal) as appropriate. + * 1 if equal, 0 otherwise. * * Side effects: - * If the paths are equal, but are not the same object, this method will - * modify the given pathPtrPtr to refer to the same object. In this case - * the object pointed to by pathPtrPtr will have its refCount - * decremented, and it will be adjusted to point to the cwd (with a new - * refCount). + * Updates TSD if needed. + * + * Stores a pointer to the current directory in *pathPtrPtr if it is not + * already there and the current directory is not NULL. * + * If *pathPtrPtr is not null its reference count is decremented + * before it is replaced. *---------------------------------------------------------------------- */ @@ -546,8 +529,8 @@ TclFSCwdPointerEquals( str2 = TclGetStringFromObj(*pathPtrPtr, &len2); if ((len1 == len2) && !memcmp(str1, str2, len1)) { /* - * They are equal, but different objects. Update so they will be - * the same object in the future. + * The values are equal but the objects are different. Cache the + * current structure in place of the old one. */ Tcl_DecrRefCount(*pathPtrPtr); @@ -590,7 +573,7 @@ FsRecacheFilesystemList(void) } /* - * Refill the cache honouring the order. + * Refill the cache, honouring the order. */ list = NULL; @@ -637,8 +620,8 @@ FsGetFirstFilesystem(void) } /* - * The epoch can be changed by filesystems being added or removed, by changing - * the "system encoding" and by env(HOME) changing. + * The epoch can is changed when a filesystems is added or removed, when + * "system encoding" changes, and when env(HOME) changes. */ int @@ -673,7 +656,7 @@ TclFSEpoch(void) } /* - * If non-NULL, clientData is owned by us and must be freed later. + * If non-NULL, take posession of clientData and free it later. */ static void @@ -702,7 +685,7 @@ FsUpdateCwd( cwdClientData = NULL; } else { /* - * This must be stored as string obj! + * This must be stored as a string obj! */ cwdPathPtr = Tcl_NewStringObj(str, len); @@ -738,17 +721,17 @@ FsUpdateCwd( * * TclFinalizeFilesystem -- * - * Clean up the filesystem. After this, calls to all Tcl_FS... functions - * will fail. + * Clean up the filesystem. After this, any call to a Tcl_FS... function + * fails. * - * We will later call TclResetFilesystem to restore the FS to a pristine - * state. + * If TclResetFilesystem is called later, it restores the filesystem to a + * pristine state. * * Results: * None. * * Side effects: - * Frees any memory allocated by the filesystem. + * Frees memory allocated for the filesystem. * *---------------------------------------------------------------------- */ @@ -759,8 +742,9 @@ TclFinalizeFilesystem(void) FilesystemRecord *fsRecPtr; /* - * Assumption that only one thread is active now. Otherwise we would need - * to put various mutexes around this code. + * Assume that only one thread is active. Otherwise mutexes would be needed + * around this code. + * TO DO: This assumption is false, isn't it? */ if (cwdPathPtr != NULL) { @@ -783,7 +767,7 @@ TclFinalizeFilesystem(void) FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr; /* - * The native filesystem is static, so we don't free it. + * The native filesystem is static, so don't free it. */ if (fsRecPtr != &nativeFilesystemRecord) { @@ -797,8 +781,8 @@ TclFinalizeFilesystem(void) filesystemList = NULL; /* - * Now filesystemList is NULL. This means that any attempt to use the - * filesystem is likely to fail. + * filesystemList is now NULL. Any attempt to use the filesystem is likely + * to fail. */ #ifdef _WIN32 @@ -836,34 +820,31 @@ TclResetFilesystem(void) * * Tcl_FSRegister -- * - * Insert the filesystem function table at the head of the list of - * functions which are used during calls to all file-system operations. - * The filesystem will be added even if it is already in the list. (You - * can use Tcl_FSData to check if it is in the list, provided the - * ClientData used was not NULL). + * Prepends to the list of registered fileystems a new FilesystemRecord + * for the given Tcl_Filesystem, which is added even if it is already in + * the list. To determine whether the filesystem is already in the list, + * use Tcl_FSData(). * - * Note that the filesystem handling is head-to-tail of the list. Each - * filesystem is asked in turn whether it can handle a particular - * request, until one of them says 'yes'. At that point no further - * filesystems are asked. - * - * In particular this means if you want to add a diagnostic filesystem - * (which simply reports all fs activity), it must be at the head of the - * list: i.e. it must be the last registered. + * Functions that use the list generally process it from head to tail and + * use the first filesystem that is suitable. Therefore, when adding a + * diagnostic filsystem (one which simply reports all fs activity), it + * must be at the head of the list. I.e. it must be the last one + * registered. * * Results: - * Normally TCL_OK; TCL_ERROR if memory for a new node in the list could + * TCL_OK, or TCL_ERROR if memory for a new node in the list could * not be allocated. * * Side effects: - * Memory allocated and modifies the link list for filesystems. + * Allocates memory for a filesystem record and modifies the list of + * registered filesystems. * *---------------------------------------------------------------------- */ int Tcl_FSRegister( - ClientData clientData, /* Client specific data for this fs. */ + ClientData clientData, /* Client-specific data for this filesystem. */ const Tcl_Filesystem *fsPtr)/* The filesystem record for the new fs. */ { FilesystemRecord *newFilesystemPtr; @@ -877,19 +858,6 @@ Tcl_FSRegister( newFilesystemPtr->clientData = clientData; newFilesystemPtr->fsPtr = fsPtr; - /* - * Is this lock and wait strictly speaking necessary? Since any iterators - * out there will have grabbed a copy of the head of the list and be - * iterating away from that, if we add a new element to the head of the - * list, it can't possibly have any effect on any of their loops. In fact - * it could be better not to wait, since we are adjusting the filesystem - * epoch, any cached representations calculated by existing iterators are - * going to have to be thrown away anyway. - * - * However, since registering and unregistering filesystems is a very rare - * action, this is not a very important point. - */ - Tcl_MutexLock(&filesystemMutex); newFilesystemPtr->nextPtr = filesystemList; @@ -900,7 +868,7 @@ Tcl_FSRegister( filesystemList = newFilesystemPtr; /* - * Increment the filesystem epoch counter, since existing paths might + * Increment the filesystem epoch counter since existing pathnames might * conceivably now belong to different filesystems. */ @@ -917,21 +885,19 @@ Tcl_FSRegister( * * Tcl_FSUnregister -- * - * Remove the passed filesystem from the list of filesystem function - * tables. It also ensures that the built-in (native) filesystem is not - * removable, although we may wish to change that decision in the future - * to allow a smaller Tcl core, in which the native filesystem is not - * used at all (we could, say, initialise Tcl completely over a network - * connection). + * Removes the record for given filesystem from the list of registered + * filesystems. Refuses to remove the built-in (native) filesystem. This + * might be changed in the future to allow a smaller Tcl core in which the + * native filesystem is not used at all, e.g. initializing Tcl over a + * network connection. * * Results: - * TCL_OK if the function pointer was successfully removed, TCL_ERROR + * TCL_OK if the function pointer was successfully removed, or TCL_ERROR * otherwise. * * Side effects: - * Memory may be deallocated (or will be later, once no "path" objects - * refer to this filesystem), but the list of registered filesystems is - * updated immediately. + * The list of registered filesystems is updated. Memory for the + * corresponding FilesystemRecord is eventually freed. * *---------------------------------------------------------------------- */ @@ -946,9 +912,9 @@ Tcl_FSUnregister( Tcl_MutexLock(&filesystemMutex); /* - * Traverse the 'filesystemList' looking for the particular node whose - * 'fsPtr' member matches 'fsPtr' and remove that one from the list. - * Ensure that the "default" node cannot be removed. + * Traverse filesystemList in search of the record whose + * 'fsPtr' member matches 'fsPtr' and remove that record from the list. + * Do not revmoe the record for the native filesystem. */ fsRecPtr = filesystemList; @@ -964,11 +930,9 @@ Tcl_FSUnregister( } /* - * Increment the filesystem epoch counter, since existing paths - * might conceivably now belong to different filesystems. This - * should also ensure that paths which have cached the filesystem - * which is about to be deleted do not reference that filesystem - * (which would of course lead to memory exceptions). + * Each cached pathname could now belong to a different filesystem, + * so increment the filesystem epoch counter to ensure that cached + * information about the removed filesystem is not used. */ if (++theFilesystemEpoch == 0) { @@ -992,52 +956,37 @@ Tcl_FSUnregister( * * Tcl_FSMatchInDirectory -- * - * This routine is used by the globbing code to search a directory for - * all files which match a given pattern. The appropriate function for - * the filesystem to which pathPtr belongs will be called. If pathPtr - * does not belong to any filesystem and if it is NULL or the empty - * string, then we assume the pattern is to be matched in the current - * working directory. To avoid have the Tcl_FSMatchInDirectoryProc for - * each filesystem from having to deal with this issue, we create a - * pathPtr on the fly (equal to the cwd), and then remove it from the - * results returned. This makes filesystems easy to write, since they can - * assume the pathPtr passed to them is an ordinary path. In fact this - * means we could remove such special case handling from Tcl's native - * filesystems. - * - * If 'pattern' is NULL, then pathPtr is assumed to be a fully specified - * path of a single file/directory which must be checked for existence - * and correct type. + * Search in the given pathname for files matching the given pattern. + * Used by [glob]. Processes just one pattern for one directory. Callers + * such as TclGlob and DoGlob implement manage the searching of multiple + * directories in cases such as + * glob -dir $dir -join * pkgIndex.tcl * * Results: * - * The return value is a standard Tcl result indicating whether an error - * occurred in globbing. Error messages are placed in interp, but good - * results are placed in the resultPtr given. - * - * Recursive searches, e.g. - * glob -dir $dir -join * pkgIndex.tcl - * which must recurse through each directory matching '*' are handled - * internally by Tcl, by passing specific flags in a modified 'types' - * parameter. This means the actual filesystem only ever sees patterns - * which match in a single directory. + * TCL_OK, or TCL_ERROR * * Side effects: - * The interpreter may have an error message inserted into it. + * resultPtr is populated, or in the case of an TCL_ERROR, an error message is + * set in the interpreter. * *---------------------------------------------------------------------- */ int Tcl_FSMatchInDirectory( - Tcl_Interp *interp, /* Interpreter to receive error messages, but - * may be NULL. */ - Tcl_Obj *resultPtr, /* List object to receive results. */ - Tcl_Obj *pathPtr, /* Contains path to directory to search. */ - const char *pattern, /* Pattern to match against. */ - Tcl_GlobTypeData *types) /* Object containing list of acceptable types. - * May be NULL. In particular the directory - * flag is very important. */ + Tcl_Interp *interp, /* Interpreter to receive error messages, or + * NULL */ + Tcl_Obj *resultPtr, /* List that results are added to. */ + Tcl_Obj *pathPtr, /* Pathname of directory to search. If NULL, + * the current working directory is used. */ + const char *pattern, /* Pattern to match. If NULL, pathPtr must be + * a fully-specified pathname of a single + * file/directory which already exists and is + * of the correct type. */ + Tcl_GlobTypeData *types) /* Specifies acceptable types. + * May be NULL. The directory flag is + * particularly significant. */ { const Tcl_Filesystem *fsPtr; Tcl_Obj *cwd, *tmpResultPtr, **elemsPtr; @@ -1045,10 +994,10 @@ Tcl_FSMatchInDirectory( if (types != NULL && (types->type & TCL_GLOB_TYPE_MOUNT)) { /* - * We don't currently allow querying of mounts by external code (a - * valuable future step), so since we're the only function that - * actually knows about mounts, this means we're being called - * recursively by ourself. Return no matches. + * Currently external callers may not query mounts, which would be a + * valuable future step. This is the only routine that knows about + * mounts, so we're being called recursively by ourself. Return no + * matches. */ return TCL_OK; @@ -1060,12 +1009,11 @@ Tcl_FSMatchInDirectory( fsPtr = NULL; } - /* - * Check if we've successfully mapped the path to a filesystem within - * which to search. - */ - if (fsPtr != NULL) { + /* + * A corresponding filesystem was found. Search within it. + */ + if (fsPtr->matchInDirectoryProc == NULL) { Tcl_SetErrno(ENOENT); return -1; @@ -1078,24 +1026,21 @@ Tcl_FSMatchInDirectory( return ret; } - /* - * If the path isn't empty, we have no idea how to match files in a - * directory which belongs to no known filesystem. - */ - if (pathPtr != NULL && TclGetString(pathPtr)[0] != '\0') { + /* + * There is a pathname but it belongs to no known filesystem. Mayday! + */ + Tcl_SetErrno(ENOENT); return -1; } /* - * We have an empty or NULL path. This is defined to mean we must search - * for files within the current 'cwd'. We therefore use that, but then - * since the proc we call will return results which include the cwd we - * must then trim it off the front of each path in the result. We choose - * to deal with this here (in the generic code), since if we don't, every - * single filesystem's implementation of Tcl_FSMatchInDirectory will have - * to deal with it for us. + * The pathname is empty or NULL so search in the current working + * directory. matchInDirectoryProc prefixes each result with this + * directory, so trim it from each result. Deal with this here in the + * generic code because otherwise every filesystem implementation of + * Tcl_FSMatchInDirectory has to do it. */ cwd = Tcl_FSGetCwd(NULL); @@ -1118,7 +1063,7 @@ Tcl_FSMatchInDirectory( FsAddMountsToGlobResult(tmpResultPtr, cwd, pattern, types); /* - * Note that we know resultPtr and tmpResultPtr are distinct. + * resultPtr and tmpResultPtr are guaranteed to be distinct. */ ret = Tcl_ListObjGetElements(interp, tmpResultPtr, @@ -1138,30 +1083,28 @@ Tcl_FSMatchInDirectory( *---------------------------------------------------------------------- * * FsAddMountsToGlobResult -- - * - * This routine is used by the globbing code to take the results of a - * directory listing and add any mounted paths to that listing. This is - * required so that simple things like 'glob *' merge mounts and listings - * correctly. + * Adds any mounted pathnames to a set of results so that simple things + * like 'glob *' merge mounts and listings correctly. Used by the + * Tcl_FSMatchInDirectory. * * Results: * None. * * Side effects: - * Modifies the resultPtr. + * Stores a result in resultPtr. * *---------------------------------------------------------------------- */ static void FsAddMountsToGlobResult( - Tcl_Obj *resultPtr, /* The current list of matching paths; must - * not be shared! */ - Tcl_Obj *pathPtr, /* The directory in question. */ - const char *pattern, /* Pattern to match against. */ - Tcl_GlobTypeData *types) /* Object containing list of acceptable types. - * May be NULL. In particular the directory - * flag is very important. */ + Tcl_Obj *resultPtr, /* The current list of matching pathnames. Must + * not be shared. */ + Tcl_Obj *pathPtr, /* The directory that was searched. */ + const char *pattern, /* Pattern to match mounts against. */ + Tcl_GlobTypeData *types) /* Acceptable types. May be NULL. The + * directory flag is particularly significant. + */ { int mLength, gLength, i; int dir = (types == NULL || (types->type & TCL_GLOB_TYPE_DIR)); @@ -1206,9 +1149,9 @@ FsAddMountsToGlobResult( int len, mlen; /* - * We know mElt is absolute normalized and lies inside pathPtr, so - * now we must add to the result the right representation of mElt, - * i.e. the representation which is relative to pathPtr. + * mElt is normalized and lies inside pathPtr so + * add to the result the right representation of mElt, + * i.e. the representation relative to pathPtr. */ norm = Tcl_FSGetNormalizedPath(NULL, pathPtr); @@ -1225,12 +1168,13 @@ FsAddMountsToGlobResult( len--; } len++; /* account for '/' in the mElt [Bug 1602539] */ + + mElt = TclNewFSPathObj(pathPtr, mount + len, mlen - len); Tcl_ListObjAppendElement(NULL, resultPtr, mElt); } /* - * No need to increment gLength, since we don't want to compare - * mounts against mounts. + * Not comparing mounts to mounts, so no need to increment gLength */ } } @@ -1244,44 +1188,41 @@ FsAddMountsToGlobResult( * * Tcl_FSMountsChanged -- * - * Notify the filesystem that the available mounted filesystems (or - * within any one filesystem type, the number or location of mount - * points) have changed. + * Announecs that mount points have changed or that the system encoding + * has changed. * * Results: * None. * * Side effects: - * The global filesystem variable 'theFilesystemEpoch' is incremented. - * The effect of this is to make all cached path representations invalid. - * Clearly it should only therefore be called when it is really required! - * There are a few circumstances when it should be called: + * The shared 'theFilesystemEpoch' is incremented, invalidating every + * exising cached internal representation of a pathname. Avoid calling + * Tcl_FSMountsChanged whenever possible. It must be called when: * - * (1) when a new filesystem is registered or unregistered. Strictly - * speaking this is only necessary if the new filesystem accepts file - * paths as is (normally the filesystem itself is really a shell which - * hasn't yet had any mount points established and so its - * 'pathInFilesystem' proc will always fail). However, for safety, Tcl - * always calls this for you in these circumstances. + * (1) A filesystem is registered or unregistered. This is only necessary + * if the new filesystem accepts file pathnames as-is. Normally the + * filesystem is really a shell which doesn't yet have any mount points + * established and so its 'pathInFilesystem' routine always fails. + * However, for safety, Tcl calls 'Tcl_FSMountsChanged' each time a + * filesystem is registered or unregistered. * - * (2) when additional mount points are established inside any existing - * filesystem (except the native fs) + * (2) An additional mount point is established inside an existing + * filesystem (except for the native file system; see note below). * - * (3) when any filesystem (except the native fs) changes the list of - * available volumes. + * (3) A filesystem changes the list of available volumes (except for the + * native file system; see note below). * - * (4) when the mapping from a string representation of a file to a full, - * normalized path changes. For example, if 'env(HOME)' is modified, then - * any path containing '~' will map to a different filesystem location. - * Therefore all such paths need to have their internal representation - * invalidated. + * (4) The mapping from a string representation of a file to a full, + * normalized pathname changes. For example, if 'env(HOME)' is modified, + * then any pathname containing '~' maps to a different item, possibly in + * a different filesystem. * - * Tcl has no control over (2) and (3), so any registered filesystem must - * make sure it calls this function when those situations occur. + * Tcl has no control over (2) and (3), so each registered filesystem must + * call Tcl_FSMountsChnaged in each of those circumstances. * - * (Note: the reason for the exception in 2,3 for the native filesystem - * is that the native filesystem by default claims all unknown files even - * if it really doesn't understand them or if they don't exist). + * The reason for the exception in 2,3 for the native filesystem is that + * the native filesystem claims every file without determining whether + * whether the file exists, or even whether the pathname makes sense. * *---------------------------------------------------------------------- */ @@ -1291,16 +1232,15 @@ Tcl_FSMountsChanged( const Tcl_Filesystem *fsPtr) { /* - * We currently don't do anything with this parameter. We could in the - * future only invalidate files for this filesystem or otherwise take more - * advanced action. + * fsPtr is currently unused. In the future it might invalidate files for + * a particular filesystem, or take some other more advanced action. */ (void)fsPtr; /* - * Increment the filesystem epoch counter, since existing paths might now - * belong to different filesystems. + * Increment the filesystem epoch to invalidate every existing cached + * internal representation. */ Tcl_MutexLock(&filesystemMutex); @@ -1315,13 +1255,11 @@ Tcl_FSMountsChanged( * * Tcl_FSData -- * - * Retrieve the clientData field for the filesystem given, or NULL if - * that filesystem is not registered. + * Retrieves the clientData member of the given filesystem. * * Results: - * A clientData value, or NULL. Note that if the filesystem was - * registered with a NULL clientData field, this function will return - * that NULL value. + * A clientData value, or NULL if the given filesystem is not registered. + * The clientData value itself may also be NULL. * * Side effects: * None. @@ -1331,15 +1269,14 @@ Tcl_FSMountsChanged( ClientData Tcl_FSData( - const Tcl_Filesystem *fsPtr) /* The filesystem record to query. */ + const Tcl_Filesystem *fsPtr) /* The filesystem to find in the list of + * registered filesystems. */ { ClientData retVal = NULL; FilesystemRecord *fsRecPtr = FsGetFirstFilesystem(); /* - * Traverse the list of filesystems look for a particular one. If found, - * return that filesystem's clientData (originally provided when calling - * Tcl_FSRegister). + * Find the filesystem in and retrieve its clientData. */ while ((retVal == NULL) && (fsRecPtr != NULL)) { @@ -1357,27 +1294,24 @@ Tcl_FSData( * * TclFSNormalizeToUniquePath -- * - * Takes a path specification containing no ../, ./ sequences, and - * converts it into a unique path for the given platform. On Unix, this - * means the path must be free of symbolic links/aliases, and on Windows - * it means we want the long form, with that long form's case-dependence - * (which gives us a unique, case-dependent path). + * Converts the given pathname, containing no ../, ./ components, into a + * unique pathname for the given platform. On Unix the resulting pathname + * is free of symbolic links/aliases, and on Windows it is the long + * case-preserving form. + * * * Results: - * The pathPtr is modified in place. The return value is the last byte - * offset which was recognised in the path string. + * Stores the resulting pathname in pathPtr and returns the offset of the + * last byte processed in pathPtr. * * Side effects: * None (beyond the memory allocation for the result). * * Special notes: * If the filesystem-specific normalizePathProcs can re-introduce ../, ./ - * sequences into the path, then this function will not return the - * correct result. This may be possible with symbolic links on unix. + * components into the pathname, this function does not return the correct + * result. This may be possible with symbolic links on unix. * - * Important assumption: if startAt is non-zero, it must point to a - * directory separator that we know exists and is already normalized (so - * it is important not to point to the char just after the separator). * *--------------------------------------------------------------------------- */ @@ -1385,8 +1319,13 @@ Tcl_FSData( int TclFSNormalizeToUniquePath( Tcl_Interp *interp, /* Used for error messages. */ - Tcl_Obj *pathPtr, /* The path to normalize in place. */ - int startAt) /* Start at this char-offset. */ + Tcl_Obj *pathPtr, /* An Pathname to normalize in-place. Must be + * unshared. */ + int startAt) /* Offset the string of pathPtr to start at. + * Must either be 0 or offset of a directory + * separator at the end of a pathname part that + * is already normalized, I.e. not the index of + * the byte just after the separator. */ { FilesystemRecord *fsRecPtr, *firstFsRecPtr; @@ -1395,10 +1334,10 @@ TclFSNormalizeToUniquePath( const char *path; /* - * Paths starting with a UNC prefix whose final character is a colon - * are reserved for VFS use. These names can not conflict with real - * UNC paths per https://msdn.microsoft.com/en-us/library/gg465305.aspx - * and rfc3986's definition of reg-name. + * Pathnames starting with a UNC prefix and ending with a colon character + * are reserved for VFS use. These names can not conflict with real UNC + * pathnames per https://msdn.microsoft.com/en-us/library/gg465305.aspx and + * rfc3986's definition of reg-name. * * We check these first to avoid useless calls to the native filesystem's * normalizePathProc. @@ -1416,7 +1355,7 @@ TclFSNormalizeToUniquePath( } /* - * Call each of the "normalise path" functions in succession. + * Call the the normalizePathProc routine of each registered filesystem. */ firstFsRecPtr = FsGetFirstFilesystem(); @@ -1425,7 +1364,7 @@ TclFSNormalizeToUniquePath( if (!isVfsPath) { /* - * If we have a native filesystem handler, we call it first. This is + * Find and call the native filesystem handler first if there is one * because the root of Tcl's filesystem is always a native filesystem * (i.e., '/' on unix is native). */ @@ -1436,8 +1375,8 @@ TclFSNormalizeToUniquePath( } /* - * TODO: Assume that we always find the native file system; it should - * always be there... + * TODO: Always call the normalizePathProc here because it should + * always exist. */ if (fsRecPtr->fsPtr->normalizePathProc != NULL) { @@ -1449,11 +1388,10 @@ TclFSNormalizeToUniquePath( } for (fsRecPtr=firstFsRecPtr; fsRecPtr!=NULL; fsRecPtr=fsRecPtr->nextPtr) { - /* - * Skip the native system next time through. - */ - if (fsRecPtr->fsPtr == &tclNativeFilesystem) { + /* + * Skip the native system this time through. + */ continue; } @@ -1463,7 +1401,7 @@ TclFSNormalizeToUniquePath( } /* - * We could add an efficiency check like this: + * This efficiency check could be added: * if (retVal == length-of(pathPtr)) {break;} * but there's not much benefit. */ @@ -1478,26 +1416,27 @@ TclFSNormalizeToUniquePath( * * TclGetOpenMode -- * - * This routine is an obsolete, limited version of TclGetOpenModeEx() - * below. It exists only to satisfy any extensions imprudently using it - * via Tcl's internal stubs table. + * Obsolete. A limited version of TclGetOpenModeEx() which exists only to + * satisfy any extensions imprudently using it via Tcl's internal stubs + * table. * * Results: - * Same as TclGetOpenModeEx(). + * See TclGetOpenModeEx(). * * Side effects: - * Same as TclGetOpenModeEx(). + * See TclGetOpenModeEx(). * *--------------------------------------------------------------------------- */ int TclGetOpenMode( - Tcl_Interp *interp, /* Interpreter to use for error reporting - - * may be NULL. */ - const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */ - int *seekFlagPtr) /* Set this to 1 if the caller should seek to - * EOF during the opening of the file. */ + Tcl_Interp *interp, /* Interpreter to use for error reporting. May + * be NULL. */ + const char *modeString, /* e.g. "r+" or "RDONLY CREAT". */ + int *seekFlagPtr) /* Sets this to 1 to tell the caller to seek to + EOF after opening the file, and + * 0 otherwise. */ { int binary = 0; return TclGetOpenModeEx(interp, modeString, seekFlagPtr, &binary); @@ -1508,46 +1447,44 @@ TclGetOpenMode( * * TclGetOpenModeEx -- * - * Computes a POSIX mode mask for opening a file, from a given string, - * and also sets flags to indicate whether the caller should seek to EOF - * after opening the file, and whether the caller should configure the - * channel for binary data. + * Computes a POSIX mode mask for opening a file. * * Results: - * On success, returns mode to pass to "open". If an error occurs, the - * return value is -1 and if interp is not NULL, sets interp's result - * object to an error message. + * The mode to pass to "open", or -1 if an error occurs. * * Side effects: - * Sets the integer referenced by seekFlagPtr to 1 to tell the caller to - * seek to EOF after opening the file, or to 0 otherwise. Sets the - * integer referenced by binaryPtr to 1 to tell the caller to seek to - * configure the channel for binary data, or to 0 otherwise. + * Sets *seekFlagPtr to 1 to tell the caller to + * seek to EOF after opening the file, or to 0 otherwise. + * + * Sets *binaryPtr to 1 to tell the caller to configure the channel as a + * binary channel, or to 0 otherwise. + * + * If there is an error and interp is not NULL, sets interpreter result to + * an error message. * * Special note: - * This code is based on a prototype implementation contributed by Mark - * Diekhans. + * Based on a prototype implementation contributed by Mark Diekhans. * *--------------------------------------------------------------------------- */ int TclGetOpenModeEx( - Tcl_Interp *interp, /* Interpreter to use for error reporting - - * may be NULL. */ + Tcl_Interp *interp, /* Interpreter, possibly NULL, to use for + * error reporting. */ const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */ - int *seekFlagPtr, /* Set this to 1 if the caller should seek to - * EOF during the opening of the file. */ - int *binaryPtr) /* Set this to 1 if the caller should - * configure the opened channel for binary - * operations. */ + int *seekFlagPtr, /* Sets this to 1 to tell the the caller to seek to + * EOF after opening the file, and 0 otherwise. */ + int *binaryPtr) /* Sets this to 1 to tell the caller to + * configure the channel for binary + * operations after opening the file. */ { int mode, modeArgc, c, i, gotRW; const char **modeArgv, *flag; #define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR) /* - * Check for the simpler fopen-like access modes (e.g., "r"). They are + * Check for the simpler fopen-like access modes like "r" which are * distinguished from the POSIX access modes by the presence of a * lower-case first letter. */ @@ -1557,8 +1494,7 @@ TclGetOpenModeEx( mode = 0; /* - * Guard against international characters before using byte oriented - * routines. + * Guard against wide characters before using byte-oriented routines. */ if (!(modeString[0] & 0x80) @@ -1572,7 +1508,7 @@ TclGetOpenModeEx( break; case 'a': /* - * Added O_APPEND for proper automatic seek-to-end-on-write by the + * Add O_APPEND for proper automatic seek-to-end-on-write by the * OS. [Bug 680143] */ @@ -1590,8 +1526,8 @@ TclGetOpenModeEx( switch (modeString[i++]) { case '+': /* - * Must remove the O_APPEND flag so that the seek command - * works. [Bug 1773127] + * Remove O_APPEND so that the seek command works. [Bug + * 1773127] */ mode &= ~(O_RDONLY|O_WRONLY|O_APPEND); @@ -1620,11 +1556,9 @@ TclGetOpenModeEx( } /* - * The access modes are specified using a list of POSIX modes such as - * O_CREAT. + * The access modes are specified as a list of POSIX modes like O_CREAT. * - * IMPORTANT NOTE: We rely on Tcl_SplitList working correctly when a NULL - * interpreter is passed in. + * Tcl_SplitList must work correctly when interp is NULL. */ if (Tcl_SplitList(interp, modeString, &modeArgc, &modeArgv) != TCL_OK) { @@ -1719,8 +1653,10 @@ TclGetOpenModeEx( * * Tcl_FSEvalFile, Tcl_FSEvalFileEx, TclNREvalFile -- * - * Read in a file and process the entire file as one gigantic Tcl - * command. Tcl_FSEvalFile is Tcl_FSEvalFileEx without encoding argument. + * Reads a file and evaluates it as a script. + * + * Tcl_FSEvalFile is Tcl_FSEvalFileEx without the encoding argument. + * * TclNREvalFile is an NRE-enabled version of Tcl_FSEvalFileEx. * * Results: @@ -1728,29 +1664,31 @@ TclGetOpenModeEx( * file or an error indicating why the file couldn't be read. * * Side effects: - * Depends on the commands in the file. During the evaluation of the - * contents of the file, iPtr->scriptFile is made to point to pathPtr - * (the old value is cached and replaced when this function returns). + * Arbitrary, depending on the contents of the script. While the script + * is evaluated iPtr->scriptFile is a reference to pathPtr, and after the + * evaluation completes, has its original value restored again. * *---------------------------------------------------------------------- */ int Tcl_FSEvalFile( - Tcl_Interp *interp, /* Interpreter in which to process file. */ - Tcl_Obj *pathPtr) /* Path of file to process. Tilde-substitution - * will be performed on this name. */ + Tcl_Interp *interp, /* Interpreter that evaluates the script. */ + Tcl_Obj *pathPtr) /* Pathname of file containing the script. + * Tilde-substitution is performed on this + * pathname. */ { return Tcl_FSEvalFileEx(interp, pathPtr, NULL); } int Tcl_FSEvalFileEx( - Tcl_Interp *interp, /* Interpreter in which to process file. */ - Tcl_Obj *pathPtr, /* Path of file to process. Tilde-substitution - * will be performed on this name. */ - const char *encodingName) /* If non-NULL, then use this encoding for the - * file. NULL means use the system encoding. */ + Tcl_Interp *interp, /* Interpreter that evaluates the script. */ + Tcl_Obj *pathPtr, /* Pathname of the file to process. + * Tilde-substitution is performed on this + * pathname. */ + const char *encodingName) /* Either the name of an encoding or NULL to + use the system encoding. */ { int length, result = TCL_ERROR; Tcl_StatBuf statBuf; @@ -1780,15 +1718,16 @@ Tcl_FSEvalFileEx( } /* - * The eofchar is \32 (^Z). This is the usual on Windows, but we effect - * this cross-platform to allow for scripted documents. [Bug: 2040] + * The eof character is \32 (^Z). This is standard on Windows, and Tcl + * uses it on every platform to allow for scripted documents. [Bug: 2040] */ Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}"); /* - * If the encoding is specified, set it for the channel. Else don't touch - * it (and use the system encoding) Report error on unknown encoding. + * If the encoding is specified, set the channel to that encoding. + * Otherwise don't touch it, leaving things up to the system encoding. If + * the encoding is unknown report an error. */ if (encodingName != NULL) { @@ -1803,8 +1742,7 @@ Tcl_FSEvalFileEx( Tcl_IncrRefCount(objPtr); /* - * Try to read first character of stream, so we can check for utf-8 BOM to - * be handled especially. + * Read first character of stream to check for utf-8 BOM */ if (Tcl_ReadChars(chan, objPtr, 1, 0) == TCL_IO_FAILURE) { @@ -1817,8 +1755,8 @@ Tcl_FSEvalFileEx( string = Tcl_GetString(objPtr); /* - * If first character is not a BOM, append the remaining characters, - * otherwise replace them. [Bug 3466099] + * If first character is not a BOM, append the remaining characters. + * Otherwise, replace them. [Bug 3466099] */ if (Tcl_ReadChars(chan, objPtr, -1, @@ -1841,16 +1779,16 @@ Tcl_FSEvalFileEx( string = TclGetStringFromObj(objPtr, &length); /* - * TIP #280 Force the evaluator to open a frame for a sourced file. + * TIP #280: Open a frame for the evaluated script. */ iPtr->evalFlags |= TCL_EVAL_FILE; result = TclEvalEx(interp, string, length, 0, 1, NULL, string); /* - * Now we have to be careful; the script may have changed the - * iPtr->scriptFile value, so we must reset it without assuming it still - * points to 'pathPtr'. + * Restore the original iPtr->scriptFile value, but because the value may + * have hanged during evaluation, don't assume it currently points to + * pathPtr. */ if (iPtr->scriptFile != NULL) { @@ -1862,7 +1800,7 @@ Tcl_FSEvalFileEx( result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { /* - * Record information telling where the error occurred. + * Record information about where the error occurred. */ const char *pathString = TclGetStringFromObj(pathPtr, &length); @@ -1882,11 +1820,12 @@ Tcl_FSEvalFileEx( int TclNREvalFile( - Tcl_Interp *interp, /* Interpreter in which to process file. */ - Tcl_Obj *pathPtr, /* Path of file to process. Tilde-substitution - * will be performed on this name. */ - const char *encodingName) /* If non-NULL, then use this encoding for the - * file. NULL means use the system encoding. */ + Tcl_Interp *interp, /* Interpreter in which to evaluate the script. */ + Tcl_Obj *pathPtr, /* Pathname of a file containing the script to + * evaluate. Tilde-substitution is performed on + * this pathname. */ + const char *encodingName) /* The name of an encoding to use, or NULL to + * use the system encoding. */ { Tcl_StatBuf statBuf; Tcl_Obj *oldScriptFile, *objPtr; @@ -1915,15 +1854,16 @@ TclNREvalFile( TclPkgFileSeen(interp, Tcl_GetString(pathPtr)); /* - * The eofchar is \32 (^Z). This is the usual on Windows, but we effect - * this cross-platform to allow for scripted documents. [Bug: 2040] + * The eof character is \32 (^Z). This is standard on Windows, and Tcl + * uses it on every platform to allow for scripted documents. [Bug: 2040] */ Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}"); /* - * If the encoding is specified, set it for the channel. Else don't touch - * it (and use the system encoding) Report error on unknown encoding. + * If the encoding is specified, set the channel to that encoding. + * Otherwise don't touch it, leaving things up to the system encoding. If + * the encoding is unknown report an error. */ if (encodingName != NULL) { @@ -1938,8 +1878,7 @@ TclNREvalFile( Tcl_IncrRefCount(objPtr); /* - * Try to read first character of stream, so we can check for utf-8 BOM to - * be handled especially. + * Read first character of stream to check for utf-8 BOM */ if (Tcl_ReadChars(chan, objPtr, 1, 0) == TCL_IO_FAILURE) { @@ -1953,8 +1892,8 @@ TclNREvalFile( string = Tcl_GetString(objPtr); /* - * If first character is not a BOM, append the remaining characters, - * otherwise replace them. [Bug 3466099] + * If first character is not a BOM, append the remaining characters. + * Otherwise, replace them. [Bug 3466099] */ if (Tcl_ReadChars(chan, objPtr, -1, @@ -1978,7 +1917,7 @@ TclNREvalFile( Tcl_IncrRefCount(iPtr->scriptFile); /* - * TIP #280: Force the evaluator to open a frame for a sourced file. + * TIP #280: Open a frame for the evaluated script. */ iPtr->evalFlags |= TCL_EVAL_FILE; @@ -1999,9 +1938,9 @@ EvalFileCallback( Tcl_Obj *objPtr = data[2]; /* - * Now we have to be careful; the script may have changed the - * iPtr->scriptFile value, so we must reset it without assuming it still - * points to 'pathPtr'. + * Restore the original iPtr->scriptFile value, but because the value may + * have hanged during evaluation, don't assume it currently points to + * pathPtr. */ if (iPtr->scriptFile != NULL) { @@ -2013,7 +1952,7 @@ EvalFileCallback( result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { /* - * Record information telling where the error occurred. + * Record information about where the error occurred. */ int length; @@ -2036,16 +1975,15 @@ EvalFileCallback( * * Tcl_GetErrno -- * - * Gets the current value of the Tcl error code variable. This is - * currently the global variable "errno" but could in the future change + * Currently the global variable "errno", but could in the future change * to something else. * * Results: - * The value of the Tcl error code variable. + * The current Tcl error number. * * Side effects: - * None. Note that the value of the Tcl error code variable is UNDEFINED - * if a call to Tcl_SetErrno did not precede this call. + * None. The value of the Tcl error code variable is only defined if it + * was set by a previous call to Tcl_SetErrno. * *---------------------------------------------------------------------- */ @@ -2054,8 +1992,8 @@ int Tcl_GetErrno(void) { /* - * On some platforms, errno is really a thread local (implemented by the C - * library). + * On some platforms errno is thread-local, as implemented by the C + * library. */ return errno; @@ -2066,15 +2004,15 @@ Tcl_GetErrno(void) * * Tcl_SetErrno -- * - * Sets the Tcl error code variable to the supplied value. On some saner - * platforms this is actually a thread-local (this is implemented in the - * C library) but this is *really* unsafe to assume! + * Sets the Tcl error code to the given value. On some saner platforms + * this is implemented in the C library as a thread-local value , but this + * is *really* unsafe to assume! * * Results: * None. * * Side effects: - * Modifies the value of the Tcl error code variable. + * Modifies the the Tcl error code value. * *---------------------------------------------------------------------- */ @@ -2084,8 +2022,8 @@ Tcl_SetErrno( int err) /* The new value. */ { /* - * On some platforms, errno is really a thread local (implemented by the C - * library). + * On some platforms, errno is implemented by the C library as a thread + * local value */ errno = err; @@ -2096,24 +2034,21 @@ Tcl_SetErrno( * * Tcl_PosixError -- * - * This function is typically called after UNIX kernel calls return - * errors. It stores machine-readable information about the error in - * errorCode field of interp and returns an information string for the - * caller's use. + * Typically called after a UNIX kernel call returns an error. Sets the + * interpreter errorCode to machine-parsable information about the error. * * Results: - * The return value is a human-readable string describing the error. + * A human-readable sring describing the error. * * Side effects: - * The errorCode field of the interp is set. + * Sets the errorCode value of the interpreter. * *---------------------------------------------------------------------- */ const char * Tcl_PosixError( - Tcl_Interp *interp) /* Interpreter whose errorCode field is to be - * set. */ + Tcl_Interp *interp) /* Interpreter to set the errorCode of */ { const char *id, *msg; @@ -2129,11 +2064,10 @@ Tcl_PosixError( *---------------------------------------------------------------------- * * Tcl_FSStat -- + * Calls 'statProc' of the filesystem corresponding to pathPtr. * - * This function replaces the library version of stat and lsat. + * Replaces the standard library routines stat. * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. * * Results: * See stat documentation. @@ -2146,8 +2080,10 @@ Tcl_PosixError( int Tcl_FSStat( - Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */ - Tcl_StatBuf *buf) /* Filled with results of stat call. */ + Tcl_Obj *pathPtr, /* Pathname of the file to call stat on (in + * current CP). */ + Tcl_StatBuf *buf) /* A buffer to hold the results of the call to + * stat. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2162,11 +2098,11 @@ Tcl_FSStat( *---------------------------------------------------------------------- * * Tcl_FSLstat -- + * Calls the 'lstatProc' of the filesystem corresponding to pathPtr. * - * This function replaces the library version of lstat. The appropriate - * function for the filesystem to which pathPtr belongs will be called. - * If no 'lstat' function is listed, but a 'stat' function is, then Tcl - * will fall back on the stat function. + * Replaces the library version of lstat. If the filesystem doesn't + * provide lstatProc but does provide statProc, Tcl falls back to + * statProc. * * Results: * See lstat documentation. @@ -2179,8 +2115,9 @@ Tcl_FSStat( int Tcl_FSLstat( - Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */ - Tcl_StatBuf *buf) /* Filled with results of stat call. */ + Tcl_Obj *pathPtr, /* Pathname of the file to call stat on (in + current CP). */ + Tcl_StatBuf *buf) /* Filled with results of that call to stat. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2201,8 +2138,9 @@ Tcl_FSLstat( * * Tcl_FSAccess -- * - * This function replaces the library version of access. The appropriate - * function for the filesystem to which pathPtr belongs will be called. + * Calls 'accessProc' of the filesystem corresponding to pathPtr. + * + * Replaces the library version of access. * * Results: * See access documentation. @@ -2215,7 +2153,7 @@ Tcl_FSLstat( int Tcl_FSAccess( - Tcl_Obj *pathPtr, /* Path of file to access (in current CP). */ + Tcl_Obj *pathPtr, /* Pathname of file to access (in current CP). */ int mode) /* Permission setting. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2232,38 +2170,36 @@ Tcl_FSAccess( * * Tcl_FSOpenFileChannel -- * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. + * Calls 'openfileChannelProc' of the filesystem corresponding to + * pathPtr. * * Results: - * The new channel or NULL, if the named file could not be opened. + * The new channel, or NULL if the named file could not be opened. * * Side effects: - * May open the channel and may cause creation of a file on the file - * system. + * Opens a channel, possibly creating the corresponding the file on the + * filesystem. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_FSOpenFileChannel( - Tcl_Interp *interp, /* Interpreter for error reporting; can be - * NULL. */ - Tcl_Obj *pathPtr, /* Name of file to open. */ + Tcl_Interp *interp, /* Interpreter for error reporting, or NULL */ + Tcl_Obj *pathPtr, /* Pathname of file to open. */ const char *modeString, /* A list of POSIX open modes or a string such * as "rw". */ - int permissions) /* If the open involves creating a file, with - * what modes to create it? */ + int permissions) /* What modes to use if opening the file + involves creating it. */ { const Tcl_Filesystem *fsPtr; Tcl_Channel retVal = NULL; - /* - * We need this just to ensure we return the correct error messages under - * some circumstances. - */ if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) { + /* + * Return the correct error message. + */ return NULL; } @@ -2272,8 +2208,8 @@ Tcl_FSOpenFileChannel( int mode, seekFlag, binary; /* - * Parse the mode, picking up whether we want to seek to start with - * and/or set the channel automatically into binary mode. + * Parse the mode to determine whether to seek at the outset + * and/or set the channel into binary mode. */ mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary); @@ -2282,7 +2218,7 @@ Tcl_FSOpenFileChannel( } /* - * Do the actual open() call. + * Open the file. */ retVal = fsPtr->openFileChannelProc(interp, pathPtr, mode, @@ -2292,7 +2228,7 @@ Tcl_FSOpenFileChannel( } /* - * Apply appropriate flags parsed out above. + * Seek and/or set binary mode as determined above. */ if (seekFlag && Tcl_Seek(retVal, (Tcl_WideInt) 0, SEEK_END) @@ -2329,8 +2265,10 @@ Tcl_FSOpenFileChannel( * * Tcl_FSUtime -- * - * This function replaces the library version of utime. The appropriate - * function for the filesystem to which pathPtr belongs will be called. + * Calls 'uTimeProc' of the filesystem corresponding to the given + * pathname. + * + * Replaces the library version of utime. * * Results: * See utime documentation. @@ -2343,9 +2281,8 @@ Tcl_FSOpenFileChannel( int Tcl_FSUtime( - Tcl_Obj *pathPtr, /* File to change access/modification - * times. */ - struct utimbuf *tval) /* Structure containing access/modification + Tcl_Obj *pathPtr, /* Pathaname of file to call uTimeProc on */ + struct utimbuf *tval) /* Specifies the access/modification * times to use. Should not be modified. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2362,11 +2299,10 @@ Tcl_FSUtime( * * NativeFileAttrStrings -- * - * This function implements the platform dependent 'file attributes' - * subcommand, for the native filesystem, for listing the set of possible - * attribute strings. This function is part of Tcl's native filesystem - * support, and is placed here because it is shared by Unix and Windows - * code. + * Implements the platform-dependent 'file attributes' subcommand for the + * native filesystem, for listing the set of possible attribute strings. + * Part of Tcl's native filesystem support. Placed here because it is used + * under both Unix and Windows. * * Results: * An array of strings @@ -2390,16 +2326,18 @@ NativeFileAttrStrings( * * NativeFileAttrsGet -- * - * This function implements the platform dependent 'file attributes' - * subcommand, for the native filesystem, for 'get' operations. This - * function is part of Tcl's native filesystem support, and is placed - * here because it is shared by Unix and Windows code. + * Implements the platform-dependent 'file attributes' subcommand for the + * native filesystem for 'get' operations. Part of Tcl's native + * filesystem support. Defined here because it is used under both Unix + * and Windows. * * Results: - * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK - * was returned) is likely to have a refCount of zero. Either way we must - * either store it somewhere (e.g. the Tcl result), or Incr/Decr its - * refCount to ensure it is properly freed. + * Standard Tcl return code. + * + * If there was no error, stores in objPtrRef a pointer to a new object + * having a refCount of zero and holding the result. The caller should + * store it somewhere, e.g. as the Tcl result, or decrement its refCount + * to free it. * * Side effects: * None. @@ -2411,8 +2349,8 @@ static int NativeFileAttrsGet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ - Tcl_Obj *pathPtr, /* path of file we are operating on. */ - Tcl_Obj **objPtrRef) /* for output. */ + Tcl_Obj *pathPtr, /* Pathname of the file */ + Tcl_Obj **objPtrRef) /* Where to store the a pointer to the result. */ { return tclpFileAttrProcs[index].getProc(interp, index, pathPtr,objPtrRef); } @@ -2422,13 +2360,13 @@ NativeFileAttrsGet( * * NativeFileAttrsSet -- * - * This function implements the platform dependent 'file attributes' - * subcommand, for the native filesystem, for 'set' operations. This - * function is part of Tcl's native filesystem support, and is placed - * here because it is shared by Unix and Windows code. + * Implements the platform-dependent 'file attributes' subcommand for the + * native filesystem for 'set' operations. A part of Tcl's native + * filesystem support, it is defined here because it is used under both + * Unix and Windows. * * Results: - * Standard Tcl return code. + * A standard Tcl return code. * * Side effects: * None. @@ -2440,8 +2378,8 @@ static int NativeFileAttrsSet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ - Tcl_Obj *pathPtr, /* path of file we are operating on. */ - Tcl_Obj *objPtr) /* set to this value. */ + Tcl_Obj *pathPtr, /* Pathname of the file */ + Tcl_Obj *objPtr) /* The value to set. */ { return tclpFileAttrProcs[index].setProc(interp, index, pathPtr, objPtr); } @@ -2451,18 +2389,16 @@ NativeFileAttrsSet( * * Tcl_FSFileAttrStrings -- * - * This function implements part of the hookable 'file attributes' - * subcommand. The appropriate function for the filesystem to which - * pathPtr belongs will be called. + * Implements part of the hookable 'file attributes' + * subcommand. + * + * Calls 'fileAttrStringsProc' of the filesystem corresponding to the + * given pathname. * * Results: - * The called function may either return an array of strings, or may - * instead return NULL and place a Tcl list into the given objPtrRef. - * Tcl will take that list and first increment its refCount before using - * it. On completion of that use, Tcl will decrement its refCount. Hence - * if the list should be disposed of by Tcl when done, it should have a - * refCount of zero, and if the list should not be disposed of, the - * filesystem should ensure it retains a refCount on the object. + * Returns an array of strings, or returns NULL and stores in objPtrRef + * a pointer to a new Tcl list having a refCount of zero, and containing + * the file attribute strings. * * Side effects: * None. @@ -2489,11 +2425,13 @@ Tcl_FSFileAttrStrings( * * TclFSFileAttrIndex -- * - * Helper function for converting an attribute name to an index into the + * Given an attribute name, determines the index of the attribute in the * attribute table. * * Results: - * Tcl result code, index written to *indexPtr on result==TCL_OK + * A standard Tcl result code. + * + * If there is no error, stores the index in *indexPtr. * * Side effects: * None. @@ -2503,10 +2441,9 @@ Tcl_FSFileAttrStrings( int TclFSFileAttrIndex( - Tcl_Obj *pathPtr, /* File whose attributes are to be indexed - * into. */ - const char *attributeName, /* The attribute being looked for. */ - int *indexPtr) /* Where to write the found index. */ + Tcl_Obj *pathPtr, /* Pathname of the file. */ + const char *attributeName, /* The name of the attribute. */ + int *indexPtr) /* A place to store the result. */ { Tcl_Obj *listObj = NULL; const char *const *attrTable; @@ -2566,15 +2503,16 @@ TclFSFileAttrIndex( * * Tcl_FSFileAttrsGet -- * - * This function implements read access for the hookable 'file - * attributes' subcommand. The appropriate function for the filesystem to - * which pathPtr belongs will be called. + * Implements read access for the hookable 'file attributes' subcommand. + * + * Calls 'fileAttrsGetProc' of the filesystem corresponding to the given + * pathname. * * Results: - * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK - * was returned) is likely to have a refCount of zero. Either way we must - * either store it somewhere (e.g. the Tcl result), or Incr/Decr its - * refCount to ensure it is properly freed. + * A standard Tcl return code. + * + * On success, stores in objPtrRef a pointer to a new Tcl_Obj having a + * refCount of zero, and containing the result. * * Side effects: * None. @@ -2585,9 +2523,9 @@ TclFSFileAttrIndex( int Tcl_FSFileAttrsGet( Tcl_Interp *interp, /* The interpreter for error reporting. */ - int index, /* index of the attribute command. */ - Tcl_Obj *pathPtr, /* filename we are operating on. */ - Tcl_Obj **objPtrRef) /* for output. */ + int index, /* The index of the attribute command. */ + Tcl_Obj *pathPtr, /* The pathname of the file. */ + Tcl_Obj **objPtrRef) /* A place to store the result. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2603,12 +2541,14 @@ Tcl_FSFileAttrsGet( * * Tcl_FSFileAttrsSet -- * - * This function implements write access for the hookable 'file - * attributes' subcommand. The appropriate function for the filesystem to - * which pathPtr belongs will be called. + * Implements write access for the hookable 'file + * attributes' subcommand. + * + * Calls 'fileAttrsSetProc' for the filesystem corresponding to the given + * pathname. * * Results: - * Standard Tcl return code. + * A standard Tcl return code. * * Side effects: * None. @@ -2619,9 +2559,9 @@ Tcl_FSFileAttrsGet( int Tcl_FSFileAttrsSet( Tcl_Interp *interp, /* The interpreter for error reporting. */ - int index, /* index of the attribute command. */ - Tcl_Obj *pathPtr, /* filename we are operating on. */ - Tcl_Obj *objPtr) /* Input value. */ + int index, /* The index of the attribute command. */ + Tcl_Obj *pathPtr, /* The pathname of the file. */ + Tcl_Obj *objPtr) /* A place to store the result. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -2637,33 +2577,25 @@ Tcl_FSFileAttrsSet( * * Tcl_FSGetCwd -- * - * This function replaces the library version of getcwd(). + * Replaces the library version of getcwd(). * - * Most VFS's will *not* implement a 'cwdProc'. Tcl now maintains its own - * record (in a Tcl_Obj) of the cwd, and an attempt is made to synch this - * with the cwd's containing filesystem, if that filesystem provides a - * cwdProc (e.g. the native filesystem). + * Most virtual filesystems do not implement cwdProc. Tcl maintains its + * own record of the current directory which it keeps synchronized with + * the filesystem corresponding to the pathname of the current directory + * if the filesystem provides a cwdProc (the native filesystem does). * - * Note that if Tcl's cwd is not in the native filesystem, then of course - * Tcl's cwd and the native cwd are different: extensions should - * therefore ensure they only access the cwd through this function to - * avoid confusion. - * - * If a global cwdPathPtr already exists, it is cached in the thread's - * private data structures and reference to the cached copy is returned, - * subject to a synchronisation attempt in that cwdPathPtr's fs. - * - * Otherwise, the chain of functions that have been "inserted" into the - * filesystem will be called in succession until either a value other - * than NULL is returned, or the entire list is visited. + * If Tcl's current directory is not in the native filesystem, Tcl's + * current directory and the current directory of the process are + * different. To avoid confusion, extensions should call Tcl_FSGetCwd to + * obtain the current directory from Tcl rather than from the operating + * system. * * Results: - * The result is a pointer to a Tcl_Obj specifying the current directory, - * or NULL if the current directory could not be determined. If NULL is - * returned, an error message is left in the interp's result. + * Returns a pointer to a Tcl_Obj having a refCount of 1 and containing + * the current thread's local copy of the global cwdPathPtr value. * - * The result already has its refCount incremented for the caller. When - * it is no longer needed, that refCount should be decremented. + * Returns NULL if the current directory could not be determined, and + * leaves an error message in the interpreter's result. * * Side effects: * Various objects may be freed and allocated. @@ -2682,9 +2614,10 @@ Tcl_FSGetCwd( Tcl_Obj *retVal = NULL; /* - * We've never been called before, try to find a cwd. Call each of the - * "Tcl_GetCwd" function in succession. A non-NULL return value - * indicates the particular function has succeeded. + * This is the first time this routine has been called. Call + * 'getCwdProc' for each registered filsystems until one returns + * something other than NULL, which is a pointer to the pathname of the + * current directory. */ fsRecPtr = FsGetFirstFilesystem(); @@ -2709,7 +2642,7 @@ Tcl_FSGetCwd( Tcl_Obj *norm; /* - * Looks like a new current directory. + * Found the pathname of the current directory. */ retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd); @@ -2717,15 +2650,15 @@ Tcl_FSGetCwd( norm = TclFSNormalizeAbsolutePath(interp,retVal); if (norm != NULL) { /* - * We found a cwd, which is now in our global storage. We - * must make a copy. Norm already has a refCount of 1. + * Assign to global storage the pathname of the current directory + * and copy it into thread-local storage as well. * - * Threading issue: note that multiple threads at system - * startup could in principle call this function - * simultaneously. They will therefore each set the - * cwdPathPtr independently. That behaviour is a bit - * peculiar, but should be fine. Once we have a cwd, we'll - * always be in the 'else' branch below which is simpler. + * At system startup multiple threads could in principle + * call this function simultaneously, which is a little + * peculiar, but should be fine given the mutex locks in + * FSUPdateCWD. Once some value is assigned to the global + * variable the 'else' branch below is always taken, which + * is simpler. */ FsUpdateCwd(norm, retCd); @@ -2745,29 +2678,27 @@ Tcl_FSGetCwd( } Disclaim(); - /* - * Now the 'cwd' may NOT be normalized, at least on some platforms. - * For the sake of efficiency, we want a completely normalized cwd at - * all times. - * - * Finally, if retVal is NULL, we do not have a cwd, which could be - * problematic. - */ - if (retVal != NULL) { + /* + * On some platforms the pathname of the current directory might + * not be normalized. For efficiency, ensure that it is + * normalized. For the sake of efficiency, we want a completely + * normalized current working directory at all times. + */ + Tcl_Obj *norm = TclFSNormalizeAbsolutePath(interp, retVal); if (norm != NULL) { /* - * We found a cwd, which is now in our global storage. We must - * make a copy. Norm already has a refCount of 1. + * We found a current working directory, which is now in our + * global storage. We must make a copy. Norm already has a + * refCount of 1. * - * Threading issue: note that multiple threads at system - * startup could in principle call this function - * simultaneously. They will therefore each set the cwdPathPtr - * independently. That behaviour is a bit peculiar, but should - * be fine. Once we have a cwd, we'll always be in the 'else' - * branch below which is simpler. + * Threading issue: Multiple threads at system startup could in + * principle call this function simultaneously. They will + * therefore each set the cwdPathPtr independently, which is a + * bit peculiar, but should be fine. Once we have a cwd, we'll + * always be in the 'else' branch below which is simpler. */ ClientData cd = (ClientData) Tcl_FSGetNativePath(norm); @@ -2776,13 +2707,19 @@ Tcl_FSGetCwd( Tcl_DecrRefCount(norm); } Tcl_DecrRefCount(retVal); + } else { + /* + * retVal is NULL. There is no current directory, which could be + * problematic. + */ } } else { /* - * We already have a cwd cached, but we want to give the filesystem it - * is in a chance to check whether that cwd has changed, or is perhaps - * no longer accessible. This allows an error to be thrown if, say, - * the permissions on that directory have changed. + * There is a thread-local value for the pathname of the current + * directory. Give corresponding filesystem a chance update the value + * if it is out-of-date. This allows an error to be thrown if, for + * example, the permissions on the current working directory have + * changed. */ const Tcl_Filesystem *fsPtr = @@ -2790,16 +2727,11 @@ Tcl_FSGetCwd( ClientData retCd = NULL; Tcl_Obj *retVal, *norm; - /* - * If the filesystem couldn't be found, or if no cwd function exists - * for this filesystem, then we simply assume the cached cwd is ok. - * If we do call a cwd, we must watch for errors (if the cwd returns - * NULL). This ensures that, say, on Unix if the permissions of the - * cwd change, 'pwd' does actually throw the correct error in Tcl. - * (This is tested for in the test suite on unix). - */ - if (fsPtr == NULL || fsPtr->getCwdProc == NULL) { + /* + * There is no corresponding filesystem or the filesystem does not + * have a getCwd routine. Just assume current local value is ok. + */ goto cdDidNotChange; } @@ -2831,28 +2763,25 @@ Tcl_FSGetCwd( Tcl_IncrRefCount(retVal); } - /* - * Check if the 'cwd' function returned an error; if so, reset the - * cwd. - */ - if (retVal == NULL) { + /* + * The current directory could not not determined. Reset the + * current direcory to ensure, for example, that 'pwd' does actually + * throw the correct error in Tcl. This is tested for in the test + * suite on unix. + */ + FsUpdateCwd(NULL, NULL); goto cdDidNotChange; } - /* - * Normalize the path. - */ - norm = TclFSNormalizeAbsolutePath(interp, retVal); - /* - * Check whether cwd has changed from the value previously stored in - * cwdPathPtr. Really 'norm' shouldn't be NULL, but we are careful. - */ - if (norm == NULL) { + /* + * 'norm' shouldn't ever be NULL, but we are careful. + */ + /* Do nothing */ if (retCd != NULL) { fsPtr->freeInternalRepProc(retCd); @@ -2860,11 +2789,12 @@ Tcl_FSGetCwd( } else if (norm == tsdPtr->cwdPathPtr) { goto cdEqual; } else { - /* - * Note that both 'norm' and 'tsdPtr->cwdPathPtr' are normalized - * paths. Therefore we can be more efficient than calling - * 'Tcl_FSEqualPaths', and in addition avoid a nasty infinite loop - * bug when trying to normalize tsdPtr->cwdPathPtr. + /* + * Determine whether the filesystem's answer is the same as the + * cached local value. Since both 'norm' and 'tsdPtr->cwdPathPtr' + * are normalized pathnames, do something more efficient than + * calling 'Tcl_FSEqualPaths', and in addition avoid a nasty + * infinite loop bug when trying to normalize tsdPtr->cwdPathPtr. */ int len1, len2; @@ -2874,18 +2804,20 @@ Tcl_FSGetCwd( str2 = TclGetStringFromObj(norm, &len2); if ((len1 == len2) && (strcmp(str1, str2) == 0)) { /* - * If the paths were equal, we can be more efficient and - * retain the old path object which will probably already be - * shared. In this case we can simply free the normalized path - * we just calculated. + * The pathname values are equal so retain the old pathname + * object which is probably already shared and free the + * normalized pathname that was just produced. */ - cdEqual: Tcl_DecrRefCount(norm); if (retCd != NULL) { fsPtr->freeInternalRepProc(retCd); } } else { + /* + * The pathname of the current directory is not the same as + * this thread's local cached value. Replace the local value. + */ FsUpdateCwd(norm, retCd); Tcl_DecrRefCount(norm); } @@ -2906,17 +2838,19 @@ Tcl_FSGetCwd( * * Tcl_FSChdir -- * - * This function replaces the library version of chdir(). + * Replaces the library version of chdir(). * - * The path is normalized and then passed to the filesystem which claims - * it. + * Calls 'chdirProc' of the filesystem that corresponds to the given + * pathname. * * Results: - * See chdir() documentation. If successful, we keep a record of the - * successful path in cwdPathPtr for subsequent calls to getcwd. + * See chdir() documentation. * * Side effects: - * See chdir() documentation. The global cwdPathPtr may change value. + * See chdir() documentation. + * + * On success stores in cwdPathPtr the pathname of the new current + * directory. * *---------------------------------------------------------------------- */ @@ -2941,70 +2875,46 @@ Tcl_FSChdir( if (fsPtr != NULL) { if (fsPtr->chdirProc != NULL) { /* - * If this fails, an appropriate errno will have been stored using - * 'Tcl_SetErrno()'. + * If this fails Tcl_SetErrno() has already been called. */ retVal = fsPtr->chdirProc(pathPtr); } else { /* - * Fallback on stat-based implementation. + * Fallback to stat-based implementation. */ Tcl_StatBuf buf; - /* - * If the file can be stat'ed and is a directory and is readable, - * then we can chdir. If any of these actions fail, then - * 'Tcl_SetErrno()' should automatically have been called to set - * an appropriate error code. - */ - if ((Tcl_FSStat(pathPtr, &buf) == 0) && (S_ISDIR(buf.st_mode)) && (Tcl_FSAccess(pathPtr, R_OK) == 0)) { /* - * We allow the chdir. + * stat was successful, and the file is a directory and is + * readable. Can proceed to change the current directory. */ retVal = 0; + } else { + /* + * 'Tcl_SetErrno()' has already been called. + */ } } } else { Tcl_SetErrno(ENOENT); } - /* - * The cwd changed, or an error was thrown. If an error was thrown, we can - * just continue (and that will report the error to the user). If there - * was no error we must assume that the cwd was actually changed to the - * normalized value we calculated above, and we must therefore cache that - * information. - * - * If the filesystem in question has a getCwdProc, then the correct logic - * which performs the part below is already part of the Tcl_FSGetCwd() - * call, so no need to replicate it again. This will have a side effect - * though. The private authoritative representation of the current working - * directory stored in cwdPathPtr in static memory will be out-of-sync - * with the real OS-maintained value. The first call to Tcl_FSGetCwd will - * however recalculate the private copy to match the OS-value so - * everything will work right. - * - * However, if there is no getCwdProc, then we _must_ update our private - * storage of the cwd, since this is the only opportunity to do that! - * - * Note: We currently call this block of code irrespective of whether - * there was a getCwdProc or not, but the code should all in principle - * work if we only call this block if fsPtr->getCwdProc == NULL. - */ - if (retVal == 0) { + + /* Assume that the cwd was actually changed to the normalized value + * just calculated, and cache that information. */ + /* - * Note that this normalized path may be different to what we found - * above (or at least a different object), if the filesystem epoch - * changed recently. This can actually happen with scripted documents - * very easily. Therefore we ask for the normalized path again (the - * correct value will have been cached as a result of the - * Tcl_FSGetFileSystemForPath call above anyway). + * If the filesystem epoch changed recently, the normalized pathname or + * its internal handle may be different from what was found above. + * This can easily be the case with scripted documents . Therefore get + * the normalized pathname again. The correct value will have been + * cached as a result of the Tcl_FSGetFileSystemForPath call, above. */ Tcl_Obj *normDirName = Tcl_FSGetNormalizedPath(NULL, pathPtr); @@ -3016,45 +2926,60 @@ Tcl_FSChdir( } if (fsPtr == &tclNativeFilesystem) { - /* - * For the native filesystem, we keep a cache of the native - * representation of the cwd. But, we want to do that for the - * exact format that is returned by 'getcwd' (so that we can later - * compare the two representations for equality), which might not - * be exactly the same char-string as the native representation of - * the fully normalized path (e.g. on Windows there's a - * forward-slash vs backslash difference). Hence we ask for this - * again here. On Unix it might actually be true that we always - * have the correct form in the native rep in which case we could - * simply use: - * cd = Tcl_FSGetNativePath(pathPtr); - * instead. This should be examined by someone on Unix. - */ - ClientData cd; ClientData oldcd = tsdPtr->cwdClientData; /* - * Assumption we are using a filesystem version 2. + * Assume that the native filesystem has a getCwdProc and that it + * is at version 2. */ TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2 *) fsPtr->getCwdProc; cd = proc2(oldcd); if (cd != oldcd) { + /* + * Call getCwdProc() and store the resulting internal handle to + * compare things with it later. This might might not be + * exactly the same string as that of the fully normalized + * pathname. For example, for the Windows internal handle the + * separator is the backslash character. On Unix it might well + * be true that the internal handle is the fully normalized + * pathname and one could simply use: + * cd = Tcl_FSGetNativePath(pathPtr); + * but this can't be guaranteed in the general case. In fact, + * the internal handle could be any value the filesystem + * decides to use to identify a node. + */ + FsUpdateCwd(normDirName, cd); - } + } } else { + /* + * Tcl_FSGetCwd() synchronizes the file-global cwdPathPtr if + * needed. However, if there is no 'getCwdProc', cwdPathPtr must be + * updated right now because there won't be another chance. This + * block of code is currently executed whether or not the + * filesystem provides a getCwdProc, but it should in principle + * work to only call this block if fsPtr->getCwdProc == NULL. + */ + FsUpdateCwd(normDirName, NULL); } - /* - * If the filesystem changed between old and new cwd - * force filesystem refresh on path objects. - */ if (oldFsPtr != NULL && fsPtr != oldFsPtr) { + /* + * The filesystem of the current directory is not the same as the + * filesystem of the previous current directory. Invalidate All + * FsPath objects. + */ Tcl_FSMountsChanged(NULL); } + } else { + /* + * The current directory is now changed or an error occurred and an + * error message is now set. Just continue. + */ } return retVal; @@ -3065,25 +2990,17 @@ Tcl_FSChdir( * * Tcl_FSLoadFile -- * - * Dynamically loads a binary code file into memory and returns the - * addresses of two functions within that file, if they are defined. The - * appropriate function for the filesystem to which pathPtr belongs will - * be called. - * - * Note that the native filesystem doesn't actually assume 'pathPtr' is a - * path. Rather it assumes pathPtr is either a path or just the name - * (tail) of a file which can be found somewhere in the environment's - * loadable path. This behaviour is not very compatible with virtual - * filesystems (and has other problems documented in the load man-page), - * so it is advised that full paths are always used. + * Loads a dynamic shared object by passing the given pathname unmodified + * to Tcl_LoadFile, and provides pointers to the functions named by 'sym1' + * and 'sym2', and another pointer to a function that unloads the object. * * Results: - * A standard Tcl completion code. If an error occurs, an error message - * is left in the interp's result. + * A standard Tcl completion code. If an error occurs, sets the + * interpreter's result to an error message. * * Side effects: - * New code suddenly appears in memory. This may later be unloaded by - * passing the clientData to the unloadProc. + * A dynamic shared object is loaded into memory. This may later be + * unloaded by passing the handlePtr to *unloadProcPtr. * *---------------------------------------------------------------------- */ @@ -3091,38 +3008,29 @@ Tcl_FSChdir( int Tcl_FSLoadFile( Tcl_Interp *interp, /* Used for error reporting. */ - Tcl_Obj *pathPtr, /* Name of the file containing the desired - * code. */ + Tcl_Obj *pathPtr, /* Pathname of the file containing the dynamic shared object. + */ const char *sym1, const char *sym2, - /* Names of two functions to look up in the - * file's symbol table. */ + /* Names of two functions to find in the + * dynamic shared object. */ Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - Tcl_LoadHandle *handlePtr, /* Filled with token for dynamically loaded - * file which will be passed back to + /* Places to store pointers to the functions + * named by sym1 and sym2. */ + Tcl_LoadHandle *handlePtr, /* A place to store the token for the loaded + * object. Can be passed to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) - /* Filled with address of Tcl_FSUnloadFileProc - * function which should be used for this - * file. */ + /* A place to store a pointer to the function + * that unloads the object. */ { const char *symbols[3]; void *procPtrs[2]; int res; - /* - * Initialize the arrays. - */ - symbols[0] = sym1; symbols[1] = sym2; symbols[2] = NULL; - /* - * Perform the load. - */ - res = Tcl_LoadFile(interp, pathPtr, symbols, 0, procPtrs, handlePtr); if (res == TCL_OK) { *proc1Ptr = (Tcl_PackageInitProc *) procPtrs[0]; @@ -3139,49 +3047,40 @@ Tcl_FSLoadFile( * * Tcl_LoadFile -- * - * Dynamically loads a binary code file into memory and returns the - * addresses of a number of given functions within that file, if they are - * defined. The appropriate function for the filesystem to which pathPtr - * belongs will be called. + * Load a dynamic shared object by calling 'loadFileProc' of the + * filesystem corresponding to the given pathname, and then finds within + * the loaded object the functions named in symbols[]. * - * Note that the native filesystem doesn't actually assume 'pathPtr' is a - * path. Rather it assumes pathPtr is either a path or just the name - * (tail) of a file which can be found somewhere in the environment's - * loadable path. This behaviour is not very compatible with virtual - * filesystems (and has other problems documented in the load man-page), - * so it is advised that full paths are always used. + * The given pathname is passed unmodified to `loadFileProc`, which + * decides how to resolve it. On POSIX systems the native filesystem + * passes the given pathname to dlopen(), which resolves the filename + * according to its own set of rules. This behaviour is not very + * compatible with virtual filesystems, and has other problems as + * documented for [load], so it is recommended to use an absolute + * pathname. * * Results: - * A standard Tcl completion code. If an error occurs, an error message - * is left in the interp's result. + * A standard Tcl completion code. If an error occurs, sets the + * interpreter result to an error message. * * Side effects: - * New code suddenly appears in memory. This may later be unloaded by - * calling TclFS_UnloadFile. + * Memory is allocated for the new object. May be freed by calling + * TclFS_UnloadFile. * *---------------------------------------------------------------------- */ /* - * Workaround for issue with modern HPUX which do allow the unlink (no ETXTBSY - * error) yet somehow trash some internal data structures which prevents the - * second and further shared libraries from getting properly loaded. Only the - * first is ok. We try to get around the issue by not unlinking, i.e., - * emulating the behaviour of the older HPUX which denied removal. + * Modern HPUX allows the unlink (no ETXTBSY error) yet somehow trashes some + * internal data structures, preventing any additional dynamic shared objects + * from getting properly loaded. Only the first is ok. Work around the issue + * by not unlinking, i.e., emulating the behaviour of the older HPUX which + * denied removal. * * Doing the unlink is also an issue within docker containers, whose AUFS * bungles this as well, see * https://github.com/dotcloud/docker/issues/1911 * - * For these situations the change below makes the execution of the unlink - * semi-controllable at runtime. - * - * An AUFS filesystem (if it can be detected) will force avoidance of - * unlink. The env variable TCL_TEMPLOAD_NO_UNLINK allows detection of a - * users general request (unlink and not. - * - * By default the unlink is done (if not in AUFS). However if the variable is - * present and set to true (any integer > 0) then the unlink is skipped. */ static int @@ -3189,21 +3088,18 @@ skipUnlink( Tcl_Obj *shlibFile) { /* - * Order of testing: - * 1. On hpux we generally want to skip unlink in general + * Unlinking is not performed in the following cases: * - * Outside of hpux then: - * 2. For a general user request (TCL_TEMPLOAD_NO_UNLINK present, - * non-empty, => int) - * 3. For general AUFS environment (statfs, if available). + * 1. The operating system is HPUX. * - * Ad 2: This variable can disable/override the AUFS detection, i.e. for - * testing if a newer AUFS does not have the bug any more. + * 2. If the environment variable TCL_TEMPLOAD_NO_UNLINK is present and + * set to true (an integer > 0) + * + * 3. TCL_TEMPLOAD_NO_UNLINK is not true (an integer > 0) and AUFS filesystem can be detected (using statfs, if available). * - * Ad 3: This is conditionally compiled in. Condition currently must be - * set manually. This part needs proper tests in the configure(.in). */ + #ifdef hpux return 1; #else @@ -3214,6 +3110,9 @@ skipUnlink( } #ifdef TCL_TEMPLOAD_NO_UNLINK +/* At built time TCL_TEMPLOAD_NO_UNLINK can be set manually to control whether + * this automatic overriding of unlink is included. + */ #ifndef NO_FSTATFS { struct statfs fs; @@ -3222,9 +3121,12 @@ skipUnlink( * box is too old to have it directly in the headers. Define taken from * http://mooon.googlecode.com/svn/trunk/linux_include/linux/aufs_type.h * http://aufs.sourceforge.net/ - * Better reference will be gladly taken. + * Better reference will be gladly accepted. */ #ifndef AUFS_SUPER_MAGIC +/* AUFS_SUPER_MAGIC can disable/override the AUFS detection, i.e. for + * testing if a newer AUFS does not have the bug any more. +*/ #define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') #endif /* AUFS_SUPER_MAGIC */ if ((statfs(Tcl_GetString(shlibFile), &fs) == 0) @@ -3236,8 +3138,8 @@ skipUnlink( #endif /* ... TCL_TEMPLOAD_NO_UNLINK */ /* - * Fallback: !hpux, no EV override, no AUFS (detection, nor detected): - * Don't skip + * No HPUX, environment variable override, or AUFS detected. Perform + * unlink. */ return 0; #endif /* hpux */ @@ -3246,16 +3148,15 @@ skipUnlink( int Tcl_LoadFile( Tcl_Interp *interp, /* Used for error reporting. */ - Tcl_Obj *pathPtr, /* Name of the file containing the desired - * code. */ - const char *const symbols[],/* Names of functions to look up in the file's - * symbol table. */ + Tcl_Obj *pathPtr, /* Pathname of the file containing the dynamic + * shared object. */ + const char *const symbols[],/* A null-terminated array of names of + * functions to find in the loaded object. */ int flags, /* Flags */ - void *procVPtrs, /* Where to return the addresses corresponding - * to symbols[]. */ - Tcl_LoadHandle *handlePtr) /* Filled with token for shared library - * information which can be used in - * TclpFindSymbol. */ + void *procVPtrs, /* A place to store pointers to the functions + * named by symbols[]. */ + Tcl_LoadHandle *handlePtr) /* A place to hold a token for the loaded object. + * Can be used by TclpFindSymbol. */ { void **procPtrs = (void **) procVPtrs; const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -3293,10 +3194,11 @@ Tcl_LoadFile( } /* - * The filesystem doesn't support 'load', so we fall back on the following - * technique: - * - * First check if it is readable -- and exists! + * The filesystem doesn't support 'load'. Fall to the following: + */ + + /* + * Make sure the file is accessible. */ if (Tcl_FSAccess(pathPtr, R_OK) != 0) { @@ -3310,9 +3212,9 @@ Tcl_LoadFile( #ifdef TCL_LOAD_FROM_MEMORY /* - * The platform supports loading code from memory, so ask for a buffer of - * the appropriate size, read the file into it and load the code from the - * buffer: + * The platform supports loading a dynamic shared object from memory. + * Create a sufficiently large buffer, read the file into it, and then load + * the dynamic shared object from the buffer: */ { @@ -3328,7 +3230,7 @@ Tcl_LoadFile( size = (int) statBuf.st_size; /* - * Tcl_Read takes an int: check that file size isn't wide. + * Tcl_Read takes an int: Determine whether the file size is wide. */ if (size != (Tcl_WideInt) statBuf.st_size) { @@ -3359,8 +3261,7 @@ Tcl_LoadFile( #endif /* TCL_LOAD_FROM_MEMORY */ /* - * Get a temporary filename to use, first to copy the file into, and then - * to load. + * Get a temporary filename, first to copy the file into, and then to load. */ copyToPtr = TclpTempFileNameForLibrary(interp, pathPtr); @@ -3372,11 +3273,15 @@ Tcl_LoadFile( copyFsPtr = Tcl_FSGetFileSystemForPath(copyToPtr); if ((copyFsPtr == NULL) || (copyFsPtr == fsPtr)) { /* - * We already know we can't use Tcl_FSLoadFile from this filesystem, - * and we must avoid a possible infinite loop. Try to delete the file - * we probably created, and then exit. + * Tcl_FSLoadFile isn't available for the filesystem of the temporary + * file. In order to avoid a possible infinite loop, do not attempt to + * load further. */ + /* + * Try to delete the file we probably created and then exit. + */ + Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); if (interp) { @@ -3387,10 +3292,6 @@ Tcl_LoadFile( } if (TclCrossFilesystemCopy(interp, pathPtr, copyToPtr) != TCL_OK) { - /* - * Cross-platform copy failed. - */ - Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); return TCL_ERROR; @@ -3398,10 +3299,9 @@ Tcl_LoadFile( #ifndef _WIN32 /* - * Do we need to set appropriate permissions on the file? This may be - * required on some systems. On Unix we could loop over the file - * attributes, and set any that are called "-permissions" to 0700. However - * we just do this directly, like this: + * It might be necessary on some systems to set the appropriate permissions + * on the file. On Unix we could loop over the file attributes and set any + * that are called "-permissions" to 0700, but just do it directly instead: */ { @@ -3418,8 +3318,8 @@ Tcl_LoadFile( #endif /* - * We need to reset the result now, because the cross-filesystem copy may - * have stored the number of bytes in the result. + * The cross-filesystem copy may have stored the number of bytes in the + * result, so reset the result now. */ if (interp) { @@ -3429,18 +3329,14 @@ Tcl_LoadFile( retVal = Tcl_LoadFile(interp, copyToPtr, symbols, flags, procPtrs, &newLoadHandle); if (retVal != TCL_OK) { - /* - * The file didn't load successfully. - */ - Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); return retVal; } /* - * Try to delete the file immediately - this is possible in some OSes, and - * avoids any worries about leaving the copy laying around on exit. + * Try to delete the file immediately. Some operatings systems allow this, + * and it avoids leaving the copy laying around after exit. */ if (!skipUnlink(copyToPtr) && @@ -3448,10 +3344,9 @@ Tcl_LoadFile( Tcl_DecrRefCount(copyToPtr); /* - * We tell our caller about the real shared library which was loaded. - * Note that this does mean that the package list maintained by 'load' - * will store the original (vfs) path alongside the temporary load - * handle and unload proc ptr. + * Tell the caller all the details: The package list maintained by + * 'load' stores the original (vfs) pathname, the handle of object + * loaded from the temporary file, and the unloadProcPtr. */ *handlePtr = newLoadHandle; @@ -3462,47 +3357,41 @@ Tcl_LoadFile( } /* - * When we unload this file, we need to divert the unloading so we can - * unload and cleanup the temporary file correctly. + * Divert the unloading in order to unload and cleanup the temporary file. */ tvdlPtr = ckalloc(sizeof(FsDivertLoad)); /* - * Remember three pieces of information. This allows us to cleanup the - * diverted load completely, on platforms which allow proper unloading of - * code. + * Remember three pieces of information in order to clean up the diverted + * load completely on platforms which allow proper unloading of code. */ tvdlPtr->loadHandle = newLoadHandle; tvdlPtr->unloadProcPtr = newUnloadProcPtr; if (copyFsPtr != &tclNativeFilesystem) { - /* - * copyToPtr is already incremented for this reference. - */ - + /* refCount of copyToPtr is already incremented. */ tvdlPtr->divertedFile = copyToPtr; /* - * This is the filesystem we loaded it into. Since we have a reference - * to 'copyToPtr', we already have a refCount on this filesystem, so - * we don't need to worry about it disappearing on us. + * This is the filesystem for the temporary file the object was loaded + * from. A reference to copyToPtr is already stored in + * tvdlPtr->divertedFile, so need need to increment the refCount again. */ tvdlPtr->divertedFilesystem = copyFsPtr; tvdlPtr->divertedFileNativeRep = NULL; } else { /* - * We need the native rep. + * Grab the native representation. */ tvdlPtr->divertedFileNativeRep = TclNativeDupInternalRep( Tcl_FSGetInternalRep(copyToPtr, copyFsPtr)); /* - * We don't need or want references to the copied Tcl_Obj or the - * filesystem if it is the native one. + * Don't keeep a reference to the Tcl_Obj or the native filesystem. */ tvdlPtr->divertedFile = NULL; @@ -3525,8 +3414,8 @@ Tcl_LoadFile( resolveSymbols: /* - * At this point, *handlePtr is already set up to the handle for the - * loaded library. We now try to resolve the symbols. + * handlePtr now contains a token for the loaded object. + * Resolve the symbols. */ if (symbols != NULL) { @@ -3535,9 +3424,8 @@ Tcl_LoadFile( if (procPtrs[i] == NULL) { /* * At least one symbol in the list was not found. Unload the - * file, and report the problem back to the caller. - * (Tcl_FindSymbol should already have left an appropriate - * error message.) + * file and return an error code. Tcl_FindSymbol should have + * already left an appropriate error message. */ (*handlePtr)->unloadFileProcPtr(*handlePtr); @@ -3554,16 +3442,17 @@ Tcl_LoadFile( * * DivertFindSymbol -- * - * Find a symbol in a shared library loaded by copy-from-VFS. + * Find a symbol in a shared library loaded by making a copying a file + * from the virtual filesystem to a native filesystem. * *---------------------------------------------------------------------- */ static void * DivertFindSymbol( - Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_LoadHandle loadHandle, /* Handle to the diverted module */ - const char *symbol) /* Symbol to resolve */ + Tcl_Interp *interp, /* The relevant interpreter. */ + Tcl_LoadHandle loadHandle, /* A handle to the diverted module. */ + const char *symbol) /* The name of symbol to resolve. */ { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle->clientData; Tcl_LoadHandle originalHandle = tvdlPtr->loadHandle; @@ -3576,83 +3465,75 @@ DivertFindSymbol( * * DivertUnloadFile -- * - * Unloads a file that has been loaded by copying from VFS to the native - * filesystem. - * - * Parameters: - * loadHandle -- Handle of the file to unload + * Unloads an object that was loaded from a temporary file copied from the + * virtual filesystem the native filesystem. * *---------------------------------------------------------------------- */ static void DivertUnloadFile( - Tcl_LoadHandle loadHandle) + Tcl_LoadHandle loadHandle) /* A handle for the loaded object. */ { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle->clientData; Tcl_LoadHandle originalHandle; - /* - * This test should never trigger, since we give the client data in the - * function above. - */ - if (tvdlPtr == NULL) { + /* + * tvdlPtr was provided by Tcl_LoadFile so it should not be NULL here. + */ + return; } originalHandle = tvdlPtr->loadHandle; /* - * Call the real 'unloadfile' proc we actually used. It is very important - * that we call this first, so that the shared library is actually - * unloaded by the OS. Otherwise, the following 'delete' may well fail - * because the shared library is still in use. + * Call the real 'unloadfile' proc. This must be called first so that the + * shared library is actually unloaded by the OS. Otherwise, the following + * 'delete' may fail because the shared library is still in use. */ originalHandle->unloadFileProcPtr(originalHandle); /* - * What filesystem contains the temp copy of the library? + * Determine which filesystem contains the temporary copy of the file. */ if (tvdlPtr->divertedFilesystem == NULL) { /* - * It was the native filesystem, and we have a special function - * available just for this purpose, which we know works even at this - * late stage. + * Use the function for the native filsystem, which works works even at + * this late stage. */ TclpDeleteFile(tvdlPtr->divertedFileNativeRep); NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep); } else { /* - * Remove the temporary file we created. Note, we may crash here - * because encodings have been taken down already. + * Remove the temporary file. If encodings have been cleaned up + * already, this may crash. */ if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile) != TCL_OK) { /* - * The above may have failed because the filesystem, or something - * it depends upon (e.g. encodings) have been taken down because - * Tcl is exiting. + * This may have happened because Tcl is exiting, and encodings may + * have already been deleted or something else the filesystem + * depends on may be gone. * - * We may need to work out how to delete this file more robustly - * (or give the filesystem the information it needs to delete the - * file more robustly). - * - * In particular, one problem might be that the filesystem cannot - * extract the information it needs from the above path object + * TO DO: Figure out how to delete this file more robustly, or + * give the filesystem the information it needs to delete the file + * more robustly. One problem might be that the filesystem cannot + * extract the information it needs from the above pathname object * because Tcl's entire filesystem apparatus (the code in this - * file) has been finalized, and it refuses to pass the internal - * representation to the filesystem. + * file) has been finalized and there is no way to get the native + * handle of the file. */ } /* - * And free up the allocations. This will also of course remove a - * refCount from the Tcl_Filesystem to which this file belongs, which - * could then free up the filesystem if we are exiting. + * This also decrements the refCount of the Tcl_Filesystem + * corresponding to this file. which might cause the filesystem to be + * deallocated if Tcl is exiting. */ Tcl_DecrRefCount(tvdlPtr->divertedFile); @@ -3667,23 +3548,23 @@ DivertUnloadFile( * * Tcl_FindSymbol -- * - * Find a symbol in a loaded library + * Find a symbol in a loaded object. * - * Results: - * Returns a pointer to the symbol if found. If not found, returns NULL - * and leaves an error message in the interpreter result. + * Previously filesystem-specific, but has been made portable by having + * TclpDlopen return a structure that includes procedure pointers. * - * This function was once filesystem-specific, but has been made portable by - * having TclpDlopen return a structure that includes procedure pointers. + * Results: + * Returns a pointer to the symbol if found. Otherwise, sets + * an error message in the interpreter result and returns NULL. * *---------------------------------------------------------------------- */ void * Tcl_FindSymbol( - Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_LoadHandle loadHandle, /* Handle to the loaded library */ - const char *symbol) /* Name of the symbol to resolve */ + Tcl_Interp *interp, /* The relevant interpreter. */ + Tcl_LoadHandle loadHandle, /* A handle for the loaded object. */ + const char *symbol) /* The name name of the symbol to resolve. */ { return loadHandle->findSymbolProcPtr(interp, loadHandle, symbol); } @@ -3693,16 +3574,15 @@ Tcl_FindSymbol( * * Tcl_FSUnloadFile -- * - * Unloads a library given its handle. Checks first that the library - * supports unloading. + * Unloads a loaded object if unloading is supported for the object. * *---------------------------------------------------------------------- */ int Tcl_FSUnloadFile( - Tcl_Interp *interp, /* Tcl interpreter */ - Tcl_LoadHandle handle) /* Handle of the file to unload */ + Tcl_Interp *interp, /* The relevant interpreter. */ + Tcl_LoadHandle handle) /* A handle for the object to unload. */ { if (handle->unloadFileProcPtr == NULL) { if (interp != NULL) { @@ -3723,52 +3603,45 @@ Tcl_FSUnloadFile( * * TclFSUnloadTempFile -- * - * This function is called when we loaded a library of code via an - * intermediate temporary file. This function ensures the library is - * correctly unloaded and the temporary file is correctly deleted. + * Unloads an object loaded via temporary file from a virtual filesystem + * to a native filesystem. * * Results: * None. * * Side effects: - * The effects of the 'unload' function called, and of course the - * temporary file will be deleted. + * Frees resources for the loaded object and deletes the temporary file. * *---------------------------------------------------------------------- */ void TclFSUnloadTempFile( - Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to - * Tcl_FSLoadFile(). The loadHandle is a token - * that represents the loaded file. */ + Tcl_LoadHandle loadHandle) /* A handle for the object, as provided by a + * previous call to Tcl_FSLoadFile(). */ { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle; - /* - * This test should never trigger, since we give the client data in the - * function above. - */ - if (tvdlPtr == NULL) { + /* + * tvdlPtr was provided by Tcl_LoadFile so it should not be NULL here. + */ return; } - /* - * Call the real 'unloadfile' proc we actually used. It is very important - * that we call this first, so that the shared library is actually - * unloaded by the OS. Otherwise, the following 'delete' may well fail - * because the shared library is still in use. - */ - if (tvdlPtr->unloadProcPtr != NULL) { + /* + * 'unloadProcPtr' must be called first so that the shared library is + * actually unloaded by the OS. Otherwise, the following 'delete' may + * well fail because the shared library is still in use. + */ + tvdlPtr->unloadProcPtr(tvdlPtr->loadHandle); } if (tvdlPtr->divertedFilesystem == NULL) { /* - * It was the native filesystem, and we have a special function - * available just for this purpose, which we know works even at this + * Call the function for the native fileystem, which works even at this * late stage. */ @@ -3776,33 +3649,32 @@ TclFSUnloadTempFile( NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep); } else { /* - * Remove the temporary file we created. Note, we may crash here - * because encodings have been taken down already. + * Remove the temporary file that was created. If encodings have + * already been freed because the interpreter is exiting this may + * crash. */ if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile) != TCL_OK) { /* - * The above may have failed because the filesystem, or something - * it depends upon (e.g. encodings) have been taken down because - * Tcl is exiting. - * - * We may need to work out how to delete this file more robustly - * (or give the filesystem the information it needs to delete the - * file more robustly). + * This may have happened because Tcl is exiting and encodings may + * have already been deleted, or something else the filesystem + * depends on may be gone. * - * In particular, one problem might be that the filesystem cannot - * extract the information it needs from the above path object + * TO DO: Figure out how to delete this file more robustly, or + * give the filesystem the information it needs to delete the file + * more robustly. One problem might be that the filesystem cannot + * extract the information it needs from the above pathname object * because Tcl's entire filesystem apparatus (the code in this - * file) has been finalized, and it refuses to pass the internal - * representation to the filesystem. + * file) has been finalized and there is no way to get the native + * handle of the file. */ } /* - * And free up the allocations. This will also of course remove a - * refCount from the Tcl_Filesystem to which this file belongs, which - * could then free up the filesystem if we are exiting. + * This also decrements the refCount of the Tcl_Filesystem + * corresponding to this file. which might case filesystem to be freed + * if Tcl is exiting. */ Tcl_DecrRefCount(tvdlPtr->divertedFile); @@ -3816,38 +3688,41 @@ TclFSUnloadTempFile( * * Tcl_FSLink -- * - * This function replaces the library version of readlink() and can also - * be used to make links. The appropriate function for the filesystem to - * which pathPtr belongs will be called. + * Creates or inspects a link by calling 'linkProc' of the filesystem + * corresponding to the given pathname. Replaces the library version of + * readlink(). * * Results: - * If toPtr is NULL, then the result is a Tcl_Obj specifying the contents - * of the symbolic link given by 'pathPtr', or NULL if the symbolic link - * could not be read. The result is owned by the caller, which should - * call Tcl_DecrRefCount when the result is no longer needed. + * If toPtr is NULL, a Tcl_Obj containing the value the symbolic link for + * 'pathPtr', or NULL if a symbolic link was not accessible. The caller + * should Tcl_DecrRefCount on the result to release it. Otherwise NULL. * - * If toPtr is non-NULL, then the result is toPtr if the link action was - * successful, or NULL if not. In this case the result has no additional - * reference count, and need not be freed. The actual action to perform - * is given by the 'linkAction' flags, which is an or'd combination of: + * In this case the result has no additional reference count and need not + * be freed. The actual action to perform is given by the 'linkAction' + * flags, which is a combination of: * * TCL_CREATE_SYMBOLIC_LINK * TCL_CREATE_HARD_LINK * - * Note that most filesystems will not support linking across to - * different filesystems, so this function will usually fail unless toPtr - * is in the same FS as pathPtr. + * Most filesystems do not support linking across to different + * filesystems, so this function usually fails if the filesystem + * corresponding to toPtr is not the same as the filesystem corresponding + * to pathPtr. * * Side effects: - * See readlink() documentation. A new filesystem link object may appear. + * Creates or sets a link if toPtr is not NULL. + * + * See readlink(). * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSLink( - Tcl_Obj *pathPtr, /* Path of file to readlink or link. */ - Tcl_Obj *toPtr, /* NULL or path to be linked to. */ + Tcl_Obj *pathPtr, /* Pathaname of file. */ + Tcl_Obj *toPtr, /* + * NULL or the pathname of a file to link to. + */ int linkAction) /* Action to perform. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -3857,11 +3732,10 @@ Tcl_FSLink( } /* - * If S_IFLNK isn't defined it means that the machine doesn't support - * symbolic links, so the file can't possibly be a symbolic link. Generate - * an EINVAL error, which is what happens on machines that do support - * symbolic links when you invoke readlink on a file that isn't a symbolic - * link. + * If S_IFLNK isn't defined the machine doesn't support symbolic links, so + * the file can't possibly be a symbolic link. Generate an EINVAL error, + * which is what happens on machines that do support symbolic links when + * readlink is called for a file that isn't a symbolic link. */ #ifndef S_IFLNK @@ -3877,16 +3751,9 @@ Tcl_FSLink( * * Tcl_FSListVolumes -- * - * Lists the currently mounted volumes. The chain of functions that have - * been "inserted" into the filesystem will be called in succession; each - * may return a list of volumes, all of which are added to the result - * until all mounted file systems are listed. - * - * Notice that we assume the lists returned by each filesystem (if non - * NULL) have been given a refCount for us already. However, we are NOT - * allowed to hang on to the list itself (it belongs to the filesystem we - * called). Therefore we quite naturally add its contents to the result - * we are building, and then decrement the refCount. + * Lists the currently mounted volumes by calling `listVolumesProc` of + * each registered filesystem, and combining the results to form a list of + * volumes. * * Results: * The list of volumes, in an object which has refCount 0. @@ -3904,10 +3771,9 @@ Tcl_FSListVolumes(void) Tcl_Obj *resultPtr = Tcl_NewObj(); /* - * Call each of the "listVolumes" function in succession. A non-NULL - * return value indicates the particular function has succeeded. We call - * all the functions registered, since we want a list of all drives from - * all filesystems. + * Call each "listVolumes" function of each registered filesystem in + * succession. A non-NULL return value indicates the particular function + * has succeeded. */ fsRecPtr = FsGetFirstFilesystem(); @@ -3918,6 +3784,10 @@ Tcl_FSListVolumes(void) if (thisFsVolumes != NULL) { Tcl_ListObjAppendList(NULL, resultPtr, thisFsVolumes); + /* The refCount of each list returned by a `listVolumesProc` is + * already incremented. Do not hang onto the list, though. It + * belongs to the filesystem. Add its contents to * the result + * we are building, and then decrement the refCount. */ Tcl_DecrRefCount(thisFsVolumes); } } @@ -3933,22 +3803,21 @@ Tcl_FSListVolumes(void) * * FsListMounts -- * - * List all mounts within the given directory, which match the given - * pattern. + * Lists the mounts mathing the given pattern in the given directory. * * Results: - * The list of mounts, in a list object which has refCount 0, or NULL if - * we didn't even find any filesystems to try to list mounts. + * A list, having a refCount of 0, of the matching mounts, or NULL if no + * search was performed because no filesystem provided a search routine. * * Side effects: - * None + * None. * *--------------------------------------------------------------------------- */ static Tcl_Obj * FsListMounts( - Tcl_Obj *pathPtr, /* Contains path to directory to search. */ + Tcl_Obj *pathPtr, /* Pathname of directory to search. */ const char *pattern) /* Pattern to match against. */ { FilesystemRecord *fsRecPtr; @@ -3956,10 +3825,8 @@ FsListMounts( Tcl_Obj *resultPtr = NULL; /* - * Call each of the "matchInDirectory" functions in succession, with the - * specific type information 'mountsOnly'. A non-NULL return value - * indicates the particular function has succeeded. We call all the - * functions registered, since we want a list from each filesystems. + * Call the matchInDirectory function of each registered filesystem, + * passing it 'mountsOnly'. Results accumulate in resultPtr. */ fsRecPtr = FsGetFirstFilesystem(); @@ -3985,34 +3852,31 @@ FsListMounts( * * Tcl_FSSplitPath -- * - * This function takes the given Tcl_Obj, which should be a valid path, - * and returns a Tcl List object containing each segment of that path as - * an element. + * Splits a pathname into its components. * * Results: - * Returns list object with refCount of zero. If the passed in lenPtr is - * non-NULL, we use it to return the number of elements in the returned - * list. + * A list with refCount of zero. * * Side effects: - * None. + * If lenPtr is not null, sets it to the number of elements in the result. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSSplitPath( - Tcl_Obj *pathPtr, /* Path to split. */ - int *lenPtr) /* int to store number of path elements. */ + Tcl_Obj *pathPtr, /* The pathname to split. */ + int *lenPtr) /* A place to hold the number of pathname + * elements. */ { - Tcl_Obj *result = NULL; /* Needed only to prevent gcc warnings. */ + Tcl_Obj *result = NULL; /* Just to squelch gcc warnings. */ const Tcl_Filesystem *fsPtr; char separator = '/'; int driveNameLength; const char *p; /* - * Perform platform specific splitting. + * Perform platform-specific splitting. */ if (TclFSGetPathType(pathPtr, &fsPtr, @@ -4024,9 +3888,7 @@ Tcl_FSSplitPath( return TclpNativeSplitPath(pathPtr, lenPtr); } - /* - * We assume separators are single characters. - */ + /* Assume each separator is a single character. */ if (fsPtr->filesystemSeparatorProc != NULL) { Tcl_Obj *sep = fsPtr->filesystemSeparatorProc(pathPtr); @@ -4039,9 +3901,9 @@ Tcl_FSSplitPath( } /* - * Place the drive name as first element of the result list. The drive - * name may contain strange characters, like colons and multiple forward - * slashes (for example 'ftp://' is a valid vfs drive name) + * Add the drive name as first element of the result. The drive name may + * contain strange characters like colons and sequences of forward slashes + * For example, 'ftp://' is a valid drive name. */ result = Tcl_NewObj(); @@ -4051,7 +3913,7 @@ Tcl_FSSplitPath( p += driveNameLength; /* - * Add the remaining path elements to the list. + * Add the remaining pathname elements to the list. */ for (;;) { @@ -4078,10 +3940,6 @@ Tcl_FSSplitPath( } } - /* - * Compute the number of elements in the result. - */ - if (lenPtr != NULL) { TclListObjLength(NULL, result, lenPtr); } @@ -4092,35 +3950,31 @@ Tcl_FSSplitPath( * * TclGetPathType -- * - * Helper function used by FSGetPathType. + * Helper function used by TclFSGetPathType and TclJoinPath. * * Results: - * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or - * TCL_PATH_VOLUME_RELATIVE. The filesystem reference will be set if and - * only if it is non-NULL and the function's return value is - * TCL_PATH_ABSOLUTE. + * One of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or + * TCL_PATH_VOLUME_RELATIVE. * * Side effects: - * None. + * See **filesystemPtrptr, *driveNameLengthPtr and **driveNameRef, * *---------------------------------------------------------------------- */ Tcl_PathType TclGetPathType( - Tcl_Obj *pathPtr, /* Path to determine type for. */ + Tcl_Obj *pathPtr, /* Pathname to determine type of. */ const Tcl_Filesystem **filesystemPtrPtr, - /* If absolute path and this is not NULL, then - * set to the filesystem which claims this - * path. */ - int *driveNameLengthPtr, /* If the path is absolute, and this is - * non-NULL, then set to the length of the - * driveName. */ - Tcl_Obj **driveNameRef) /* If the path is absolute, and this is - * non-NULL, then set to the name of the - * drive, network-volume which contains the - * path, already with a refCount for the - * caller. */ + /* If not NULL, a place in which to store a + * pointer to the filesystem for this pathname + * if it is absolute. */ + int *driveNameLengthPtr, /* If not NULL, a place in which to store the + * length of the volume name. */ + Tcl_Obj **driveNameRef) /* If not NULL, for an absolute pathname, a + * place to store a pointer to an object with a + * refCount of 1, and whose value is the name + * of the volume. */ { int pathLen; const char *path = TclGetStringFromObj(pathPtr, &pathLen); @@ -4144,14 +3998,14 @@ TclGetPathType( * * TclFSNonnativePathType -- * - * Helper function used by TclGetPathType. Its purpose is to check - * whether the given path starts with a string which corresponds to a - * file volume in any registered filesystem except the native one. For - * speed and historical reasons the native filesystem has special - * hard-coded checks dotted here and there in the filesystem code. + * Helper function used by TclGetPathType. Checks whether the given + * pathname starts with a string which corresponds to a file volume in + * some registered filesystem other than the native one. For speed and + * historical reasons the native filesystem has special hard-coded checks + * dotted here and there in the filesystem code. * * Results: - * Returns one of TCL_PATH_ABSOLUTE or TCL_PATH_RELATIVE. The filesystem + * One of TCL_PATH_ABSOLUTE or TCL_PATH_RELATIVE. The filesystem * reference will be set if and only if it is non-NULL and the function's * return value is TCL_PATH_ABSOLUTE. * @@ -4163,49 +4017,45 @@ TclGetPathType( Tcl_PathType TclFSNonnativePathType( - const char *path, /* Path to determine type for. */ - int pathLen, /* Length of the path. */ + const char *path, /* Pathname to determine the type of. */ + int pathLen, /* Length of the pathname. */ const Tcl_Filesystem **filesystemPtrPtr, - /* If absolute path and this is not NULL, then - * set to the filesystem which claims this - * path. */ - int *driveNameLengthPtr, /* If the path is absolute, and this is - * non-NULL, then set to the length of the - * driveName. */ - Tcl_Obj **driveNameRef) /* If the path is absolute, and this is - * non-NULL, then set to the name of the - * drive, network-volume which contains the - * path, already with a refCount for the - * caller. */ + /* If not NULL, a place to store a pointer to + * the filesystem for this pathname when it is + * an absolute pathname. */ + int *driveNameLengthPtr, /* If not NULL, a place to store the length of + * the volume name if the pathname is absolute. + */ + Tcl_Obj **driveNameRef) /* If not NULL, a place to store a pointer to + * an object having its its refCount already + * incremented, and contining the name of the + * volume if the pathname is absolute. */ { FilesystemRecord *fsRecPtr; Tcl_PathType type = TCL_PATH_RELATIVE; /* - * Call each of the "listVolumes" function in succession, checking whether - * the given path is an absolute path on any of the volumes returned (this - * is done by checking whether the path's prefix matches). + * Determine whether the given pathname is an absolute pathname on some + * filesystem other than the native filesystem. */ fsRecPtr = FsGetFirstFilesystem(); Claim(); while (fsRecPtr != NULL) { /* - * We want to skip the native filesystem in this loop because - * otherwise we won't necessarily pass all the Tcl testsuite - this is - * because some of the tests artificially change the current platform - * (between win, unix) but the list of volumes we get by calling - * fsRecPtr->fsPtr->listVolumesProc will reflect the current (real) - * platform only and this may cause some tests to fail. In particular, - * on Unix '/' will match the beginning of certain absolute Windows - * paths starting '//' and those tests will go wrong. + * Skip the the native filesystem because otherwise some of the tests + * in the Tcl testsuite might fail because some of the tests + * artificially change the current platform (between win, unix) but the + * list of volumes obtained by calling fsRecPtr->fsPtr->listVolumesProc + * reflects the current (real) platform only. In particular, on Unix + * '/' matchs the beginning of certain absolute Windows pathnames + * starting '//' and those tests go wrong. * - * Besides these test-suite issues, there is one other reason to skip - * the native filesystem - since the tclFilename.c code has nice fast - * 'absolute path' checkers, we don't want to waste time repeating - * that effort here, and this function is actually called quite often, - * so if we can save the overhead of the native filesystem returning - * us a list of volumes all the time, it is better. + * There is another reason to skip the native filesystem: Since the + * tclFilename.c code has nice fast 'absolute path' checkers, there is + * no reason to waste time doing that in this frequently-called + * function. It is better to save the overhead of the native + * filesystem continuously returning a list of volumes. */ if ((fsRecPtr->fsPtr != &tclNativeFilesystem) @@ -4218,12 +4068,11 @@ TclFSNonnativePathType( != TCL_OK) { /* * This is VERY bad; the listVolumesProc didn't return a - * valid list. Set numVolumes to -1 so that we skip the - * while loop below and just return with the current value - * of 'type'. + * valid list. Set numVolumes to -1 to skip the loop below + * and just return with the current value of 'type'. * - * It would be better if we could signal an error here - * (but Tcl_Panic seems a bit excessive). + * It would be better to signal an error here, but + * Tcl_Panic seems a bit excessive. */ numVolumes = -1; @@ -4257,7 +4106,7 @@ TclFSNonnativePathType( Tcl_DecrRefCount(thisFsVolumes); if (type == TCL_PATH_ABSOLUTE) { /* - * We don't need to examine any more filesystems. + * No need to to examine additional filesystems. */ break; @@ -4275,12 +4124,13 @@ TclFSNonnativePathType( * * Tcl_FSRenameFile -- * - * If the two paths given belong to the same filesystem, we call that - * filesystems rename function. Otherwise we simply return the POSIX - * error 'EXDEV', and -1. + * If the two pathnames correspond to the same filesystem, call + * 'renameFileProc' of that filesystem. Otherwise return the POSIX error + * 'EXDEV', and -1. * * Results: - * Standard Tcl error code if a function was called. + * A standard Tcl error code if a rename function was called, or -1 + * otherwise. * * Side effects: * A file may be renamed. @@ -4290,10 +4140,9 @@ TclFSNonnativePathType( int Tcl_FSRenameFile( - Tcl_Obj *srcPathPtr, /* Pathname of file or dir to be renamed - * (UTF-8). */ - Tcl_Obj *destPathPtr) /* New pathname of file or directory - * (UTF-8). */ + Tcl_Obj *srcPathPtr, /* The pathname of a file or directory to be + renamed. */ + Tcl_Obj *destPathPtr) /* The new pathname for the file. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; @@ -4316,27 +4165,27 @@ Tcl_FSRenameFile( * * Tcl_FSCopyFile -- * - * If the two paths given belong to the same filesystem, we call that - * filesystem's copy function. Otherwise we simply return the POSIX error - * 'EXDEV', and -1. + * If both pathnames correspond to the same filesystem, calls + * 'copyFileProc' of that filesystem. * - * Note that in the native filesystems, 'copyFileProc' is defined to copy - * soft links (i.e. it copies the links themselves, not the things they - * point to). + * In the native filesystems, 'copyFileProc' copies a link itself, not the + * thing the link points to. * * Results: - * Standard Tcl error code if a function was called. + * A standard Tcl return code if a copyFileProc was called, or -1 + * otherwise. * * Side effects: - * A file may be copied. + * A file might be copied. The POSIX error 'EXDEV' is set if a copy + * function was not called. * *--------------------------------------------------------------------------- */ int Tcl_FSCopyFile( - Tcl_Obj *srcPathPtr, /* Pathname of file to be copied (UTF-8). */ - Tcl_Obj *destPathPtr) /* Pathname of file to copy to (UTF-8). */ + Tcl_Obj *srcPathPtr, /* The pathname of file to be copied. */ + Tcl_Obj *destPathPtr) /* The new pathname to copy the file to. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; @@ -4358,15 +4207,14 @@ Tcl_FSCopyFile( * * TclCrossFilesystemCopy -- * - * Helper for above function, and for Tcl_FSLoadFile, to copy files from - * one filesystem to another. This function will overwrite the target - * file if it already exists. + * Helper for Tcl_FSCopyFile and Tcl_FSLoadFile. Copies a file from one + * filesystem to another, overwiting any file that already exists. * * Results: - * Standard Tcl error code. + * A standard Tcl return code. * * Side effects: - * A file may be created. + * A file may be copied. * *--------------------------------------------------------------------------- */ @@ -4374,8 +4222,8 @@ Tcl_FSCopyFile( int TclCrossFilesystemCopy( Tcl_Interp *interp, /* For error messages. */ - Tcl_Obj *source, /* Pathname of file to be copied (UTF-8). */ - Tcl_Obj *target) /* Pathname of file to copy to (UTF-8). */ + Tcl_Obj *source, /* Pathname of file to be copied. */ + Tcl_Obj *target) /* Pathname to copy the file to. */ { int result = TCL_ERROR; int prot = 0666; @@ -4386,7 +4234,7 @@ TclCrossFilesystemCopy( out = Tcl_FSOpenFileChannel(interp, target, "wb", prot); if (out == NULL) { /* - * It looks like we cannot copy it over. Bail out... + * Failed to open an output channel. Bail out. */ goto done; } @@ -4394,7 +4242,7 @@ TclCrossFilesystemCopy( in = Tcl_FSOpenFileChannel(interp, source, "rb", prot); if (in == NULL) { /* - * This is very strange, caller should have checked this... + * Could not open an input channel. Why didn't the caller check this? */ Tcl_Close(interp, out); @@ -4402,8 +4250,8 @@ TclCrossFilesystemCopy( } /* - * Copy it synchronously. We might wish to add an asynchronous option to - * support vfs's which are slow (e.g. network sockets). + * Copy the file synchronously. TO DO: Maybe add an asynchronous option + * to support virtual filesystems that are slow (e.g. network sockets). */ if (TclCopyChannel(interp, in, out, -1, NULL) == TCL_OK) { @@ -4411,7 +4259,7 @@ TclCrossFilesystemCopy( } /* - * If the copy failed, assume that copy channel left a good error message. + * If the copy failed, assume that copy channel left an error message. */ Tcl_Close(interp, in); @@ -4436,11 +4284,11 @@ TclCrossFilesystemCopy( * * Tcl_FSDeleteFile -- * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. + * Calls 'deleteFileProc' of the filesystem corresponding to the given + * pathname. * * Results: - * Standard Tcl error code. + * A standard Tcl return code. * * Side effects: * A file may be deleted. @@ -4466,14 +4314,15 @@ Tcl_FSDeleteFile( * * Tcl_FSCreateDirectory -- * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. + * Calls 'createDirectoryProc' of the filesystem corresponding to the + * given pathname. * * Results: - * Standard Tcl error code. + * A standard Tcl return code, or -1 if no createDirectoryProc is found. * * Side effects: - * A directory may be created. + * A directory may be created. POSIX error 'ENOENT' is set if no + * createDirectoryProc is found. * *--------------------------------------------------------------------------- */ @@ -4496,27 +4345,30 @@ Tcl_FSCreateDirectory( * * Tcl_FSCopyDirectory -- * - * If the two paths given belong to the same filesystem, we call that - * filesystems copy-directory function. Otherwise we simply return the - * POSIX error 'EXDEV', and -1. + * If both pathnames correspond to the the same filesystem, calls + * 'copyDirectoryProc' of that filesystem. * * Results: - * Standard Tcl error code if a function was called. + * A standard Tcl return code, or -1 if no 'copyDirectoryProc' is found. * * Side effects: - * A directory may be copied. + * A directory may be copied. POSIX error 'EXDEV' is set if no + * copyDirectoryProc is found. * *--------------------------------------------------------------------------- */ int Tcl_FSCopyDirectory( - Tcl_Obj *srcPathPtr, /* Pathname of directory to be copied - * (UTF-8). */ - Tcl_Obj *destPathPtr, /* Pathname of target directory (UTF-8). */ - Tcl_Obj **errorPtr) /* If non-NULL, then will be set to a new - * object containing name of file causing - * error, with refCount 1. */ + Tcl_Obj *srcPathPtr, /* + * The pathname of the directory to be copied. + */ + Tcl_Obj *destPathPtr, /* The pathname of the target directory. */ + Tcl_Obj **errorPtr) /* If not NULL, and there is an error, a place + * to store a pointer to a new object, with + * its refCount already incremented, and + * containing the pathname name of file + * causing the error. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; @@ -4538,28 +4390,31 @@ Tcl_FSCopyDirectory( * * Tcl_FSRemoveDirectory -- * - * The appropriate function for the filesystem to which pathPtr belongs - * will be called. + * Calls 'removeDirectoryProc' of the filesystem corresponding to remove + * pathPtr. * * Results: - * Standard Tcl error code. + * A standard Tcl return code, or -1 if no removeDirectoryProc is found. * * Side effects: - * A directory may be deleted. + * A directory may be removed. POSIX error 'ENOENT' is set if no + * removeDirectoryProc is found. * *--------------------------------------------------------------------------- */ int Tcl_FSRemoveDirectory( - Tcl_Obj *pathPtr, /* Pathname of directory to be removed - * (UTF-8). */ - int recursive, /* If non-zero, removes directories that are - * nonempty. Otherwise, will only remove empty - * directories. */ - Tcl_Obj **errorPtr) /* If non-NULL, then will be set to a new - * object containing name of file causing - * error, with refCount 1. */ + Tcl_Obj *pathPtr, /* The pathname of the directory to be removed. + */ + int recursive, /* If zero, removes only an empty directory. + * Otherwise, removes the directory and all its + * contents. */ + Tcl_Obj **errorPtr) /* If not NULL and an error occurs, stores a + * place to store a a pointer to a new + * object having a refCount of 1 and containing + * the name of the file that produced an error. + * */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); @@ -4568,14 +4423,8 @@ Tcl_FSRemoveDirectory( return -1; } - /* - * When working recursively, we check whether the cwd lies inside this - * directory and move it if it does. - */ - if (recursive) { Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL); - if (cwdPtr != NULL) { const char *cwdStr, *normPathStr; int cwdLen, normLen; @@ -4587,8 +4436,8 @@ Tcl_FSRemoveDirectory( if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr, (size_t) normLen) == 0)) { /* - * The cwd is inside the directory, so we perform a 'cd - * [file dirname $path]'. + * The cwd is inside the directory to be removed. Change + * the cwd to [file dirname $path]. */ Tcl_Obj *dirPtr = TclPathPart(NULL, pathPtr, @@ -4609,16 +4458,14 @@ Tcl_FSRemoveDirectory( * * Tcl_FSGetFileSystemForPath -- * - * This function determines which filesystem to use for a particular path - * object, and returns the filesystem which accepts this file. If no - * filesystem will accept this object as a valid file path, then NULL is - * returned. + * Produces the filesystem that corresponds to the given pathname. * * Results: - * NULL or a filesystem which will accept this path. + * The corresponding Tcl_Filesystem, or NULL if the pathname is invalid. * * Side effects: - * The object may be converted to a path type. + * The internal representation of fsPtrPtr is converted to fsPathType if + * needed, and that internal representation is updated as needed. * *--------------------------------------------------------------------------- */ @@ -4635,41 +4482,38 @@ Tcl_FSGetFileSystemForPath( return NULL; } - /* - * If the object has a refCount of zero, we reject it. This is to avoid - * possible segfaults or nondeterministic memory leaks (i.e. the user - * doesn't know if they should decrement the ref count on return or not). - */ - if (pathPtr->refCount == 0) { + /* + * Avoid possible segfaults or nondeterministic memory leaks where the + * reference count has been incorreclty managed. + */ Tcl_Panic("Tcl_FSGetFileSystemForPath called with object with refCount == 0"); return NULL; } - /* - * Check if the filesystem has changed in some way since this object's - * internal representation was calculated. Before doing that, assure we - * have the most up-to-date copy of the master filesystem. This is - * accomplished by the FsGetFirstFilesystem() call. - */ - + /* Start with an up-to-date copy of the master filesystem. */ fsRecPtr = FsGetFirstFilesystem(); Claim(); + /* + * Ensure that pathPtr is a valid pathname. + */ if (TclFSEnsureEpochOk(pathPtr, &retVal) != TCL_OK) { + /* not a valid pathname */ Disclaim(); return NULL; } else if (retVal != NULL) { - /* TODO: Can this happen? */ + /* + * Found the filesystem in the internal representation of pathPtr. + */ Disclaim(); return retVal; } /* - * Call each of the "pathInFilesystem" functions in succession. A - * non-return value of -1 indicates the particular function has succeeded. - */ - + * Call each of the "pathInFilesystem" functions in succession until the + * corresponding filesystem is found. + */ for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) { ClientData clientData = NULL; @@ -4678,10 +4522,10 @@ Tcl_FSGetFileSystemForPath( } if (fsRecPtr->fsPtr->pathInFilesystemProc(pathPtr, &clientData)!=-1) { - /* - * We assume the type of pathPtr hasn't been changed by the above - * call to the pathInFilesystemProc. - */ + /* This is the filesystem for pathPtr. Assume the type of pathPtr + * hasn't been changed by the above call to the + * pathInFilesystemProc, and cache this result in the internal + * representation of pathPtr. */ TclFSSetPathDetails(pathPtr, fsRecPtr->fsPtr, clientData); Disclaim(); @@ -4698,26 +4542,7 @@ Tcl_FSGetFileSystemForPath( * * Tcl_FSGetNativePath -- * - * This function is for use by the Win/Unix native filesystems, so that - * they can easily retrieve the native (char* or WCHAR*) representation - * of a path. Other filesystems will probably want to implement similar - * functions. They basically act as a safety net around - * Tcl_FSGetInternalRep. Normally your file-system functions will always - * be called with path objects already converted to the correct - * filesystem, but if for some reason they are called directly (i.e. by - * functions not in this file), then one cannot necessarily guarantee - * that the path object pointer is from the correct filesystem. - * - * Note: in the future it might be desirable to have separate versions - * of this function with different signatures, for example - * Tcl_FSGetNativeWinPath, Tcl_FSGetNativeUnixPath etc. Right now, since - * native paths are all string based, we use just one function. - * - * Results: - * NULL or a valid native path. - * - * Side effects: - * See Tcl_FSGetInternalRep. + * See Tcl_FSGetInternalRep. * *--------------------------------------------------------------------------- */ @@ -4734,7 +4559,7 @@ Tcl_FSGetNativePath( * * NativeFreeInternalRep -- * - * Free a native internal representation, which will be non-NULL. + * Free a native internal representation. * * Results: * None. @@ -4756,16 +4581,17 @@ NativeFreeInternalRep( *--------------------------------------------------------------------------- * * Tcl_FSFileSystemInfo -- + * Produce the type of a pathname and the type of its filesystem. * - * This function returns a list of two elements. The first element is the - * name of the filesystem (e.g. "native" or "vfs"), and the second is the - * particular type of the given path within that filesystem. * * Results: - * A list of two elements. + * A list where the first item is the name of the filesystem (e.g. + * "native" or "vfs"), and the second item is the type of the given + * pathname within that filesystem. * * Side effects: - * The object may be converted to a path type. + * The internal representation of pathPtr may be converted to a + * fsPathType. * *--------------------------------------------------------------------------- */ @@ -4801,16 +4627,13 @@ Tcl_FSFileSystemInfo( * * Tcl_FSPathSeparator -- * - * This function returns the separator to be used for a given path. The - * object returned should have a refCount of zero + * Produces the separator for given pathname. * * Results: - * A Tcl object, with a refCount of zero. If the caller needs to retain a - * reference to the object, it should call Tcl_IncrRefCount, and should - * otherwise free the object. + * A Tcl object having a refCount of zero. * * Side effects: - * The path object may be converted to a path type. + * The internal representation of pathPtr may be converted to a fsPathType * *--------------------------------------------------------------------------- */ @@ -4831,8 +4654,8 @@ Tcl_FSPathSeparator( } /* - * Allow filesystems not to provide a filesystemSeparatorProc if they wish - * to use the standard forward slash. + * Use the standard forward slash character if filesystem does not to + * provide a filesystemSeparatorProc. */ TclNewLiteralStringObj(resultObj, "/"); @@ -4844,11 +4667,11 @@ Tcl_FSPathSeparator( * * NativeFilesystemSeparator -- * - * This function is part of the native filesystem support, and returns - * the separator for the given path. + * This function, part of the native filesystem support, returns the + * separator for the given pathname. * * Results: - * String object containing the separator character. + * The separator character. * * Side effects: * None. 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 e488edd..82038df 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -3604,7 +3604,7 @@ GetBignumFromObj( return TCL_OK; } if (objPtr->typePtr == &tclIntType) { - TclBNInitBignumFromWideInt(bignumValue, + mp_init_ll(bignumValue, objPtr->internalRep.wideValue); return TCL_OK; } diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c index f7f1c8f..660db03 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 FsPath { - 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 FsPath { * 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. * *--------------------------------------------------------------------------- */ @@ -710,9 +694,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. */ @@ -871,7 +854,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) @@ -1508,7 +1491,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 @@ -1571,16 +1554,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. * *--------------------------------------------------------------------------- */ @@ -1598,7 +1583,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 @@ -1625,14 +1615,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) { @@ -2064,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. * *--------------------------------------------------------------------------- */ @@ -2090,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); @@ -2108,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 +2180,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 +2269,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 8f2c892..50a3fe3 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_u64(&big, (Tcl_WideUInt)wideValue); + Tcl_SetBignumObj(objPtr, &big); + } } else { TclSetIntObj(objPtr, wideValue); } @@ -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_u64(&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 5477868..d46c852 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -711,7 +711,7 @@ TclParseNumber( || (octalSignificandWide > ((Tcl_WideUInt)-1 >> shift)))) { octalSignificandOverflow = 1; - TclBNInitBignumFromWideUInt(&octalSignificandBig, + mp_init_ull(&octalSignificandBig, octalSignificandWide); } } @@ -828,7 +828,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, + mp_init_ull(&significandBig, significandWide); } } @@ -869,7 +869,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, + mp_init_ull(&significandBig, significandWide); } } @@ -1214,7 +1214,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_ull(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { @@ -1235,7 +1235,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_ull(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { @@ -1256,7 +1256,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || octalSignificandWide > (MOST_BITS + signum) >> shift)) { octalSignificandOverflow = 1; - TclBNInitBignumFromWideUInt(&octalSignificandBig, + mp_init_ull(&octalSignificandBig, octalSignificandWide); } if (shift) { @@ -1269,7 +1269,7 @@ TclParseNumber( } if (!octalSignificandOverflow) { if (octalSignificandWide > (MOST_BITS + signum)) { - TclBNInitBignumFromWideUInt(&octalSignificandBig, + mp_init_ull(&octalSignificandBig, octalSignificandWide); octalSignificandOverflow = 1; } else { @@ -1297,12 +1297,12 @@ TclParseNumber( &significandWide, &significandBig, significandOverflow); if (!significandOverflow && (significandWide > MOST_BITS+signum)){ significandOverflow = 1; - TclBNInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_ull(&significandBig, significandWide); } returnInteger: if (!significandOverflow) { if (significandWide > MOST_BITS+signum) { - TclBNInitBignumFromWideUInt(&significandBig, + mp_init_ull(&significandBig, significandWide); significandOverflow = 1; } else { @@ -1457,7 +1457,7 @@ AccumulateDecimalDigit( * bignum and fall through into the bignum case. */ - TclBNInitBignumFromWideUInt(bignumRepPtr, w); + mp_init_ull(bignumRepPtr, w); } else { /* * Wide multiplication. @@ -1600,7 +1600,7 @@ MakeLowPrecisionDouble( * call MakeHighPrecisionDouble to do it the hard way. */ - TclBNInitBignumFromWideUInt(&significandBig, significand); + mp_init_ull(&significandBig, significand); retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs, exponent); mp_clear(&significandBig); @@ -3267,7 +3267,7 @@ ShorteningBignumConversionPowD( * mminus = 5**m5 */ - TclBNInitBignumFromWideUInt(&b, bw); + mp_init_ull(&b, bw); mp_init_set(&mminus, 1); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); @@ -3451,7 +3451,7 @@ StrictBignumConversionPowD( * b = bw * 2**b2 * 5**b5 */ - TclBNInitBignumFromWideUInt(&b, bw); + mp_init_ull(&b, bw); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); @@ -3651,7 +3651,7 @@ ShorteningBignumConversion( * S = 2**s2 * 5*s5 */ - TclBNInitBignumFromWideUInt(&b, bw); + mp_init_ull(&b, bw); mp_mul_2d(&b, b2, &b); mp_init_set(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); @@ -3860,7 +3860,7 @@ StrictBignumConversion( */ mp_init_multi(&dig, NULL); - TclBNInitBignumFromWideUInt(&b, bw); + mp_init_ull(&b, bw); mp_mul_2d(&b, b2, &b); mp_init_set(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); @@ -4503,7 +4503,7 @@ Tcl_InitBignumFromDouble( Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits); int shift = expt - mantBits; - TclBNInitBignumFromWideInt(b, w); + mp_init_ll(b, w); if (shift < 0) { mp_div_2d(b, -shift, b, NULL); } else if (shift > 0) { diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 405f92b..0ae187a 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -58,7 +58,6 @@ #undef TclWinSetSockOpt #undef TclWinNToHS #undef TclStaticPackage -#undef TclBNInitBignumFromLong #undef Tcl_BackgroundError #define TclStaticPackage Tcl_StaticPackage #undef Tcl_UniCharToUtfDString @@ -86,6 +85,9 @@ #define TclBN_mp_init_copy mp_init_copy #define TclBN_mp_init_multi mp_init_multi #define TclBN_mp_init_size mp_init_size +#define TclBN_mp_init_l mp_init_l +#define TclBN_mp_init_i64 mp_init_i64 +#define TclBN_mp_init_u64 mp_init_u64 #define TclBN_mp_init_ul mp_init_ul #define TclBN_mp_lshd mp_lshd #define TclBN_mp_mod mp_mod @@ -96,18 +98,21 @@ #define TclBN_mp_neg mp_neg #define TclBN_mp_or mp_or #define TclBN_mp_radix_size mp_radix_size +#define TclBN_mp_reverse mp_reverse #define TclBN_mp_read_radix mp_read_radix #define TclBN_mp_rshd mp_rshd +#define TclBN_mp_set_l mp_set_l +#define TclBN_mp_set_i64 mp_set_i64 #define TclBN_mp_set_u64 mp_set_u64 #define TclBN_mp_shrink mp_shrink #define TclBN_mp_sqr mp_sqr #define TclBN_mp_sqrt mp_sqrt #define TclBN_mp_sub mp_sub #define TclBN_mp_signed_rsh mp_signed_rsh -#define TclBN_mp_tc_and mp_and +#define TclBN_mp_tc_and TclBN_mp_and #define TclBN_mp_tc_div_2d mp_signed_rsh -#define TclBN_mp_tc_or mp_or -#define TclBN_mp_tc_xor mp_xor +#define TclBN_mp_tc_or TclBN_mp_or +#define TclBN_mp_tc_xor TclBN_mp_xor #define TclBN_mp_toradix_n mp_toradix_n #define TclBN_mp_to_radix mp_to_radix #define TclBN_mp_to_ubin mp_to_ubin @@ -187,22 +192,6 @@ mp_err TclBN_mp_div_ld(const mp_int *a, uint64_t b, mp_int *c, uint64_t *d) { } return result; } -mp_err TclBN_mp_div_3(const mp_int *a, mp_int *c, unsigned int *d) { - mp_digit d2; - mp_err result = mp_div_3(a, c, (d ? &d2 : NULL)); - if (d) { - *d = d2; - } - return result; -} -mp_err TclBN_mp_div_l3(const mp_int *a, mp_int *c, uint64_t *d) { - mp_digit d2; - mp_err result = mp_div_3(a, c, (d ? &d2 : NULL)); - if (d) { - *d = d2; - } - return result; -} mp_err TclBN_mp_init_set(mp_int *a, unsigned int b) { return mp_init_set(a, b); } @@ -221,6 +210,9 @@ void TclBN_mp_set(mp_int *a, unsigned int b) { # define TclBN_mp_to_unsigned_bin_n 0 # undef TclBN_mp_toradix_n # define TclBN_mp_toradix_n 0 +# define TclBN_mp_sqr 0 +# undef TclBN_mp_div_3 +# define TclBN_mp_div_3 0 # define TclSetStartupScriptPath 0 # define TclGetStartupScriptPath 0 # define TclSetStartupScriptFileName 0 @@ -235,9 +227,6 @@ void TclBN_mp_set(mp_int *a, unsigned int b) { # define TclWinResetInterfaces 0 # define TclWinSetInterfaces 0 # define TclWinGetPlatformId 0 -# define TclBNInitBignumFromWideUInt 0 -# define TclBNInitBignumFromWideInt 0 -# define TclBNInitBignumFromLong 0 # define Tcl_Backslash 0 # define Tcl_GetDefaultEncodingDir 0 # define Tcl_SetDefaultEncodingDir 0 @@ -253,46 +242,50 @@ void TclBN_mp_set(mp_int *a, unsigned int b) { # define Tcl_BackgroundError 0 #else +mp_err TclBN_mp_div_3(const mp_int *a, mp_int *c, unsigned int *d) { + mp_digit d2; + mp_err result = mp_div_d(a, 3, c, &d2); + if (d) { + *d = d2; + } + return result; +} + int TclBN_mp_expt_d_ex(const mp_int *a, unsigned int b, mp_int *c, int fast) { - return mp_expt_u32(a, b, c); + return TclBN_mp_expt_u32(a, b, c); } mp_err TclBN_mp_to_unsigned_bin(const mp_int *a, unsigned char *b) { - return mp_to_ubin(a, b, INT_MAX, NULL); + return TclBN_mp_to_ubin(a, b, INT_MAX, NULL); } mp_err TclBN_mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen) { - size_t n = mp_ubin_size(a); + size_t n = TclBN_mp_ubin_size(a); if (*outlen < (unsigned long)n) { return MP_VAL; } *outlen = (unsigned long)n; - return mp_to_ubin(a, b, n, NULL); + return TclBN_mp_to_ubin(a, b, n, NULL); } void TclBN_reverse(unsigned char *s, int len) { if (len > 0) { - s_mp_reverse(s, (size_t)len); + TclBN_s_mp_reverse(s, (size_t)len); } } -mp_err mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) +mp_err TclBN_mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) { if (maxlen < 0) { return MP_VAL; } - return mp_to_radix(a, str, (size_t)maxlen, NULL, radix); + return TclBN_mp_to_radix(a, str, (size_t)maxlen, NULL, radix); } -#define TclBNInitBignumFromLong initBignumFromLong -static void TclBNInitBignumFromLong(mp_int *a, long b) -{ - TclBNInitBignumFromWideInt(a, b); -} #define TclSetStartupScriptPath setStartupScriptPath static void TclSetStartupScriptPath(Tcl_Obj *path) { @@ -1129,22 +1122,22 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_mp_init_ul, /* 61 */ TclBN_mp_set_ul, /* 62 */ TclBN_mp_cnt_lsb, /* 63 */ - TclBNInitBignumFromLong, /* 64 */ - TclBNInitBignumFromWideInt, /* 65 */ - TclBNInitBignumFromWideUInt, /* 66 */ + TclBN_mp_init_l, /* 64 */ + TclBN_mp_init_i64, /* 65 */ + TclBN_mp_init_u64, /* 66 */ TclBN_mp_expt_d_ex, /* 67 */ TclBN_mp_set_u64, /* 68 */ TclBN_mp_get_mag_u64, /* 69 */ - TclBN_mp_div_l3, /* 70 */ + TclBN_mp_set_i64, /* 70 */ TclBN_mp_get_mag_ul, /* 71 */ - TclBN_mp_div_ld, /* 72 */ + TclBN_mp_set_l, /* 72 */ TclBN_mp_tc_and, /* 73 */ TclBN_mp_tc_or, /* 74 */ TclBN_mp_tc_xor, /* 75 */ TclBN_mp_signed_rsh, /* 76 */ TclBN_mp_get_bit, /* 77 */ TclBN_mp_to_ubin, /* 78 */ - 0, /* 79 */ + TclBN_mp_div_ld, /* 79 */ TclBN_mp_to_radix, /* 80 */ }; diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index 65a8887..a692bce 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 fc04a8b..45579f4 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -74,7 +74,7 @@ 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 { +declare 17 {deprecated {is private function in libtommath}} { mp_err MP_WUR TclBN_mp_div_3(const mp_int *a, mp_int *q, unsigned int *r) } declare 18 { @@ -143,7 +143,7 @@ declare 38 { declare 39 { void TclBN_mp_set(mp_int *a, unsigned int b) } -declare 40 { +declare 40 {nostub {is private function in libtommath}} { mp_err MP_WUR TclBN_mp_sqr(const mp_int *a, mp_int *b) } declare 41 { @@ -220,17 +220,14 @@ declare 62 { declare 63 { int MP_WUR TclBN_mp_cnt_lsb(const mp_int *a) } - -# Formerly internal API to allow initialisation of bignums without knowing the -# typedefs of how a bignum works internally. -declare 64 {deprecated {Use mp_init() + mp_set_l()}} { - void TclBNInitBignumFromLong(mp_int *bignum, long initVal) +declare 64 { + int MP_WUR TclBN_mp_init_l(mp_int *bignum, long initVal) } -declare 65 {deprecated {Use mp_init() + mp_set_i64()}} { - void TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal) +declare 65 { + int MP_WUR TclBN_mp_init_i64(mp_int *bignum, int64_t initVal) } -declare 66 {deprecated {Use mp_init() + mp_set_u64()}} { - void TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal) +declare 66 { + int MP_WUR TclBN_mp_init_u64(mp_int *bignum, uint64_t initVal) } # Added in libtommath 1.0 @@ -245,13 +242,13 @@ declare 69 { uint64_t MP_WUR TclBN_mp_get_mag_u64(const mp_int *a) } declare 70 { - mp_err MP_WUR TclBN_mp_div_l3(const mp_int *a, mp_int *q, uint64_t *r) + void TclBN_mp_set_i64(mp_int *a, int64_t i) } declare 71 { unsigned long MP_WUR TclBN_mp_get_mag_ul(const mp_int *a) } declare 72 { - mp_err MP_WUR TclBN_mp_div_ld(const mp_int *a, uint64_t b, mp_int *q, uint64_t *r) + void TclBN_mp_set_l(mp_int *a, long i) } # Added in libtommath 1.1.0 @@ -275,6 +272,9 @@ declare 77 {deprecated {is private function in libtommath}} { declare 78 { int MP_WUR TclBN_mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) } +declare 79 { + mp_err MP_WUR TclBN_mp_div_ld(const mp_int *a, uint64_t b, mp_int *q, uint64_t *r) +} declare 80 { int MP_WUR TclBN_mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) } diff --git a/generic/tclTomMath.h b/generic/tclTomMath.h index 8cc5cc2..caa2f05 100644 --- a/generic/tclTomMath.h +++ b/generic/tclTomMath.h @@ -15,5 +15,4 @@ #undef mp_isodd #define mp_iseven(a) (!mp_isodd(a)) #define mp_isodd(a) (((a)->used != 0 && (((a)->dp[0] & 1) != 0)) ? MP_YES : MP_NO) - #endif diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index ae2e7ea..159cf8f 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -16,7 +16,10 @@ #define _TCLTOMMATHDECLS #include "tcl.h" +#include <string.h> +#ifndef BN_H_ #include "tclTomMath.h" +#endif /* * Define the version of the Stubs table that's exported for tommath @@ -49,13 +52,15 @@ #define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc(mem, newsize) #define MP_FREE(mem, size) TclBNFree(mem) +#ifndef MODULE_SCOPE +# define MODULE_SCOPE extern +#endif 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); @@ -64,13 +69,86 @@ MODULE_SCOPE mp_err TclBN_s_mp_expt_u32(const mp_int *a, unsigned int b, mp_int /* Rename the global symbols in libtommath to avoid linkage conflicts */ +#ifndef TCL_WITH_EXTERNAL_TOMMATH #define bn_reverse TclBN_reverse -#define mp_get_mag_ull(a) ((unsigned long long)mp_get_mag_u64(a)) -#define mp_init_set_int(a,i) (MP_DEPRECATED_PRAGMA("replaced by mp_init_ul") mp_init_ul(a,(unsigned int)(i))) +#define mp_add TclBN_mp_add +#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_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_2d TclBN_mp_div_2d +#define mp_exch TclBN_mp_exch +#define mp_expt_d TclBN_mp_expt_d +#define mp_expt_d_ex TclBN_mp_expt_d_ex +#define mp_get_bit TclBN_mp_get_bit +#define mp_get_mag_u64 TclBN_mp_get_mag_u64 +#define mp_get_mag_ul TclBN_mp_get_mag_ul +#define mp_grow TclBN_mp_grow +#define mp_init TclBN_mp_init +#define mp_init_copy TclBN_mp_init_copy +#define mp_init_i64 TclBN_mp_init_i64 +#define mp_init_l TclBN_mp_init_l +#define mp_init_multi TclBN_mp_init_multi +#define mp_init_size TclBN_mp_init_size +#define mp_init_u64 TclBN_mp_init_u64 +#define mp_init_ul TclBN_mp_init_ul +#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_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_l TclBN_mp_set_l +#define mp_set_i64 TclBN_mp_set_i64 +#define mp_set_ul TclBN_mp_set_ul +#define mp_set_ull TclBN_mp_set_ull +#define mp_shrink TclBN_mp_shrink +#define mp_sqrt TclBN_mp_sqrt +#define mp_sub TclBN_mp_sub +#define mp_signed_rsh TclBN_mp_signed_rsh +#define mp_tc_and TclBN_mp_and +#define mp_tc_div_2d TclBN_mp_signed_rsh +#define mp_tc_or TclBN_mp_or +#define mp_tc_xor TclBN_mp_xor +#define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin +#define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n +#define mp_toradix_n TclBN_mp_toradix_n +#define mp_to_radix TclBN_mp_to_radix +#define mp_to_ubin TclBN_mp_to_ubin +#define mp_ubin_size TclBN_mp_ubin_size +#define mp_xor TclBN_mp_xor +#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_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 +#define s_mp_mul_digs_fast TclBN_s_mp_mul_digs_fast +#define s_mp_reverse TclBN_s_mp_reverse +#define s_mp_sqr TclBN_s_mp_sqr +#define s_mp_sqr_fast TclBN_s_mp_sqr_fast +#define s_mp_sub TclBN_s_mp_sub +#define s_mp_toom_mul TclBN_mp_toom_mul +#define s_mp_toom_sqr TclBN_mp_toom_sqr +#endif /* !TCL_WITH_EXTERNAL_TOMMATH */ + +#define mp_init_set_int(a,i) (MP_DEPRECATED_PRAGMA("replaced by mp_init_ul") TclBN_mp_init_ul(a,(unsigned int)(i))) #define mp_set_int(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_ul") (TclBN_mp_set_ul((a),((unsigned int)(b))),MP_OKAY)) #define mp_set_long(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_ul") (TclBN_mp_set_ul((a),(b)),MP_OKAY)) -#define mp_set_long_long(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_u64") (TclBN_mp_set_u64((a),(b)),MP_OKAY)) -#define mp_set_ull(a,b) TclBN_mp_set_u64(a,(uint64_t)(b)) +#define mp_set_long_long(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_u64") (TclBN_mp_set_ull((a),(b)),MP_OKAY)) #define mp_unsigned_bin_size(mp) (MP_DEPRECATED_PRAGMA("replaced by mp_ubin_size") (int)TclBN_mp_ubin_size(mp)) #undef TCL_STORAGE_CLASS @@ -141,7 +219,8 @@ EXTERN mp_err TclBN_mp_div_2(const mp_int *a, mp_int *q) MP_WUR; 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, +TCL_DEPRECATED("is private function in libtommath") +mp_err MP_WUR TclBN_mp_div_3(const mp_int *a, mp_int *q, unsigned int *r) MP_WUR; /* 18 */ EXTERN void TclBN_mp_exch(mp_int *a, mp_int *b); @@ -269,16 +348,11 @@ EXTERN void TclBN_mp_set_ul(mp_int *a, unsigned long i); /* 63 */ EXTERN int TclBN_mp_cnt_lsb(const mp_int *a) MP_WUR; /* 64 */ -TCL_DEPRECATED("Use mp_init() + mp_set_l()") -void TclBNInitBignumFromLong(mp_int *bignum, long initVal); +EXTERN int TclBN_mp_init_l(mp_int *bignum, long initVal) MP_WUR; /* 65 */ -TCL_DEPRECATED("Use mp_init() + mp_set_i64()") -void TclBNInitBignumFromWideInt(mp_int *bignum, - Tcl_WideInt initVal); +EXTERN int TclBN_mp_init_i64(mp_int *bignum, int64_t initVal) MP_WUR; /* 66 */ -TCL_DEPRECATED("Use mp_init() + mp_set_u64()") -void TclBNInitBignumFromWideUInt(mp_int *bignum, - Tcl_WideUInt initVal); +EXTERN int TclBN_mp_init_u64(mp_int *bignum, uint64_t initVal) MP_WUR; /* 67 */ TCL_DEPRECATED("Use mp_expt_u32") mp_err TclBN_mp_expt_d_ex(const mp_int *a, unsigned int b, @@ -288,13 +362,11 @@ EXTERN void TclBN_mp_set_u64(mp_int *a, uint64_t i); /* 69 */ EXTERN uint64_t TclBN_mp_get_mag_u64(const mp_int *a) MP_WUR; /* 70 */ -EXTERN mp_err TclBN_mp_div_l3(const mp_int *a, mp_int *q, - uint64_t *r) MP_WUR; +EXTERN void TclBN_mp_set_i64(mp_int *a, int64_t i); /* 71 */ EXTERN unsigned long TclBN_mp_get_mag_ul(const mp_int *a) MP_WUR; /* 72 */ -EXTERN mp_err TclBN_mp_div_ld(const mp_int *a, uint64_t b, - mp_int *q, uint64_t *r) MP_WUR; +EXTERN void TclBN_mp_set_l(mp_int *a, long i); /* 73 */ EXTERN mp_err TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; @@ -313,7 +385,9 @@ mp_bool TclBN_mp_get_bit(const mp_int *a, unsigned int b); /* 78 */ EXTERN int TclBN_mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) MP_WUR; -/* Slot 79 is reserved */ +/* 79 */ +EXTERN mp_err TclBN_mp_div_ld(const mp_int *a, uint64_t b, + mp_int *q, uint64_t *r) MP_WUR; /* 80 */ EXTERN int TclBN_mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) MP_WUR; @@ -339,7 +413,7 @@ typedef struct TclTomMathStubs { 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, unsigned int *r) MP_WUR; /* 17 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_mp_div_3) (const mp_int *a, mp_int *q, unsigned int *r) MP_WUR; /* 17 */ 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 */ @@ -362,7 +436,7 @@ typedef struct TclTomMathStubs { 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, unsigned int b); /* 39 */ - mp_err (*tclBN_mp_sqr) (const mp_int *a, mp_int *b) MP_WUR; /* 40 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_mp_sqr) (const mp_int *a, mp_int *b) MP_WUR; /* 40 */ 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, unsigned int b, mp_int *c) MP_WUR; /* 43 */ @@ -386,22 +460,22 @@ typedef struct TclTomMathStubs { mp_err (*tclBN_mp_init_ul) (mp_int *a, unsigned long i) MP_WUR; /* 61 */ void (*tclBN_mp_set_ul) (mp_int *a, unsigned long i); /* 62 */ int (*tclBN_mp_cnt_lsb) (const mp_int *a) MP_WUR; /* 63 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_l()") void (*tclBNInitBignumFromLong) (mp_int *bignum, long initVal); /* 64 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_i64()") void (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_u64()") void (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ + int (*tclBN_mp_init_l) (mp_int *bignum, long initVal) MP_WUR; /* 64 */ + int (*tclBN_mp_init_i64) (mp_int *bignum, int64_t initVal) MP_WUR; /* 65 */ + int (*tclBN_mp_init_u64) (mp_int *bignum, uint64_t initVal) MP_WUR; /* 66 */ TCL_DEPRECATED_API("Use mp_expt_u32") mp_err (*tclBN_mp_expt_d_ex) (const mp_int *a, unsigned int b, mp_int *c, int fast); /* 67 */ void (*tclBN_mp_set_u64) (mp_int *a, uint64_t i); /* 68 */ uint64_t (*tclBN_mp_get_mag_u64) (const mp_int *a) MP_WUR; /* 69 */ - mp_err (*tclBN_mp_div_l3) (const mp_int *a, mp_int *q, uint64_t *r) MP_WUR; /* 70 */ + void (*tclBN_mp_set_i64) (mp_int *a, int64_t i); /* 70 */ unsigned long (*tclBN_mp_get_mag_ul) (const mp_int *a) MP_WUR; /* 71 */ - mp_err (*tclBN_mp_div_ld) (const mp_int *a, uint64_t b, mp_int *q, uint64_t *r) MP_WUR; /* 72 */ + void (*tclBN_mp_set_l) (mp_int *a, long i); /* 72 */ mp_err (*tclBN_mp_tc_and) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 73 */ mp_err (*tclBN_mp_tc_or) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 74 */ mp_err (*tclBN_mp_tc_xor) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 75 */ mp_err (*tclBN_mp_signed_rsh) (const mp_int *a, int b, mp_int *c) MP_WUR; /* 76 */ TCL_DEPRECATED_API("is private function in libtommath") mp_bool (*tclBN_mp_get_bit) (const mp_int *a, unsigned int b); /* 77 */ int (*tclBN_mp_to_ubin) (const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) MP_WUR; /* 78 */ - void (*reserved79)(void); + mp_err (*tclBN_mp_div_ld) (const mp_int *a, uint64_t b, mp_int *q, uint64_t *r) MP_WUR; /* 79 */ int (*tclBN_mp_to_radix) (const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) MP_WUR; /* 80 */ } TclTomMathStubs; @@ -545,24 +619,24 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_mp_set_ul) /* 62 */ #define TclBN_mp_cnt_lsb \ (tclTomMathStubsPtr->tclBN_mp_cnt_lsb) /* 63 */ -#define TclBNInitBignumFromLong \ - (tclTomMathStubsPtr->tclBNInitBignumFromLong) /* 64 */ -#define TclBNInitBignumFromWideInt \ - (tclTomMathStubsPtr->tclBNInitBignumFromWideInt) /* 65 */ -#define TclBNInitBignumFromWideUInt \ - (tclTomMathStubsPtr->tclBNInitBignumFromWideUInt) /* 66 */ +#define TclBN_mp_init_l \ + (tclTomMathStubsPtr->tclBN_mp_init_l) /* 64 */ +#define TclBN_mp_init_i64 \ + (tclTomMathStubsPtr->tclBN_mp_init_i64) /* 65 */ +#define TclBN_mp_init_u64 \ + (tclTomMathStubsPtr->tclBN_mp_init_u64) /* 66 */ #define TclBN_mp_expt_d_ex \ (tclTomMathStubsPtr->tclBN_mp_expt_d_ex) /* 67 */ #define TclBN_mp_set_u64 \ (tclTomMathStubsPtr->tclBN_mp_set_u64) /* 68 */ #define TclBN_mp_get_mag_u64 \ (tclTomMathStubsPtr->tclBN_mp_get_mag_u64) /* 69 */ -#define TclBN_mp_div_l3 \ - (tclTomMathStubsPtr->tclBN_mp_div_l3) /* 70 */ +#define TclBN_mp_set_i64 \ + (tclTomMathStubsPtr->tclBN_mp_set_i64) /* 70 */ #define TclBN_mp_get_mag_ul \ (tclTomMathStubsPtr->tclBN_mp_get_mag_ul) /* 71 */ -#define TclBN_mp_div_ld \ - (tclTomMathStubsPtr->tclBN_mp_div_ld) /* 72 */ +#define TclBN_mp_set_l \ + (tclTomMathStubsPtr->tclBN_mp_set_l) /* 72 */ #define TclBN_mp_tc_and \ (tclTomMathStubsPtr->tclBN_mp_tc_and) /* 73 */ #define TclBN_mp_tc_or \ @@ -575,7 +649,8 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_mp_get_bit) /* 77 */ #define TclBN_mp_to_ubin \ (tclTomMathStubsPtr->tclBN_mp_to_ubin) /* 78 */ -/* Slot 79 is reserved */ +#define TclBN_mp_div_ld \ + (tclTomMathStubsPtr->tclBN_mp_div_ld) /* 79 */ #define TclBN_mp_to_radix \ (tclTomMathStubsPtr->tclBN_mp_to_radix) /* 80 */ @@ -588,67 +663,47 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; #define mp_cmp_d TclBN_mp_cmp_d #ifdef MP_64BIT #define mp_div_d TclBN_mp_div_ld -#define mp_div_3 TclBN_mp_div_l3 #else #define mp_div_d TclBN_mp_div_d -#define mp_div_3 TclBN_mp_div_3 #endif #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 -#define mp_add TclBN_mp_add -#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_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_2d TclBN_mp_div_2d -#define mp_exch TclBN_mp_exch -#define mp_expt_d TclBN_mp_expt_d -#define mp_expt_d_ex TclBN_mp_expt_d_ex -#define mp_get_mag_u64 TclBN_mp_get_mag_u64 -#define mp_get_mag_ul TclBN_mp_get_mag_ul -#define mp_grow TclBN_mp_grow -#define mp_init TclBN_mp_init -#define mp_init_copy TclBN_mp_init_copy -#define mp_init_multi TclBN_mp_init_multi -#define mp_init_size TclBN_mp_init_size -#define mp_init_ul TclBN_mp_init_ul -#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_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_u64 TclBN_mp_set_u64 -#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_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 -#define mp_toradix_n TclBN_mp_toradix_n -#define mp_to_radix TclBN_mp_to_radix -#define mp_to_ubin TclBN_mp_to_ubin -#define mp_ubin_size TclBN_mp_ubin_size -#define mp_xor TclBN_mp_xor -#define mp_zero TclBN_mp_zero #endif /* USE_TCL_STUBS */ +#define TclBNInitBignumFromLong(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)mp_init_l((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromLong"); \ + } \ + } while (0) +#undef TclBNInitBignumFromWideInt +#define TclBNInitBignumFromWideInt(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)mp_init_i64((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromWideInt"); \ + } \ + } while (0) +#undef TclBNInitBignumFromWideUInt +#define TclBNInitBignumFromWideUInt(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)mp_init_u64((a),(b)); \ + if ((a)->dp == NULL) { \ + Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt"); \ + } \ + } while (0) +#define mp_init_i32(a,b) mp_init_l((a),(int32_t)(b)) +#define mp_init_ll(a,b) mp_init_i64((a),(b)) +#define mp_init_u32(a,b) mp_init_u64((a),(uint32_t)(b)) +#define mp_init_ull(a,b) mp_init_u64((a),(b)) + #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT diff --git a/generic/tclTomMathInterface.c b/generic/tclTomMathInterface.c index 2d29487..60ed123 100644 --- a/generic/tclTomMathInterface.c +++ b/generic/tclTomMathInterface.c @@ -91,66 +91,6 @@ TclBN_revision(void) } /* - *---------------------------------------------------------------------- - * - * TclBNInitBignumFromWideInt -- - * - * Allocate and initialize a 'bignum' from a Tcl_WideInt - * - * Results: - * None. - * - * Side effects: - * The 'bignum' is constructed. - * - *---------------------------------------------------------------------- - */ - -void -TclBNInitBignumFromWideInt( - mp_int *a, /* Bignum to initialize */ - Tcl_WideInt v) /* Initial value */ -{ - if (mp_init(a) != MP_OKAY) { - wipanic: - Tcl_Panic("initialization failure in TclBNInitBignumFromWideInt"); - } - if (v < 0) { - mp_set_u64(a, (uint64_t)(-v)); - if (mp_neg(a, a) != MP_OKAY) goto wipanic; - } else { - mp_set_u64(a, (uint64_t)v); - } -} - -/* - *---------------------------------------------------------------------- - * - * TclBNInitBignumFromWideUInt -- - * - * Allocate and initialize a 'bignum' from a Tcl_WideUInt - * - * Results: - * None. - * - * Side effects: - * The 'bignum' is constructed. - * - *---------------------------------------------------------------------- - */ - -void -TclBNInitBignumFromWideUInt( - mp_int *a, /* Bignum to initialize */ - Tcl_WideUInt v) /* Initial value */ -{ - if (mp_init(a) != MP_OKAY) { - Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt"); - } - mp_set_u64(a, (uint64_t)v); -} - -/* * Local Variables: * mode: c * c-basic-offset: 4 |