diff options
Diffstat (limited to 'generic')
95 files changed, 5213 insertions, 4988 deletions
diff --git a/generic/regc_lex.c b/generic/regc_lex.c index 4c8f15f..d299b49 100644 --- a/generic/regc_lex.c +++ b/generic/regc_lex.c @@ -905,9 +905,7 @@ lexescape( v->now = save; - /* - * And fall through into octal number. - */ + /* FALLTHRU */ case CHR('0'): NOTE(REG_UUNPORT); diff --git a/generic/regc_nfa.c b/generic/regc_nfa.c index 240fcfe..7507137 100644 --- a/generic/regc_nfa.c +++ b/generic/regc_nfa.c @@ -2978,6 +2978,9 @@ dumpnfa( dumpcolors(nfa->cm, f); } fflush(f); +#else + (void)nfa; + (void)f; #endif } @@ -3157,6 +3160,9 @@ dumpcnfa( dumpcstate(st, cnfa, f); } fflush(f); +#else + (void)cnfa; + (void)f; #endif } diff --git a/generic/regcomp.c b/generic/regcomp.c index 49b024f..79e6536 100644 --- a/generic/regcomp.c +++ b/generic/regcomp.c @@ -59,7 +59,6 @@ static void wordchrs(struct vars *); static struct subre *subre(struct vars *, int, int, struct state *, struct state *); static void freesubre(struct vars *, struct subre *); static void freesrnode(struct vars *, struct subre *); -static void optst(struct vars *, struct subre *); static int numst(struct subre *, int); static void markst(struct subre *); static void cleanst(struct vars *); @@ -244,6 +243,7 @@ struct vars { #define EMPTYARC(x, y) newarc(v->nfa, EMPTY, 0, x, y) /* token type codes, some also used as NFA arc types */ +#undef DIGIT /* prevent conflict with libtommath */ #define EMPTY 'n' /* no token present */ #define EOS 'e' /* end of string */ #define PLAIN 'p' /* ordinary character */ @@ -394,7 +394,6 @@ compile( dumpnfa(v->nfa, debug); dumpst(v->tree, debug, 1); } - optst(v, v->tree); v->ntree = numst(v->tree, 1); markst(v->tree); cleanst(v); @@ -512,7 +511,7 @@ freev( struct vars *v, int err) { - register int ret; + int ret; if (v->re != NULL) { rfree(v->re); @@ -922,7 +921,7 @@ parseqatom( */ NOTE(REG_UPBOTCH); - /* fallthrough into case PLAIN */ + /* FALLTHRU */ case PLAIN: onechr(v, v->nextvalue, lp, rp); okcolors(v->nfa, v->cm); @@ -1811,25 +1810,6 @@ freesrnode( } /* - - optst - optimize a subRE subtree - ^ static void optst(struct vars *, struct subre *); - */ -static void -optst( - struct vars *v, - struct subre *t) -{ - /* - * DGP (2007-11-13): I assume it was the programmer's intent to eventually - * come back and add code to optimize subRE trees, but the routine coded - * just spends effort traversing the tree and doing nothing. We can do - * nothing with less effort. - */ - - return; -} - -/* - numst - number tree nodes (assigning "id" indexes) ^ static int numst(struct subre *, int); */ @@ -2100,6 +2080,9 @@ dump( } fprintf(f, "\n"); dumpst(g->tree, f, 0); +#else + (void)re; + (void)f; #endif } diff --git a/generic/regcustom.h b/generic/regcustom.h index 095385d..4396399 100644 --- a/generic/regcustom.h +++ b/generic/regcustom.h @@ -131,7 +131,7 @@ typedef int celt; /* Type to hold chr, or NOCELT */ #if 1 #define AllocVars(vPtr) \ static Tcl_ThreadDataKey varsKey; \ - register struct vars *vPtr = (struct vars *) \ + struct vars *vPtr = (struct vars *) \ Tcl_GetThreadData(&varsKey, sizeof(struct vars)) #else /* @@ -140,7 +140,7 @@ typedef int celt; /* Type to hold chr, or NOCELT */ * faster in practice (measured!) */ #define AllocVars(vPtr) \ - register struct vars *vPtr = (struct vars *) MALLOC(sizeof(struct vars)) + struct vars *vPtr = (struct vars *) MALLOC(sizeof(struct vars)) #define FreeVars(vPtr) \ FREE(vPtr) #endif diff --git a/generic/regerror.c b/generic/regerror.c index 49d93ed..f783217 100644 --- a/generic/regerror.c +++ b/generic/regerror.c @@ -58,7 +58,6 @@ static const struct rerr { size_t /* Actual space needed (including NUL) */ regerror( int code, /* Error code, or REG_ATOI or REG_ITOA */ - const regex_t *preg, /* Associated regex_t (unused at present) */ char *errbuf, /* Result buffer (unless errbuf_size==0) */ size_t errbuf_size) /* Available space in errbuf, can be 0 */ { diff --git a/generic/regex.h b/generic/regex.h index 8845f72..dba3ab4 100644 --- a/generic/regex.h +++ b/generic/regex.h @@ -151,8 +151,8 @@ typedef struct { int re_csize; /* sizeof(character) */ char *re_endp; /* backward compatibility kludge */ /* the rest is opaque pointers to hidden innards */ - char *re_guts; /* `char *' is more portable than `void *' */ - char *re_fns; + void *re_guts; + void *re_fns; } regex_t; /* result reporting (may acquire more fields later) */ @@ -232,7 +232,7 @@ typedef struct { * of character is used for error reports is independent of what kind is used * in matching. * - ^ extern size_t regerror(int, const regex_t *, char *, size_t); + ^ extern size_t regerror(int, char *, size_t); */ #define REG_OKAY 0 /* no errors detected */ #define REG_NOMATCH 1 /* failed to match */ @@ -283,7 +283,7 @@ int regexec(regex_t *, const char *, size_t, regmatch_t [], int); MODULE_SCOPE int __REG_WIDE_EXEC(regex_t *, const __REG_WIDE_T *, size_t, rm_detail_t *, size_t, regmatch_t [], int); #endif MODULE_SCOPE void regfree(regex_t *); -MODULE_SCOPE size_t regerror(int, const regex_t *, char *, size_t); +MODULE_SCOPE size_t regerror(int, char *, size_t); /* automatically gathered by fwd; do not hand-edit */ /* =====^!^===== end forwards =====^!^===== */ diff --git a/generic/regexec.c b/generic/regexec.c index c57f42c..b5f161b 100644 --- a/generic/regexec.c +++ b/generic/regexec.c @@ -91,7 +91,6 @@ struct smalldfa { struct sset *outsarea[FEWSTATES*2 * FEWCOLORS]; struct arcp incarea[FEWSTATES*2 * FEWCOLORS]; }; -#define DOMALLOC ((struct smalldfa *)NULL) /* force malloc */ /* * Internal variables, bundled for easy passing around. @@ -129,7 +128,7 @@ int exec(regex_t *, const chr *, size_t, rm_detail_t *, size_t, regmatch_t [], i static struct dfa *getsubdfa(struct vars *, struct subre *); static int simpleFind(struct vars *const, struct cnfa *const, struct colormap *const); static int complicatedFind(struct vars *const, struct cnfa *const, struct colormap *const); -static int complicatedFindLoop(struct vars *const, struct cnfa *const, struct colormap *const, struct dfa *const, struct dfa *const, chr **const); +static int complicatedFindLoop(struct vars *const, struct dfa *const, struct dfa *const, chr **const); static void zapallsubs(regmatch_t *const, const size_t); static void zaptreesubs(struct vars *const, struct subre *const); static void subset(struct vars *const, struct subre *const, chr *const, chr *const); @@ -299,7 +298,7 @@ getsubdfa(struct vars * v, struct subre * t) { if (v->subdfas[t->id] == NULL) { - v->subdfas[t->id] = newDFA(v, &t->cnfa, &v->g->cmap, DOMALLOC); + v->subdfas[t->id] = newDFA(v, &t->cnfa, &v->g->cmap, NULL); if (ISERR()) return NULL; } @@ -434,7 +433,7 @@ complicatedFind( return v->err; } - ret = complicatedFindLoop(v, cnfa, cm, d, s, &cold); + ret = complicatedFindLoop(v, d, s, &cold); freeDFA(d); freeDFA(s); @@ -453,14 +452,12 @@ complicatedFind( /* - complicatedFindLoop - the heart of complicatedFind - ^ static int complicatedFindLoop(struct vars *, struct cnfa *, struct colormap *, + ^ static int complicatedFindLoop(struct vars *, ^ struct dfa *, struct dfa *, chr **); */ static int complicatedFindLoop( struct vars *const v, - struct cnfa *const cnfa, - struct colormap *const cm, struct dfa *const d, struct dfa *const s, chr **const coldp) /* where to put coldstart pointer */ @@ -889,7 +886,7 @@ cbrdissect( MDEBUG(("cbackref n%d %d{%d-%d}\n", t->id, n, min, max)); /* get the backreferenced string */ - if (v->pmatch[n].rm_so == -1) { + if (v->pmatch[n].rm_so == TCL_INDEX_NONE) { return REG_NOMATCH; } brstring = v->start + v->pmatch[n].rm_so; diff --git a/generic/regguts.h b/generic/regguts.h index b3dbaa4..da38ef2 100644 --- a/generic/regguts.h +++ b/generic/regguts.h @@ -411,7 +411,7 @@ struct guts { #ifndef AllocVars #define AllocVars(vPtr) \ struct vars var; \ - register struct vars *vPtr = &var + struct vars *vPtr = &var #endif #ifndef FreeVars #define FreeVars(vPtr) ((void) 0) diff --git a/generic/tcl.decls b/generic/tcl.decls index 7d3b535..8555ac2 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -132,9 +132,8 @@ declare 28 { declare 29 { Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *objPtr) } -# Only available as stub-entry, for backwards-compatible stub-enabled extensions declare 30 { - void TclOldFreeObj(Tcl_Obj *objPtr) + void TclFreeObj(Tcl_Obj *objPtr) } declare 31 { int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *boolPtr) @@ -1198,7 +1197,7 @@ declare 335 { int Tcl_UtfToTitle(char *src) } declare 336 { - int Tcl_UtfToUniChar(const char *src, Tcl_UniChar *chPtr) + int Tcl_UtfToChar16(const char *src, unsigned short *chPtr) } declare 337 { int Tcl_UtfToUpper(char *src) @@ -1253,11 +1252,11 @@ declare 353 { unsigned long numChars) } declare 354 { - char *Tcl_UniCharToUtfDString(const Tcl_UniChar *uniStr, + char *Tcl_Char16ToUtfDString(const unsigned short *uniStr, int uniLength, Tcl_DString *dsPtr) } declare 355 { - Tcl_UniChar *Tcl_UtfToUniCharDString(const char *src, + unsigned short *Tcl_UtfToChar16DString(const char *src, int length, Tcl_DString *dsPtr) } declare 356 { @@ -2385,6 +2384,24 @@ declare 644 { int type, int size) } +declare 645 { + int Tcl_GetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, + int endValue, int *indexPtr) +} + +# TIP #548 +declare 646 { + int Tcl_UtfToUniChar(const char *src, int *chPtr) +} +declare 647 { + char *Tcl_UniCharToUtfDString(const int *uniStr, + int uniLength, Tcl_DString *dsPtr) +} +declare 648 { + int *Tcl_UtfToUniCharDString(const char *src, + int length, Tcl_DString *dsPtr) +} + # ----- BASELINE -- FOR -- 8.7.0 ----- # ############################################################################## @@ -2463,6 +2480,9 @@ export { export { void Tcl_GetMemoryInfo(Tcl_DString *dsPtr) } +export { + void Tcl_InitSubsystems(void) +} # Local Variables: # mode: tcl diff --git a/generic/tcl.h b/generic/tcl.h index d76b334..7f1a2a5 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -51,10 +51,10 @@ extern "C" { #define TCL_MAJOR_VERSION 8 #define TCL_MINOR_VERSION 7 #define TCL_RELEASE_LEVEL TCL_ALPHA_RELEASE -#define TCL_RELEASE_SERIAL 2 +#define TCL_RELEASE_SERIAL 4 #define TCL_VERSION "8.7" -#define TCL_PATCH_LEVEL "8.7a2" +#define TCL_PATCH_LEVEL "8.7a4" #if !defined(TCL_NO_DEPRECATED) || defined(RC_INVOKED) /* @@ -406,7 +406,7 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt; #if defined(_WIN32) # ifdef __BORLANDC__ typedef struct stati64 Tcl_StatBuf; -# elif defined(_WIN64) +# elif defined(_WIN64) || defined(_USE_64BIT_TIME_T) typedef struct __stat64 Tcl_StatBuf; # elif (defined(_MSC_VER) && (_MSC_VER < 1400)) || defined(_USE_32BIT_TIME_T) typedef struct _stati64 Tcl_StatBuf; @@ -1657,7 +1657,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. * @@ -1672,147 +1672,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; /* @@ -2073,29 +2045,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 @@ -2158,7 +2129,7 @@ typedef struct Tcl_EncodingType { #if TCL_UTF_MAX > 4 /* - * unsigned int isn't 100% accurate as it should be a strict 4-byte value + * int isn't 100% accurate as it should be a strict 4-byte value * (perhaps wchar_t). 64-bit systems may have troubles. The size of this * value must be reflected correctly in regcustom.h and * in tclEncoding.c. @@ -2166,7 +2137,7 @@ typedef struct Tcl_EncodingType { * XXX: string rep that Tcl_UniChar represents. Changing the size * XXX: of Tcl_UniChar is /not/ supported. */ -typedef unsigned int Tcl_UniChar; +typedef int Tcl_UniChar; #else typedef unsigned short Tcl_UniChar; #endif @@ -2206,12 +2177,10 @@ typedef void (Tcl_LimitHandlerDeleteProc) (ClientData clientData); * Override definitions for libtommath. */ -typedef struct mp_int mp_int; +#ifndef MP_INT_DECLARED #define MP_INT_DECLARED -typedef unsigned int mp_digit; -#define MP_DIGIT_DECLARED -typedef unsigned TCL_WIDE_INT_TYPE mp_word; -#define MP_WORD_DECLARED +typedef struct mp_int mp_int; +#endif /* *---------------------------------------------------------------------------- @@ -2333,6 +2302,7 @@ typedef int (Tcl_ArgvGenFuncProc)(ClientData clientData, Tcl_Interp *interp, #define TCL_IO_FAILURE (-1) #define TCL_AUTO_LENGTH (-1) +#define TCL_INDEX_NONE (-1) /* *---------------------------------------------------------------------------- @@ -2402,8 +2372,11 @@ EXTERN void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, const char *version, int exact); +EXTERN void Tcl_InitSubsystems(void); EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr); -#ifndef _WIN32 +#ifdef _WIN32 +EXTERN int TclZipfs_AppHook(int *argc, wchar_t ***argv); +#else EXTERN int TclZipfs_AppHook(int *argc, char ***argv); #endif @@ -2485,14 +2458,7 @@ EXTERN int TclZipfs_AppHook(int *argc, char ***argv); # undef Tcl_IsShared # define Tcl_IsShared(objPtr) \ Tcl_DbIsShared(objPtr, __FILE__, __LINE__) -#elif (!defined(TCL_NO_DEPRECATED) && defined(USE_TCL_STUBS)) -/* - * When compiling stub-enabled extensions without -DTCL_NO_DEPRECATED, - * those extensions are expected to run fine with Tcl 8.6 as well. - * This means we must continue to use macro's for the above 3 functions, - * and the old stub entry for TclFreeObj. All other usage of TclFreeObj() - * is forbidden now, therefore it is changed to be MODULE_SCOPE internal. - */ +#else # undef Tcl_IncrRefCount # define Tcl_IncrRefCount(objPtr) \ ++(objPtr)->refCount @@ -2505,7 +2471,7 @@ EXTERN int TclZipfs_AppHook(int *argc, char ***argv); do { \ Tcl_Obj *_objPtr = (objPtr); \ if ((_objPtr)->refCount-- <= 1) { \ - TclOldFreeObj(_objPtr); \ + TclFreeObj(_objPtr); \ } \ } while(0) # undef Tcl_IsShared diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c index bad3d8a..0c0ab7b 100644 --- a/generic/tclAlloc.c +++ b/generic/tclAlloc.c @@ -253,9 +253,9 @@ char * TclpAlloc( unsigned int numBytes) /* Number of bytes to allocate. */ { - register union overhead *overPtr; - register size_t bucket; - register unsigned amount; + union overhead *overPtr; + size_t bucket; + unsigned amount; struct block *bigBlockPtr = NULL; if (!allocInit) { @@ -304,7 +304,7 @@ TclpAlloc( #endif Tcl_MutexUnlock(allocMutexPtr); - return (void *)(overPtr+1); + return (char *)(overPtr+1); } /* @@ -387,8 +387,8 @@ static void MoreCore( size_t bucket) /* What bucket to allocate to. */ { - register union overhead *overPtr; - register size_t size; /* size of desired block */ + union overhead *overPtr; + size_t size; /* size of desired block */ size_t amount; /* amount to allocate */ size_t numBlocks; /* how many blocks we get */ struct block *blockPtr; @@ -448,8 +448,8 @@ void TclpFree( char *oldPtr) /* Pointer to memory to free. */ { - register size_t size; - register union overhead *overPtr; + size_t size; + union overhead *overPtr; struct block *bigBlockPtr; if (oldPtr == NULL) { @@ -592,7 +592,7 @@ TclpRealloc( } if (expensive) { - void *newPtr; + char *newPtr; Tcl_MutexUnlock(allocMutexPtr); @@ -645,8 +645,8 @@ void mstats( char *s) /* Where to write info. */ { - register unsigned int i, j; - register union overhead *overPtr; + unsigned int i, j; + union overhead *overPtr; size_t totalFree = 0, totalUsed = 0; Tcl_MutexLock(allocMutexPtr); diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c index 47f7100..881d99a 100644 --- a/generic/tclAssembly.c +++ b/generic/tclAssembly.c @@ -287,8 +287,7 @@ static int GetIntegerOperand(AssemblyEnv*, Tcl_Token**, int*); static int GetNextOperand(AssemblyEnv*, Tcl_Token**, Tcl_Obj**); static void LookForFreshCatches(BasicBlock*, BasicBlock**); static void MoveCodeForJumps(AssemblyEnv*, int); -static void MoveExceptionRangesToBasicBlock(AssemblyEnv*, int, - int); +static void MoveExceptionRangesToBasicBlock(AssemblyEnv*, int); static AssemblyEnv* NewAssemblyEnv(CompileEnv*, int); static int ProcessCatches(AssemblyEnv*); static int ProcessCatchesInBasicBlock(AssemblyEnv*, BasicBlock*, @@ -474,8 +473,12 @@ static const TalInstDesc TalInstructionTable[] = { {"strcat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1}, {"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1}, {"strfind", ASSEM_1BYTE, INST_STR_FIND, 2, 1}, + {"strge", ASSEM_1BYTE, INST_STR_GE, 2, 1}, + {"strgt", ASSEM_1BYTE, INST_STR_GT, 2, 1}, {"strindex", ASSEM_1BYTE, INST_STR_INDEX, 2, 1}, + {"strle", ASSEM_1BYTE, INST_STR_LE, 2, 1}, {"strlen", ASSEM_1BYTE, INST_STR_LEN, 1, 1}, + {"strlt", ASSEM_1BYTE, INST_STR_LT, 2, 1}, {"strmap", ASSEM_1BYTE, INST_STR_MAP, 3, 1}, {"strmatch", ASSEM_BOOL, INST_STR_MATCH, 2, 1}, {"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1}, @@ -502,7 +505,7 @@ static const TalInstDesc TalInstructionTable[] = { {"variable", ASSEM_LVT4, INST_VARIABLE, 1, 0}, {"verifyDict", ASSEM_1BYTE, INST_DICT_VERIFY, 1, 0}, {"yield", ASSEM_1BYTE, INST_YIELD, 1, 1}, - {NULL, 0, 0, 0, 0} + {NULL, ASSEM_1BYTE, 0, 0, 0} }; /* @@ -517,6 +520,7 @@ static const unsigned char NonThrowingByteCodes[] = { INST_PUSH1, INST_PUSH4, INST_POP, INST_DUP, /* 1-4 */ INST_JUMP1, INST_JUMP4, /* 34-35 */ INST_END_CATCH, INST_PUSH_RESULT, INST_PUSH_RETURN_CODE, /* 70-72 */ + INST_STR_EQ, INST_STR_NEQ, INST_STR_CMP, INST_STR_LEN, /* 73-76 */ INST_LIST, /* 79 */ INST_OVER, /* 95 */ INST_PUSH_RETURN_OPTIONS, /* 108 */ @@ -531,7 +535,8 @@ static const unsigned char NonThrowingByteCodes[] = { INST_STR_TRIM, INST_STR_TRIM_LEFT, INST_STR_TRIM_RIGHT, /* 166-168 */ INST_CONCAT_STK, /* 169 */ INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE, /* 170-172 */ - INST_NUM_TYPE /* 180 */ + INST_NUM_TYPE, /* 180 */ + INST_STR_LT, INST_STR_GT, INST_STR_LE, INST_STR_GE /* 191-194 */ }; /* @@ -791,6 +796,7 @@ TclNRAssembleObjCmd( Tcl_Obj* backtrace; /* Object where extra error information is * constructed. */ + (void)dummy; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "bytecodeList"); return TCL_ERROR; @@ -847,7 +853,7 @@ CompileAssembleObj( Interp *iPtr = (Interp *) interp; /* Internals of the interpreter */ CompileEnv compEnv; /* Compilation environment structure */ - register ByteCode *codePtr = NULL; + ByteCode *codePtr = NULL; /* Bytecode resulting from the assembly */ Namespace* namespacePtr; /* Namespace in which variable and command * names in the bytecode resolve */ @@ -964,7 +970,7 @@ TclCompileAssembleCmd( int numCommands = envPtr->numCommands; int offset = envPtr->codeNext - envPtr->codeStart; int depth = envPtr->currStackDepth; - + (void)cmdPtr; /* * Make sure that the command has a single arg that is a simple word. */ @@ -1149,9 +1155,9 @@ NewAssemblyEnv( { Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ - AssemblyEnv* assemEnvPtr = TclStackAlloc(interp, sizeof(AssemblyEnv)); + AssemblyEnv* assemEnvPtr = (AssemblyEnv*)TclStackAlloc(interp, sizeof(AssemblyEnv)); /* Assembler environment under construction */ - Tcl_Parse* parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); + Tcl_Parse* parsePtr = (Tcl_Parse*)TclStackAlloc(interp, sizeof(Tcl_Parse)); /* Parse of one line of assembly code */ assemEnvPtr->envPtr = envPtr; @@ -1540,7 +1546,7 @@ AssembleOneLine( goto cleanup; } - jtPtr = ckalloc(sizeof(JumptableInfo)); + jtPtr = (JumptableInfo*)ckalloc(sizeof(JumptableInfo)); Tcl_InitHashTable(&jtPtr->hashTable, TCL_STRING_KEYS); assemEnvPtr->curr_bb->jumpLine = assemEnvPtr->cmdLine; @@ -1814,7 +1820,6 @@ CompileEmbeddedScript( int savedStackDepth = envPtr->currStackDepth; int savedMaxStackDepth = envPtr->maxStackDepth; - int savedCodeIndex = envPtr->codeNext - envPtr->codeStart; int savedExceptArrayNext = envPtr->exceptArrayNext; envPtr->currStackDepth = 0; @@ -1847,8 +1852,7 @@ CompileEmbeddedScript( * need to be fixed up once the stack depth is known. */ - MoveExceptionRangesToBasicBlock(assemEnvPtr, savedCodeIndex, - savedExceptArrayNext); + MoveExceptionRangesToBasicBlock(assemEnvPtr, savedExceptArrayNext); /* * Flush the current basic block. @@ -1907,7 +1911,6 @@ SyncStackDepth( static void MoveExceptionRangesToBasicBlock( AssemblyEnv* assemEnvPtr, /* Assembly environment */ - int savedCodeIndex, /* Start of the embedded code */ int savedExceptArrayNext) /* Saved index of the end of the exception * range array */ { @@ -1939,7 +1942,7 @@ MoveExceptionRangesToBasicBlock( curr_bb->foreignExceptionBase = savedExceptArrayNext; curr_bb->foreignExceptionCount = exceptionCount; curr_bb->foreignExceptions = - ckalloc(exceptionCount * sizeof(ExceptionRange)); + (ExceptionRange*)ckalloc(exceptionCount * sizeof(ExceptionRange)); memcpy(curr_bb->foreignExceptions, envPtr->exceptArrayPtr + savedExceptArrayNext, exceptionCount * sizeof(ExceptionRange)); @@ -2004,7 +2007,7 @@ CreateMirrorJumpTable( * Allocate the jumptable. */ - jtPtr = ckalloc(sizeof(JumptableInfo)); + jtPtr = (JumptableInfo*)ckalloc(sizeof(JumptableInfo)); jtHashPtr = &jtPtr->hashTable; Tcl_InitHashTable(jtHashPtr, TCL_STRING_KEYS); @@ -2064,7 +2067,7 @@ DeleteMirrorJumpTable( for (entry = Tcl_FirstHashEntry(jtHashPtr, &search); entry != NULL; entry = Tcl_NextHashEntry(&search)) { - label = Tcl_GetHashValue(entry); + label = (Tcl_Obj*)Tcl_GetHashValue(entry); Tcl_DecrRefCount(label); Tcl_SetHashValue(entry, NULL); } @@ -2652,7 +2655,7 @@ AllocBB( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; - BasicBlock *bb = ckalloc(sizeof(BasicBlock)); + BasicBlock *bb = (BasicBlock*)ckalloc(sizeof(BasicBlock)); bb->originalStartOffset = bb->startOffset = envPtr->codeNext - envPtr->codeStart; @@ -2843,7 +2846,7 @@ CalculateJumpRelocations( * target is out of range. */ - jumpTarget = Tcl_GetHashValue(entry); + jumpTarget = (BasicBlock*)Tcl_GetHashValue(entry); if (bbPtr->flags & BB_JUMP1) { offset = jumpTarget->startOffset - (bbPtr->jumpOffset + motion); @@ -2910,7 +2913,7 @@ CheckJumpTableLabels( for (symEntryPtr = Tcl_FirstHashEntry(symHash, &search); symEntryPtr != NULL; symEntryPtr = Tcl_NextHashEntry(&search)) { - symbolObj = Tcl_GetHashValue(symEntryPtr); + symbolObj = (Tcl_Obj*)Tcl_GetHashValue(symEntryPtr); valEntryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash, TclGetString(symbolObj)); DEBUG_PRINT(" %s -> %s (%d)\n", @@ -3039,7 +3042,7 @@ FillInJumpOffsets( if (bbPtr->jumpTarget != NULL) { entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, TclGetString(bbPtr->jumpTarget)); - jumpTarget = Tcl_GetHashValue(entry); + jumpTarget = (BasicBlock*)Tcl_GetHashValue(entry); fromOffset = bbPtr->jumpOffset; targetOffset = jumpTarget->startOffset; if (bbPtr->flags & BB_JUMP1) { @@ -3098,7 +3101,7 @@ ResolveJumpTableTargets( auxDataIndex = TclGetInt4AtPtr(envPtr->codeStart + bbPtr->jumpOffset + 1); DEBUG_PRINT("bbPtr = %p jumpOffset = %d auxDataIndex = %d\n", bbPtr, bbPtr->jumpOffset, auxDataIndex); - realJumpTablePtr = TclFetchAuxData(envPtr, auxDataIndex); + realJumpTablePtr = (JumptableInfo*)TclFetchAuxData(envPtr, auxDataIndex); realJumpHashPtr = &realJumpTablePtr->hashTable; /* @@ -3109,12 +3112,12 @@ ResolveJumpTableTargets( for (symEntryPtr = Tcl_FirstHashEntry(symHash, &search); symEntryPtr != NULL; symEntryPtr = Tcl_NextHashEntry(&search)) { - symbolObj = Tcl_GetHashValue(symEntryPtr); + symbolObj = (Tcl_Obj*)Tcl_GetHashValue(symEntryPtr); DEBUG_PRINT(" symbol %s\n", TclGetString(symbolObj)); valEntryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash, TclGetString(symbolObj)); - jumpTargetBBPtr = Tcl_GetHashValue(valEntryPtr); + jumpTargetBBPtr = (BasicBlock*)Tcl_GetHashValue(valEntryPtr); realJumpEntryPtr = Tcl_CreateHashEntry(realJumpHashPtr, Tcl_GetHashKey(symHash, symEntryPtr), &junk); @@ -3493,7 +3496,7 @@ StackCheckBasicBlock( if (result == TCL_OK && blockPtr->jumpTarget != NULL) { entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, TclGetString(blockPtr->jumpTarget)); - jumpTarget = Tcl_GetHashValue(entry); + jumpTarget = (BasicBlock*)Tcl_GetHashValue(entry); result = StackCheckBasicBlock(assemEnvPtr, jumpTarget, blockPtr, stackDepth); } @@ -3507,10 +3510,10 @@ StackCheckBasicBlock( &jtSearch); result == TCL_OK && jtEntry != NULL; jtEntry = Tcl_NextHashEntry(&jtSearch)) { - targetLabel = Tcl_GetHashValue(jtEntry); + targetLabel = (Tcl_Obj*)Tcl_GetHashValue(jtEntry); entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, TclGetString(targetLabel)); - jumpTarget = Tcl_GetHashValue(entry); + jumpTarget = (BasicBlock*)Tcl_GetHashValue(entry); result = StackCheckBasicBlock(assemEnvPtr, jumpTarget, blockPtr, stackDepth); } @@ -3815,7 +3818,7 @@ ProcessCatchesInBasicBlock( if (result == TCL_OK && bbPtr->jumpTarget != NULL) { entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, TclGetString(bbPtr->jumpTarget)); - jumpTarget = Tcl_GetHashValue(entry); + jumpTarget = (BasicBlock*)Tcl_GetHashValue(entry); result = ProcessCatchesInBasicBlock(assemEnvPtr, jumpTarget, jumpEnclosing, jumpState, catchDepth); } @@ -3828,10 +3831,10 @@ ProcessCatchesInBasicBlock( for (jtEntry = Tcl_FirstHashEntry(&bbPtr->jtPtr->hashTable,&jtSearch); result == TCL_OK && jtEntry != NULL; jtEntry = Tcl_NextHashEntry(&jtSearch)) { - targetLabel = Tcl_GetHashValue(jtEntry); + targetLabel = (Tcl_Obj*)Tcl_GetHashValue(jtEntry); entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, TclGetString(targetLabel)); - jumpTarget = Tcl_GetHashValue(entry); + jumpTarget = (BasicBlock*)Tcl_GetHashValue(entry); result = ProcessCatchesInBasicBlock(assemEnvPtr, jumpTarget, jumpEnclosing, jumpState, catchDepth); } @@ -3930,8 +3933,8 @@ BuildExceptionRanges( * Allocate memory for a stack of active catches. */ - catches = ckalloc(maxCatchDepth * sizeof(BasicBlock*)); - catchIndices = ckalloc(maxCatchDepth * sizeof(int)); + catches = (BasicBlock**)ckalloc(maxCatchDepth * sizeof(BasicBlock*)); + catchIndices = (int *)ckalloc(maxCatchDepth * sizeof(int)); for (i = 0; i < maxCatchDepth; ++i) { catches[i] = NULL; catchIndices[i] = -1; @@ -3999,7 +4002,7 @@ UnstackExpiredCatches( * corresponding to the catch contexts */ { ExceptionRange* range; /* Exception range for a specific catch */ - BasicBlock* catch; /* Catch block being examined */ + BasicBlock* block; /* Catch block being examined */ BasicBlockCatchState catchState; /* State of the code relative to the catch * block being examined ("in catch" or @@ -4027,18 +4030,18 @@ UnstackExpiredCatches( */ catchState = bbPtr->catchState; - catch = bbPtr->enclosingCatch; + block = bbPtr->enclosingCatch; while (catchDepth > 0) { --catchDepth; if (catches[catchDepth] != NULL) { - if (catches[catchDepth] != catch || catchState >= BBCS_CAUGHT) { + if (catches[catchDepth] != block || catchState >= BBCS_CAUGHT) { range = envPtr->exceptArrayPtr + catchIndices[catchDepth]; range->numCodeBytes = bbPtr->startOffset - range->codeOffset; catches[catchDepth] = NULL; catchIndices[catchDepth] = -1; } - catchState = catch->catchState; - catch = catch->enclosingCatch; + catchState = block->catchState; + block = block->enclosingCatch; } } } @@ -4067,19 +4070,19 @@ LookForFreshCatches( BasicBlockCatchState catchState; /* State ("in catch" or "caught") of the * current catch. */ - BasicBlock* catch; /* Current enclosing catch */ + BasicBlock* block; /* Current enclosing catch */ int catchDepth; /* Nesting depth of the current catch */ catchState = bbPtr->catchState; - catch = bbPtr->enclosingCatch; + block = bbPtr->enclosingCatch; catchDepth = bbPtr->catchDepth; while (catchDepth > 0) { --catchDepth; - if (catches[catchDepth] != catch && catchState < BBCS_CAUGHT) { - catches[catchDepth] = catch; + if (catches[catchDepth] != block && catchState < BBCS_CAUGHT) { + catches[catchDepth] = block; } - catchState = catch->catchState; - catch = catch->enclosingCatch; + catchState = block->catchState; + block = block->enclosingCatch; } } @@ -4107,7 +4110,7 @@ StackFreshCatches( CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ ExceptionRange* range; /* Exception range for a specific catch */ - BasicBlock* catch; /* Catch block being examined */ + BasicBlock* block; /* Catch block being examined */ BasicBlock* errorExit; /* Error exit from the catch block */ Tcl_HashEntry* entryPtr; @@ -4124,7 +4127,7 @@ StackFreshCatches( * Create an exception range for a block that needs one. */ - catch = catches[catchDepth]; + block = catches[catchDepth]; catchIndices[catchDepth] = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); range = envPtr->exceptArrayPtr + catchIndices[catchDepth]; @@ -4134,13 +4137,13 @@ StackFreshCatches( range->codeOffset = bbPtr->startOffset; entryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash, - TclGetString(catch->jumpTarget)); + TclGetString(block->jumpTarget)); if (entryPtr == NULL) { Tcl_Panic("undefined label in tclAssembly.c:" "BuildExceptionRanges, can't happen"); } - errorExit = Tcl_GetHashValue(entryPtr); + errorExit = (BasicBlock*)Tcl_GetHashValue(entryPtr); range->catchOffset = errorExit->startOffset; } } @@ -4316,6 +4319,8 @@ DupAssembleCodeInternalRep( Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) { + (void)srcPtr; + (void)copyPtr; return; } diff --git a/generic/tclAsync.c b/generic/tclAsync.c index 14804e4..c432e4f 100644 --- a/generic/tclAsync.c +++ b/generic/tclAsync.c @@ -118,7 +118,7 @@ Tcl_AsyncCreate( AsyncHandler *asyncPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - asyncPtr = ckalloc(sizeof(AsyncHandler)); + asyncPtr = (AsyncHandler*)ckalloc(sizeof(AsyncHandler)); asyncPtr->ready = 0; asyncPtr->nextPtr = NULL; asyncPtr->proc = proc; diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 87533ac..ac290b6 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -20,10 +20,50 @@ #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" -#include "tommath.h" +#include "tclTomMath.h" #include <math.h> #include <assert.h> +/* + * TCL_FPCLASSIFY_MODE: + * 0 - fpclassify + * 1 - _fpclass + * 2 - simulate + * 3 - __builtin_fpclassify + */ + +#ifndef TCL_FPCLASSIFY_MODE +#if defined(__MINGW32__) && defined(_X86_) /* mingw 32-bit */ +/* + * MINGW x86 (tested up to gcc 8.1) seems to have a bug in fpclassify, + * [fpclassify 1e-314], x86 => normal, x64 => subnormal, so switch to using a + * version using a compiler built-in. + */ +#define TCL_FPCLASSIFY_MODE 1 +#elif defined(fpclassify) /* fpclassify */ +/* + * This is the C99 standard. + */ +#include <float.h> +#define TCL_FPCLASSIFY_MODE 0 +#elif defined(_FPCLASS_NN) /* _fpclass */ +/* + * This case handles newer MSVC on Windows, which doesn't have the standard + * operation but does have something that can tell us the same thing. + */ +#define TCL_FPCLASSIFY_MODE 1 +#else /* !fpclassify && !_fpclass (older MSVC), simulate */ +/* + * Older MSVC on Windows. So broken that we just have to do it our way. This + * assumes that we're on x86 (or at least a system with classic little-endian + * double layout and a 32-bit 'int' type). + */ +#define TCL_FPCLASSIFY_MODE 2 +#endif /* !fpclassify */ +/* actually there is no fallback to builtin fpclassify */ +#endif /* !TCL_FPCLASSIFY_MODE */ + + #define INTERP_STACK_INITIAL_SIZE 2000 #define CORO_STACK_INITIAL_SIZE 200 @@ -129,6 +169,12 @@ static Tcl_ObjCmdProc ExprDoubleFunc; static Tcl_ObjCmdProc ExprFloorFunc; static Tcl_ObjCmdProc ExprIntFunc; static Tcl_ObjCmdProc ExprIsqrtFunc; +static Tcl_ObjCmdProc ExprIsFiniteFunc; +static Tcl_ObjCmdProc ExprIsInfinityFunc; +static Tcl_ObjCmdProc ExprIsNaNFunc; +static Tcl_ObjCmdProc ExprIsNormalFunc; +static Tcl_ObjCmdProc ExprIsSubnormalFunc; +static Tcl_ObjCmdProc ExprIsUnorderedFunc; static Tcl_ObjCmdProc ExprMaxFunc; static Tcl_ObjCmdProc ExprMinFunc; static Tcl_ObjCmdProc ExprRandFunc; @@ -137,6 +183,7 @@ static Tcl_ObjCmdProc ExprSqrtFunc; static Tcl_ObjCmdProc ExprSrandFunc; static Tcl_ObjCmdProc ExprUnaryFunc; static Tcl_ObjCmdProc ExprWideFunc; +static Tcl_ObjCmdProc FloatClassifyObjCmd; static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; @@ -171,9 +218,13 @@ static Tcl_NRPostProc TEOV_RunLeaveTraces; static Tcl_NRPostProc EvalObjvCore; static Tcl_NRPostProc Dispatch; -static Tcl_ObjCmdProc NRCoroInjectObjCmd; +static Tcl_ObjCmdProc NRInjectObjCmd; static Tcl_NRPostProc NRPostInvoke; static Tcl_ObjCmdProc CoroTypeObjCmd; +static Tcl_ObjCmdProc TclNRCoroInjectObjCmd; +static Tcl_ObjCmdProc TclNRCoroProbeObjCmd; +static Tcl_NRPostProc InjectHandler; +static Tcl_NRPostProc InjectHandlerPostCall; MODULE_SCOPE const TclStubs tclStubs; @@ -243,6 +294,8 @@ static const CmdInfo builtInCmds[] = { {"catch", Tcl_CatchObjCmd, TclCompileCatchCmd, TclNRCatchObjCmd, CMD_IS_SAFE}, {"concat", Tcl_ConcatObjCmd, TclCompileConcatCmd, NULL, CMD_IS_SAFE}, {"continue", Tcl_ContinueObjCmd, TclCompileContinueCmd, NULL, CMD_IS_SAFE}, + {"coroinject", NULL, NULL, TclNRCoroInjectObjCmd, CMD_IS_SAFE}, + {"coroprobe", NULL, NULL, TclNRCoroProbeObjCmd, CMD_IS_SAFE}, {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, @@ -250,6 +303,7 @@ static const CmdInfo builtInCmds[] = { {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, + {"fpclassify", FloatClassifyObjCmd, NULL, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, @@ -366,6 +420,7 @@ static const UnsafeEnsembleInfo unsafeEnsembleCommands[] = { {"file", "size"}, {"file", "stat"}, {"file", "tail"}, + {"file", "tempdir"}, {"file", "tempfile"}, {"file", "type"}, {"file", "volumes"}, @@ -417,7 +472,13 @@ static const BuiltinFuncDef BuiltinFuncTable[] = { { "fmod", ExprBinaryFunc, (ClientData) fmod }, { "hypot", ExprBinaryFunc, (ClientData) hypot }, { "int", ExprIntFunc, NULL }, + { "isfinite", ExprIsFiniteFunc, NULL }, + { "isinf", ExprIsInfinityFunc, NULL }, + { "isnan", ExprIsNaNFunc, NULL }, + { "isnormal", ExprIsNormalFunc, NULL }, { "isqrt", ExprIsqrtFunc, NULL }, + { "issubnormal", ExprIsSubnormalFunc, NULL, }, + { "isunordered", ExprIsUnorderedFunc, NULL, }, { "log", ExprUnaryFunc, (ClientData) log }, { "log10", ExprUnaryFunc, (ClientData) log10 }, { "max", ExprMaxFunc, NULL }, @@ -497,6 +558,14 @@ static const OpCmdInfo mathOpCmds[] = { /* unused */ {0}, NULL}, { "eq", TclSortingOpCmd, TclCompileStreqOpCmd, /* unused */ {0}, NULL}, + { "lt", TclSortingOpCmd, TclCompileStrLtOpCmd, + /* unused */ {0}, NULL}, + { "le", TclSortingOpCmd, TclCompileStrLeOpCmd, + /* unused */ {0}, NULL}, + { "gt", TclSortingOpCmd, TclCompileStrGtOpCmd, + /* unused */ {0}, NULL}, + { "ge", TclSortingOpCmd, TclCompileStrGeOpCmd, + /* unused */ {0}, NULL}, { NULL, NULL, NULL, {0}, NULL} }; @@ -576,7 +645,7 @@ Tcl_CreateInterp(void) char mathFuncName[32]; CallFrame *framePtr; - TclInitSubsystems(); + Tcl_InitSubsystems(); /* * Panic if someone updated the CallFrame structure without also updating @@ -588,13 +657,15 @@ Tcl_CreateInterp(void) Tcl_Panic("Tcl_CallFrame must not be smaller than CallFrame"); } -#if defined(_WIN32) && !defined(_WIN64) - if (sizeof(time_t) != 4) { - /*NOTREACHED*/ - Tcl_Panic("<time.h> is not compatible with MSVC"); - } - if ((TclOffset(Tcl_StatBuf,st_atime) != 32) - || (TclOffset(Tcl_StatBuf,st_ctime) != 40)) { +#if defined(_WIN32) && !defined(_WIN64) && !defined(_USE_64BIT_TIME_T) + /* If Tcl is compiled on Win32 using -D_USE_64BIT_TIME_T + * the result is a binary incompatible with the 'standard' build of + * Tcl: All extensions using Tcl_StatBuf need to be recompiled in + * the same way. Therefore, this is not officially supported. + * In stead, it is recommended to use Win64 or Tcl 9.0 (not released yet) + */ + if ((offsetof(Tcl_StatBuf,st_atime) != 32) + || (offsetof(Tcl_StatBuf,st_ctime) != 40)) { /*NOTREACHED*/ Tcl_Panic("<sys/stat.h> is not compatible with MSVC"); } @@ -976,7 +1047,7 @@ Tcl_CreateInterp(void) /* Coroutine monkeybusiness */ Tcl_NRCreateCommand(interp, "::tcl::unsupported::inject", NULL, - NRCoroInjectObjCmd, NULL, NULL); + NRInjectObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "::tcl::unsupported::corotype", CoroTypeObjCmd, NULL, NULL); @@ -1228,8 +1299,8 @@ int TclHideUnsafeCommands( Tcl_Interp *interp) /* Hide commands in this interpreter. */ { - register const CmdInfo *cmdInfoPtr; - register const UnsafeEnsembleInfo *unsafePtr; + const CmdInfo *cmdInfoPtr; + const UnsafeEnsembleInfo *unsafePtr; if (interp == NULL) { return TCL_ERROR; @@ -2566,7 +2637,7 @@ TclCreateObjCommandInNs( Tcl_Interp *interp, const char *cmdName, /* Name of command, without any namespace * components. */ - Tcl_Namespace *namespace, /* The namespace to create the command in */ + Tcl_Namespace *namesp, /* The namespace to create the command in */ Tcl_ObjCmdProc *proc, /* Object-based function to associate with * name. */ ClientData clientData, /* Arbitrary value to pass to object @@ -2580,7 +2651,7 @@ TclCreateObjCommandInNs( ImportRef *oldRefPtr = NULL; ImportedCmdData *dataPtr; Tcl_HashEntry *hPtr; - Namespace *nsPtr = (Namespace *) namespace; + Namespace *nsPtr = (Namespace *) namesp; /* * If the command name we seek to create already exists, we need to delete @@ -2755,7 +2826,7 @@ int TclInvokeStringCommand( ClientData clientData, /* Points to command's Command structure. */ Tcl_Interp *interp, /* Current interpreter. */ - register int objc, /* Number of arguments. */ + int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Command *cmdPtr = clientData; @@ -2804,7 +2875,7 @@ TclInvokeObjectCommand( ClientData clientData, /* Points to command's Command structure. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ - register const char **argv) /* Argument strings. */ + const char **argv) /* Argument strings. */ { Command *cmdPtr = clientData; Tcl_Obj *objPtr; @@ -3295,7 +3366,7 @@ Tcl_GetCommandFullName( { Interp *iPtr = (Interp *) interp; - register Command *cmdPtr = (Command *) command; + Command *cmdPtr = (Command *) command; char *name; /* @@ -3579,7 +3650,7 @@ CallCommandTraces( * trigger, either TCL_TRACE_DELETE or * TCL_TRACE_RENAME. */ { - register CommandTrace *tracePtr; + CommandTrace *tracePtr; ActiveCommandTrace active; char *result; Tcl_Obj *oldNamePtr = NULL; @@ -3769,7 +3840,7 @@ CancelEvalProc( void TclCleanupCommand( - register Command *cmdPtr) /* Points to the Command structure to + Command *cmdPtr) /* Points to the Command structure to * be freed. */ { if (cmdPtr->refCount-- <= 1) { @@ -4160,7 +4231,7 @@ int TclInterpReady( Tcl_Interp *interp) { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; /* * Reset both the interpreter's string and object results and clear out @@ -4232,7 +4303,7 @@ TclResetCancellation( Tcl_Interp *interp, int force) { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; if (iPtr == NULL) { return TCL_ERROR; @@ -4274,7 +4345,7 @@ Tcl_Canceled( Tcl_Interp *interp, int flags) { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; /* * Has the current script in progress for this interpreter been canceled @@ -5795,7 +5866,7 @@ TclAdvanceLines( const char *start, const char *end) { - register const char *p; + const char *p; for (p = start; p < end; p++) { if (*p == '\n') { @@ -5890,7 +5961,7 @@ TclArgumentEnter( CmdFrame *cfPtr) { Interp *iPtr = (Interp *) interp; - int new, i; + int isNew, i; Tcl_HashEntry *hPtr; CFWord *cfwPtr; @@ -5906,8 +5977,8 @@ TclArgumentEnter( if (cfPtr->line[i] < 0) { continue; } - hPtr = Tcl_CreateHashEntry(iPtr->lineLAPtr, objv[i], &new); - if (new) { + hPtr = Tcl_CreateHashEntry(iPtr->lineLAPtr, objv[i], &isNew); + if (isNew) { /* * The word is not on the stack yet, remember the current location * and initialize references. @@ -6321,7 +6392,7 @@ int Tcl_EvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ - register Tcl_Obj *objPtr, /* Pointer to object containing commands to + Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Supported values @@ -6334,7 +6405,7 @@ int TclEvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ - register Tcl_Obj *objPtr, /* Pointer to object containing commands to + Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Supported values @@ -6353,7 +6424,7 @@ int TclNREvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ - register Tcl_Obj *objPtr, /* Pointer to object containing commands to + Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Supported values @@ -6661,7 +6732,7 @@ Tcl_ExprLong( const char *exprstring, /* Expression to evaluate. */ long *ptr) /* Where to store result. */ { - register Tcl_Obj *exprPtr; + Tcl_Obj *exprPtr; int result = TCL_OK; if (*exprstring == '\0') { /* @@ -6688,7 +6759,7 @@ Tcl_ExprDouble( const char *exprstring, /* Expression to evaluate. */ double *ptr) /* Where to store result. */ { - register Tcl_Obj *exprPtr; + Tcl_Obj *exprPtr; int result = TCL_OK; if (*exprstring == '\0') { @@ -6768,7 +6839,7 @@ int Tcl_ExprLongObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ - register Tcl_Obj *objPtr, /* Expression to evaluate. */ + Tcl_Obj *objPtr, /* Expression to evaluate. */ long *ptr) /* Where to store long result. */ { Tcl_Obj *resultPtr; @@ -6795,8 +6866,8 @@ Tcl_ExprLongObj( return TCL_ERROR; } resultPtr = Tcl_NewBignumObj(&big); - /* FALLTHROUGH */ } + /* FALLTHRU */ case TCL_NUMBER_INT: case TCL_NUMBER_BIG: result = TclGetLongFromObj(interp, resultPtr, ptr); @@ -6815,7 +6886,7 @@ int Tcl_ExprDoubleObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ - register Tcl_Obj *objPtr, /* Expression to evaluate. */ + Tcl_Obj *objPtr, /* Expression to evaluate. */ double *ptr) /* Where to store double result. */ { Tcl_Obj *resultPtr; @@ -6851,7 +6922,7 @@ int Tcl_ExprBooleanObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ - register Tcl_Obj *objPtr, /* Expression to evaluate. */ + Tcl_Obj *objPtr, /* Expression to evaluate. */ int *ptr) /* Where to store 0/1 result. */ { Tcl_Obj *resultPtr; @@ -6963,7 +7034,7 @@ TclNRInvoke( int objc, Tcl_Obj *const objv[]) { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; Tcl_HashTable *hTblPtr; /* Table of hidden commands. */ const char *cmdName; /* Name of the command from objv[0]. */ Tcl_HashEntry *hPtr = NULL; @@ -7158,7 +7229,7 @@ Tcl_AddObjErrorInfo( int length) /* The number of bytes in the message. If < 0, * then append all bytes up to a NULL byte. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; /* * If we are just starting to log an error, errorInfo is initialized from @@ -7308,7 +7379,7 @@ Tcl_GlobalEval( * command. */ const char *command) /* Command to evaluate. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; int result; CallFrame *savedVarFramePtr; @@ -7574,7 +7645,7 @@ ExprIsqrtFunc( if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) { return TCL_ERROR; } - if (big.sign != MP_ZPOS) { + if (mp_isneg(&big)) { mp_clear(&big); goto negarg; } @@ -7820,7 +7891,7 @@ ExprAbsFunc( } goto unChanged; } else if (l == WIDE_MIN) { - TclInitBignumFromWideInt(&big, l); + mp_init_i64(&big, l); goto tooLarge; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l)); @@ -7848,10 +7919,10 @@ ExprAbsFunc( } if (type == TCL_NUMBER_BIG) { - if (((const mp_int *) ptr)->sign != MP_ZPOS) { + if (mp_isneg((const mp_int *) ptr)) { Tcl_GetBignumFromObj(NULL, objv[1], &big); tooLarge: - mp_neg(&big, &big); + (void)mp_neg(&big, &big); Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big)); } else { unChanged: @@ -8276,6 +8347,395 @@ ExprSrandFunc( /* *---------------------------------------------------------------------- * + * Double Classification Functions -- + * + * This page contains the functions that implement all of the built-in + * math functions for classifying IEEE doubles. + * + * These have to be a little bit careful while Tcl_GetDoubleFromObj() + * rejects NaN values, which these functions *explicitly* accept. + * + * Results: + * Each function returns TCL_OK if it succeeds and pushes an Tcl object + * holding the result. If it fails it returns TCL_ERROR and leaves an + * error message in the interpreter's result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + * + * Older MSVC is supported by Tcl, but doesn't have fpclassify(). Of course. + * But it does sometimes have _fpclass() which does almost the same job; if + * even that is absent, we grobble around directly in the platform's binary + * representation of double. + * + * The ClassifyDouble() function makes all that conform to a common API + * (effectively the C99 standard API renamed), and just delegates to the + * standard macro on platforms that do it correctly. + */ + +static inline int +ClassifyDouble( + double d) +{ +#if TCL_FPCLASSIFY_MODE == 0 + return fpclassify(d); +#else /* TCL_FPCLASSIFY_MODE != 0 */ + /* + * If we don't have fpclassify(), we also don't have the values it returns. + * Hence we define those here. + */ +#ifndef FP_NAN +# define FP_NAN 1 /* Value is NaN */ +# define FP_INFINITE 2 /* Value is an infinity */ +# define FP_ZERO 3 /* Value is a zero */ +# define FP_NORMAL 4 /* Value is a normal float */ +# define FP_SUBNORMAL 5 /* Value has lost accuracy */ +#endif /* !FP_NAN */ + +#if TCL_FPCLASSIFY_MODE == 3 + return __builtin_fpclassify( + FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, d); +#elif TCL_FPCLASSIFY_MODE == 2 + /* + * We assume this hack is only needed on little-endian systems. + * Specifically, x86 running Windows. It's fairly easy to enable for + * others if they need it (because their libc/libm is broken) but we'll + * jump that hurdle when requred. We can solve the word ordering then. + */ + + union { + double d; /* Interpret as double */ + struct { + unsigned int low; /* Lower 32 bits */ + unsigned int high; /* Upper 32 bits */ + } w; /* Interpret as unsigned integer words */ + } doubleMeaning; /* So we can look at the representation of a + * double directly. Platform (i.e., processor) + * specific; this is for x86 (and most other + * little-endian processors, but those are + * untested). */ + unsigned int exponent, mantissaLow, mantissaHigh; + /* The pieces extracted from the double. */ + int zeroMantissa; /* Was the mantissa zero? That's special. */ + + /* + * Shifts and masks to use with the doubleMeaning variable above. + */ + +#define EXPONENT_MASK 0x7ff /* 11 bits (after shifting) */ +#define EXPONENT_SHIFT 20 /* Moves exponent to bottom of word */ +#define MANTISSA_MASK 0xfffff /* 20 bits (plus 32 from other word) */ + + /* + * Extract the exponent (11 bits) and mantissa (52 bits). Note that we + * totally ignore the sign bit. + */ + + doubleMeaning.d = d; + exponent = (doubleMeaning.w.high >> EXPONENT_SHIFT) & EXPONENT_MASK; + mantissaLow = doubleMeaning.w.low; + mantissaHigh = doubleMeaning.w.high & MANTISSA_MASK; + zeroMantissa = (mantissaHigh == 0 && mantissaLow == 0); + + /* + * Look for the special cases of exponent. + */ + + switch (exponent) { + case 0: + /* + * When the exponent is all zeros, it's a ZERO or a SUBNORMAL. + */ + + return zeroMantissa ? FP_ZERO : FP_SUBNORMAL; + case EXPONENT_MASK: + /* + * When the exponent is all ones, it's an INF or a NAN. + */ + + return zeroMantissa ? FP_INFINITE : FP_NAN; + default: + /* + * Everything else is a NORMAL double precision float. + */ + + return FP_NORMAL; + } +#elif TCL_FPCLASSIFY_MODE == 1 + switch (_fpclass(d)) { + case _FPCLASS_NZ: + case _FPCLASS_PZ: + return FP_ZERO; + case _FPCLASS_NN: + case _FPCLASS_PN: + return FP_NORMAL; + case _FPCLASS_ND: + case _FPCLASS_PD: + return FP_SUBNORMAL; + case _FPCLASS_NINF: + case _FPCLASS_PINF: + return FP_INFINITE; + default: + Tcl_Panic("result of _fpclass() outside documented range!"); + case _FPCLASS_QNAN: + case _FPCLASS_SNAN: + return FP_NAN; + } +#else /* TCL_FPCLASSIFY_MODE not in (0..3) */ +#error "unknown or unexpected TCL_FPCLASSIFY_MODE" +#endif /* TCL_FPCLASSIFY_MODE */ +#endif /* !fpclassify */ +} + +static int +ExprIsFiniteFunc( + ClientData ignored, + Tcl_Interp *interp, /* The interpreter in which to execute the + * function. */ + int objc, /* Actual parameter count */ + Tcl_Obj *const *objv) /* Actual parameter list */ +{ + double d; + ClientData ptr; + int type, result = 0; + + if (objc != 2) { + MathFuncWrongNumArgs(interp, 2, objc, objv); + return TCL_ERROR; + } + + if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + return TCL_ERROR; + } + if (type != TCL_NUMBER_NAN) { + if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { + return TCL_ERROR; + } + type = ClassifyDouble(d); + result = (type != FP_INFINITE && type != FP_NAN); + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + return TCL_OK; +} + +static int +ExprIsInfinityFunc( + ClientData ignored, + Tcl_Interp *interp, /* The interpreter in which to execute the + * function. */ + int objc, /* Actual parameter count */ + Tcl_Obj *const *objv) /* Actual parameter list */ +{ + double d; + ClientData ptr; + int type, result = 0; + + if (objc != 2) { + MathFuncWrongNumArgs(interp, 2, objc, objv); + return TCL_ERROR; + } + + if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + return TCL_ERROR; + } + if (type != TCL_NUMBER_NAN) { + if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { + return TCL_ERROR; + } + result = (ClassifyDouble(d) == FP_INFINITE); + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + return TCL_OK; +} + +static int +ExprIsNaNFunc( + ClientData ignored, + Tcl_Interp *interp, /* The interpreter in which to execute the + * function. */ + int objc, /* Actual parameter count */ + Tcl_Obj *const *objv) /* Actual parameter list */ +{ + double d; + ClientData ptr; + int type, result = 1; + + if (objc != 2) { + MathFuncWrongNumArgs(interp, 2, objc, objv); + return TCL_ERROR; + } + + if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + return TCL_ERROR; + } + if (type != TCL_NUMBER_NAN) { + if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { + return TCL_ERROR; + } + result = (ClassifyDouble(d) == FP_NAN); + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + return TCL_OK; +} + +static int +ExprIsNormalFunc( + ClientData ignored, + Tcl_Interp *interp, /* The interpreter in which to execute the + * function. */ + int objc, /* Actual parameter count */ + Tcl_Obj *const *objv) /* Actual parameter list */ +{ + double d; + ClientData ptr; + int type, result = 0; + + if (objc != 2) { + MathFuncWrongNumArgs(interp, 2, objc, objv); + return TCL_ERROR; + } + + if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + return TCL_ERROR; + } + if (type != TCL_NUMBER_NAN) { + if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { + return TCL_ERROR; + } + result = (ClassifyDouble(d) == FP_NORMAL); + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + return TCL_OK; +} + +static int +ExprIsSubnormalFunc( + ClientData ignored, + Tcl_Interp *interp, /* The interpreter in which to execute the + * function. */ + int objc, /* Actual parameter count */ + Tcl_Obj *const *objv) /* Actual parameter list */ +{ + double d; + ClientData ptr; + int type, result = 0; + + if (objc != 2) { + MathFuncWrongNumArgs(interp, 2, objc, objv); + return TCL_ERROR; + } + + if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + return TCL_ERROR; + } + if (type != TCL_NUMBER_NAN) { + if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { + return TCL_ERROR; + } + result = (ClassifyDouble(d) == FP_SUBNORMAL); + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + return TCL_OK; +} + +static int +ExprIsUnorderedFunc( + ClientData ignored, + Tcl_Interp *interp, /* The interpreter in which to execute the + * function. */ + int objc, /* Actual parameter count */ + Tcl_Obj *const *objv) /* Actual parameter list */ +{ + double d; + ClientData ptr; + int type, result = 0; + + if (objc != 3) { + MathFuncWrongNumArgs(interp, 3, objc, objv); + return TCL_ERROR; + } + + if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + return TCL_ERROR; + } + if (type == TCL_NUMBER_NAN) { + result = 1; + } else { + d = *((const double *) ptr); + result = (ClassifyDouble(d) == FP_NAN); + } + + if (TclGetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) { + return TCL_ERROR; + } + if (type == TCL_NUMBER_NAN) { + result |= 1; + } else { + d = *((const double *) ptr); + result |= (ClassifyDouble(d) == FP_NAN); + } + + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + return TCL_OK; +} + +static int +FloatClassifyObjCmd( + ClientData ignored, + Tcl_Interp *interp, /* The interpreter in which to execute the + * function. */ + int objc, /* Actual parameter count */ + Tcl_Obj *const *objv) /* Actual parameter list */ +{ + double d; + Tcl_Obj *objPtr; + ClientData ptr; + int type; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "floatValue"); + return TCL_ERROR; + } + + if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + return TCL_ERROR; + } + if (type == TCL_NUMBER_NAN) { + goto gotNaN; + } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { + return TCL_ERROR; + } + switch (ClassifyDouble(d)) { + case FP_INFINITE: + TclNewLiteralStringObj(objPtr, "infinite"); + break; + case FP_NAN: + gotNaN: + TclNewLiteralStringObj(objPtr, "nan"); + break; + case FP_NORMAL: + TclNewLiteralStringObj(objPtr, "normal"); + break; + case FP_SUBNORMAL: + TclNewLiteralStringObj(objPtr, "subnormal"); + break; + case FP_ZERO: + TclNewLiteralStringObj(objPtr, "zero"); + break; + default: + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "unable to classify number: %f", d)); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * MathFuncWrongNumArgs -- * * Generate an error message when a math function presents the wrong @@ -9278,27 +9738,47 @@ CoroTypeObjCmd( /* *---------------------------------------------------------------------- * - * NRCoroInjectObjCmd -- + * TclNRCoroInjectObjCmd, TclNRCoroProbeObjCmd -- * - * Implementation of [::tcl::unsupported::inject] command. + * Implementation of [coroinject] and [coroprobe] commands. * *---------------------------------------------------------------------- */ +static inline CoroutineData * +GetCoroutineFromObj( + Tcl_Interp *interp, + Tcl_Obj *objPtr, + const char *errMsg) +{ + /* + * How to get a coroutine from its handle. + */ + + Command *cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objPtr); + + if ((!cmdPtr) || (cmdPtr->nreProc != TclNRInterpCoroutine)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1)); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE", + TclGetString(objPtr), NULL); + return NULL; + } + return cmdPtr->objClientData; +} + static int -NRCoroInjectObjCmd( +TclNRCoroInjectObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Command *cmdPtr; CoroutineData *corPtr; ExecEnv *savedEEPtr = iPtr->execEnvPtr; /* * Usage more or less like tailcall: - * inject coroName cmd ?arg1 arg2 ...? + * coroinject coroName cmd ?arg1 arg2 ...? */ if (objc < 3) { @@ -9306,16 +9786,249 @@ NRCoroInjectObjCmd( return TCL_ERROR; } - cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[1]); - if ((!cmdPtr) || (cmdPtr->nreProc != TclNRInterpCoroutine)) { + corPtr = GetCoroutineFromObj(interp, objv[1], + "can only inject a command into a coroutine"); + if (!corPtr) { + return TCL_ERROR; + } + if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "can only inject a command into a coroutine", -1)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE", - TclGetString(objv[1]), NULL); + "can only inject a command into a suspended coroutine", -1)); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", NULL); return TCL_ERROR; } - corPtr = cmdPtr->objClientData; + /* + * Add the callback to the coro's execEnv, so that it is the first thing + * to happen when the coro is resumed. + */ + + iPtr->execEnvPtr = corPtr->eePtr; + TclNRAddCallback(interp, InjectHandler, corPtr, + Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), NULL); + iPtr->execEnvPtr = savedEEPtr; + + return TCL_OK; +} + +static int +TclNRCoroProbeObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + CoroutineData *corPtr; + ExecEnv *savedEEPtr = iPtr->execEnvPtr; + int numLevels, unused; + int *stackLevel = &unused; + + /* + * Usage more or less like tailcall: + * coroprobe coroName cmd ?arg1 arg2 ...? + */ + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); + return TCL_ERROR; + } + + corPtr = GetCoroutineFromObj(interp, objv[1], + "can only inject a probe command into a coroutine"); + if (!corPtr) { + return TCL_ERROR; + } + if (!COR_IS_SUSPENDED(corPtr)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "can only inject a probe command into a suspended coroutine", + -1)); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", NULL); + return TCL_ERROR; + } + + /* + * Add the callback to the coro's execEnv, so that it is the first thing + * to happen when the coro is resumed. + */ + + iPtr->execEnvPtr = corPtr->eePtr; + TclNRAddCallback(interp, InjectHandler, corPtr, + Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), corPtr); + iPtr->execEnvPtr = savedEEPtr; + + /* + * Now we immediately transfer control to the coroutine to run our probe. + * TRICKY STUFF copied from the [yield] implementation. + * + * Push the callback to restore the caller's context on yield back. + */ + + TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr, + NULL, NULL, NULL); + + /* + * Record the stackLevel at which the resume is happening, then swap + * the interp's environment to make it suitable to run this coroutine. + */ + + corPtr->stackLevel = stackLevel; + numLevels = corPtr->auxNumLevels; + corPtr->auxNumLevels = iPtr->numLevels; + + /* + * Do the actual stack swap. + */ + + SAVE_CONTEXT(corPtr->caller); + corPtr->callerEEPtr = iPtr->execEnvPtr; + RESTORE_CONTEXT(corPtr->running); + iPtr->execEnvPtr = corPtr->eePtr; + iPtr->numLevels += numLevels; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * InjectHandler, InjectHandlerPostProc -- + * + * Part of the implementation of [coroinject] and [coroprobe]. These are + * run inside the context of the coroutine being injected/probed into. + * + * InjectHandler runs a script (possibly adding arguments) in the context + * of the coroutine. The script is specified as a one-shot list (with + * reference count equal to 1) in data[1]. This function also arranges + * for InjectHandlerPostProc to be the part that runs after the script + * completes. + * + * InjectHandlerPostProc cleans up after InjectHandler (deleting the + * list) and, for the [coroprobe] command *only*, yields back to the + * caller context (i.e., where [coroprobe] was run). + *s + *---------------------------------------------------------------------- + */ + +static int +InjectHandler( + ClientData data[], + Tcl_Interp *interp, + int result) +{ + CoroutineData *corPtr = data[0]; + Tcl_Obj *listPtr = data[1]; + int nargs = PTR2INT(data[2]); + ClientData isProbe = data[3]; + int objc; + Tcl_Obj **objv; + + if (!isProbe) { + /* + * If this is [coroinject], add the extra arguments now. + */ + + if (nargs == COROUTINE_ARGUMENTS_SINGLE_OPTIONAL) { + Tcl_ListObjAppendElement(NULL, listPtr, + Tcl_NewStringObj("yield", -1)); + } else if (nargs == COROUTINE_ARGUMENTS_ARBITRARY) { + Tcl_ListObjAppendElement(NULL, listPtr, + Tcl_NewStringObj("yieldto", -1)); + } else { + /* + * I don't think this is reachable... + */ + + Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewIntObj(nargs)); + } + Tcl_ListObjAppendElement(NULL, listPtr, Tcl_GetObjResult(interp)); + } + + /* + * Call the user's script; we're in the right place. + */ + + Tcl_IncrRefCount(listPtr); + TclMarkTailcall(interp); + TclNRAddCallback(interp, InjectHandlerPostCall, corPtr, listPtr, + INT2PTR(nargs), isProbe); + TclListObjGetElements(NULL, listPtr, &objc, &objv); + return TclNREvalObjv(interp, objc, objv, 0, NULL); +} + +static int +InjectHandlerPostCall( + ClientData data[], + Tcl_Interp *interp, + int result) +{ + CoroutineData *corPtr = data[0]; + Tcl_Obj *listPtr = data[1]; + int nargs = PTR2INT(data[2]); + ClientData isProbe = data[3]; + int numLevels; + + /* + * Delete the command words for what we just executed. + */ + + Tcl_DecrRefCount(listPtr); + + /* + * If we were doing a probe, splice ourselves back out of the stack + * cleanly here. General injection should instead just look after itself. + * + * Code from guts of [yield] implementation. + */ + + if (isProbe) { + if (result == TCL_ERROR) { + Tcl_AddErrorInfo(interp, + "\n (injected coroutine probe command)"); + } + corPtr->nargs = nargs; + corPtr->stackLevel = NULL; + numLevels = iPtr->numLevels; + iPtr->numLevels = corPtr->auxNumLevels; + corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels; + iPtr->execEnvPtr = corPtr->callerEEPtr; + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * NRInjectObjCmd -- + * + * Implementation of [::tcl::unsupported::inject] command. + * + *---------------------------------------------------------------------- + */ + +static int +NRInjectObjCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + CoroutineData *corPtr; + ExecEnv *savedEEPtr = iPtr->execEnvPtr; + + /* + * Usage more or less like tailcall: + * inject coroName cmd ?arg1 arg2 ...? + */ + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); + return TCL_ERROR; + } + + corPtr = GetCoroutineFromObj(interp, objv[1], + "can only inject a command into a coroutine"); + if (!corPtr) { + return TCL_ERROR; + } if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only inject a command into a suspended coroutine", -1)); diff --git a/generic/tclBinary.c b/generic/tclBinary.c index 246c371..8ba0fab 100644 --- a/generic/tclBinary.c +++ b/generic/tclBinary.c @@ -12,7 +12,7 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tclTomMath.h" #include <math.h> #include <assert.h> @@ -159,93 +159,88 @@ static const EnsembleImplMap decodeMap[] = { }; /* - * The following object types represent an array of bytes. The intent is - * to allow arbitrary binary data to pass through Tcl as a Tcl value - * without loss or damage. Such values are useful for things like - * encoded strings or Tk images to name just two. - * - * It's strange to have two Tcl_ObjTypes in place for this task when - * one would do, so a bit of detail and history how we got to this point - * and where we might go from here. - * - * A bytearray is an ordered sequence of bytes. Each byte is an integer - * value in the range [0-255]. To be a Tcl value type, we need a way to - * encode each value in the value set as a Tcl string. The simplest - * encoding is to represent each byte value as the same codepoint value. - * A bytearray of N bytes is encoded into a Tcl string of N characters - * where the codepoint of each character is the value of corresponding byte. - * This approach creates a one-to-one map between all bytearray values - * and a subset of Tcl string values. + * The following object types represent an array of bytes. The intent is to + * allow arbitrary binary data to pass through Tcl as a Tcl value without loss + * or damage. Such values are useful for things like encoded strings or Tk + * images to name just two. + * + * It's strange to have two Tcl_ObjTypes in place for this task when one would + * do, so a bit of detail and history how we got to this point and where we + * might go from here. + * + * A bytearray is an ordered sequence of bytes. Each byte is an integer value + * in the range [0-255]. To be a Tcl value type, we need a way to encode each + * value in the value set as a Tcl string. The simplest encoding is to + * represent each byte value as the same codepoint value. A bytearray of N + * bytes is encoded into a Tcl string of N characters where the codepoint of + * each character is the value of corresponding byte. This approach creates a + * one-to-one map between all bytearray values and a subset of Tcl string + * values. * * When converting a Tcl string value to the bytearray internal rep, the * question arises what to do with strings outside that subset? That is, - * those Tcl strings containing at least one codepoint greater than 255? - * The obviously correct answer is to raise an error! That string value - * does not represent any valid bytearray value. Full Stop. The - * setFromAnyProc signature has a completion code return value for just - * this reason, to reject invalid inputs. - * - * Unfortunately this was not the path taken by the authors of the - * original tclByteArrayType. They chose to accept all Tcl string values - * as acceptable string encodings of the bytearray values that result - * from masking away the high bits of any codepoint value at all. This - * meant that every bytearray value had multiple accepted string - * representations. - * - * The implications of this choice are truly ugly. When a Tcl value has - * a string representation, we are required to accept that as the true - * value. Bytearray values that possess a string representation cannot - * be processed as bytearrays because we cannot know which true value - * that bytearray represents. The consequence is that we drag around - * an internal rep that we cannot make any use of. This painful price - * is extracted at any point after a string rep happens to be generated - * for the value. This happens even when the troublesome codepoints - * outside the byte range never show up. This happens rather routinely - * in normal Tcl operations unless we burden the script writer with the - * cognitive burden of avoiding it. The price is also paid by callers - * of the C interface. The routine + * those Tcl strings containing at least one codepoint greater than 255? The + * obviously correct answer is to raise an error! That string value does not + * represent any valid bytearray value. Full Stop. The setFromAnyProc + * signature has a completion code return value for just this reason, to + * reject invalid inputs. + * + * Unfortunately this was not the path taken by the authors of the original + * tclByteArrayType. They chose to accept all Tcl string values as acceptable + * string encodings of the bytearray values that result from masking away the + * high bits of any codepoint value at all. This meant that every bytearray + * value had multiple accepted string representations. + * + * The implications of this choice are truly ugly. When a Tcl value has a + * string representation, we are required to accept that as the true value. + * Bytearray values that possess a string representation cannot be processed + * as bytearrays because we cannot know which true value that bytearray + * represents. The consequence is that we drag around an internal rep that we + * cannot make any use of. This painful price is extracted at any point after + * a string rep happens to be generated for the value. This happens even when + * the troublesome codepoints outside the byte range never show up. This + * happens rather routinely in normal Tcl operations unless we burden the + * script writer with the cognitive burden of avoiding it. The price is also + * paid by callers of the C interface. The routine * * unsigned char *Tcl_GetByteArrayFromObj(objPtr, lenPtr) * - * has a guarantee to always return a non-NULL value, but that value - * points to a byte sequence that cannot be used by the caller to - * process the Tcl value absent some sideband testing that objPtr - * is "pure". Tcl offers no public interface to perform this test, - * so callers either break encapsulation or are unavoidably buggy. Tcl - * has defined a public interface that cannot be used correctly. The - * Tcl source code itself suffers the same problem, and has been buggy, - * but progressively less so as more and more portions of the code have - * been retrofitted with the required "purity testing". The set of values - * able to pass the purity test can be increased via the introduction of - * a "canonical" flag marker, but the only way the broken interface itself + * has a guarantee to always return a non-NULL value, but that value points to + * a byte sequence that cannot be used by the caller to process the Tcl value + * absent some sideband testing that objPtr is "pure". Tcl offers no public + * interface to perform this test, so callers either break encapsulation or + * are unavoidably buggy. Tcl has defined a public interface that cannot be + * used correctly. The Tcl source code itself suffers the same problem, and + * has been buggy, but progressively less so as more and more portions of the + * code have been retrofitted with the required "purity testing". The set of + * values able to pass the purity test can be increased via the introduction + * of a "canonical" flag marker, but the only way the broken interface itself * can be discarded is to start over and define the Tcl_ObjType properly. - * Bytearrays should simply be usable as bytearrays without a kabuki - * dance of testing. - * - * The Tcl_ObjType "properByteArrayType" is (nearly) a correct - * implementation of bytearrays. Any Tcl value with the type - * properByteArrayType can have its bytearray value fetched and - * used with confidence that acting on that value is equivalent to - * acting on the true Tcl string value. This still implies a side - * testing burden -- past mistakes will not let us avoid that - * immediately, but it is at least a conventional test of type, and - * can be implemented entirely by examining the objPtr fields, with - * no need to query the intrep, as a canonical flag would require. - * - * Until Tcl_GetByteArrayFromObj() and Tcl_SetByteArrayLength() can - * be revised to admit the possibility of returning NULL when the true - * value is not a valid bytearray, we need a mechanism to retain - * compatibility with the deployed callers of the broken interface. - * That's what the retained "tclByteArrayType" provides. In those - * unusual circumstances where we convert an invalid bytearray value - * to a bytearray type, it is to this legacy type. Essentially any - * time this legacy type gets used, it's a signal of a bug being ignored. - * A TIP should be drafted to remove this connection to the broken past - * so that Tcl 9 will no longer have any trace of it. Prescribing a - * migration path will be the key element of that work. The internal - * changes now in place are the limit of what can be done short of - * interface repair. They provide a great expansion of the histories - * over which bytearray values can be useful in the meanwhile. + * Bytearrays should simply be usable as bytearrays without a kabuki dance of + * testing. + * + * The Tcl_ObjType "properByteArrayType" is (nearly) a correct implementation + * of bytearrays. Any Tcl value with the type properByteArrayType can have + * its bytearray value fetched and used with confidence that acting on that + * value is equivalent to acting on the true Tcl string value. This still + * implies a side testing burden -- past mistakes will not let us avoid that + * immediately, but it is at least a conventional test of type, and can be + * implemented entirely by examining the objPtr fields, with no need to query + * the intrep, as a canonical flag would require. + * + * Until Tcl_GetByteArrayFromObj() and Tcl_SetByteArrayLength() can be revised + * to admit the possibility of returning NULL when the true value is not a + * valid bytearray, we need a mechanism to retain compatibility with the + * deployed callers of the broken interface. That's what the retained + * "tclByteArrayType" provides. In those unusual circumstances where we + * convert an invalid bytearray value to a bytearray type, it is to this + * legacy type. Essentially any time this legacy type gets used, it's a + * signal of a bug being ignored. A TIP should be drafted to remove this + * connection to the broken past so that Tcl 9 will no longer have any trace + * of it. Prescribing a migration path will be the key element of that work. + * The internal changes now in place are the limit of what can be done short + * of interface repair. They provide a great expansion of the histories over + * which bytearray values can be useful in the meanwhile. */ static const Tcl_ObjType properByteArrayType = { @@ -282,7 +277,7 @@ typedef struct ByteArray { } ByteArray; #define BYTEARRAY_SIZE(len) \ - ((unsigned) (TclOffset(ByteArray, bytes) + (len))) + (offsetof(ByteArray, bytes) + (len)) #define GET_BYTEARRAY(irPtr) ((ByteArray *) (irPtr)->twoPtrValue.ptr1) #define SET_BYTEARRAY(irPtr, baPtr) \ (irPtr)->twoPtrValue.ptr1 = (void *) (baPtr) @@ -400,10 +395,10 @@ Tcl_DbNewByteArrayObj( void Tcl_SetByteArrayObj( Tcl_Obj *objPtr, /* Object to initialize as a ByteArray. */ - const unsigned char *bytes, /* The array of bytes to use as the new - value. May be NULL even if length > 0. */ + const unsigned char *bytes, /* The array of bytes to use as the new value. + * May be NULL even if length > 0. */ int length) /* Length of the array of bytes, which must - be >= 0. */ + * be >= 0. */ { ByteArray *byteArrayPtr; Tcl_ObjIntRep ir; @@ -723,14 +718,16 @@ UpdateStringOfByteArray( if (size == length) { char *dst = Tcl_InitStringRep(objPtr, (char *)src, size); + TclOOM(dst, size); } else { char *dst = Tcl_InitStringRep(objPtr, NULL, size); + TclOOM(dst, size); for (i = 0; i < length; i++) { dst += Tcl_UniCharToUtf(src[i], dst); } - (void)Tcl_InitStringRep(objPtr, NULL, size); + (void) Tcl_InitStringRep(objPtr, NULL, size); } } @@ -778,7 +775,7 @@ TclAppendBytesToByteArray( return; } - length = (unsigned int)len; + length = (unsigned int) len; irPtr = TclFetchIntRep(objPtr, &properByteArrayType); if (irPtr == NULL) { @@ -807,12 +804,18 @@ TclAppendBytesToByteArray( unsigned int attempt; if (needed <= INT_MAX/2) { - /* Try to allocate double the total space that is needed. */ + /* + * Try to allocate double the total space that is needed. + */ + attempt = 2 * needed; ptr = attemptckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt)); } if (ptr == NULL) { - /* Try to allocate double the increment that is needed (plus). */ + /* + * Try to allocate double the increment that is needed (plus). + */ + unsigned int limit = INT_MAX - needed; unsigned int extra = length + TCL_MIN_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); @@ -821,7 +824,10 @@ TclAppendBytesToByteArray( ptr = attemptckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt)); } if (ptr == NULL) { - /* Last chance: Try to allocate exactly what is needed. */ + /* + * Last chance: Try to allocate exactly what is needed. + */ + attempt = needed; ptr = ckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt)); } @@ -896,7 +902,7 @@ BinaryFormatCmd( int count; /* Count associated with current format * character. */ int flags; /* Format field flags */ - const char *format; /* Pointer to current position in format + const char *format; /* Pointer to current position in format * string. */ Tcl_Obj *resultPtr = NULL; /* Object holding result buffer. */ unsigned char *buffer; /* Start of result buffer. */ @@ -1082,9 +1088,9 @@ BinaryFormatCmd( memset(buffer, 0, length); /* - * Pack the data into the result object. Note that we can skip the - * error checking during this pass, since we have already parsed the - * string once. + * Pack the data into the result object. Note that we can skip the error + * checking during this pass, since we have already parsed the string + * once. */ arg = 2; @@ -1297,7 +1303,7 @@ BinaryFormatCmd( } arg++; for (i = 0; i < count; i++) { - if (FormatNumber(interp, cmd, listv[i], &cursor)!=TCL_OK) { + if (FormatNumber(interp, cmd, listv[i], &cursor) != TCL_OK) { Tcl_DecrRefCount(resultPtr); return TCL_ERROR; } @@ -1401,7 +1407,7 @@ BinaryScanCmd( int count; /* Count associated with current format * character. */ int flags; /* Format field flags */ - const char *format; /* Pointer to current position in format + const char *format; /* Pointer to current position in format * string. */ Tcl_Obj *resultPtr = NULL; /* Object holding result buffer. */ unsigned char *buffer; /* Start of result buffer. */ @@ -1460,7 +1466,7 @@ BinaryScanCmd( if (cmd == 'A') { while (size > 0) { - if (src[size-1] != '\0' && src[size-1] != ' ') { + if (src[size - 1] != '\0' && src[size - 1] != ' ') { break; } size--; @@ -2055,6 +2061,7 @@ FormatNumber( if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) { const Tcl_ObjIntRep *irPtr = TclFetchIntRep(src, &tclDoubleType); + if (irPtr == NULL) { return TCL_ERROR; } @@ -2067,7 +2074,7 @@ FormatNumber( * valid range for float. */ - if (fabs(dvalue) > (double)FLT_MAX) { + if (fabs(dvalue) > (double) FLT_MAX) { fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX; } else { fvalue = (float) dvalue; @@ -2188,9 +2195,9 @@ ScanNumber( int type, /* Format character from "binary scan" */ int flags, /* Format field flags */ Tcl_HashTable **numberCachePtrPtr) - /* Place to look for cache of scanned - * value objects, or NULL if too many - * different numbers have been scanned. */ + /* Place to look for cache of scanned value + * objects, or NULL if too many different + * numbers have been scanned. */ { long value; float fvalue; @@ -2264,6 +2271,7 @@ ScanNumber( /* * Check to see if the value was sign extended properly on systems * where an int is more than 32-bits. + * * We avoid caching unsigned integers as we cannot distinguish between * 32bit signed and unsigned in the hash (short and char are ok). */ @@ -2271,17 +2279,17 @@ ScanNumber( if (flags & BINARY_UNSIGNED) { return Tcl_NewWideIntObj((Tcl_WideInt)(unsigned long)value); } - if ((value & (((unsigned) 1)<<31)) && (value > 0)) { - value -= (((unsigned) 1)<<31); - value -= (((unsigned) 1)<<31); + if ((value & (((unsigned) 1) << 31)) && (value > 0)) { + value -= (((unsigned) 1) << 31); + value -= (((unsigned) 1) << 31); } returnNumericObject: if (*numberCachePtrPtr == NULL) { return Tcl_NewWideIntObj(value); } else { - register Tcl_HashTable *tablePtr = *numberCachePtrPtr; - register Tcl_HashEntry *hPtr; + Tcl_HashTable *tablePtr = *numberCachePtrPtr; + Tcl_HashEntry *hPtr; int isNew; hPtr = Tcl_CreateHashEntry(tablePtr, INT2PTR(value), &isNew); @@ -2289,7 +2297,7 @@ ScanNumber( return Tcl_GetHashValue(hPtr); } if (tablePtr->numEntries <= BINARY_SCAN_MAX_CACHE) { - register Tcl_Obj *objPtr = Tcl_NewWideIntObj(value); + Tcl_Obj *objPtr = Tcl_NewWideIntObj(value); Tcl_IncrRefCount(objPtr); Tcl_SetHashValue(hPtr, objPtr); @@ -2341,8 +2349,9 @@ ScanNumber( Tcl_Obj *bigObj = NULL; mp_int big; - TclInitBignumFromWideUInt(&big, uwvalue); - bigObj = Tcl_NewBignumObj(&big); + if (mp_init_u64(&big, uwvalue) == MP_OKAY) { + bigObj = Tcl_NewBignumObj(&big); + } return bigObj; } return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue); @@ -2408,7 +2417,7 @@ DeleteScanNumberCache( hEntry = Tcl_FirstHashEntry(numberCachePtr, &search); while (hEntry != NULL) { - register Tcl_Obj *value = Tcl_GetHashValue(hEntry); + Tcl_Obj *value = Tcl_GetHashValue(hEntry); if (value != NULL) { Tcl_DecrRefCount(value); @@ -2473,8 +2482,8 @@ BinaryEncodeHex( data = Tcl_GetByteArrayFromObj(objv[1], &count); cursor = Tcl_SetByteArrayLength(resultObj, count * 2); for (offset = 0; offset < count; ++offset) { - *cursor++ = HexDigits[((data[offset] >> 4) & 0x0f)]; - *cursor++ = HexDigits[(data[offset] & 0x0f)]; + *cursor++ = HexDigits[(data[offset] >> 4) & 0x0f]; + *cursor++ = HexDigits[data[offset] & 0x0f]; } Tcl_SetObjResult(interp, resultObj); return TCL_OK; @@ -2514,7 +2523,7 @@ BinaryDecodeHex( Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } - for (i = 1; i < objc-1; ++i) { + for (i = 1; i < objc - 1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; @@ -2528,13 +2537,13 @@ BinaryDecodeHex( TclNewObj(resultObj); datastart = data = (unsigned char *) - TclGetStringFromObj(objv[objc-1], &count); + TclGetStringFromObj(objv[objc - 1], &count); dataend = data + count; size = (count + 1) / 2; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); while (data < dataend) { value = 0; - for (i=0 ; i<2 ; i++) { + for (i = 0 ; i < 2 ; i++) { if (data >= dataend) { value <<= 4; break; @@ -2557,7 +2566,7 @@ BinaryDecodeHex( if (c > 16) { c += ('A' - 'a'); } - value |= (c & 0xf); + value |= c & 0xf; } if (i < 2) { cut++; @@ -2628,22 +2637,22 @@ BinaryEncode64( const char *wrapchar = "\n"; int wrapcharlen = 1; int offset, i, index, size, outindex = 0, count = 0; - enum {OPT_MAXLEN, OPT_WRAPCHAR }; + enum { OPT_MAXLEN, OPT_WRAPCHAR }; static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL }; - if (objc < 2 || objc%2 != 0) { + if (objc < 2 || objc % 2 != 0) { Tcl_WrongNumArgs(interp, 1, objv, "?-maxlen len? ?-wrapchar char? data"); return TCL_ERROR; } - for (i = 1; i < objc-1; i += 2) { + for (i = 1; i < objc - 1; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case OPT_MAXLEN: - if (Tcl_GetIntFromObj(interp, objv[i+1], &maxlen) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) { return TCL_ERROR; } if (maxlen < 0) { @@ -2655,7 +2664,7 @@ BinaryEncode64( } break; case OPT_WRAPCHAR: - wrapchar = TclGetStringFromObj(objv[i+1], &wrapcharlen); + wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen); if (wrapcharlen == 0) { maxlen = 0; } @@ -2664,9 +2673,9 @@ BinaryEncode64( } resultObj = Tcl_NewObj(); - data = Tcl_GetByteArrayFromObj(objv[objc-1], &count); + data = Tcl_GetByteArrayFromObj(objv[objc - 1], &count); if (count > 0) { - size = (((count * 4) / 3) + 3) & ~3; /* ensure 4 byte chunks */ + size = (((count * 4) / 3) + 3) & ~3; /* ensure 4 byte chunks */ if (maxlen > 0 && size > maxlen) { int adjusted = size + (wrapcharlen * (size / maxlen)); @@ -2677,15 +2686,15 @@ BinaryEncode64( } cursor = Tcl_SetByteArrayLength(resultObj, size); limit = cursor + size; - for (offset = 0; offset < count; offset+=3) { + for (offset = 0; offset < count; offset += 3) { unsigned char d[3] = {0, 0, 0}; - for (i = 0; i < 3 && offset+i < count; ++i) { + for (i = 0; i < 3 && offset + i < count; ++i) { d[i] = data[offset + i]; } OUTPUT(B64Digits[d[0] >> 2]); OUTPUT(B64Digits[((d[0] & 0x03) << 4) | (d[1] >> 4)]); - if (offset+1 < count) { + if (offset + 1 < count) { OUTPUT(B64Digits[((d[1] & 0x0f) << 2) | (d[2] >> 6)]); } else { OUTPUT(B64Digits[64]); @@ -2738,19 +2747,20 @@ BinaryEncodeUu( enum { OPT_MAXLEN, OPT_WRAPCHAR }; static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL }; - if (objc < 2 || objc%2 != 0) { + if (objc < 2 || objc % 2 != 0) { Tcl_WrongNumArgs(interp, 1, objv, "?-maxlen len? ?-wrapchar char? data"); return TCL_ERROR; } - for (i = 1; i < objc-1; i += 2) { + for (i = 1; i < objc - 1; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case OPT_MAXLEN: - if (Tcl_GetIntFromObj(interp, objv[i+1], &lineLength) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[i + 1], + &lineLength) != TCL_OK) { return TCL_ERROR; } if (lineLength < 3 || lineLength > 85) { @@ -2762,7 +2772,7 @@ BinaryEncodeUu( } break; case OPT_WRAPCHAR: - wrapchar = Tcl_GetByteArrayFromObj(objv[i+1], &wrapcharlen); + wrapchar = Tcl_GetByteArrayFromObj(objv[i + 1], &wrapcharlen); break; } } @@ -2774,7 +2784,7 @@ BinaryEncodeUu( resultObj = Tcl_NewObj(); offset = 0; - data = Tcl_GetByteArrayFromObj(objv[objc-1], &count); + data = Tcl_GetByteArrayFromObj(objv[objc - 1], &count); rawLength = (lineLength - 1) * 3 / 4; start = cursor = Tcl_SetByteArrayLength(resultObj, (lineLength + wrapcharlen) * @@ -2795,11 +2805,11 @@ BinaryEncodeUu( lineLen = rawLength; } *cursor++ = UueDigits[lineLen]; - for (i=0 ; i<lineLen ; i++) { + for (i = 0 ; i < lineLen ; i++) { n <<= 8; n |= data[offset++]; for (bits += 8; bits > 6 ; bits -= 6) { - *cursor++ = UueDigits[(n >> (bits-6)) & 0x3f]; + *cursor++ = UueDigits[(n >> (bits - 6)) & 0x3f]; } } if (bits > 0) { @@ -2807,7 +2817,7 @@ BinaryEncodeUu( *cursor++ = UueDigits[(n >> (bits + 2)) & 0x3f]; bits = 0; } - for (j=0 ; j<wrapcharlen ; ++j) { + for (j = 0 ; j < wrapcharlen ; ++j) { *cursor++ = wrapchar[j]; } } @@ -2816,7 +2826,7 @@ BinaryEncodeUu( * Fix the length of the output bytearray. */ - Tcl_SetByteArrayLength(resultObj, cursor-start); + Tcl_SetByteArrayLength(resultObj, cursor - start); Tcl_SetObjResult(interp, resultObj); return TCL_OK; } @@ -2849,14 +2859,14 @@ BinaryDecodeUu( unsigned char *begin, *cursor; int i, index, size, count = 0, strict = 0, lineLen; unsigned char c; - enum {OPT_STRICT }; + enum { OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } - for (i = 1; i < objc-1; ++i) { + for (i = 1; i < objc - 1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; @@ -2870,7 +2880,7 @@ BinaryDecodeUu( TclNewObj(resultObj); datastart = data = (unsigned char *) - TclGetStringFromObj(objv[objc-1], &count); + TclGetStringFromObj(objv[objc - 1], &count); dataend = data + count; size = ((count + 3) & ~3) * 3 / 4; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); @@ -2902,7 +2912,7 @@ BinaryDecodeUu( * Now we read a four-character grouping. */ - for (i=0 ; i<4 ; i++) { + for (i = 0 ; i < 4 ; i++) { if (data < dataend) { d[i] = c = *data++; if (c < 32 || c > 96) { @@ -3020,7 +3030,7 @@ BinaryDecode64( Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } - for (i = 1; i < objc-1; ++i) { + for (i = 1; i < objc - 1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; @@ -3034,7 +3044,7 @@ BinaryDecode64( TclNewObj(resultObj); datastart = data = (unsigned char *) - TclGetStringFromObj(objv[objc-1], &count); + TclGetStringFromObj(objv[objc - 1], &count); dataend = data + count; size = ((count + 3) & ~3) * 3 / 4; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); @@ -3062,8 +3072,11 @@ BinaryDecode64( c = '='; } else { if (strict && i <= 1) { - /* single resp. unfulfilled char (each 4th next single char) - * is rather bad64 error case in strict mode */ + /* + * Single resp. unfulfilled char (each 4th next single + * char) is rather bad64 error case in strict mode. + */ + goto bad64; } cut += 3; @@ -3079,10 +3092,10 @@ BinaryDecode64( if (cut) { if (c == '=' && i > 1) { - value <<= 6; - cut++; + value <<= 6; + cut++; } else if (!strict && TclIsSpaceProc(c)) { - i--; + i--; } else { goto bad64; } @@ -3096,11 +3109,15 @@ BinaryDecode64( value = (value << 6) | 0x3e; } else if (c == '/') { value = (value << 6) | 0x3f; - } else if (c == '=' && ( - !strict || i > 1) /* "=" and "a=" is rather bad64 error case in strict mode */ - ) { + } else if (c == '=' && (!strict || i > 1)) { + /* + * "=" and "a=" is rather bad64 error case in strict mode. + */ + value <<= 6; - if (i) cut++; + if (i) { + cut++; + } } else if (strict || !TclIsSpaceProc(c)) { goto bad64; } else { @@ -3147,4 +3164,3 @@ BinaryDecode64( * fill-column: 78 * End: */ - diff --git a/generic/tclCkalloc.c b/generic/tclCkalloc.c index 94327b5..8746241 100644 --- a/generic/tclCkalloc.c +++ b/generic/tclCkalloc.c @@ -41,7 +41,7 @@ typedef struct MemTag { * last field in the structure. */ } MemTag; -#define TAG_SIZE(bytesInString) ((TclOffset(MemTag, string) + 1) + bytesInString) +#define TAG_SIZE(bytesInString) ((offsetof(MemTag, string) + 1) + bytesInString) static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers (set * by "memory tag" command). */ @@ -131,10 +131,12 @@ static int ckallocInit = 0; * Prototypes for procedures defined in this file: */ -static int CheckmemCmd(ClientData clientData, Tcl_Interp *interp, - int argc, const char *argv[]); -static int MemoryCmd(ClientData clientData, Tcl_Interp *interp, - int argc, const char *argv[]); +static int CheckmemCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int MemoryCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); static void ValidateMemory(struct mem_header *memHeaderP, const char *file, int line, int nukeGuards); @@ -145,7 +147,7 @@ static void ValidateMemory(struct mem_header *memHeaderP, * * Initialize the locks used by the allocator. This is only appropriate * to call in a single threaded environment, such as during - * TclInitSubsystems. + * Tcl_InitSubsystems. * *---------------------------------------------------------------------- */ @@ -811,8 +813,8 @@ static int MemoryCmd( ClientData clientData, Tcl_Interp *interp, - int argc, - const char *argv[]) + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Obj values of arguments. */ { const char *fileName; FILE *fileP; @@ -820,20 +822,17 @@ MemoryCmd( int result; size_t len; - if (argc < 2) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s option [args..]\"", argv[0])); + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option [args..]"); return TCL_ERROR; } - if (strcmp(argv[1], "active") == 0 || strcmp(argv[1], "display") == 0) { - if (argc != 3) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s %s file\"", - argv[0], argv[1])); + if (strcmp(TclGetString(objv[1]), "active") == 0 || strcmp(TclGetString(objv[1]), "display") == 0) { + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "file"); return TCL_ERROR; } - fileName = Tcl_TranslateFileName(interp, argv[2], &buffer); + fileName = Tcl_TranslateFileName(interp, TclGetString(objv[2]), &buffer); if (fileName == NULL) { return TCL_ERROR; } @@ -841,23 +840,23 @@ MemoryCmd( Tcl_DStringFree(&buffer); if (result != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("error accessing %s: %s", - argv[2], Tcl_PosixError(interp))); + TclGetString(objv[2]), Tcl_PosixError(interp))); return TCL_ERROR; } return TCL_OK; } - if (strcmp(argv[1],"break_on_malloc") == 0) { + if (strcmp(TclGetString(objv[1]),"break_on_malloc") == 0) { int value; - if (argc != 3) { + if (objc != 3) { goto argError; } - if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) { return TCL_ERROR; } break_on_malloc = (unsigned int) value; return TCL_OK; } - if (strcmp(argv[1],"info") == 0) { + if (strcmp(TclGetString(objv[1]),"info") == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%-25s %10u\n%-25s %10u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER"u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER "u\n", "total mallocs", total_mallocs, "total frees", total_frees, @@ -867,20 +866,19 @@ MemoryCmd( "maximum bytes allocated", maximum_bytes_malloced)); return TCL_OK; } - if (strcmp(argv[1], "init") == 0) { - if (argc != 3) { + if (strcmp(TclGetString(objv[1]), "init") == 0) { + if (objc != 3) { goto bad_suboption; } - init_malloced_bodies = (strcmp(argv[2],"on") == 0); + init_malloced_bodies = (strcmp(TclGetString(objv[2]),"on") == 0); return TCL_OK; } - if (strcmp(argv[1], "objs") == 0) { - if (argc != 3) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s objs file\"", argv[0])); + if (strcmp(TclGetString(objv[1]), "objs") == 0) { + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "file"); return TCL_ERROR; } - fileName = Tcl_TranslateFileName(interp, argv[2], &buffer); + fileName = Tcl_TranslateFileName(interp, TclGetString(objv[2]), &buffer); if (fileName == NULL) { return TCL_ERROR; } @@ -896,13 +894,12 @@ MemoryCmd( Tcl_DStringFree(&buffer); return TCL_OK; } - if (strcmp(argv[1],"onexit") == 0) { - if (argc != 3) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s onexit file\"", argv[0])); + if (strcmp(TclGetString(objv[1]),"onexit") == 0) { + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "file"); return TCL_ERROR; } - fileName = Tcl_TranslateFileName(interp, argv[2], &buffer); + fileName = Tcl_TranslateFileName(interp, TclGetString(objv[2]), &buffer); if (fileName == NULL) { return TCL_ERROR; } @@ -911,62 +908,59 @@ MemoryCmd( Tcl_DStringFree(&buffer); return TCL_OK; } - if (strcmp(argv[1],"tag") == 0) { - if (argc != 3) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s tag string\"", argv[0])); + if (strcmp(TclGetString(objv[1]),"tag") == 0) { + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "file"); return TCL_ERROR; } if ((curTagPtr != NULL) && (curTagPtr->refCount == 0)) { TclpFree((char *) curTagPtr); } - len = strlen(argv[2]); + len = strlen(TclGetString(objv[2])); curTagPtr = (MemTag *) TclpAlloc(TAG_SIZE(len)); curTagPtr->refCount = 0; - memcpy(curTagPtr->string, argv[2], len + 1); + memcpy(curTagPtr->string, TclGetString(objv[2]), len + 1); return TCL_OK; } - if (strcmp(argv[1],"trace") == 0) { - if (argc != 3) { + if (strcmp(TclGetString(objv[1]),"trace") == 0) { + if (objc != 3) { goto bad_suboption; } - alloc_tracing = (strcmp(argv[2],"on") == 0); + alloc_tracing = (strcmp(TclGetString(objv[2]),"on") == 0); return TCL_OK; } - if (strcmp(argv[1],"trace_on_at_malloc") == 0) { + if (strcmp(TclGetString(objv[1]),"trace_on_at_malloc") == 0) { int value; - if (argc != 3) { + if (objc != 3) { goto argError; } - if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) { return TCL_ERROR; } trace_on_at_malloc = value; return TCL_OK; } - if (strcmp(argv[1],"validate") == 0) { - if (argc != 3) { + if (strcmp(TclGetString(objv[1]),"validate") == 0) { + if (objc != 3) { goto bad_suboption; } - validate_memory = (strcmp(argv[2],"on") == 0); + validate_memory = (strcmp(TclGetString(objv[2]),"on") == 0); return TCL_OK; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": should be active, break_on_malloc, info, " "init, objs, onexit, tag, trace, trace_on_at_malloc, or validate", - argv[1])); + TclGetString(objv[1]))); return TCL_ERROR; argError: - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s %s count\"", argv[0], argv[1])); + Tcl_WrongNumArgs(interp, 2, objv, "count"); return TCL_ERROR; bad_suboption: - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s %s on|off\"", argv[0], argv[1])); + Tcl_WrongNumArgs(interp, 2, objv, "on|off"); return TCL_ERROR; } @@ -987,21 +981,23 @@ MemoryCmd( * *---------------------------------------------------------------------- */ +static int CheckmemCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); static int CheckmemCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Interpreter for evaluation. */ - int argc, /* Number of arguments. */ - const char *argv[]) /* String values of arguments. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Obj values of arguments. */ { - if (argc != 2) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "wrong # args: should be \"%s fileName\"", argv[0])); + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "fileName"); return TCL_ERROR; } tclMemDumpFileName = dumpFile; - strcpy(tclMemDumpFileName, argv[1]); + strcpy(tclMemDumpFileName, TclGetString(objv[1])); return TCL_OK; } @@ -1027,8 +1023,8 @@ Tcl_InitMemory( * added */ { TclInitDbCkalloc(); - Tcl_CreateCommand(interp, "memory", MemoryCmd, NULL, NULL); - Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "memory", MemoryCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "checkmem", CheckmemCmd, NULL, NULL); } @@ -1121,6 +1117,8 @@ Tcl_AttemptDbCkalloc( int line) { char *result; + (void)file; + (void)line; result = (char *) TclpAlloc(size); return result; @@ -1200,6 +1198,8 @@ Tcl_AttemptDbCkrealloc( int line) { char *result; + (void)file; + (void)line; result = (char *) TclpRealloc(ptr, size); return result; @@ -1230,6 +1230,8 @@ Tcl_DbCkfree( const char *file, int line) { + (void)file; + (void)line; TclpFree(ptr); } @@ -1248,12 +1250,14 @@ void Tcl_InitMemory( Tcl_Interp *interp) { + (void)interp; } int Tcl_DumpActiveMemory( const char *fileName) { + (void)fileName; return TCL_OK; } @@ -1262,6 +1266,8 @@ Tcl_ValidateAllMemory( const char *file, int line) { + (void)file; + (void)line; } int @@ -1269,6 +1275,8 @@ TclDumpMemoryInfo( ClientData clientData, int flags) { + (void)clientData; + (void)flags; return 1; } diff --git a/generic/tclClock.c b/generic/tclClock.c index aeff164..c601521 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -1513,7 +1513,7 @@ GetJulianDayFromEraYearMonthDay( * Try an initial conversion in the Gregorian calendar. */ -#if 0 /* BUG http://core.tcl.tk/tcl/tktview?name=da340d4f32 */ +#if 0 /* BUG https://core.tcl-lang.org/tcl/tktview?name=da340d4f32 */ ym1o4 = ym1 / 4; #else /* @@ -1652,6 +1652,7 @@ ClockGetenvObjCmd( { const char *varName; const char *varValue; + (void)clientData; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); @@ -1744,6 +1745,7 @@ ClockClicksObjCmd( int index = CLICKS_NATIVE; Tcl_Time now; Tcl_WideInt clicks = 0; + (void)clientData; switch (objc) { case 1: @@ -1806,6 +1808,7 @@ ClockMillisecondsObjCmd( Tcl_Obj *const *objv) /* Parameter values */ { Tcl_Time now; + (void)clientData; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -1842,6 +1845,7 @@ ClockMicrosecondsObjCmd( int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { + (void)clientData; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; @@ -1994,6 +1998,7 @@ ClockSecondsObjCmd( Tcl_Obj *const *objv) /* Parameter values */ { Tcl_Time now; + (void)clientData; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c index 1811c5c..c895817 100644 --- a/generic/tclCmdAH.c +++ b/generic/tclCmdAH.c @@ -15,7 +15,6 @@ #ifdef _WIN32 # include "tclWinInt.h" #endif -#include <locale.h> /* * The state structure used by [foreach]. Note that the actual structure has @@ -169,7 +168,7 @@ Tcl_CaseObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register int i; + int i; int body, result, caseObjc; const char *stringPtr, *arg; Tcl_Obj *const *caseObjv; @@ -872,7 +871,7 @@ TclNREvalObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; Interp *iPtr = (Interp *) interp; CmdFrame *invoker = NULL; int word = 0; @@ -1093,6 +1092,7 @@ TclInitFileCmd( {"stat", FileAttrStatCmd, TclCompileBasic2ArgCmd, NULL, NULL, 1}, {"system", PathFilesystemCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"tail", PathTailCmd, TclCompileBasic1ArgCmd, NULL, NULL, 1}, + {"tempdir", TclFileTempDirCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 1}, {"tempfile", TclFileTemporaryCmd, TclCompileBasic0To2ArgCmd, NULL, NULL, 1}, {"type", FileAttrTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 1}, {"volumes", FilesystemVolumesCmd, TclCompileBasic0ArgCmd, NULL, NULL, 1}, @@ -1138,7 +1138,7 @@ FileAttrAccessTimeCmd( } #if defined(_WIN32) /* We use a value of 0 to indicate the access time not available */ - if (buf.st_atime == 0) { + if (Tcl_GetAccessTimeFromStat(&buf) == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not get access time for file \"%s\"", TclGetString(objv[1]))); @@ -1159,7 +1159,7 @@ FileAttrAccessTimeCmd( } tval.actime = newTime; - tval.modtime = buf.st_mtime; + tval.modtime = Tcl_GetModificationTimeFromStat(&buf); if (Tcl_FSUtime(objv[1], &tval) != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -1179,7 +1179,7 @@ FileAttrAccessTimeCmd( } } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj((long) buf.st_atime)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(&buf))); return TCL_OK; } @@ -1220,7 +1220,7 @@ FileAttrModifyTimeCmd( } #if defined(_WIN32) /* We use a value of 0 to indicate the modification time not available */ - if (buf.st_mtime == 0) { + if (Tcl_GetModificationTimeFromStat(&buf) == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not get modification time for file \"%s\"", TclGetString(objv[1]))); @@ -1239,7 +1239,7 @@ FileAttrModifyTimeCmd( return TCL_ERROR; } - tval.actime = buf.st_atime; + tval.actime = Tcl_GetAccessTimeFromStat(&buf); tval.modtime = newTime; if (Tcl_FSUtime(objv[1], &tval) != 0) { @@ -1259,7 +1259,7 @@ FileAttrModifyTimeCmd( } } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj((long) buf.st_mtime)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(&buf))); return TCL_OK; } @@ -2253,7 +2253,7 @@ StoreStatData( * store in varName. */ { Tcl_Obj *field, *value; - register unsigned short mode; + unsigned short mode; /* * Assume Tcl_ObjSetVar2() does not keep a copy of the field name! @@ -2290,9 +2290,9 @@ StoreStatData( #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize)); #endif - STORE_ARY("atime", Tcl_NewWideIntObj((long)statPtr->st_atime)); - STORE_ARY("mtime", Tcl_NewWideIntObj((long)statPtr->st_mtime)); - STORE_ARY("ctime", Tcl_NewWideIntObj((long)statPtr->st_ctime)); + STORE_ARY("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr))); + STORE_ARY("mtime", Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr))); + STORE_ARY("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr))); mode = (unsigned short) statPtr->st_mode; STORE_ARY("mode", Tcl_NewWideIntObj(mode)); STORE_ARY("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1)); @@ -2630,7 +2630,7 @@ EachloopCmd( Tcl_Obj *const objv[]) { int numLists = (objc-2) / 2; - register struct ForeachState *statePtr; + struct ForeachState *statePtr; int i, j, result; if (objc < 4 || (objc%2 != 0)) { @@ -2755,7 +2755,7 @@ ForeachLoopStep( Tcl_Interp *interp, int result) { - register struct ForeachState *statePtr = data[0]; + struct ForeachState *statePtr = data[0]; /* * Process the result code from this run of the [foreach] body. Note that diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index c11534e..9d4bbf3 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -475,7 +475,7 @@ InfoArgsCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; const char *name; Proc *procPtr; CompiledLocal *localPtr; @@ -538,7 +538,7 @@ InfoBodyCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; const char *name, *bytes; Proc *procPtr; int numBytes; @@ -643,7 +643,7 @@ InfoCommandsCmd( { const char *cmdName, *pattern; const char *simplePattern; - register Tcl_HashEntry *entryPtr; + Tcl_HashEntry *entryPtr; Tcl_HashSearch search; Namespace *nsPtr; Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); @@ -1843,7 +1843,7 @@ InfoProcsCmd( Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); Tcl_Obj *listPtr, *elemObjPtr; int specificNsInPattern = 0;/* Init. to avoid compiler warning. */ - register Tcl_HashEntry *entryPtr; + Tcl_HashEntry *entryPtr; Tcl_HashSearch search; Command *cmdPtr, *realCmdPtr; @@ -1958,7 +1958,7 @@ InfoProcsCmd( /* * If "info procs" worked like "info commands", returning the commands * also seen in the global namespace, then you would include this - * code. As this could break backwards compatibilty with 8.0-8.2, we + * code. As this could break backwards compatibility with 8.0-8.2, we * decided not to "fix" it in 8.3, leaving the behavior slightly * different. */ @@ -2415,7 +2415,7 @@ int Tcl_LinsertObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ - register int objc, /* Number of arguments. */ + int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *listPtr; @@ -2497,8 +2497,8 @@ int Tcl_ListObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ - register int objc, /* Number of arguments. */ - register Tcl_Obj *const objv[]) + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* The argument objects. */ { /* @@ -2534,7 +2534,7 @@ Tcl_LlengthObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - register Tcl_Obj *const objv[]) + Tcl_Obj *const objv[]) /* Argument objects. */ { int listLen, result; @@ -2580,7 +2580,7 @@ Tcl_LpopObjCmd( ClientData notUsed, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - register Tcl_Obj *const objv[]) + Tcl_Obj *const objv[]) /* Argument objects. */ { int listLen, result; @@ -2673,7 +2673,7 @@ Tcl_LrangeObjCmd( ClientData notUsed, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - register Tcl_Obj *const objv[]) + Tcl_Obj *const objv[]) /* Argument objects. */ { int listLen, first, last, result; @@ -2859,8 +2859,8 @@ int Tcl_LrepeatObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ - register int objc, /* Number of arguments. */ - register Tcl_Obj *const objv[]) + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* The argument objects. */ { int elementCount, i, totalElems; @@ -2925,7 +2925,7 @@ Tcl_LrepeatObjCmd( CLANG_ASSERT(dataArray || totalElems == 0 ); if (objc == 1) { - register Tcl_Obj *tmpPtr = objv[0]; + Tcl_Obj *tmpPtr = objv[0]; tmpPtr->refCount += elementCount; for (i=0 ; i<elementCount ; i++) { @@ -2971,7 +2971,7 @@ Tcl_LreplaceObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register Tcl_Obj *listPtr; + Tcl_Obj *listPtr; int first, last, listLen, numToDelete, result; if (objc < 4) { diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 6792378..ecb13b1 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1662,7 +1662,7 @@ StringIsCmd( const char *elemStart, *nextElem; int lenRemain, elemSize; - register const char *p; + const char *p; string1 = TclGetStringFromObj(objPtr, &length1); end = string1 + length1; @@ -1842,7 +1842,7 @@ StringIsCmd( const char *elemStart, *nextElem; int lenRemain, elemSize; - register const char *p; + const char *p; string1 = TclGetStringFromObj(objPtr, &length1); end = string1 + length1; @@ -4060,9 +4060,9 @@ Tcl_TimeObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; Tcl_Obj *objs[4]; - register int i, result; + int i, result; int count; double totalMicroSec; #ifndef TCL_WIDE_CLICKS @@ -4161,22 +4161,22 @@ Tcl_TimeRateObjCmd( static double measureOverhead = 0; /* global measure-overhead */ double overhead = -1; /* given measure-overhead */ - register Tcl_Obj *objPtr; - register int result, i; + Tcl_Obj *objPtr; + int result, i; Tcl_Obj *calibrate = NULL, *direct = NULL; - Tcl_WideUInt count = 0; /* Holds repetition count */ + TclWideMUInt count = 0; /* Holds repetition count */ Tcl_WideInt maxms = WIDE_MIN; /* Maximal running time (in milliseconds) */ - Tcl_WideUInt maxcnt = WIDE_MAX; + TclWideMUInt maxcnt = WIDE_MAX; /* Maximal count of iterations. */ - Tcl_WideUInt threshold = 1; /* Current threshold for check time (faster + TclWideMUInt threshold = 1; /* Current threshold for check time (faster * repeat count without time check) */ - Tcl_WideUInt maxIterTm = 1; /* Max time of some iteration as max + TclWideMUInt maxIterTm = 1; /* Max time of some iteration as max * threshold, additionally avoiding divide to * zero (i.e., never < 1) */ unsigned short factor = 50; /* Factor (4..50) limiting threshold to avoid * growth of execution time. */ - register Tcl_WideInt start, middle, stop; + Tcl_WideInt start, middle, stop; #ifndef TCL_WIDE_CLICKS Tcl_Time now; #endif /* !TCL_WIDE_CLICKS */ @@ -4413,28 +4413,37 @@ Tcl_TimeRateObjCmd( count++; if (!direct) { /* precompiled */ rootPtr = TOP_CB(interp); + /* + * Use loop optimized TEBC call (TCL_EVAL_DISCARD_RESULT): it's a part of + * iteration, this way evaluation will be more similar to a cycle (also + * avoids extra overhead to set result to interp, etc.) + */ + ((Interp *)interp)->evalFlags |= TCL_EVAL_DISCARD_RESULT; result = TclNRExecuteByteCode(interp, codePtr); result = TclNRRunCallbacks(interp, result, rootPtr); } else { /* eval */ result = TclEvalObjEx(interp, objPtr, 0, NULL, 0); } - if (result != TCL_OK) { - /* - * Allow break from measurement cycle (used for conditional - * stop). - */ + /* + * Allow break and continue from measurement cycle (used for + * conditional stop and flow control of iterations). + */ - if (result != TCL_BREAK) { + switch (result) { + case TCL_OK: + break; + case TCL_BREAK: + /* + * Force stop immediately. + */ + threshold = 1; + maxcnt = 0; + /* FALLTHRU */ + case TCL_CONTINUE: + result = TCL_OK; + break; + default: goto done; - } - - /* - * Force stop immediately. - */ - - threshold = 1; - maxcnt = 0; - result = TCL_OK; } /* @@ -4534,17 +4543,20 @@ Tcl_TimeRateObjCmd( { Tcl_Obj *objarr[8], **objs = objarr; - Tcl_WideInt val; + TclWideMUInt usec, val; int digits; - middle -= start; /* execution time in microsecs */ + /* + * Absolute execution time in microseconds or in wide clicks. + */ + usec = (TclWideMUInt)(middle - start); #ifdef TCL_WIDE_CLICKS /* - * convert execution time in wide clicks to microsecs. + * convert execution time (in wide clicks) to microsecs. */ - middle *= TclpWideClickInMicrosec(); + usec *= TclpWideClickInMicrosec(); #endif /* TCL_WIDE_CLICKS */ if (!count) { /* no iterations - avoid divide by zero */ @@ -4566,12 +4578,12 @@ Tcl_TimeRateObjCmd( * Estimate the time of overhead (microsecs). */ - Tcl_WideUInt curOverhead = overhead * count; + TclWideMUInt curOverhead = overhead * count; - if (middle > (Tcl_WideInt) curOverhead) { - middle -= curOverhead; + if (usec > curOverhead) { + usec -= curOverhead; } else { - middle = 0; + usec = 0; } } } else { @@ -4579,15 +4591,15 @@ Tcl_TimeRateObjCmd( * Calibration: obtaining new measurement overhead. */ - if (measureOverhead > ((double) middle) / count) { - measureOverhead = ((double) middle) / count; + if (measureOverhead > ((double) usec) / count) { + measureOverhead = ((double) usec) / count; } objs[0] = Tcl_NewDoubleObj(measureOverhead); TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#-overhead"); /* mics */ objs += 2; } - val = middle / count; /* microsecs per iteration */ + val = usec / count; /* microsecs per iteration */ if (val >= 1000000) { objs[0] = Tcl_NewWideIntObj(val); } else { @@ -4602,7 +4614,7 @@ Tcl_TimeRateObjCmd( } else { digits = 1; } - objs[0] = Tcl_ObjPrintf("%.*f", digits, ((double) middle)/count); + objs[0] = Tcl_ObjPrintf("%.*f", digits, ((double) usec)/count); } objs[2] = Tcl_NewWideIntObj(count); /* iterations */ @@ -4611,11 +4623,11 @@ Tcl_TimeRateObjCmd( * Calculate speed as rate (count) per sec */ - if (!middle) { - middle++; /* Avoid divide by zero. */ + if (!usec) { + usec++; /* Avoid divide by zero. */ } if (count < (WIDE_MAX / 1000000)) { - val = (count * 1000000) / middle; + val = (count * 1000000) / usec; if (val < 100000) { if (val < 100) { digits = 3; @@ -4625,12 +4637,12 @@ Tcl_TimeRateObjCmd( digits = 1; } objs[4] = Tcl_ObjPrintf("%.*f", - digits, ((double) (count * 1000000)) / middle); + digits, ((double) (count * 1000000)) / usec); } else { objs[4] = Tcl_NewWideIntObj(val); } } else { - objs[4] = Tcl_NewWideIntObj((count / middle) * 1000000); + objs[4] = Tcl_NewWideIntObj((count / usec) * 1000000); } retRes: @@ -4639,12 +4651,12 @@ Tcl_TimeRateObjCmd( */ if (!calibrate) { - if (middle >= 1) { - objs[6] = Tcl_ObjPrintf("%.3f", (double)middle / 1000); + if (usec >= 1) { + objs[6] = Tcl_ObjPrintf("%.3f", (double)usec / 1000); } else { objs[6] = Tcl_NewWideIntObj(0); } - TclNewLiteralStringObj(objs[7], "nett-ms"); + TclNewLiteralStringObj(objs[7], "net-ms"); } /* diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 4844dd8..8c6050d 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -2912,9 +2912,9 @@ DupForeachInfo( ClientData clientData) /* The foreach command's compilation auxiliary * data to duplicate. */ { - register ForeachInfo *srcPtr = clientData; + ForeachInfo *srcPtr = clientData; ForeachInfo *dupPtr; - register ForeachVarList *srcListPtr, *dupListPtr; + ForeachVarList *srcListPtr, *dupListPtr; int numVars, i, j, numLists = srcPtr->numLists; dupPtr = ckalloc(sizeof(ForeachInfo) @@ -2961,10 +2961,10 @@ FreeForeachInfo( ClientData clientData) /* The foreach command's compilation auxiliary * data to free. */ { - register ForeachInfo *infoPtr = clientData; - register ForeachVarList *listPtr; + ForeachInfo *infoPtr = clientData; + ForeachVarList *listPtr; int numLists = infoPtr->numLists; - register int i; + int i; for (i = 0; i < numLists; i++) { listPtr = infoPtr->varLists[i]; @@ -2997,8 +2997,8 @@ PrintForeachInfo( ByteCode *codePtr, unsigned int pcOffset) { - register ForeachInfo *infoPtr = clientData; - register ForeachVarList *varsPtr; + ForeachInfo *infoPtr = clientData; + ForeachVarList *varsPtr; int i, j; Tcl_AppendToObj(appendObj, "data=[", -1); @@ -3037,8 +3037,8 @@ PrintNewForeachInfo( ByteCode *codePtr, unsigned int pcOffset) { - register ForeachInfo *infoPtr = clientData; - register ForeachVarList *varsPtr; + ForeachInfo *infoPtr = clientData; + ForeachVarList *varsPtr; int i, j; Tcl_AppendPrintfToObj(appendObj, "jumpOffset=%+d, vars=", @@ -3067,8 +3067,8 @@ DisassembleForeachInfo( ByteCode *codePtr, unsigned int pcOffset) { - register ForeachInfo *infoPtr = clientData; - register ForeachVarList *varsPtr; + ForeachInfo *infoPtr = clientData; + ForeachVarList *varsPtr; int i, j; Tcl_Obj *objPtr, *innerPtr; @@ -3114,8 +3114,8 @@ DisassembleNewForeachInfo( ByteCode *codePtr, unsigned int pcOffset) { - register ForeachInfo *infoPtr = clientData; - register ForeachVarList *varsPtr; + ForeachInfo *infoPtr = clientData; + ForeachVarList *varsPtr; int i, j; Tcl_Obj *objPtr, *innerPtr; @@ -3174,7 +3174,7 @@ TclCompileFormatCmd( DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; Tcl_Obj **objv, *formatObj, *tmpObj; - char *bytes, *start; + const char *bytes, *start; int i, j, len; /* @@ -3301,7 +3301,7 @@ TclCompileFormatCmd( if (*++bytes == '%') { Tcl_AppendToObj(tmpObj, "%", 1); } else { - char *b = TclGetStringFromObj(tmpObj, &len); + const char *b = TclGetStringFromObj(tmpObj, &len); /* * If there is a non-empty literal from the format string, @@ -3439,9 +3439,9 @@ TclPushVarName( int *localIndexPtr, /* Must not be NULL. */ int *isScalarPtr) /* Must not be NULL. */ { - register const char *p; + const char *p; const char *last, *name, *elName; - register int n; + int n; Tcl_Token *elemTokenPtr = NULL; int nameLen, elNameLen, simpleVarName, localIndex; int elemTokenCount = 0, allocedTokens = 0, removedParen = 0; diff --git a/generic/tclCompCmdsGR.c b/generic/tclCompCmdsGR.c index a8a85f8..3c8a156 100644 --- a/generic/tclCompCmdsGR.c +++ b/generic/tclCompCmdsGR.c @@ -589,7 +589,7 @@ TclCompileInfoCommandsCmd( DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; Tcl_Obj *objPtr; - char *bytes; + const char *bytes; /* * We require one compile-time known argument for the case we can compile. diff --git a/generic/tclCompCmdsSZ.c b/generic/tclCompCmdsSZ.c index 83ade0b..db51890 100644 --- a/generic/tclCompCmdsSZ.c +++ b/generic/tclCompCmdsSZ.c @@ -925,7 +925,7 @@ TclCompileStringMapCmd( DefineLineInformation; /* TIP #280 */ Tcl_Token *mapTokenPtr, *stringTokenPtr; Tcl_Obj *mapObj, **objv; - char *bytes; + const char *bytes; int len; /* @@ -1862,8 +1862,8 @@ TclCompileSwitchCmd( */ for (; numWords>=3 ; tokenPtr=TokenAfter(tokenPtr),numWords--) { - register unsigned size = tokenPtr[1].size; - register const char *chrs = tokenPtr[1].start; + unsigned size = tokenPtr[1].size; + const char *chrs = tokenPtr[1].start; /* * We only process literal options, and we assume that -e, -g and -n @@ -2602,7 +2602,7 @@ PrintJumptableInfo( ByteCode *codePtr, unsigned int pcOffset) { - register JumptableInfo *jtPtr = clientData; + JumptableInfo *jtPtr = clientData; Tcl_HashEntry *hPtr; Tcl_HashSearch search; const char *keyPtr; @@ -2631,7 +2631,7 @@ DisassembleJumptableInfo( ByteCode *codePtr, unsigned int pcOffset) { - register JumptableInfo *jtPtr = clientData; + JumptableInfo *jtPtr = clientData; Tcl_Obj *mapping = Tcl_NewObj(); Tcl_HashEntry *hPtr; Tcl_HashSearch search; @@ -4493,6 +4493,50 @@ TclCompileStreqOpCmd( { return CompileComparisonOpCmd(interp, parsePtr, INST_STR_EQ, envPtr); } + +int +TclCompileStrLtOpCmd( + Tcl_Interp *interp, + Tcl_Parse *parsePtr, + Command *cmdPtr, /* Points to defintion of command being + * compiled. */ + CompileEnv *envPtr) +{ + return CompileComparisonOpCmd(interp, parsePtr, INST_STR_LT, envPtr); +} + +int +TclCompileStrLeOpCmd( + Tcl_Interp *interp, + Tcl_Parse *parsePtr, + Command *cmdPtr, /* Points to defintion of command being + * compiled. */ + CompileEnv *envPtr) +{ + return CompileComparisonOpCmd(interp, parsePtr, INST_STR_LE, envPtr); +} + +int +TclCompileStrGtOpCmd( + Tcl_Interp *interp, + Tcl_Parse *parsePtr, + Command *cmdPtr, /* Points to defintion of command being + * compiled. */ + CompileEnv *envPtr) +{ + return CompileComparisonOpCmd(interp, parsePtr, INST_STR_GT, envPtr); +} + +int +TclCompileStrGeOpCmd( + Tcl_Interp *interp, + Tcl_Parse *parsePtr, + Command *cmdPtr, /* Points to defintion of command being + * compiled. */ + CompileEnv *envPtr) +{ + return CompileComparisonOpCmd(interp, parsePtr, INST_STR_GE, envPtr); +} int TclCompileMinusOpCmd( diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c index 56c8931..a6ac797 100644 --- a/generic/tclCompExpr.c +++ b/generic/tclCompExpr.c @@ -281,7 +281,11 @@ enum Marks { * parse tree. The sub-expression between * parens becomes the single argument of the * matching OPEN_PAREN unary operator. */ -#define END (BINARY | 28) +#define STR_LT (BINARY | 28) +#define STR_GT (BINARY | 29) +#define STR_LEQ (BINARY | 30) +#define STR_GEQ (BINARY | 31) +#define END (BINARY | 32) /* This lexeme represents the end of the * string being parsed. Treating it as a * binary operator follows the same logic as @@ -360,12 +364,14 @@ static const unsigned char prec[] = { PREC_EQUAL, /* IN_LIST */ PREC_EQUAL, /* NOT_IN_LIST */ PREC_CLOSE_PAREN, /* CLOSE_PAREN */ + PREC_COMPARE, /* STR_LT */ + PREC_COMPARE, /* STR_GT */ + PREC_COMPARE, /* STR_LEQ */ + PREC_COMPARE, /* STR_GEQ */ PREC_END, /* END */ /* Expansion room for more binary operators */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, /* Unary operator lexemes */ PREC_UNARY, /* UNARY_PLUS */ PREC_UNARY, /* UNARY_MINUS */ @@ -415,12 +421,14 @@ static const unsigned char instruction[] = { INST_LIST_IN, /* IN_LIST */ INST_LIST_NOT_IN, /* NOT_IN_LIST */ 0, /* CLOSE_PAREN */ + INST_STR_LT, /* STR_LT */ + INST_STR_GT, /* STR_GT */ + INST_STR_LE, /* STR_LEQ */ + INST_STR_GE, /* STR_GEQ */ 0, /* END */ /* Expansion room for more binary operators */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, /* Unary operator lexemes */ INST_UPLUS, /* UNARY_PLUS */ INST_UMINUS, /* UNARY_MINUS */ @@ -2001,6 +2009,35 @@ ParseLexeme( return 2; } } + break; + + case 'l': + if ((numBytes > 1) + && ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) { + switch (start[1]) { + case 't': + *lexemePtr = STR_LT; + return 2; + case 'e': + *lexemePtr = STR_LEQ; + return 2; + } + } + break; + + case 'g': + if ((numBytes > 1) + && ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) { + switch (start[1]) { + case 't': + *lexemePtr = STR_GT; + return 2; + case 'e': + *lexemePtr = STR_GEQ; + return 2; + } + } + break; } literal = Tcl_NewObj(); @@ -2568,7 +2605,7 @@ TclSingleOpCmd( * * TclSortingOpCmd -- * Implements the commands: - * <, <=, >, >=, ==, eq + * <, <=, >, >=, ==, eq, lt, le, gt, ge * in the ::tcl::mathop namespace. These commands are defined for * arbitrary number of arguments by computing the AND of the base * operator applied to all neighbor argument pairs. diff --git a/generic/tclCompile.c b/generic/tclCompile.c index c53d3ad..9c887e4 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -667,6 +667,15 @@ InstructionDesc const tclInstructionTable[] = { * default is pushed instead. * Stack: ... dict key1 ... keyN default => ... value */ + {"strlt", 1, -1, 0, {OPERAND_NONE}}, + /* String Less: push (stknext < stktop) */ + {"strgt", 1, -1, 0, {OPERAND_NONE}}, + /* String Greater: push (stknext > stktop) */ + {"strle", 1, -1, 0, {OPERAND_NONE}}, + /* String Less or equal: push (stknext <= stktop) */ + {"strge", 1, -1, 0, {OPERAND_NONE}}, + /* String Greater or equal: push (stknext >= stktop) */ + {NULL, 0, 0, 0, {OPERAND_NONE}} }; @@ -981,7 +990,7 @@ DupByteCodeInternalRep( static void FreeByteCodeInternalRep( - register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ + Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { ByteCode *codePtr; @@ -1012,14 +1021,14 @@ FreeByteCodeInternalRep( void TclPreserveByteCode( - register ByteCode *codePtr) + ByteCode *codePtr) { codePtr->refCount++; } void TclReleaseByteCode( - register ByteCode *codePtr) + ByteCode *codePtr) { if (codePtr->refCount-- > 1) { return; @@ -1031,14 +1040,14 @@ TclReleaseByteCode( static void CleanupByteCode( - register ByteCode *codePtr) /* Points to the ByteCode to free. */ + ByteCode *codePtr) /* Points to the ByteCode to free. */ { Tcl_Interp *interp = (Tcl_Interp *) *codePtr->interpHandle; Interp *iPtr = (Interp *) interp; int numLitObjects = codePtr->numLitObjects; int numAuxDataItems = codePtr->numAuxDataItems; - register Tcl_Obj **objArrayPtr, *objPtr; - register const AuxData *auxDataPtr; + Tcl_Obj **objArrayPtr, *objPtr; + const AuxData *auxDataPtr; int i; #ifdef TCL_COMPILE_STATS @@ -1383,9 +1392,9 @@ CompileSubstObj( static void FreeSubstCodeInternalRep( - register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ + Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { - register ByteCode *codePtr; + ByteCode *codePtr; ByteCodeGetIntRep(objPtr, &substCodeType, codePtr); assert(codePtr != NULL); @@ -1434,7 +1443,7 @@ void TclInitCompileEnv( Tcl_Interp *interp, /* The interpreter for which a CompileEnv * structure is initialized. */ - register CompileEnv *envPtr,/* Points to the CompileEnv structure to + CompileEnv *envPtr,/* Points to the CompileEnv structure to * initialize. */ const char *stringPtr, /* The source string to be compiled. */ int numBytes, /* Number of bytes in source string. */ @@ -1641,7 +1650,7 @@ TclInitCompileEnv( void TclFreeCompileEnv( - register CompileEnv *envPtr)/* Points to the CompileEnv structure. */ + CompileEnv *envPtr)/* Points to the CompileEnv structure. */ { if (envPtr->localLitTable.buckets != envPtr->localLitTable.staticBuckets){ ckfree(envPtr->localLitTable.buckets); @@ -2150,25 +2159,48 @@ TclCompileScript( * has not yet generated any bytecode. */ const char *p = script; /* Where we are in our compile. */ int depth = TclGetStackDepth(envPtr); + Interp *iPtr = (Interp *) interp; if (envPtr->iPtr == NULL) { Tcl_Panic("TclCompileScript() called on uninitialized CompileEnv"); } + /* + * Check depth to avoid overflow of the C execution stack by too many + * nested calls of TclCompileScript (considering interp recursionlimit). + * Factor 5/4 (1.25) is used to avoid too mistaken limit recognition + * during "mixed" evaluation and compilation process (nested eval+compile) + * and is good enough for default recursionlimit (1000). + */ + if (iPtr->numLevels / 5 > iPtr->maxNestingDepth / 4) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "too many nested compilations (infinite loop?)", -1)); + Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", NULL); + TclCompileSyntaxError(interp, envPtr); + return; + } /* Each iteration compiles one command from the script. */ - while (numBytes > 0) { - Tcl_Parse parse; + if (numBytes > 0) { + /* + * Don't use system stack (size of Tcl_Parse is ca. 400 bytes), so + * many nested compilations (body enclosed in body) can cause abnormal + * program termination with a stack overflow exception, bug [fec0c17d39]. + */ + Tcl_Parse *parsePtr = ckalloc(sizeof(Tcl_Parse)); + + do { const char *next; - if (TCL_OK != Tcl_ParseCommand(interp, p, numBytes, 0, &parse)) { + if (TCL_OK != Tcl_ParseCommand(interp, p, numBytes, 0, parsePtr)) { /* - * Compile bytecodes to report the parse error at runtime. + * Compile bytecodes to report the parsePtr error at runtime. */ - Tcl_LogCommandInfo(interp, script, parse.commandStart, - parse.term + 1 - parse.commandStart); + Tcl_LogCommandInfo(interp, script, parsePtr->commandStart, + parsePtr->term + 1 - parsePtr->commandStart); TclCompileSyntaxError(interp, envPtr); + ckfree(parsePtr); return; } @@ -2179,9 +2211,9 @@ TclCompileScript( */ if ((tclTraceCompile >= 1) && (envPtr->procPtr == NULL)) { - int commandLength = parse.term - parse.commandStart; + int commandLength = parsePtr->term - parsePtr->commandStart; fprintf(stdout, " Compiling: "); - TclPrintSource(stdout, parse.commandStart, + TclPrintSource(stdout, parsePtr->commandStart, TclMin(commandLength, 55)); fprintf(stdout, "\n"); } @@ -2192,48 +2224,59 @@ TclCompileScript( * (See test info-30.33). */ - TclAdvanceLines(&envPtr->line, p, parse.commandStart); + TclAdvanceLines(&envPtr->line, p, parsePtr->commandStart); TclAdvanceContinuations(&envPtr->line, &envPtr->clNext, - parse.commandStart - envPtr->source); + parsePtr->commandStart - envPtr->source); /* * Advance parser to the next command in the script. */ - next = parse.commandStart + parse.commandSize; + next = parsePtr->commandStart + parsePtr->commandSize; numBytes -= next - p; p = next; - if (parse.numWords == 0) { + if (parsePtr->numWords == 0) { /* * The "command" parsed has no words. In this case we can skip * the rest of the loop body. With no words, clearly * CompileCommandTokens() has nothing to do. Since the parser * aggressively sucks up leading comment and white space, - * including newlines, parse.commandStart must be pointing at + * including newlines, parsePtr->commandStart must be pointing at * either the end of script, or a command-terminating semi-colon. * In either case, the TclAdvance*() calls have nothing to do. * Finally, when no words are parsed, no tokens have been - * allocated at parse.tokenPtr so there's also nothing for + * allocated at parsePtr->tokenPtr so there's also nothing for * Tcl_FreeParse() to do. * * The advantage of this shortcut is that CompileCommandTokens() - * can be written with an assumption that parse.numWords > 0, with + * can be written with an assumption that parsePtr->numWords > 0, with * the implication the CCT() always generates bytecode. */ continue; } - lastCmdIdx = CompileCommandTokens(interp, &parse, envPtr); + /* + * Avoid stack exhaustion by too many nested calls of TclCompileScript + * (considering interp recursionlimit). + */ + iPtr->numLevels++; + + lastCmdIdx = CompileCommandTokens(interp, parsePtr, envPtr); + + iPtr->numLevels--; /* * TIP #280: Track lines in the just compiled command. */ - TclAdvanceLines(&envPtr->line, parse.commandStart, p); + TclAdvanceLines(&envPtr->line, parsePtr->commandStart, p); TclAdvanceContinuations(&envPtr->line, &envPtr->clNext, p - envPtr->source); - Tcl_FreeParse(&parse); + Tcl_FreeParse(parsePtr); + } while (numBytes > 0); + + ckfree(parsePtr); } if (lastCmdIdx == -1) { @@ -2773,13 +2816,13 @@ PreventCycle( ByteCode * TclInitByteCode( - register CompileEnv *envPtr)/* Points to the CompileEnv structure from + CompileEnv *envPtr)/* Points to the CompileEnv structure from * which to create a ByteCode structure. */ { - register ByteCode *codePtr; + ByteCode *codePtr; size_t codeBytes, objArrayBytes, exceptArrayBytes, cmdLocBytes; size_t auxDataArrayBytes, structureSize; - register unsigned char *p; + unsigned char *p; #ifdef TCL_COMPILE_DEBUG unsigned char *nextPtr; #endif @@ -2914,7 +2957,7 @@ TclInitByteCodeObj( * and whose string rep contains the source * code. */ const Tcl_ObjType *typePtr, - register CompileEnv *envPtr)/* Points to the CompileEnv structure from + CompileEnv *envPtr)/* Points to the CompileEnv structure from * which to create a ByteCode structure. */ { ByteCode *codePtr; @@ -2959,7 +3002,7 @@ TclInitByteCodeObj( int TclFindCompiledLocal( - register const char *name, /* Points to first character of the name of a + const char *name, /* Points to first character of the name of a * scalar or array variable. If NULL, a * temporary var should be created. */ int nameBytes, /* Number of bytes in the name. */ @@ -2967,9 +3010,9 @@ TclFindCompiledLocal( * variable if it is new. */ CompileEnv *envPtr) /* Points to the current compile environment*/ { - register CompiledLocal *localPtr; + CompiledLocal *localPtr; int localVar = -1; - register int i; + int i; Proc *procPtr; /* @@ -3030,7 +3073,7 @@ TclFindCompiledLocal( if (create || (name == NULL)) { localVar = procPtr->numCompiledLocals; - localPtr = ckalloc(TclOffset(CompiledLocal, name) + nameBytes + 1); + localPtr = ckalloc(offsetof(CompiledLocal, name) + nameBytes + 1); if (procPtr->firstLocalPtr == NULL) { procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr; } else { @@ -3342,11 +3385,11 @@ EnterCmdWordData( int TclCreateExceptRange( ExceptionRangeType type, /* The kind of ExceptionRange desired. */ - register CompileEnv *envPtr)/* Points to CompileEnv for which to create a + CompileEnv *envPtr)/* Points to CompileEnv for which to create a * new ExceptionRange structure. */ { - register ExceptionRange *rangePtr; - register ExceptionAux *auxPtr; + ExceptionRange *rangePtr; + ExceptionAux *auxPtr; int index = envPtr->exceptArrayNext; if (index >= envPtr->exceptArrayEnd) { @@ -3710,11 +3753,11 @@ TclCreateAuxData( * the new aux data record. */ const AuxDataType *typePtr, /* Pointer to the type to attach to this * AuxData */ - register CompileEnv *envPtr)/* Points to the CompileEnv for which a new + CompileEnv *envPtr)/* Points to the CompileEnv for which a new * aux data structure is to be allocated. */ { int index; /* Index for the new AuxData structure. */ - register AuxData *auxDataPtr; + AuxData *auxDataPtr; /* Points to the new AuxData structure */ index = envPtr->auxDataArrayNext; @@ -3773,7 +3816,7 @@ TclCreateAuxData( void TclInitJumpFixupArray( - register JumpFixupArray *fixupArrayPtr) + JumpFixupArray *fixupArrayPtr) /* Points to the JumpFixupArray structure to * initialize. */ { @@ -3805,7 +3848,7 @@ TclInitJumpFixupArray( void TclExpandJumpFixupArray( - register JumpFixupArray *fixupArrayPtr) + JumpFixupArray *fixupArrayPtr) /* Points to the JumpFixupArray structure to * enlarge. */ { @@ -3854,7 +3897,7 @@ TclExpandJumpFixupArray( void TclFreeJumpFixupArray( - register JumpFixupArray *fixupArrayPtr) + JumpFixupArray *fixupArrayPtr) /* Points to the JumpFixupArray structure to * free. */ { @@ -4301,7 +4344,7 @@ GetCmdLocEncodingSize( * containing the CmdLocation structure to * encode. */ { - register CmdLocation *mapPtr = envPtr->cmdMapPtr; + CmdLocation *mapPtr = envPtr->cmdMapPtr; int numCmds = envPtr->numCommands; int codeDelta, codeLen, srcDelta, srcLen; int codeDeltaNext, codeLengthNext, srcDeltaNext, srcLengthNext; @@ -4385,11 +4428,11 @@ EncodeCmdLocMap( * memory block where the location information * is to be stored. */ { - register CmdLocation *mapPtr = envPtr->cmdMapPtr; + CmdLocation *mapPtr = envPtr->cmdMapPtr; int numCmds = envPtr->numCommands; - register unsigned char *p = startPtr; + unsigned char *p = startPtr; int codeDelta, codeLen, srcDelta, srcLen, prevOffset; - register int i; + int i; /* * Encode the code offset for each command as a sequence of deltas. @@ -4503,7 +4546,7 @@ RecordByteCodeStats( * to add to accumulated statistics. */ { Interp *iPtr = (Interp *) *codePtr->interpHandle; - register ByteCodeStats *statsPtr; + ByteCodeStats *statsPtr; if (iPtr == NULL) { /* Avoid segfaulting in case we're called in a deleted interp */ diff --git a/generic/tclCompile.h b/generic/tclCompile.h index 117fa46..5e39a21 100644 --- a/generic/tclCompile.h +++ b/generic/tclCompile.h @@ -529,7 +529,7 @@ typedef struct ByteCode { do { \ const Tcl_ObjIntRep *irPtr; \ irPtr = TclFetchIntRep((objPtr), (typePtr)); \ - (codePtr) = irPtr ? irPtr->twoPtrValue.ptr1 : NULL; \ + (codePtr) = irPtr ? (ByteCode*)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* @@ -842,8 +842,14 @@ typedef struct ByteCode { #define INST_DICT_GET_DEF 190 +/* TIP 461 */ +#define INST_STR_LT 191 +#define INST_STR_GT 192 +#define INST_STR_LE 193 +#define INST_STR_GE 194 + /* The last opcode */ -#define LAST_INST_OPCODE 190 +#define LAST_INST_OPCODE 194 /* * Table describing the Tcl bytecode instructions: their name (for displaying @@ -1211,7 +1217,7 @@ MODULE_SCOPE Tcl_Obj *TclGetInnerContext(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj **tosPtr); MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst); MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData, - register Tcl_Interp *interp, int objc, + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int isLambda); @@ -1399,7 +1405,7 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData, #define TclEmitPush(objIndex, envPtr) \ do { \ - register int _objIndexCopy = (objIndex); \ + int _objIndexCopy = (objIndex); \ if (_objIndexCopy <= 255) { \ TclEmitInstInt1(INST_PUSH1, _objIndexCopy, (envPtr)); \ } else { \ diff --git a/generic/tclDTrace.d b/generic/tclDTrace.d index 360bdff..f5493b1 100644 --- a/generic/tclDTrace.d +++ b/generic/tclDTrace.d @@ -10,7 +10,6 @@ */ typedef struct Tcl_Obj Tcl_Obj; -typedef const char* TclDTraceStr; /* * Tcl DTrace probes @@ -25,14 +24,14 @@ provider tcl { * arg1: number of arguments (int) * arg2: array of proc argument objects (Tcl_Obj**) */ - probe proc__entry(TclDTraceStr name, int objc, struct Tcl_Obj **objv); + probe proc__entry(const char *name, int objc, struct Tcl_Obj **objv); /* * tcl*:::proc-return probe * triggered immediately after proc bytecode execution * arg0: proc name (string) * arg1: return code (int) */ - probe proc__return(TclDTraceStr name, int code); + probe proc__return(const char *name, int code); /* * tcl*:::proc-result probe * triggered after proc-return probe and result processing @@ -41,7 +40,7 @@ provider tcl { * arg2: proc result (string) * arg3: proc result object (Tcl_Obj*) */ - probe proc__result(TclDTraceStr name, int code, TclDTraceStr result, + probe proc__result(const char *name, int code, const char *result, struct Tcl_Obj *resultobj); /* * tcl*:::proc-args probe @@ -50,10 +49,10 @@ provider tcl { * arg0: proc name (string) * arg1-arg9: proc arguments or NULL (strings) */ - probe proc__args(TclDTraceStr name, TclDTraceStr arg1, TclDTraceStr arg2, - TclDTraceStr arg3, TclDTraceStr arg4, TclDTraceStr arg5, - TclDTraceStr arg6, TclDTraceStr arg7, TclDTraceStr arg8, - TclDTraceStr arg9); + probe proc__args(const char *name, const char *arg1, const char *arg2, + const char *arg3, const char *arg4, const char *arg5, + const char *arg6, const char *arg7, const char *arg8, + const char *arg9); /* * tcl*:::proc-info probe * triggered before proc-entry probe, gives access to TIP 280 @@ -67,9 +66,9 @@ provider tcl { * arg6: TclOO method (string) * arg7: TclOO class/object (string) */ - probe proc__info(TclDTraceStr cmd, TclDTraceStr type, TclDTraceStr proc, - TclDTraceStr file, int line, int level, TclDTraceStr method, - TclDTraceStr class); + probe proc__info(const char *cmd, const char *type, const char *proc, + const char *file, int line, int level, const char *method, + const char *class); /***************************** cmd probes ******************************/ /* @@ -79,14 +78,14 @@ provider tcl { * arg1: number of arguments (int) * arg2: array of command argument objects (Tcl_Obj**) */ - probe cmd__entry(TclDTraceStr name, int objc, struct Tcl_Obj **objv); + probe cmd__entry(const char *name, int objc, struct Tcl_Obj **objv); /* * tcl*:::cmd-return probe * triggered immediately after commmand execution * arg0: command name (string) * arg1: return code (int) */ - probe cmd__return(TclDTraceStr name, int code); + probe cmd__return(const char *name, int code); /* * tcl*:::cmd-result probe * triggered after cmd-return probe and result processing @@ -95,7 +94,7 @@ provider tcl { * arg2: command result (string) * arg3: command result object (Tcl_Obj*) */ - probe cmd__result(TclDTraceStr name, int code, TclDTraceStr result, + probe cmd__result(const char *name, int code, const char *result, struct Tcl_Obj *resultobj); /* * tcl*:::cmd-args probe @@ -104,10 +103,10 @@ provider tcl { * arg0: command name (string) * arg1-arg9: command arguments or NULL (strings) */ - probe cmd__args(TclDTraceStr name, TclDTraceStr arg1, TclDTraceStr arg2, - TclDTraceStr arg3, TclDTraceStr arg4, TclDTraceStr arg5, - TclDTraceStr arg6, TclDTraceStr arg7, TclDTraceStr arg8, - TclDTraceStr arg9); + probe cmd__args(const char *name, const char *arg1, const char *arg2, + const char *arg3, const char *arg4, const char *arg5, + const char *arg6, const char *arg7, const char *arg8, + const char *arg9); /* * tcl*:::cmd-info probe * triggered before cmd-entry probe, gives access to TIP 280 @@ -121,9 +120,9 @@ provider tcl { * arg6: TclOO method (string) * arg7: TclOO class/object (string) */ - probe cmd__info(TclDTraceStr cmd, TclDTraceStr type, TclDTraceStr proc, - TclDTraceStr file, int line, int level, TclDTraceStr method, - TclDTraceStr class); + probe cmd__info(const char *cmd, const char *type, const char *proc, + const char *file, int line, int level, const char *method, + const char *class); /***************************** inst probes *****************************/ /* @@ -133,7 +132,7 @@ provider tcl { * arg1: depth of stack (int) * arg2: top of stack (Tcl_Obj**) */ - probe inst__start(TclDTraceStr name, int depth, struct Tcl_Obj **stack); + probe inst__start(const char *name, int depth, struct Tcl_Obj **stack); /* * tcl*:::inst-done probe * triggered immediately after execution of a bytecode @@ -141,7 +140,7 @@ provider tcl { * arg1: depth of stack (int) * arg2: top of stack (Tcl_Obj**) */ - probe inst__done(TclDTraceStr name, int depth, struct Tcl_Obj **stack); + probe inst__done(const char *name, int depth, struct Tcl_Obj **stack); /***************************** obj probes ******************************/ /* @@ -163,10 +162,10 @@ provider tcl { * triggered when the ::tcl::dtrace command is called * arg0-arg9: command arguments (strings) */ - probe tcl__probe(TclDTraceStr arg0, TclDTraceStr arg1, TclDTraceStr arg2, - TclDTraceStr arg3, TclDTraceStr arg4, TclDTraceStr arg5, - TclDTraceStr arg6, TclDTraceStr arg7, TclDTraceStr arg8, - TclDTraceStr arg9); + probe tcl__probe(const char *arg0, const char *arg1, const char *arg2, + const char *arg3, const char *arg4, const char *arg5, + const char *arg6, const char *arg7, const char *arg8, + const char *arg9); }; /* @@ -174,7 +173,7 @@ provider tcl { */ typedef struct Tcl_ObjType { - char *name; + const char *name; void *freeIntRepProc; void *dupIntRepProc; void *updateStringProc; @@ -185,7 +184,7 @@ struct Tcl_Obj { int refCount; char *bytes; int length; - Tcl_ObjType *typePtr; + const Tcl_ObjType *typePtr; union { long longValue; double doubleValue; diff --git a/generic/tclDate.c b/generic/tclDate.c index 32c71de..fb4f3cf 100644 --- a/generic/tclDate.c +++ b/generic/tclDate.c @@ -95,6 +95,17 @@ #endif /* _MSC_VER */ /* + * Meridian: am, pm, or 24-hour style. + */ + +typedef enum _MERIDIAN { + MERam, MERpm, MER24 +} MERIDIAN; + + + + +/* * yyparse will accept a 'struct DateInfo' as its parameter; that's where the * parsed fields will be returned. */ @@ -112,7 +123,7 @@ typedef struct DateInfo { time_t dateHour; time_t dateMinutes; time_t dateSeconds; - int dateMeridian; + MERIDIAN dateMeridian; int dateHaveTime; time_t dateTimezone; @@ -199,17 +210,6 @@ typedef enum _DSTMODE { DSTon, DSToff, DSTmaybe } DSTMODE; -/* - * Meridian: am, pm, or 24-hour style. - */ - -typedef enum _MERIDIAN { - MERam, MERpm, MER24 -} MERIDIAN; - - - - # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULLPTR nullptr @@ -2549,9 +2549,9 @@ LookupWord( YYSTYPE* yylvalPtr, char *buff) { - register char *p; - register char *q; - register const TABLE *tp; + char *p; + char *q; + const TABLE *tp; int i, abbrev; /* @@ -2674,8 +2674,8 @@ TclDatelex( YYLTYPE* location, DateInfo *info) { - register char c; - register char *p; + char c; + char *p; char buff[20]; int Count; diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 3d40bef..4f2d63f 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -143,7 +143,7 @@ EXTERN Tcl_Obj * Tcl_DbNewStringObj(const char *bytes, int length, /* 29 */ EXTERN Tcl_Obj * Tcl_DuplicateObj(Tcl_Obj *objPtr); /* 30 */ -EXTERN void TclOldFreeObj(Tcl_Obj *objPtr); +EXTERN void TclFreeObj(Tcl_Obj *objPtr); /* 31 */ EXTERN int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *boolPtr); @@ -1027,7 +1027,8 @@ EXTERN int Tcl_UtfToLower(char *src); /* 335 */ EXTERN int Tcl_UtfToTitle(char *src); /* 336 */ -EXTERN int Tcl_UtfToUniChar(const char *src, Tcl_UniChar *chPtr); +EXTERN int Tcl_UtfToChar16(const char *src, + unsigned short *chPtr); /* 337 */ EXTERN int Tcl_UtfToUpper(char *src); /* 338 */ @@ -1068,10 +1069,10 @@ EXTERN int Tcl_UniCharNcmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned long numChars); /* 354 */ -EXTERN char * Tcl_UniCharToUtfDString(const Tcl_UniChar *uniStr, +EXTERN char * Tcl_Char16ToUtfDString(const unsigned short *uniStr, int uniLength, Tcl_DString *dsPtr); /* 355 */ -EXTERN Tcl_UniChar * Tcl_UtfToUniCharDString(const char *src, int length, +EXTERN unsigned short * Tcl_UtfToChar16DString(const char *src, int length, Tcl_DString *dsPtr); /* 356 */ EXTERN Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, @@ -1901,6 +1902,17 @@ EXTERN int Tcl_IsShared(Tcl_Obj *objPtr); EXTERN int Tcl_LinkArray(Tcl_Interp *interp, const char *varName, void *addr, int type, int size); +/* 645 */ +EXTERN int Tcl_GetIntForIndex(Tcl_Interp *interp, + Tcl_Obj *objPtr, int endValue, int *indexPtr); +/* 646 */ +EXTERN int Tcl_UtfToUniChar(const char *src, int *chPtr); +/* 647 */ +EXTERN char * Tcl_UniCharToUtfDString(const int *uniStr, + int uniLength, Tcl_DString *dsPtr); +/* 648 */ +EXTERN int * Tcl_UtfToUniCharDString(const char *src, int length, + Tcl_DString *dsPtr); typedef struct { const struct TclPlatStubs *tclPlatStubs; @@ -1958,7 +1970,7 @@ typedef struct TclStubs { Tcl_Obj * (*tcl_DbNewObj) (const char *file, int line); /* 27 */ Tcl_Obj * (*tcl_DbNewStringObj) (const char *bytes, int length, const char *file, int line); /* 28 */ Tcl_Obj * (*tcl_DuplicateObj) (Tcl_Obj *objPtr); /* 29 */ - void (*tclOldFreeObj) (Tcl_Obj *objPtr); /* 30 */ + void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */ int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *boolPtr); /* 31 */ int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr); /* 32 */ unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */ @@ -2272,7 +2284,7 @@ typedef struct TclStubs { char * (*tcl_UtfToExternalDString) (Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 333 */ int (*tcl_UtfToLower) (char *src); /* 334 */ int (*tcl_UtfToTitle) (char *src); /* 335 */ - int (*tcl_UtfToUniChar) (const char *src, Tcl_UniChar *chPtr); /* 336 */ + int (*tcl_UtfToChar16) (const char *src, unsigned short *chPtr); /* 336 */ int (*tcl_UtfToUpper) (char *src); /* 337 */ int (*tcl_WriteChars) (Tcl_Channel chan, const char *src, int srcLen); /* 338 */ int (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */ @@ -2290,8 +2302,8 @@ typedef struct TclStubs { int (*tcl_UniCharIsWordChar) (int ch); /* 351 */ int (*tcl_UniCharLen) (const Tcl_UniChar *uniStr); /* 352 */ int (*tcl_UniCharNcmp) (const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned long numChars); /* 353 */ - char * (*tcl_UniCharToUtfDString) (const Tcl_UniChar *uniStr, int uniLength, Tcl_DString *dsPtr); /* 354 */ - Tcl_UniChar * (*tcl_UtfToUniCharDString) (const char *src, int length, Tcl_DString *dsPtr); /* 355 */ + char * (*tcl_Char16ToUtfDString) (const unsigned short *uniStr, int uniLength, Tcl_DString *dsPtr); /* 354 */ + unsigned short * (*tcl_UtfToChar16DString) (const char *src, int length, Tcl_DString *dsPtr); /* 355 */ Tcl_RegExp (*tcl_GetRegExpFromObj) (Tcl_Interp *interp, Tcl_Obj *patObj, int flags); /* 356 */ TCL_DEPRECATED_API("Use Tcl_EvalTokensStandard") Tcl_Obj * (*tcl_EvalTokens) (Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 357 */ void (*tcl_FreeParse) (Tcl_Parse *parsePtr); /* 358 */ @@ -2581,6 +2593,10 @@ typedef struct TclStubs { void (*tcl_DecrRefCount) (Tcl_Obj *objPtr); /* 642 */ int (*tcl_IsShared) (Tcl_Obj *objPtr); /* 643 */ int (*tcl_LinkArray) (Tcl_Interp *interp, const char *varName, void *addr, int type, int size); /* 644 */ + int (*tcl_GetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* 645 */ + int (*tcl_UtfToUniChar) (const char *src, int *chPtr); /* 646 */ + char * (*tcl_UniCharToUtfDString) (const int *uniStr, int uniLength, Tcl_DString *dsPtr); /* 647 */ + int * (*tcl_UtfToUniCharDString) (const char *src, int length, Tcl_DString *dsPtr); /* 648 */ } TclStubs; extern const TclStubs *tclStubsPtr; @@ -2667,8 +2683,8 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_DbNewStringObj) /* 28 */ #define Tcl_DuplicateObj \ (tclStubsPtr->tcl_DuplicateObj) /* 29 */ -#define TclOldFreeObj \ - (tclStubsPtr->tclOldFreeObj) /* 30 */ +#define TclFreeObj \ + (tclStubsPtr->tclFreeObj) /* 30 */ #define Tcl_GetBoolean \ (tclStubsPtr->tcl_GetBoolean) /* 31 */ #define Tcl_GetBooleanFromObj \ @@ -3283,8 +3299,8 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_UtfToLower) /* 334 */ #define Tcl_UtfToTitle \ (tclStubsPtr->tcl_UtfToTitle) /* 335 */ -#define Tcl_UtfToUniChar \ - (tclStubsPtr->tcl_UtfToUniChar) /* 336 */ +#define Tcl_UtfToChar16 \ + (tclStubsPtr->tcl_UtfToChar16) /* 336 */ #define Tcl_UtfToUpper \ (tclStubsPtr->tcl_UtfToUpper) /* 337 */ #define Tcl_WriteChars \ @@ -3319,10 +3335,10 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_UniCharLen) /* 352 */ #define Tcl_UniCharNcmp \ (tclStubsPtr->tcl_UniCharNcmp) /* 353 */ -#define Tcl_UniCharToUtfDString \ - (tclStubsPtr->tcl_UniCharToUtfDString) /* 354 */ -#define Tcl_UtfToUniCharDString \ - (tclStubsPtr->tcl_UtfToUniCharDString) /* 355 */ +#define Tcl_Char16ToUtfDString \ + (tclStubsPtr->tcl_Char16ToUtfDString) /* 354 */ +#define Tcl_UtfToChar16DString \ + (tclStubsPtr->tcl_UtfToChar16DString) /* 355 */ #define Tcl_GetRegExpFromObj \ (tclStubsPtr->tcl_GetRegExpFromObj) /* 356 */ #define Tcl_EvalTokens \ @@ -3901,6 +3917,14 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_IsShared) /* 643 */ #define Tcl_LinkArray \ (tclStubsPtr->tcl_LinkArray) /* 644 */ +#define Tcl_GetIntForIndex \ + (tclStubsPtr->tcl_GetIntForIndex) /* 645 */ +#define Tcl_UtfToUniChar \ + (tclStubsPtr->tcl_UtfToUniChar) /* 646 */ +#define Tcl_UniCharToUtfDString \ + (tclStubsPtr->tcl_UniCharToUtfDString) /* 647 */ +#define Tcl_UtfToUniCharDString \ + (tclStubsPtr->tcl_UtfToUniCharDString) /* 648 */ #endif /* defined(USE_TCL_STUBS) */ @@ -3927,7 +3951,6 @@ extern const TclStubs *tclStubsPtr; # define Tcl_MainEx Tcl_MainExW EXTERN void Tcl_MainExW(int argc, wchar_t **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); - EXTERN int TclZipfs_AppHook(int *argc, wchar_t ***argv); #endif #undef TCL_STORAGE_CLASS @@ -4086,6 +4109,36 @@ extern const TclStubs *tclStubsPtr; #undef Tcl_StringMatch #define Tcl_StringMatch(str, pattern) Tcl_StringCaseMatch((str), (pattern), 0) +#if TCL_UTF_MAX <= 4 +# undef Tcl_UniCharToUtfDString +# define Tcl_UniCharToUtfDString Tcl_Char16ToUtfDString +# undef Tcl_UtfToUniCharDString +# define Tcl_UtfToUniCharDString Tcl_UtfToChar16DString +# undef Tcl_UtfToUniChar +# define Tcl_UtfToUniChar Tcl_UtfToChar16 +#endif +#if defined(USE_TCL_STUBS) +# define Tcl_WCharToUtfDString (sizeof(wchar_t) != sizeof(short) \ + ? (char *(*)(const wchar_t *, int, Tcl_DString *))tclStubsPtr->tcl_UniCharToUtfDString \ + : (char *(*)(const wchar_t *, int, Tcl_DString *))Tcl_Char16ToUtfDString) +# define Tcl_UtfToWCharDString (sizeof(wchar_t) != sizeof(short) \ + ? (wchar_t *(*)(const char *, int, Tcl_DString *))tclStubsPtr->tcl_UtfToUniCharDString \ + : (wchar_t *(*)(const char *, int, Tcl_DString *))Tcl_UtfToChar16DString) +# define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \ + ? (int (*)(const char *, wchar_t *))tclStubsPtr->tcl_UtfToChar16 \ + : (int (*)(const char *, wchar_t *))Tcl_UtfToUniChar) +#else +# define Tcl_WCharToUtfDString (sizeof(wchar_t) != sizeof(short) \ + ? (char *(*)(const wchar_t *, int, Tcl_DString *))Tcl_UniCharToUtfDString \ + : (char *(*)(const wchar_t *, int, Tcl_DString *))Tcl_Char16ToUtfDString) +# define Tcl_UtfToWCharDString (sizeof(wchar_t) != sizeof(short) \ + ? (wchar_t *(*)(const char *, int, Tcl_DString *))Tcl_UtfToUniCharDString \ + : (wchar_t *(*)(const char *, int, Tcl_DString *))Tcl_UtfToChar16DString) +# define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \ + ? (int (*)(const char *, wchar_t *))Tcl_UtfToChar16 \ + : (int (*)(const char *, wchar_t *))Tcl_UtfToUniChar) +#endif + /* * Deprecated Tcl procedures: */ diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c index f3b0981..5c6cb52 100644 --- a/generic/tclDictObj.c +++ b/generic/tclDictObj.c @@ -11,7 +11,7 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tclTomMath.h" #include <assert.h> /* @@ -3211,6 +3211,7 @@ DictFilterCmd( Tcl_ResetResult(interp); Tcl_DictObjDone(&search); + /* FALLTHRU */ case TCL_CONTINUE: result = TCL_OK; break; @@ -3309,7 +3310,7 @@ DictUpdateCmd( } if (objPtr == NULL) { /* ??? */ - Tcl_UnsetVar(interp, Tcl_GetString(objv[i+1]), 0); + Tcl_UnsetVar2(interp, Tcl_GetString(objv[i+1]), NULL, 0); } else if (Tcl_ObjSetVar2(interp, objv[i+1], NULL, objPtr, TCL_LEAVE_ERR_MSG) == NULL) { TclDecrRefCount(dictPtr); diff --git a/generic/tclDisassemble.c b/generic/tclDisassemble.c index e5fce72..3204619 100644 --- a/generic/tclDisassemble.c +++ b/generic/tclDisassemble.c @@ -542,7 +542,7 @@ FormatInstruction( { Proc *procPtr = codePtr->procPtr; unsigned char opCode = *pc; - register const InstructionDesc *instDesc = &tclInstructionTable[opCode]; + const InstructionDesc *instDesc = &tclInstructionTable[opCode]; unsigned char *codeStart = codePtr->codeStart; unsigned pcOffset = pc - codeStart; int opnd = 0, i, j, numBytes = 1; @@ -837,7 +837,7 @@ UpdateStringOfInstName( if (inst > LAST_INST_OPCODE) { dst = Tcl_InitStringRep(objPtr, NULL, TCL_INTEGER_SPACE + 5); TclOOM(dst, TCL_INTEGER_SPACE + 5); - sprintf(dst, "inst_%" TCL_Z_MODIFIER "d", inst); + sprintf(dst, "inst_%" TCL_Z_MODIFIER "u", inst); (void) Tcl_InitStringRep(objPtr, NULL, strlen(dst)); } else { const char *s = tclInstructionTable[inst].name; @@ -863,8 +863,8 @@ PrintSourceToObj( const char *stringPtr, /* The string to print. */ int maxChars) /* Maximum number of chars to print. */ { - register const char *p; - register int i = 0, len; + const char *p; + int i = 0, len; Tcl_UniChar ch = 0; if (stringPtr == NULL) { diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 7eb73e8..6740565 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; @@ -234,12 +234,17 @@ static int TableToUtfProc(ClientData clientData, const char *src, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static size_t unilen(const char *src); -static int UniCharToUtfProc(ClientData clientData, +static int Utf16ToUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); -static int UtfToUniCharProc(ClientData clientData, +static int UtfToUtf16Proc(ClientData clientData, + const char *src, int srcLen, int flags, + Tcl_EncodingState *statePtr, char *dst, int dstLen, + int *srcReadPtr, int *dstWrotePtr, + int *dstCharsPtr); +static int UtfToUcs2Proc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, @@ -446,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. * *---------------------------------------------------------------------- */ @@ -470,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. @@ -564,19 +567,24 @@ TclInitEncodingSubsystem(void) TableEncodingData *dataPtr; unsigned size; unsigned short i; + union { + char c; + short s; + } isLe; if (encodingsInitialized) { return; } + isLe.s = 1; Tcl_MutexLock(&encodingMutex); Tcl_InitHashTable(&encodingTable, TCL_STRING_KEYS); 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; @@ -595,13 +603,38 @@ TclInitEncodingSubsystem(void) type.clientData = NULL; Tcl_CreateEncoding(&type); - type.encodingName = "unicode"; - type.toUtfProc = UniCharToUtfProc; - type.fromUtfProc = UtfToUniCharProc; + type.toUtfProc = Utf16ToUtfProc; + type.fromUtfProc = UtfToUcs2Proc; type.freeProc = NULL; type.nullSize = 2; - type.clientData = NULL; + type.encodingName = "ucs-2le"; + type.clientData = INT2PTR(1); + Tcl_CreateEncoding(&type); + type.encodingName = "ucs-2be"; + type.clientData = INT2PTR(0); + Tcl_CreateEncoding(&type); + type.encodingName = "ucs-2"; + type.clientData = INT2PTR(isLe.c); + Tcl_CreateEncoding(&type); + + type.toUtfProc = Utf16ToUtfProc; + type.fromUtfProc = UtfToUtf16Proc; + type.freeProc = NULL; + type.nullSize = 2; + type.encodingName = "utf-16le"; + type.clientData = INT2PTR(1); + Tcl_CreateEncoding(&type); + type.encodingName = "utf-16be"; + type.clientData = INT2PTR(0); + Tcl_CreateEncoding(&type); + type.encodingName = "utf-16"; + type.clientData = INT2PTR(isLe.c); + Tcl_CreateEncoding(&type); + +#ifndef TCL_NO_DEPRECATED + type.encodingName = "unicode"; Tcl_CreateEncoding(&type); +#endif /* * Need the iso8859-1 encoding in order to process binary data, so force @@ -771,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. * *------------------------------------------------------------------------- */ @@ -813,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. * *--------------------------------------------------------------------------- */ @@ -840,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. * @@ -1034,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. * *--------------------------------------------------------------------------- */ @@ -1279,7 +1308,7 @@ Tcl_ExternalToUtf( if (*dstCharsPtr <= maxChars) { break; } - dstLen = Tcl_UtfAtIndex(dst, maxChars) - 1 - dst + TCL_UTF_MAX; + dstLen = Tcl_UtfAtIndex(dst, maxChars) - dst + (TCL_UTF_MAX - 1); flags = savedFlags; *statePtr = savedState; } while (1); @@ -1297,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 @@ -1480,7 +1508,7 @@ Tcl_FindExecutable( const char *argv0) /* The value of the application's argv[0] * (native). */ { - TclInitSubsystems(); + Tcl_InitSubsystems(); TclpSetInitialEncodings(); TclpFindExecutable(argv0); } @@ -1611,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. * *--------------------------------------------------------------------------- */ @@ -1625,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; @@ -1680,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. */ { @@ -1817,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) { @@ -1859,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. */ @@ -1872,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]; @@ -1925,7 +1953,7 @@ LoadTableEncoding( } /* - * Read lines from the encoding until EOF. + * Read lines until EOF. */ for (TclDStringClear(&lineString); @@ -2002,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; @@ -2174,7 +2202,7 @@ BinaryProc( /* *------------------------------------------------------------------------- * - * UtfExtToUtfIntProc -- + * UtfIntToUtfExtProc -- * * Convert from UTF-8 to UTF-8. While converting null-bytes from the * Tcl's internal representation (0xc0, 0x80) to the official @@ -2315,7 +2343,7 @@ UtfToUtfProc( * output buffer. */ int pureNullMode) /* Convert embedded nulls from internal * representation to real null-bytes or vice - * versa. */ + * versa. Also combine or separate surrogate pairs */ { const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; @@ -2331,7 +2359,7 @@ UtfToUtfProc( srcEnd = src + srcLen; srcClose = srcEnd; if ((flags & TCL_ENCODING_END) == 0) { - srcClose -= TCL_UTF_MAX; + srcClose -= 6; } if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; @@ -2380,15 +2408,22 @@ UtfToUtfProc( src += 1; dst += Tcl_UniCharToUtf(*chPtr, dst); } else { - int len = TclUtfToUniChar(src, chPtr); - src += len; - dst += Tcl_UniCharToUtf(*chPtr, dst); -#if TCL_UTF_MAX <= 4 - if ((*chPtr >= 0xD800) && (len < 3)) { - src += TclUtfToUniChar(src + len, chPtr); + src += TclUtfToUniChar(src, chPtr); + if ((*chPtr | 0x7FF) == 0xDFFF) { + /* A surrogate character is detected, handle especially */ + Tcl_UniChar low = *chPtr; + size_t len = (src <= srcEnd-3) ? Tcl_UtfToUniChar(src, &low) : 0; + if (((low | 0x3FF) != 0xDFFF) || (*chPtr & 0x400)) { + *dst++ = (char) (((*chPtr >> 12) | 0xE0) & 0xEF); + *dst++ = (char) (((*chPtr >> 6) | 0x80) & 0xBF); + *dst++ = (char) ((*chPtr | 0x80) & 0xBF); + continue; + } + src += len; dst += Tcl_UniCharToUtf(*chPtr, dst); + *chPtr = low; } -#endif + dst += Tcl_UniCharToUtf(*chPtr, dst); } } @@ -2401,9 +2436,9 @@ UtfToUtfProc( /* *------------------------------------------------------------------------- * - * UniCharToUtfProc -- + * Utf16ToUtfProc -- * - * Convert from Unicode to UTF-8. + * Convert from UTF-16 to UTF-8. * * Results: * Returns TCL_OK if conversion was successful. @@ -2415,8 +2450,8 @@ UtfToUtfProc( */ static int -UniCharToUtfProc( - ClientData clientData, /* Not used. */ +Utf16ToUtfProc( + ClientData clientData, /* != NULL means LE, == NUL means BE */ const char *src, /* Source string in Unicode. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ @@ -2450,10 +2485,16 @@ UniCharToUtfProc( charLimit = *dstCharsPtr; } result = TCL_OK; - if ((srcLen % sizeof(unsigned short)) != 0) { + + /* check alignment with utf-16 (2 == sizeof(UTF-16)) */ + if ((srcLen % 2) != 0) { result = TCL_CONVERT_MULTIBYTE; - srcLen /= sizeof(unsigned short); - srcLen *= sizeof(unsigned short); + srcLen--; + } + /* If last code point is a high surrogate, we cannot handle that yet */ + if ((srcLen >= 2) && ((src[srcLen - (clientData?1:2)] & 0xFC) == 0xD8)) { + result = TCL_CONVERT_MULTIBYTE; + srcLen-= 2; } srcStart = src; @@ -2468,12 +2509,15 @@ UniCharToUtfProc( break; } + if (clientData) { + ch = (src[1] & 0xFF) << 8 | (src[0] & 0xFF); + } else { + ch = (src[0] & 0xFF) << 8 | (src[1] & 0xFF); + } /* * Special case for 1-byte utf chars for speed. Make sure we work with * unsigned short-size data. */ - - ch = *(unsigned short *)src; if (ch && ch < 0x80) { *dst++ = (ch & 0xFF); } else { @@ -2491,9 +2535,9 @@ UniCharToUtfProc( /* *------------------------------------------------------------------------- * - * UtfToUniCharProc -- + * UtfToUtf16Proc -- * - * Convert from UTF-8 to Unicode. + * Convert from UTF-8 to UTF-16. * * Results: * Returns TCL_OK if conversion was successful. @@ -2505,9 +2549,8 @@ UniCharToUtfProc( */ static int -UtfToUniCharProc( - ClientData clientData, /* TableEncodingData that specifies - * encoding. */ +UtfToUtf16Proc( + ClientData clientData, /* != NULL means LE, == NUL means BE */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ @@ -2571,44 +2614,151 @@ UtfToUniCharProc( * casting dst to a Tcl_UniChar. [Bug 1122671] */ -#ifdef WORDS_BIGENDIAN + if (clientData) { #if TCL_UTF_MAX > 4 - if (*chPtr <= 0xFFFF) { - *dst++ = (*chPtr >> 8); - *dst++ = (*chPtr & 0xFF); - } else { - *dst++ = ((*chPtr & 0x3) >> 8) | 0xDC; - *dst++ = (*chPtr & 0xFF); - *dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8; - *dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF); - } -#else - *dst++ = (*chPtr >> 8); - *dst++ = (*chPtr & 0xFF); -#endif + if (*chPtr <= 0xFFFF) { + *dst++ = (*chPtr & 0xFF); + *dst++ = (*chPtr >> 8); + } else { + *dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF); + *dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8; + *dst++ = (*chPtr & 0xFF); + *dst++ = ((*chPtr & 0x3) >> 8) | 0xDC; + } #else -#if TCL_UTF_MAX > 4 - if (*chPtr <= 0xFFFF) { *dst++ = (*chPtr & 0xFF); *dst++ = (*chPtr >> 8); +#endif } else { - *dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF); - *dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8; +#if TCL_UTF_MAX > 4 + if (*chPtr <= 0xFFFF) { + *dst++ = (*chPtr >> 8); + *dst++ = (*chPtr & 0xFF); + } else { + *dst++ = ((*chPtr & 0x3) >> 8) | 0xDC; + *dst++ = (*chPtr & 0xFF); + *dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8; + *dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF); + } +#else + *dst++ = (*chPtr >> 8); *dst++ = (*chPtr & 0xFF); - *dst++ = ((*chPtr & 0x3) >> 8) | 0xDC; +#endif } -#else - *dst++ = (*chPtr & 0xFF); - *dst++ = (*chPtr >> 8); + } + *srcReadPtr = src - srcStart; + *dstWrotePtr = dst - dstStart; + *dstCharsPtr = numChars; + return result; +} + +/* + *------------------------------------------------------------------------- + * + * UtfToUcs2Proc -- + * + * Convert from UTF-8 to UCS-2. + * + * Results: + * Returns TCL_OK if conversion was successful. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static int +UtfToUcs2Proc( + ClientData clientData, /* != NULL means LE, == NUL means BE */ + const char *src, /* Source string in UTF-8. */ + int srcLen, /* Source string length in bytes. */ + int flags, /* Conversion control flags. */ + Tcl_EncodingState *statePtr,/* Place for conversion routine to store state + * information used during a piecewise + * conversion. Contents of statePtr are + * initialized and/or reset by conversion + * routine under control of flags argument. */ + char *dst, /* Output buffer in which converted string is + * stored. */ + int dstLen, /* The maximum length of output buffer in + * bytes. */ + int *srcReadPtr, /* Filled with the number of bytes from the + * source string that were converted. This may + * be less than the original source length if + * there was a problem converting some source + * characters. */ + int *dstWrotePtr, /* Filled with the number of bytes that were + * stored in the output buffer as a result of + * the conversion. */ + int *dstCharsPtr) /* Filled with the number of characters that + * correspond to the bytes stored in the + * output buffer. */ +{ + const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd; + int result, numChars; +#if TCL_UTF_MAX <= 4 + int len; #endif + Tcl_UniChar ch = 0; + + srcStart = src; + srcEnd = src + srcLen; + srcClose = srcEnd; + if ((flags & TCL_ENCODING_END) == 0) { + srcClose -= TCL_UTF_MAX; + } + + dstStart = dst; + dstEnd = dst + dstLen - sizeof(Tcl_UniChar); + + result = TCL_OK; + for (numChars = 0; src < srcEnd; numChars++) { + if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) { + /* + * If there is more string to follow, this will ensure that the + * last UTF-8 character in the source buffer hasn't been cut off. + */ + + result = TCL_CONVERT_MULTIBYTE; + break; + } + if (dst > dstEnd) { + result = TCL_CONVERT_NOSPACE; + break; + } +#if TCL_UTF_MAX <= 4 + src += (len = TclUtfToUniChar(src, &ch)); + if ((ch >= 0xD800) && (len < 3)) { + src += TclUtfToUniChar(src, &ch); + ch = 0xFFFD; + } +#else + src += TclUtfToUniChar(src, &ch); + if (ch > 0xFFFF) { + ch = 0xFFFD; + } #endif + + /* + * Need to handle this in a way that won't cause misalignment by + * casting dst to a Tcl_UniChar. [Bug 1122671] + */ + + if (clientData) { + *dst++ = (ch & 0xFF); + *dst++ = (ch >> 8); + } else { + *dst++ = (ch >> 8); + *dst++ = (ch & 0xFF); + } } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } - + /* *------------------------------------------------------------------------- * @@ -2979,6 +3129,7 @@ Iso88591FromUtfProc( const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; int result, numChars; + Tcl_UniChar ch = 0; result = TCL_OK; @@ -2993,7 +3144,6 @@ Iso88591FromUtfProc( dstEnd = dst + dstLen - 1; for (numChars = 0; src < srcEnd; numChars++) { - Tcl_UniChar ch = 0; int len; if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) { @@ -3346,6 +3496,7 @@ EscapeFromUtfProc( const TableEncodingData *tableDataPtr; const char *tablePrefixBytes; const unsigned short *const *tableFromUnicode; + Tcl_UniChar ch = 0; result = TCL_OK; @@ -3386,7 +3537,6 @@ EscapeFromUtfProc( for (numChars = 0; src < srcEnd; numChars++) { unsigned len; int word; - Tcl_UniChar ch = 0; if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) { /* @@ -3511,14 +3661,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/tclEnsemble.c b/generic/tclEnsemble.c index 53b8bfb..16d8310 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -119,7 +119,7 @@ static inline Tcl_Obj * NewNsObj( Tcl_Namespace *namespacePtr) { - register Namespace *nsPtr = (Namespace *) namespacePtr; + Namespace *nsPtr = (Namespace *) namespacePtr; if (namespacePtr == TclGetGlobalNamespace(nsPtr->interp)) { return Tcl_NewStringObj("::", 2); @@ -1813,7 +1813,7 @@ NsEnsembleImplementationCmdNR( subcmdName = TclGetStringFromObj(subObj, &stringLength); for (i=0 ; i<tableLength ; i++) { - register int cmp = strncmp(subcmdName, + int cmp = strncmp(subcmdName, ensemblePtr->subcommandArrayPtr[i], stringLength); @@ -2404,7 +2404,7 @@ MakeCachedEnsembleCommand( Tcl_HashEntry *hPtr, Tcl_Obj *fix) { - register EnsembleCmdRep *ensembleCmd; + EnsembleCmdRep *ensembleCmd; ECRGetIntRep(objPtr, ensembleCmd); if (ensembleCmd) { @@ -2580,7 +2580,7 @@ BuildEnsembleConfig( if (subList) { int subc; Tcl_Obj **subv, *target, *cmdObj, *cmdPrefixObj; - char *name; + const char *name; /* * There is a list of exactly what subcommands go in the table. @@ -2665,7 +2665,7 @@ BuildEnsembleConfig( Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch, &keyObj, &valueObj, &done); while (!done) { - char *name = TclGetString(keyObj); + const char *name = TclGetString(keyObj); hPtr = Tcl_CreateHashEntry(hash, name, &isNew); Tcl_SetHashValue(hPtr, valueObj); @@ -2707,7 +2707,11 @@ BuildEnsembleConfig( if (isNew) { Tcl_Obj *cmdObj, *cmdPrefixObj; - cmdObj = Tcl_NewStringObj(nsCmdName, -1); + TclNewObj(cmdObj); + Tcl_AppendStringsToObj(cmdObj, + ensemblePtr->nsPtr->fullName, + (ensemblePtr->nsPtr->parentPtr ? "::" : ""), + nsCmdName, NULL); cmdPrefixObj = Tcl_NewListObj(1, &cmdObj); Tcl_SetHashValue(hPtr, cmdPrefixObj); Tcl_IncrRefCount(cmdPrefixObj); @@ -3375,7 +3379,7 @@ CompileToInvokedCommand( { Tcl_Token *tokPtr; Tcl_Obj *objPtr, **words; - char *bytes; + const char *bytes; int i, numWords, cmdLit, extraLiteralFlags = LITERAL_CMD_NAME; DefineLineInformation; diff --git a/generic/tclEvent.c b/generic/tclEvent.c index 7ce5ddd..41aeca4 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -947,16 +947,20 @@ Tcl_Exit( currentAppExitPtr = appExitPtr; Tcl_MutexUnlock(&exitMutex); + /* + * Warning: this function SHOULD NOT return, as there is code that depends + * on Tcl_Exit never returning. In fact, we will Tcl_Panic if anyone + * returns, so critical is this dependcy. + * + * If subsystems are not (yet) initialized, proper Tcl-finalization is + * impossible, so fallback to system exit, see bug-[f8a33ce3db5d8cc2]. + */ + if (currentAppExitPtr) { - /* - * Warning: this code SHOULD NOT return, as there is code that depends - * on Tcl_Exit never returning. In fact, we will Tcl_Panic if anyone - * returns, so critical is this dependcy. - */ currentAppExitPtr(INT2PTR(status)); - Tcl_Panic("AppExitProc returned unexpectedly"); - } else { + + } else if (subsystemsInitialized) { if (TclFullFinalizationRequested()) { @@ -989,15 +993,16 @@ Tcl_Exit( FinalizeThread(/* quick */ 1); } - TclpExit(status); - Tcl_Panic("OS exit failed!"); } + + TclpExit(status); + Tcl_Panic("OS exit failed!"); } /* *------------------------------------------------------------------------- * - * TclInitSubsystems -- + * Tcl_InitSubsystems -- * * Initialize various subsytems in Tcl. This should be called the first * time an interp is created, or before any of the subsystems are used. @@ -1020,10 +1025,10 @@ Tcl_Exit( */ void -TclInitSubsystems(void) +Tcl_InitSubsystems(void) { if (inExit != 0) { - Tcl_Panic("TclInitSubsystems called while exiting"); + Tcl_Panic("Tcl_InitSubsystems called while exiting"); } if (subsystemsInitialized == 0) { diff --git a/generic/tclExecute.c b/generic/tclExecute.c index ed4fdd7..72b9746 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -18,7 +18,7 @@ #include "tclInt.h" #include "tclCompile.h" #include "tclOOInt.h" -#include "tommath.h" +#include "tclTomMath.h" #include <math.h> #include <assert.h> @@ -97,9 +97,9 @@ static const char *const resultStrings[] = { */ #ifdef TCL_COMPILE_STATS -long tclObjsAlloced = 0; -long tclObjsFreed = 0; -long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 }; +size_t tclObjsAlloced = 0; +size_t tclObjsFreed = 0; +size_t tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 }; #endif /* TCL_COMPILE_STATS */ /* @@ -211,7 +211,7 @@ typedef struct TEBCdata { */ #define VarHashGetValue(hPtr) \ - ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry))) + ((Var *) ((char *)hPtr - offsetof(VarInHash, entry))) static inline Var * VarHashCreateVar( @@ -1327,7 +1327,7 @@ int Tcl_ExprObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ - register Tcl_Obj *objPtr, /* Points to Tcl object containing expression + Tcl_Obj *objPtr, /* Points to Tcl object containing expression * to evaluate. */ Tcl_Obj **resultPtrPtr) /* Where the Tcl_Obj* that is the expression * result is stored if no errors occur. */ @@ -1444,7 +1444,7 @@ CompileExprObj( Interp *iPtr = (Interp *) interp; CompileEnv compEnv; /* Compilation environment structure allocated * in frame. */ - register ByteCode *codePtr = NULL; + ByteCode *codePtr = NULL; /* Tcl Internal type of bytecode. Initialized * to avoid compiler warning. */ @@ -1598,8 +1598,8 @@ TclCompileObj( const CmdFrame *invoker, int word) { - register Interp *iPtr = (Interp *) interp; - register ByteCode *codePtr; /* Tcl Internal type of bytecode. */ + Interp *iPtr = (Interp *) interp; + ByteCode *codePtr; /* Tcl Internal type of bytecode. */ Namespace *namespacePtr = iPtr->varFramePtr->nsPtr; /* @@ -1981,7 +1981,14 @@ TclNRExecuteByteCode( */ TclNRAddCallback(interp, TEBCresume, TD, /* pc */ NULL, - /* cleanup */ INT2PTR(0), NULL); + /* cleanup */ INT2PTR(0), INT2PTR(iPtr->evalFlags)); + + /* + * Reset discard result flag - because it is applicable for this call only, + * and should not affect all the nested invocations may return result. + */ + iPtr->evalFlags &= ~TCL_EVAL_DISCARD_RESULT; + return TCL_OK; } @@ -2043,6 +2050,7 @@ TEBCresume( #define auxObjList (TD->auxObjList) #define catchTop (TD->catchTop) #define codePtr (TD->codePtr) +#define curEvalFlags PTR2INT(data[3]) /* calling iPtr->evalFlags */ /* * Globals: variables that store state, must remain valid at all times. @@ -2061,7 +2069,7 @@ TEBCresume( int cleanup = PTR2INT(data[2]); Tcl_Obj *objResultPtr; - int checkInterp; /* Indicates when a check of interp readyness + int checkInterp = 0; /* Indicates when a check of interp readyness * is necessary. Set by CACHE_STACK_INFO() */ /* @@ -2071,7 +2079,7 @@ TEBCresume( */ Tcl_Obj *objPtr, *valuePtr, *value2Ptr, *part1Ptr, *part2Ptr, *tmpPtr; - Tcl_Obj **objv; + Tcl_Obj **objv = NULL; int objc = 0; int opnd, length, pcAdjustment; Var *varPtr, *arrayPtr; @@ -2096,7 +2104,6 @@ TEBCresume( if (!pc) { /* bytecode is starting from scratch */ - checkInterp = 0; pc = codePtr->codeStart; goto cleanup0; } else { @@ -2118,8 +2125,9 @@ TEBCresume( goto abnormalReturn; } if (codePtr->flags & TCL_BYTECODE_RECOMPILE) { - iPtr->flags |= ERR_ALREADY_LOGGED; codePtr->flags &= ~TCL_BYTECODE_RECOMPILE; + checkInterp = 1; + iPtr->flags |= ERR_ALREADY_LOGGED; } if (result != TCL_OK) { @@ -2179,10 +2187,12 @@ TEBCresume( objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); } + /* FALLTHRU */ case 2: cleanup2_pushObjResultPtr: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); + /* FALLTHRU */ case 1: cleanup1_pushObjResultPtr: objPtr = OBJ_AT_TOS; @@ -2199,14 +2209,17 @@ TEBCresume( objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); } + /* FALLTHRU */ case 2: cleanup2: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); + /* FALLTHRU */ case 1: cleanup1: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); + /* FALLTHRU */ case 0: /* * We really want to do nothing now, but this is needed for some @@ -2294,12 +2307,12 @@ TEBCresume( iPtr->cmdCount += TclGetUInt4AtPtr(pc+5); if (checkInterp) { - checkInterp = 0; if (((codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsEpoch != iPtr->varFramePtr->nsPtr->resolverEpoch)) && !(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) { goto instStartCmdFailed; } + checkInterp = 0; } inst = *(pc += 9); goto peepholeStart; @@ -2493,7 +2506,7 @@ TEBCresume( #ifdef TCL_COMPILE_DEBUG /* FIXME: What is the right thing to trace? */ { - register int i; + int i; TRACE(("%d [", opnd)); for (i=opnd-1 ; i>=0 ; i--) { @@ -2526,6 +2539,14 @@ TEBCresume( case INST_DONE: if (tosPtr > initTosPtr) { + + if ((curEvalFlags & TCL_EVAL_DISCARD_RESULT) && (result == TCL_OK)) { + /* simulate pop & fast done (like it does continue in loop) */ + TRACE_WITH_OBJ(("=> discarding "), OBJ_AT_TOS); + objPtr = POP_OBJECT(); + TclDecrRefCount(objPtr); + goto abnormalReturn; + } /* * Set the interpreter's object result to point to the topmost * object from the stack, and check for a possible [catch]. The @@ -2725,15 +2746,18 @@ TEBCresume( * INVOCATION BLOCK */ - instEvalStk: case INST_EVAL_STK: + instEvalStk: bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; cleanup = 1; pc += 1; + /* yield next instruction */ TEBC_YIELD(); - return TclNREvalObjEx(interp, OBJ_AT_TOS, 0, NULL, 0); + /* add TEBCResume for object at top of stack */ + return TclNRExecuteByteCode(interp, + TclCompileObj(interp, OBJ_AT_TOS, NULL, 0)); case INST_INVOKE_EXPANDED: CLANG_ASSERT(auxObjList); @@ -3482,31 +3506,36 @@ TEBCresume( { int createdNewObj = 0; + Tcl_Obj *valueToAssign; if (!objResultPtr) { - objResultPtr = valuePtr; + valueToAssign = valuePtr; } else if (TclListObjLength(interp, objResultPtr, &len)!=TCL_OK) { TRACE_ERROR(interp); goto gotError; } else { if (Tcl_IsShared(objResultPtr)) { - objResultPtr = Tcl_DuplicateObj(objResultPtr); + valueToAssign = Tcl_DuplicateObj(objResultPtr); createdNewObj = 1; + } else { + valueToAssign = objResultPtr; } - if (Tcl_ListObjReplace(interp, objResultPtr, len,0, objc,objv) - != TCL_OK) { + if (Tcl_ListObjReplace(interp, valueToAssign, len, 0, + objc, objv) != TCL_OK) { + if (createdNewObj) { + TclDecrRefCount(valueToAssign); + } goto errorInLappendListPtr; } } DECACHE_STACK_INFO(); + Tcl_IncrRefCount(valueToAssign); objResultPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, - part2Ptr, objResultPtr, TCL_LEAVE_ERR_MSG, opnd); + part2Ptr, valueToAssign, TCL_LEAVE_ERR_MSG, opnd); + TclDecrRefCount(valueToAssign); CACHE_STACK_INFO(); if (!objResultPtr) { errorInLappendListPtr: - if (createdNewObj) { - TclDecrRefCount(objResultPtr); - } TRACE_ERROR(interp); goto gotError; } @@ -4390,8 +4419,8 @@ TEBCresume( NEXT_INST_F(1, 0, 1); case INST_INFO_LEVEL_ARGS: { int level; - register CallFrame *framePtr = iPtr->varFramePtr; - register CallFrame *rootFramePtr = iPtr->rootFramePtr; + CallFrame *framePtr = iPtr->varFramePtr; + CallFrame *rootFramePtr = iPtr->rootFramePtr; TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS))); if (TclGetIntFromObj(interp, OBJ_AT_TOS, &level) != TCL_OK) { @@ -4688,7 +4717,7 @@ TEBCresume( } { - register Method *const mPtr = + Method *const mPtr = contextPtr->callPtr->chain[newDepth].mPtr; return mPtr->typePtr->callProc(mPtr->clientData, interp, @@ -5084,6 +5113,10 @@ TEBCresume( case INST_STR_EQ: case INST_STR_NEQ: /* String (in)equality check */ case INST_STR_CMP: /* String compare. */ + case INST_STR_LT: + case INST_STR_GT: + case INST_STR_LE: + case INST_STR_GE: stringCompare: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; @@ -5114,15 +5147,19 @@ TEBCresume( match = (match != 0); break; case INST_LT: + case INST_STR_LT: match = (match < 0); break; case INST_GT: + case INST_STR_GT: match = (match > 0); break; case INST_LE: + case INST_STR_LE: match = (match <= 0); break; case INST_GE: + case INST_STR_GE: match = (match >= 0); break; } @@ -6471,7 +6508,7 @@ TEBCresume( listTmpIndex++; } } - TRACE_APPEND(("%d lists, iter %" TCL_Z_MODIFIER "d, %s loop\n", + TRACE_APPEND(("%d lists, iter %" TCL_Z_MODIFIER "u, %s loop\n", numLists, iterNum, (continueLoop? "continue" : "exit"))); /* @@ -6770,7 +6807,7 @@ TEBCresume( NEXT_INST_F(1, 1, 0); case INST_DICT_EXISTS: { - register int found; + int found; opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => ", opnd)); @@ -7682,7 +7719,7 @@ TEBCresume( */ /* - * Abnormal return code. Restore the stack to state it had when + * Done or abnormal return code. Restore the stack to state it had when * starting to execute the ByteCode. Panic if the stack is below the * initial level. */ @@ -7737,19 +7774,22 @@ TEBCresume( { const char *bytes; - checkInterp = 1; length = 0; + if (TclInterpReady(interp) == TCL_ERROR) { + goto gotError; + } + /* * We used to switch to direct eval; for NRE-awareness we now * compile and eval the command so that this evaluation does not - * add a new TEBC instance. [Bug 2910748] + * add a new TEBC instance. Bug [2910748], bug [fa6bf38d07] + * + * TODO: recompile, search this command and eval a code starting from, + * so that this evaluation does not add a new TEBC instance without + * NRE-trampoline. */ - if (TclInterpReady(interp) == TCL_ERROR) { - goto gotError; - } - codePtr->flags |= TCL_BYTECODE_RECOMPILE; bytes = GetSrcInfoForPc(pc, codePtr, &length, NULL, NULL); opnd = TclGetUInt4AtPtr(pc+1); @@ -8027,12 +8067,12 @@ ExecuteExtendedBinaryMathOp( Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); /* TODO: internals intrusion */ - if ((w1 > ((Tcl_WideInt) 0)) ^ (big2.sign == MP_ZPOS)) { + if ((w1 > ((Tcl_WideInt) 0)) ^ !mp_isneg(&big2)) { /* * Arguments are opposite sign; remainder is sum. */ - TclInitBignumFromWideInt(&big1, w1); + mp_init_i64(&big1, w1); mp_add(&big2, &big1, &big2); mp_clear(&big1); BIG_RESULT(&big2); @@ -8076,7 +8116,7 @@ ExecuteExtendedBinaryMathOp( break; case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); - invalid = big2.sign != MP_ZPOS; + invalid = mp_isneg(&big2); mp_clear(&big2); break; default: @@ -8155,7 +8195,7 @@ ExecuteExtendedBinaryMathOp( break; case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); - zero = (big1.sign == MP_ZPOS); + zero = !mp_isneg(&big1); mp_clear(&big1); break; default: @@ -8191,7 +8231,7 @@ ExecuteExtendedBinaryMathOp( if (opcode == INST_LSHIFT) { mp_mul_2d(&big1, shift, &bigResult); } else { - mp_tc_div_2d(&big1, shift, &bigResult); + mp_signed_rsh(&big1, shift, &bigResult); } mp_clear(&big1); BIG_RESULT(&bigResult); @@ -8208,15 +8248,15 @@ ExecuteExtendedBinaryMathOp( switch (opcode) { case INST_BITAND: - mp_tc_and(&big1, &big2, &bigResult); + mp_and(&big1, &big2, &bigResult); break; case INST_BITOR: - mp_tc_or(&big1, &big2, &bigResult); + mp_or(&big1, &big2, &bigResult); break; case INST_BITXOR: - mp_tc_xor(&big1, &big2, &bigResult); + mp_xor(&big1, &big2, &bigResult); break; } @@ -8279,7 +8319,7 @@ ExecuteExtendedBinaryMathOp( oddExponent = (int) (w2 & (Tcl_WideInt)1); } else { Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); - negativeExponent = big2.sign != MP_ZPOS; + negativeExponent = mp_isneg(&big2); mp_mod_2d(&big2, 1, &big2); oddExponent = big2.used != 0; mp_clear(&big2); @@ -8439,7 +8479,7 @@ ExecuteExtendedBinaryMathOp( } Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); mp_init(&bigResult); - mp_expt_d_ex(&big1, w2, &bigResult, 1); + mp_expt_u32(&big1, (unsigned int)w2, &bigResult); mp_clear(&big1); BIG_RESULT(&bigResult); } @@ -8649,7 +8689,7 @@ ExecuteExtendedUnaryMathOp( } Tcl_TakeBignumFromObj(NULL, valuePtr, &big); /* ~a = - a - 1 */ - mp_neg(&big, &big); + (void)mp_neg(&big, &big); mp_sub_d(&big, 1, &big); BIG_RESULT(&big); case INST_UMINUS: @@ -8661,12 +8701,12 @@ ExecuteExtendedUnaryMathOp( if (w != WIDE_MIN) { WIDE_RESULT(-w); } - TclInitBignumFromWideInt(&big, w); + mp_init_i64(&big, w); break; default: Tcl_TakeBignumFromObj(NULL, valuePtr, &big); } - mp_neg(&big, &big); + (void)mp_neg(&big, &big); BIG_RESULT(&big); } @@ -8754,7 +8794,7 @@ TclCompareTwoNumbers( goto wideCompare; case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); - if (big2.sign != MP_ZPOS) { + if (mp_isneg(&big2)) { compare = MP_GT; } else { compare = MP_LT; @@ -8791,7 +8831,7 @@ TclCompareTwoNumbers( } Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); if ((d1 < (double)WIDE_MAX) && (d1 > (double)WIDE_MIN)) { - if (big2.sign != MP_ZPOS) { + if (mp_isneg(&big2)) { compare = MP_GT; } else { compare = MP_LT; @@ -8871,7 +8911,7 @@ TclCompareTwoNumbers( static void PrintByteCodeInfo( - register ByteCode *codePtr) /* The bytecode whose summary is printed to + ByteCode *codePtr) /* The bytecode whose summary is printed to * stdout. */ { Proc *procPtr = codePtr->procPtr; @@ -8935,7 +8975,7 @@ PrintByteCodeInfo( #ifdef TCL_COMPILE_DEBUG static void ValidatePcAndStackTop( - register ByteCode *codePtr, /* The bytecode whose summary is printed to + ByteCode *codePtr, /* The bytecode whose summary is printed to * stdout. */ const unsigned char *pc, /* Points to first byte of a bytecode * instruction. The program counter. */ @@ -8947,19 +8987,19 @@ ValidatePcAndStackTop( { int stackUpperBound = codePtr->maxStackDepth; /* Greatest legal value for stackTop. */ - unsigned relativePc = (unsigned) (pc - codePtr->codeStart); - unsigned long codeStart = (unsigned long) codePtr->codeStart; - unsigned long codeEnd = (unsigned long) + size_t relativePc = (size_t) (pc - codePtr->codeStart); + size_t codeStart = (size_t) codePtr->codeStart; + size_t codeEnd = (size_t) (codePtr->codeStart + codePtr->numCodeBytes); unsigned char opCode = *pc; - if (((unsigned long) pc < codeStart) || ((unsigned long) pc > codeEnd)) { + if (((size_t) pc < codeStart) || ((size_t) pc > codeEnd)) { fprintf(stderr, "\nBad instruction pc 0x%p in TclNRExecuteByteCode\n", pc); Tcl_Panic("TclNRExecuteByteCode execution failure: bad pc"); } if ((unsigned) opCode > LAST_INST_OPCODE) { - fprintf(stderr, "\nBad opcode %d at pc %u in TclNRExecuteByteCode\n", + fprintf(stderr, "\nBad opcode %d at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode\n", (unsigned) opCode, relativePc); Tcl_Panic("TclNRExecuteByteCode execution failure: bad opcode"); } @@ -8968,7 +9008,7 @@ ValidatePcAndStackTop( int numChars; const char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars, NULL, NULL); - fprintf(stderr, "\nBad stack top %d at pc %u in TclNRExecuteByteCode (min 0, max %i)", + fprintf(stderr, "\nBad stack top %d at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode (min 0, max %i)", stackTop, relativePc, stackUpperBound); if (cmd != NULL) { Tcl_Obj *message; @@ -9178,7 +9218,7 @@ GetSrcInfoForPc( * of the command containing the pc should * be stored. */ { - register int pcOffset = (pc - codePtr->codeStart); + int pcOffset = (pc - codePtr->codeStart); int numCmds = codePtr->numCommands; unsigned char *codeDeltaNext, *codeLengthNext; unsigned char *srcDeltaNext, *srcLengthNext; @@ -9331,9 +9371,9 @@ GetExceptRangeForPc( { ExceptionRange *rangeArrayPtr; int numRanges = codePtr->numExceptRanges; - register ExceptionRange *rangePtr; + ExceptionRange *rangePtr; int pcOffset = pc - codePtr->codeStart; - register int start; + int start; if (numRanges == 0) { return NULL; @@ -9465,11 +9505,11 @@ TclExprFloatError( int TclLog2( - register int value) /* The integer for which to compute the log + int value) /* The integer for which to compute the log * base 2. */ { - register int n = value; - register int result = 0; + int n = value; + int result = 0; while (n > 1) { n = n >> 1; @@ -9510,10 +9550,10 @@ EvalStatsCmd( double objBytesIfUnshared, strBytesIfUnshared, sharingBytesSaved; double strBytesSharedMultX, strBytesSharedOnce; double numInstructions, currentHeaderBytes; - long numCurrentByteCodes, numByteCodeLits; - long refCountSum, literalMgmtBytes, sum; - int numSharedMultX, numSharedOnce; - int decadeHigh, minSizeDecade, maxSizeDecade, length, i; + size_t numCurrentByteCodes, numByteCodeLits; + size_t refCountSum, literalMgmtBytes, sum; + size_t numSharedMultX, numSharedOnce, minSizeDecade, maxSizeDecade, i; + int decadeHigh, length; char *litTableStats; LiteralEntry *entryPtr; Tcl_Obj *objPtr; @@ -9555,12 +9595,12 @@ EvalStatsCmd( Tcl_AppendPrintfToObj(objPtr, "\n----------------------------------------------------------------\n"); Tcl_AppendPrintfToObj(objPtr, - "Compilation and execution statistics for interpreter %#lx\n", - (long int)iPtr); + "Compilation and execution statistics for interpreter %#" TCL_Z_MODIFIER "x\n", + (size_t)iPtr); - Tcl_AppendPrintfToObj(objPtr, "\nNumber ByteCodes executed\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, "\nNumber ByteCodes executed\t%" TCL_Z_MODIFIER "u\n", statsPtr->numExecutions); - Tcl_AppendPrintfToObj(objPtr, "Number ByteCodes compiled\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, "Number ByteCodes compiled\t%" TCL_Z_MODIFIER "u\n", statsPtr->numCompilations); Tcl_AppendPrintfToObj(objPtr, " Mean executions/compile\t%.1f\n", statsPtr->numExecutions / (float)statsPtr->numCompilations); @@ -9572,7 +9612,7 @@ EvalStatsCmd( Tcl_AppendPrintfToObj(objPtr, " Mean inst/execution\t\t%.0f\n", numInstructions / statsPtr->numExecutions); - Tcl_AppendPrintfToObj(objPtr, "\nTotal ByteCodes\t\t\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, "\nTotal ByteCodes\t\t\t%" TCL_Z_MODIFIER "u\n", statsPtr->numCompilations); Tcl_AppendPrintfToObj(objPtr, " Source bytes\t\t\t%.6g\n", statsPtr->totalSrcBytes); @@ -9582,18 +9622,18 @@ EvalStatsCmd( statsPtr->totalByteCodeBytes); Tcl_AppendPrintfToObj(objPtr, " Literal bytes\t\t%.6g\n", totalLiteralBytes); - Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n", - (unsigned long) sizeof(LiteralTable), - (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)), - (unsigned long) (statsPtr->numLiteralsCreated * sizeof(LiteralEntry)), - (unsigned long) (statsPtr->numLiteralsCreated * sizeof(Tcl_Obj)), + Tcl_AppendPrintfToObj(objPtr, " table %" TCL_Z_MODIFIER "u + bkts %" TCL_Z_MODIFIER "u + entries %" TCL_Z_MODIFIER "u + objects %" TCL_Z_MODIFIER "u + strings %.6g\n", + sizeof(LiteralTable), + iPtr->literalTable.numBuckets * sizeof(LiteralEntry *), + statsPtr->numLiteralsCreated * sizeof(LiteralEntry), + statsPtr->numLiteralsCreated * sizeof(Tcl_Obj), statsPtr->totalLitStringBytes); Tcl_AppendPrintfToObj(objPtr, " Mean code/compile\t\t%.1f\n", totalCodeBytes / statsPtr->numCompilations); Tcl_AppendPrintfToObj(objPtr, " Mean code/source\t\t%.1f\n", totalCodeBytes / statsPtr->totalSrcBytes); - Tcl_AppendPrintfToObj(objPtr, "\nCurrent (active) ByteCodes\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, "\nCurrent (active) ByteCodes\t%" TCL_Z_MODIFIER "u\n", numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, " Source bytes\t\t\t%.6g\n", statsPtr->currentSrcBytes); @@ -9624,17 +9664,17 @@ EvalStatsCmd( numSharedMultX = 0; Tcl_AppendPrintfToObj(objPtr, "\nTcl_IsShared object check (all objects):\n"); - Tcl_AppendPrintfToObj(objPtr, " Object had refcount <=1 (not shared)\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, " Object had refcount <=1 (not shared)\t%" TCL_Z_MODIFIER "u\n", tclObjsShared[1]); for (i = 2; i < TCL_MAX_SHARED_OBJ_STATS; i++) { - Tcl_AppendPrintfToObj(objPtr, " refcount ==%d\t\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, " refcount ==%" TCL_Z_MODIFIER "u\t\t%" TCL_Z_MODIFIER "u\n", i, tclObjsShared[i]); numSharedMultX += tclObjsShared[i]; } - Tcl_AppendPrintfToObj(objPtr, " refcount >=%d\t\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, " refcount >=%" TCL_Z_MODIFIER "u\t\t%" TCL_Z_MODIFIER "u\n", i, tclObjsShared[0]); numSharedMultX += tclObjsShared[0]; - Tcl_AppendPrintfToObj(objPtr, " Total shared objects\t\t\t%d\n", + Tcl_AppendPrintfToObj(objPtr, " Total shared objects\t\t\t%" TCL_Z_MODIFIER "u\n", numSharedMultX); /* @@ -9671,20 +9711,20 @@ EvalStatsCmd( sharingBytesSaved = (objBytesIfUnshared + strBytesIfUnshared) - currentLiteralBytes; - Tcl_AppendPrintfToObj(objPtr, "\nTotal objects (all interps)\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, "\nTotal objects (all interps)\t%" TCL_Z_MODIFIER "u\n", tclObjsAlloced); - Tcl_AppendPrintfToObj(objPtr, "Current objects\t\t\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, "Current objects\t\t\t%" TCL_Z_MODIFIER "u\n", (tclObjsAlloced - tclObjsFreed)); - Tcl_AppendPrintfToObj(objPtr, "Total literal objects\t\t%ld\n", + Tcl_AppendPrintfToObj(objPtr, "Total literal objects\t\t%" TCL_Z_MODIFIER "u\n", statsPtr->numLiteralsCreated); Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%d (%0.1f%% of current objects)\n", globalTablePtr->numEntries, Percent(globalTablePtr->numEntries, tclObjsAlloced-tclObjsFreed)); - Tcl_AppendPrintfToObj(objPtr, " ByteCode literals\t\t%ld (%0.1f%% of current literals)\n", + Tcl_AppendPrintfToObj(objPtr, " ByteCode literals\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of current literals)\n", numByteCodeLits, Percent(numByteCodeLits, globalTablePtr->numEntries)); - Tcl_AppendPrintfToObj(objPtr, " Literals reused > 1x\t\t%d\n", + Tcl_AppendPrintfToObj(objPtr, " Literals reused > 1x\t\t%" TCL_Z_MODIFIER "u\n", numSharedMultX); Tcl_AppendPrintfToObj(objPtr, " Mean reference count\t\t%.2f\n", ((double) refCountSum) / globalTablePtr->numEntries); @@ -9709,7 +9749,7 @@ EvalStatsCmd( Tcl_AppendPrintfToObj(objPtr, " String sharing savings \t%.6g = unshared %.6g - shared %.6g\n", (strBytesIfUnshared - statsPtr->currentLitStringBytes), strBytesIfUnshared, statsPtr->currentLitStringBytes); - Tcl_AppendPrintfToObj(objPtr, " Literal mgmt overhead\t\t%ld (%0.1f%% of bytes with sharing)\n", + Tcl_AppendPrintfToObj(objPtr, " Literal mgmt overhead\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of bytes with sharing)\n", literalMgmtBytes, Percent(literalMgmtBytes, currentLiteralBytes)); Tcl_AppendPrintfToObj(objPtr, " table %lu + buckets %lu + entries %lu\n", @@ -9759,7 +9799,8 @@ EvalStatsCmd( Tcl_AppendPrintfToObj(objPtr, "\nLiteral string sizes:\n"); Tcl_AppendPrintfToObj(objPtr, "\t Up to length\t\tPercentage\n"); maxSizeDecade = 0; - for (i = 31; i >= 0; i--) { + i = 32; + while (i-- > 0) { if (statsPtr->literalCount[i] > 0) { maxSizeDecade = i; break; @@ -9857,7 +9898,7 @@ EvalStatsCmd( Tcl_AppendPrintfToObj(objPtr, "\nInstruction counts:\n"); for (i = 0; i <= LAST_INST_OPCODE; i++) { - Tcl_AppendPrintfToObj(objPtr, "%20s %8ld ", + Tcl_AppendPrintfToObj(objPtr, "%20s %8" TCL_Z_MODIFIER "u ", tclInstructionTable[i].name, statsPtr->instructionCount[i]); if (statsPtr->instructionCount[i]) { Tcl_AppendPrintfToObj(objPtr, "%6.1f%%\n", diff --git a/generic/tclFCmd.c b/generic/tclFCmd.c index a4dded2..8ef0456 100644 --- a/generic/tclFCmd.c +++ b/generic/tclFCmd.c @@ -1345,7 +1345,7 @@ TclFileReadLinkCmd( /* *--------------------------------------------------------------------------- * - * TclFileTemporaryCmd + * TclFileTemporaryCmd -- * * This function implements the "tempfile" subcommand of the "file" * command. @@ -1505,6 +1505,151 @@ TclFileTemporaryCmd( } /* + *--------------------------------------------------------------------------- + * + * TclFileTempDirCmd -- + * + * This function implements the "tempdir" subcommand of the "file" + * command. + * + * Results: + * Returns a standard Tcl result. + * + * Side effects: + * Creates a temporary directory. + * + *--------------------------------------------------------------------------- + */ + +int +TclFileTempDirCmd( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + Tcl_Obj *dirNameObj; /* Object that will contain the directory + * name. */ + Tcl_Obj *baseDirObj = NULL, *nameBaseObj = NULL; + /* Pieces of template. Each piece is NULL if + * it is omitted. The platform temporary file + * engine might ignore some pieces. */ + + if (objc < 1 || objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "?template?"); + return TCL_ERROR; + } + + if (objc > 1) { + int length; + Tcl_Obj *templateObj = objv[1]; + const char *string = TclGetStringFromObj(templateObj, &length); + const int onWindows = (tclPlatform == TCL_PLATFORM_WINDOWS); + + /* + * Treat an empty string as if it wasn't there. + */ + + if (length == 0) { + goto makeTemporary; + } + + /* + * The template only gives a directory if there is a directory + * separator in it, and only gives a base name if there's at least one + * character after the last directory separator. + */ + + if (strchr(string, '/') == NULL + && (!onWindows || strchr(string, '\\') == NULL)) { + /* + * No directory separator, so just assume we have a file name. + * This is a bit wrong on Windows where we could have problems + * with disk name prefixes... but those are much less common in + * naked form so we just pass through and let the OS figure it out + * instead. + */ + + nameBaseObj = templateObj; + Tcl_IncrRefCount(nameBaseObj); + } else if (string[length-1] != '/' + && (!onWindows || string[length-1] != '\\')) { + /* + * If the template has a non-terminal directory separator, split + * into dirname and tail. + */ + + baseDirObj = TclPathPart(interp, templateObj, TCL_PATH_DIRNAME); + nameBaseObj = TclPathPart(interp, templateObj, TCL_PATH_TAIL); + } else { + /* + * Otherwise, there must be a terminal directory separator, so + * just the directory is given. + */ + + baseDirObj = templateObj; + Tcl_IncrRefCount(baseDirObj); + } + + /* + * Only allow creation of temporary directories in the native + * filesystem since they are frequently used for integration with + * external tools or system libraries. + */ + + if (baseDirObj != NULL && Tcl_FSGetFileSystemForPath(baseDirObj) + != &tclNativeFilesystem) { + TclDecrRefCount(baseDirObj); + baseDirObj = NULL; + } + } + + /* + * Convert empty parts of the template into unspecified parts. + */ + + if (baseDirObj && !TclGetString(baseDirObj)[0]) { + TclDecrRefCount(baseDirObj); + baseDirObj = NULL; + } + if (nameBaseObj && !TclGetString(nameBaseObj)[0]) { + TclDecrRefCount(nameBaseObj); + nameBaseObj = NULL; + } + + /* + * Create and open the temporary file. + */ + + makeTemporary: + dirNameObj = TclpCreateTemporaryDirectory(baseDirObj, nameBaseObj); + + /* + * If we created pieces of template, get rid of them now. + */ + + if (baseDirObj) { + TclDecrRefCount(baseDirObj); + } + if (nameBaseObj) { + TclDecrRefCount(nameBaseObj); + } + + /* + * Deal with results. + */ + + if (dirNameObj == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't create temporary directory: %s", + Tcl_PosixError(interp))); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, dirNameObj); + return TCL_OK; +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/generic/tclFileName.c b/generic/tclFileName.c index 98ee37c..834eef7 100644 --- a/generic/tclFileName.c +++ b/generic/tclFileName.c @@ -1072,7 +1072,7 @@ Tcl_TranslateFileName( */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { - register char *p; + char *p; for (p = Tcl_DStringValue(bufferPtr); *p != '\0'; p++) { if (*p == '/') { *p = '\\'; @@ -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 @@ -2077,7 +2076,7 @@ SkipToChar( int match) /* Character to find. */ { int quoted, level; - register char *p; + char *p; quoted = 0; level = 0; @@ -2628,7 +2627,7 @@ Tcl_GetBlocksFromStat( #ifdef HAVE_STRUCT_STAT_ST_BLOCKS return (Tcl_WideUInt) statPtr->st_blocks; #else - register unsigned blksize = Tcl_GetBlockSizeFromStat(statPtr); + unsigned blksize = Tcl_GetBlockSizeFromStat(statPtr); return ((Tcl_WideUInt) statPtr->st_size + blksize - 1) / blksize; #endif diff --git a/generic/tclGetDate.y b/generic/tclGetDate.y index 59f85bd..3b6134c 100644 --- a/generic/tclGetDate.y +++ b/generic/tclGetDate.y @@ -46,6 +46,14 @@ #endif /* _MSC_VER */ /* + * Meridian: am, pm, or 24-hour style. + */ + +typedef enum _MERIDIAN { + MERam, MERpm, MER24 +} MERIDIAN; + +/* * yyparse will accept a 'struct DateInfo' as its parameter; that's where the * parsed fields will be returned. */ @@ -63,7 +71,7 @@ typedef struct DateInfo { time_t dateHour; time_t dateMinutes; time_t dateSeconds; - int dateMeridian; + MERIDIAN dateMeridian; int dateHaveTime; time_t dateTimezone; @@ -150,14 +158,6 @@ typedef enum _DSTMODE { DSTon, DSToff, DSTmaybe } DSTMODE; -/* - * Meridian: am, pm, or 24-hour style. - */ - -typedef enum _MERIDIAN { - MERam, MERpm, MER24 -} MERIDIAN; - %} %union { @@ -765,9 +765,9 @@ LookupWord( YYSTYPE* yylvalPtr, char *buff) { - register char *p; - register char *q; - register const TABLE *tp; + char *p; + char *q; + const TABLE *tp; int i, abbrev; /* @@ -890,8 +890,8 @@ TclDatelex( YYLTYPE* location, DateInfo *info) { - register char c; - register char *p; + char c; + char *p; char buff[20]; int Count; diff --git a/generic/tclHash.c b/generic/tclHash.c index f7f9b32..9ea8807 100644 --- a/generic/tclHash.c +++ b/generic/tclHash.c @@ -113,7 +113,7 @@ const Tcl_HashKeyType tclStringHashKeyType = { void Tcl_InitHashTable( - register Tcl_HashTable *tablePtr, + Tcl_HashTable *tablePtr, /* Pointer to table record, which is supplied * by the caller. */ int keyType) /* Type of keys to use in table: @@ -151,7 +151,7 @@ Tcl_InitHashTable( void Tcl_InitCustomHashTable( - register Tcl_HashTable *tablePtr, + Tcl_HashTable *tablePtr, /* Pointer to table record, which is supplied * by the caller. */ int keyType, /* Type of keys to use in table: @@ -271,7 +271,7 @@ CreateHashEntry( int *newPtr) /* Store info here telling whether a new entry * was created. */ { - register Tcl_HashEntry *hPtr; + Tcl_HashEntry *hPtr; const Tcl_HashKeyType *typePtr; unsigned int hash; int index; @@ -311,7 +311,10 @@ CreateHashEntry( if (hash != PTR2UINT(hPtr->hash)) { continue; } - if (((void *) key == hPtr) || compareKeysProc((void *) key, hPtr)) { + /* if keys pointers or values are equal */ + if ((key == hPtr->key.oneWordValue) + || compareKeysProc((void *) key, hPtr) + ) { if (newPtr) { *newPtr = 0; } @@ -389,7 +392,7 @@ void Tcl_DeleteHashEntry( Tcl_HashEntry *entryPtr) { - register Tcl_HashEntry *prevPtr; + Tcl_HashEntry *prevPtr; const Tcl_HashKeyType *typePtr; Tcl_HashTable *tablePtr; Tcl_HashEntry **bucketPtr; @@ -458,9 +461,9 @@ Tcl_DeleteHashEntry( void Tcl_DeleteHashTable( - register Tcl_HashTable *tablePtr) /* Table to delete. */ + Tcl_HashTable *tablePtr) /* Table to delete. */ { - register Tcl_HashEntry *hPtr, *nextPtr; + Tcl_HashEntry *hPtr, *nextPtr; const Tcl_HashKeyType *typePtr; int i; @@ -566,7 +569,7 @@ Tcl_FirstHashEntry( Tcl_HashEntry * Tcl_NextHashEntry( - register Tcl_HashSearch *searchPtr) + Tcl_HashSearch *searchPtr) /* Place to store information about progress * through the table. Must have been * initialized by calling @@ -613,7 +616,7 @@ Tcl_HashStats( #define NUM_COUNTERS 10 int count[NUM_COUNTERS], overflow, i, j; double average, tmp; - register Tcl_HashEntry *hPtr; + Tcl_HashEntry *hPtr; char *result, *p; /* @@ -683,7 +686,7 @@ AllocArrayEntry( void *keyPtr) /* Key to store in the hash table entry. */ { int *array = (int *) keyPtr; - register int *iPtr1, *iPtr2; + int *iPtr1, *iPtr2; Tcl_HashEntry *hPtr; int count; unsigned int size; @@ -727,8 +730,8 @@ CompareArrayKeys( void *keyPtr, /* New key to compare. */ Tcl_HashEntry *hPtr) /* Existing key to compare. */ { - register const int *iPtr1 = (const int *) keyPtr; - register const int *iPtr2 = (const int *) hPtr->key.words; + const int *iPtr1 = (const int *) keyPtr; + const int *iPtr2 = (const int *) hPtr->key.words; Tcl_HashTable *tablePtr = hPtr->tablePtr; int count; @@ -766,8 +769,8 @@ HashArrayKey( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key from which to compute hash value. */ { - register const int *array = (const int *) keyPtr; - register unsigned int result; + const int *array = (const int *) keyPtr; + unsigned int result; int count; for (result = 0, count = tablePtr->keyType; count > 0; @@ -806,7 +809,8 @@ AllocStringEntry( if (size < sizeof(hPtr->key)) { allocsize = sizeof(hPtr->key); } - hPtr = ckalloc(TclOffset(Tcl_HashEntry, key) + allocsize); + hPtr = ckalloc(offsetof(Tcl_HashEntry, key) + allocsize); + memset(hPtr, 0, sizeof(Tcl_HashEntry) + allocsize - sizeof(hPtr->key)); memcpy(hPtr->key.string, string, size); hPtr->clientData = 0; return hPtr; @@ -834,8 +838,8 @@ CompareStringKeys( void *keyPtr, /* New key to compare. */ Tcl_HashEntry *hPtr) /* Existing key to compare. */ { - register const char *p1 = (const char *) keyPtr; - register const char *p2 = (const char *) hPtr->key.string; + const char *p1 = (const char *) keyPtr; + const char *p2 = (const char *) hPtr->key.string; return !strcmp(p1, p2); } @@ -862,9 +866,9 @@ HashStringKey( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key from which to compute hash value. */ { - register const char *string = keyPtr; - register unsigned int result; - register char c; + const char *string = keyPtr; + unsigned int result; + char c; /* * I tried a zillion different hash functions and asked many other people @@ -983,12 +987,12 @@ BogusCreate( static void RebuildTable( - register Tcl_HashTable *tablePtr) /* Table to enlarge. */ + Tcl_HashTable *tablePtr) /* Table to enlarge. */ { int count, index, oldSize = tablePtr->numBuckets; Tcl_HashEntry **oldBuckets = tablePtr->buckets; - register Tcl_HashEntry **oldChainPtr, **newChainPtr; - register Tcl_HashEntry *hPtr; + Tcl_HashEntry **oldChainPtr, **newChainPtr; + Tcl_HashEntry *hPtr; const Tcl_HashKeyType *typePtr; /* Avoid outgrowing capability of the memory allocators */ diff --git a/generic/tclHistory.c b/generic/tclHistory.c index 47806d4..46e6989 100644 --- a/generic/tclHistory.c +++ b/generic/tclHistory.c @@ -61,7 +61,7 @@ Tcl_RecordAndEval( * TCL_EVAL_GLOBAL means use Tcl_GlobalEval * instead of Tcl_Eval. */ { - register Tcl_Obj *cmdPtr; + Tcl_Obj *cmdPtr; int result; if (cmd[0]) { @@ -213,7 +213,7 @@ DeleteHistoryObjs( ClientData clientData, Tcl_Interp *interp) { - register HistoryObjs *histObjsPtr = clientData; + HistoryObjs *histObjsPtr = clientData; TclDecrRefCount(histObjsPtr->historyObj); TclDecrRefCount(histObjsPtr->addObj); diff --git a/generic/tclIO.c b/generic/tclIO.c index 118820a..3ba577d 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -2927,7 +2927,7 @@ FlushChannel( * there is some kind failure in the writable event machinery. * * The tls extension indeed suffers from flaws in its channel - * event mgmt. See http://core.tcl.tk/tcl/info/c31ca233ca. + * event mgmt. See https://core.tcl-lang.org/tcl/info/c31ca233ca. * Until that patch is broadly distributed, disable the * assertion checking here, so that programs using Tcl and * tls can be debugged. @@ -4712,8 +4712,8 @@ Tcl_GetsObj( * Skip the raw bytes that make up the '\n'. */ - char tmp[TCL_UTF_MAX]; int rawRead; + char tmp[TCL_UTF_MAX]; bufPtr = gs.bufPtr; Tcl_ExternalToUtf(NULL, gs.encoding, RemovePoint(bufPtr), @@ -6265,8 +6265,8 @@ ReadChars( */ if (code != TCL_OK) { - char buffer[TCL_UTF_MAX + 1]; int read, decoded, count; + char buffer[TCL_UTF_MAX + 1]; /* * Didn't get everything the buffer could offer @@ -7480,7 +7480,7 @@ Tcl_OutputBuffered( bytesBuffered += BytesLeft(bufPtr); } if (statePtr->curOutPtr != NULL) { - register ChannelBuffer *curOutPtr = statePtr->curOutPtr; + ChannelBuffer *curOutPtr = statePtr->curOutPtr; if (IsBufferReady(curOutPtr)) { bytesBuffered += BytesLeft(curOutPtr); @@ -11235,9 +11235,9 @@ Tcl_ChannelTruncateProc( static void DupChannelIntRep( - register Tcl_Obj *srcPtr, /* Object with internal rep to copy. Must have + Tcl_Obj *srcPtr, /* Object with internal rep to copy. Must have * an internal rep of type "Channel". */ - register Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not + Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not * currently have an internal rep.*/ { ResolvedChanName *resPtr; diff --git a/generic/tclIO.h b/generic/tclIO.h index 15f0f78..d10f268 100644 --- a/generic/tclIO.h +++ b/generic/tclIO.h @@ -50,7 +50,7 @@ typedef struct ChannelBuffer { * structure. */ } ChannelBuffer; -#define CHANNELBUFFER_HEADER_SIZE TclOffset(ChannelBuffer, buf) +#define CHANNELBUFFER_HEADER_SIZE offsetof(ChannelBuffer, buf) /* * How much extra space to allocate in buffer to hold bytes from previous diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 23049fb..1d90def 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -2125,7 +2125,7 @@ static Tcl_Obj * DecodeEventMask( int mask) { - register const char *eventStr; + const char *eventStr; Tcl_Obj *evObj; switch (mask & RANDW) { diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c index 8e24cf7..8385d88 100644 --- a/generic/tclIORTrans.c +++ b/generic/tclIORTrans.c @@ -1706,7 +1706,7 @@ static Tcl_Obj * DecodeEventMask( int mask) { - register const char *eventStr; + const char *eventStr; Tcl_Obj *evObj; switch (mask & RANDW) { diff --git a/generic/tclIOSock.c b/generic/tclIOSock.c index 12e2900..adf729a 100644 --- a/generic/tclIOSock.c +++ b/generic/tclIOSock.c @@ -30,11 +30,12 @@ gai_strerror( ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->initialized) { - Tcl_DStringFree(&tsdPtr->errorMsg); + Tcl_DStringSetLength(&tsdPtr->errorMsg, 0); } else { + Tcl_DStringInit(&tsdPtr->errorMsg); tsdPtr->initialized = 1; } - Tcl_WinTCharToUtf(gai_strerrorW(code), -1, &tsdPtr->errorMsg); + Tcl_WCharToUtfDString(gai_strerrorW(code), -1, &tsdPtr->errorMsg); return Tcl_DStringValue(&tsdPtr->errorMsg); } #endif diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 4b3eaa5..28e1df5 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; @@ -327,9 +309,9 @@ Tcl_Stat( oldStyleBuf->st_uid = buf.st_uid; oldStyleBuf->st_gid = buf.st_gid; oldStyleBuf->st_size = (off_t) buf.st_size; - oldStyleBuf->st_atime = buf.st_atime; - oldStyleBuf->st_mtime = buf.st_mtime; - oldStyleBuf->st_ctime = buf.st_ctime; + oldStyleBuf->st_atime = Tcl_GetAccessTimeFromStat(&buf); + oldStyleBuf->st_mtime = Tcl_GetModificationTimeFromStat(&buf); + oldStyleBuf->st_ctime = Tcl_GetChangeTimeFromStat(&buf); #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE oldStyleBuf->st_blksize = buf.st_blksize; #endif @@ -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,20 +1319,25 @@ 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; int i; int isVfsPath = 0; - char *path; + 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(). - * - * 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). + * Replaces the library version of getcwd(). * - * 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. + * 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). * - * 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. + * 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 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); @@ -4422,8 +4270,8 @@ TclCrossFilesystemCopy( */ if (Tcl_FSLstat(source, &sourceStatBuf) == 0) { - tval.actime = sourceStatBuf.st_atime; - tval.modtime = sourceStatBuf.st_mtime; + tval.actime = Tcl_GetAccessTimeFromStat(&sourceStatBuf); + tval.modtime = Tcl_GetModificationTimeFromStat(&sourceStatBuf); Tcl_FSUtime(target, &tval); } @@ -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/tclIndexObj.c b/generic/tclIndexObj.c index 919db92..e7c3b46 100644 --- a/generic/tclIndexObj.c +++ b/generic/tclIndexObj.c @@ -426,7 +426,7 @@ Tcl_GetIndexFromObjStruct( static int SetIndexFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr) /* The object to convert. */ + Tcl_Obj *objPtr) /* The object to convert. */ { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( @@ -458,7 +458,7 @@ UpdateStringOfIndex( Tcl_Obj *objPtr) { IndexRep *indexRep = TclFetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1; - register const char *indexStr = EXPAND_OF(indexRep); + const char *indexStr = EXPAND_OF(indexRep); Tcl_InitStringRep(objPtr, indexStr, strlen(indexStr)); } @@ -967,7 +967,7 @@ Tcl_WrongNumArgs( const Tcl_ObjIntRep *irPtr; if ((irPtr = TclFetchIntRep(origObjv[i], &indexType))) { - register IndexRep *indexRep = irPtr->twoPtrValue.ptr1; + IndexRep *indexRep = irPtr->twoPtrValue.ptr1; elementStr = EXPAND_OF(indexRep); elemLen = strlen(elementStr); @@ -1016,7 +1016,7 @@ Tcl_WrongNumArgs( const Tcl_ObjIntRep *irPtr; if ((irPtr = TclFetchIntRep(objv[i], &indexType))) { - register IndexRep *indexRep = irPtr->twoPtrValue.ptr1; + IndexRep *indexRep = irPtr->twoPtrValue.ptr1; Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL); } else { @@ -1107,14 +1107,14 @@ Tcl_ParseArgsObjv( * successful exit. Will include the name of * the command. */ int nrem; /* Size of leftovers.*/ - register const Tcl_ArgvInfo *infoPtr; + const Tcl_ArgvInfo *infoPtr; /* Pointer to the current entry in the table * of argument descriptions. */ const Tcl_ArgvInfo *matchPtr; /* Descriptor that matches current argument */ Tcl_Obj *curArg; /* Current argument */ const char *str = NULL; - register char c; /* Second character of current arg (used for + char c; /* Second character of current arg (used for * quick check for matching; use 2nd char. * because first char. will almost always be * '-'). */ @@ -1362,7 +1362,7 @@ PrintUsage( /* Array of command-specific argument * descriptions. */ { - register const Tcl_ArgvInfo *infoPtr; + const Tcl_ArgvInfo *infoPtr; int width, numSpaces; #define NUM_SPACES 20 static const char spaces[] = " "; diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 106b4e9..556da28 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -151,7 +151,7 @@ declare 32 { #declare 33 { # TclCmdProcType TclGetInterpProc(void) #} -declare 34 { +declare 34 {deprecated {Use Tcl_GetIntForIndex}} { int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr) } @@ -1028,6 +1028,12 @@ declare 257 { void TclStaticPackage(Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc) } + +# TIP 431: temporary directory creation function +declare 258 { + Tcl_Obj *TclpCreateTemporaryDirectory(Tcl_Obj *dirObj, + Tcl_Obj *basenameObj) +} ############################################################################## diff --git a/generic/tclInt.h b/generic/tclInt.h index e76b2a8..8b150db 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -78,12 +78,12 @@ #else #include <string.h> #endif -#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \ - || defined(__cplusplus) || defined(_MSC_VER) -#include <stddef.h> -#else +#if !defined(STDC_HEADERS) && !defined(__STDC__) && !defined(__C99__FUNC__) \ + && !defined(__cplusplus) && !defined(_MSC_VER) && !defined(__ICC) typedef int ptrdiff_t; #endif +#include <stddef.h> +#include <locale.h> /* * Ensure WORDS_BIGENDIAN is defined correctly: @@ -569,7 +569,7 @@ typedef struct CommandTrace { struct CommandTrace *nextPtr; /* Next in list of traces associated with a * particular command. */ - size_t refCount; /* Used to ensure this structure is not + unsigned int refCount; /* Used to ensure this structure is not * deleted too early. Keeps track of how many * pieces of code have a pointer to this * structure. */ @@ -1384,7 +1384,7 @@ MODULE_SCOPE void TclThreadDataKeySet(Tcl_ThreadDataKey *keyPtr, */ #define TCL_TSD_INIT(keyPtr) \ - Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) + (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) /* *---------------------------------------------------------------- @@ -1519,11 +1519,11 @@ typedef struct LiteralEntry { * NULL if end of chain. */ Tcl_Obj *objPtr; /* Points to Tcl object that holds the * literal's bytes and length. */ - size_t refCount; /* If in an interpreter's global literal + unsigned int refCount; /* If in an interpreter's global literal * table, the number of ByteCode structures * that share the literal object; the literal * entry can be freed when refCount drops to - * 0. If in a local literal table, (size_t)-1. */ + * 0. If in a local literal table, (unsigned)-1. */ Namespace *nsPtr; /* Namespace in which this literal is used. We * try to avoid sharing literal non-FQ command * names among different namespaces to reduce @@ -1537,11 +1537,11 @@ typedef struct LiteralTable { LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables to avoid * mallocs and frees. */ - int numBuckets; /* Total number of buckets allocated at + unsigned int numBuckets; /* Total number of buckets allocated at * **buckets. */ - int numEntries; /* Total number of entries present in + unsigned int numEntries; /* Total number of entries present in * table. */ - int rebuildSize; /* Enlarge table when numEntries gets to be + unsigned int rebuildSize; /* Enlarge table when numEntries gets to be * this large. */ unsigned int mask; /* Mask value used in hashing function. */ } LiteralTable; @@ -1554,10 +1554,10 @@ typedef struct LiteralTable { #ifdef TCL_COMPILE_STATS typedef struct ByteCodeStats { - long numExecutions; /* Number of ByteCodes executed. */ - long numCompilations; /* Number of ByteCodes created. */ - long numByteCodesFreed; /* Number of ByteCodes destroyed. */ - long instructionCount[256]; /* Number of times each instruction was + size_t numExecutions; /* Number of ByteCodes executed. */ + size_t numCompilations; /* Number of ByteCodes created. */ + size_t numByteCodesFreed; /* Number of ByteCodes destroyed. */ + size_t instructionCount[256]; /* Number of times each instruction was * executed. */ double totalSrcBytes; /* Total source bytes ever compiled. */ @@ -1565,10 +1565,10 @@ typedef struct ByteCodeStats { double currentSrcBytes; /* Src bytes for all current ByteCodes. */ double currentByteCodeBytes;/* Code bytes in all current ByteCodes. */ - long srcCount[32]; /* Source size distribution: # of srcs of + size_t srcCount[32]; /* Source size distribution: # of srcs of * size [2**(n-1)..2**n), n in [0..32). */ - long byteCodeCount[32]; /* ByteCode size distribution. */ - long lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */ + size_t byteCodeCount[32]; /* ByteCode size distribution. */ + size_t lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */ double currentInstBytes; /* Instruction bytes-current ByteCodes. */ double currentLitBytes; /* Current literal bytes. */ @@ -1576,11 +1576,11 @@ typedef struct ByteCodeStats { double currentAuxBytes; /* Current auxiliary information bytes. */ double currentCmdMapBytes; /* Current src<->code map bytes. */ - long numLiteralsCreated; /* Total literal objects ever compiled. */ + size_t numLiteralsCreated; /* Total literal objects ever compiled. */ double totalLitStringBytes; /* Total string bytes in all literals. */ double currentLitStringBytes; /* String bytes in current literals. */ - long literalCount[32]; /* Distribution of literal string sizes. */ + size_t literalCount[32]; /* Distribution of literal string sizes. */ } ByteCodeStats; #endif /* TCL_COMPILE_STATS */ @@ -2259,6 +2259,7 @@ typedef struct Interp { #define TCL_EVAL_FILE 0x02 #define TCL_EVAL_SOURCE_IN_FRAME 0x10 #define TCL_EVAL_NORESOLVE 0x20 +#define TCL_EVAL_DISCARD_RESULT 0x40 /* * Flag bits for Interp structures: @@ -2477,7 +2478,7 @@ typedef struct List { /* * Macros providing a faster path to booleans and integers: * Tcl_GetBooleanFromObj, Tcl_GetLongFromObj, Tcl_GetIntFromObj - * and TclGetIntForIndex. + * and Tcl_GetIntForIndex. * * WARNING: these macros eval their args more than once. */ @@ -2513,8 +2514,8 @@ typedef struct List { (((objPtr)->typePtr == &tclIntType \ && (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(INT_MAX)) \ ? ((*(idxPtr) = ((objPtr)->internalRep.wideValue >= 0) \ - ? (int)(objPtr)->internalRep.wideValue : -1), TCL_OK) \ - : TclGetIntForIndex((interp), (objPtr), (endValue), (idxPtr))) + ? (int)(objPtr)->internalRep.wideValue : TCL_INDEX_NONE), TCL_OK) \ + : Tcl_GetIntForIndex((interp), (objPtr), (endValue), (idxPtr))) /* * Macro used to save a function call for common uses of @@ -2776,10 +2777,10 @@ MODULE_SCOPE const Tcl_HashKeyType tclObjHashKeyType; MODULE_SCOPE Tcl_Obj * tclFreeObjList; #ifdef TCL_COMPILE_STATS -MODULE_SCOPE long tclObjsAlloced; -MODULE_SCOPE long tclObjsFreed; +MODULE_SCOPE size_t tclObjsAlloced; +MODULE_SCOPE size_t tclObjsFreed; #define TCL_MAX_SHARED_OBJ_STATS 5 -MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS]; +MODULE_SCOPE size_t tclObjsShared[TCL_MAX_SHARED_OBJ_STATS]; #endif /* TCL_COMPILE_STATS */ /* @@ -2874,18 +2875,14 @@ struct Tcl_LoadHandle_ { /* Flags for conversion of doubles to digit strings */ -#define TCL_DD_SHORTEST 0x4 - /* Use the shortest possible string */ #define TCL_DD_E_FORMAT 0x2 /* Use a fixed-length string of digits, * suitable for E format*/ #define TCL_DD_F_FORMAT 0x3 /* Use a fixed number of digits after the * decimal point, suitable for F format */ - -#define TCL_DD_SHORTEN_FLAG 0x4 - /* Allow return of a shorter digit string - * if it converts losslessly */ +#define TCL_DD_SHORTEST 0x4 + /* Use the shortest possible string */ #define TCL_DD_NO_QUICK 0x8 /* Debug flag: forbid quick FP conversion */ @@ -2967,6 +2964,7 @@ MODULE_SCOPE Tcl_ObjCmdProc TclFileLinkCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileMakeDirsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileReadLinkCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileRenameCmd; +MODULE_SCOPE Tcl_ObjCmdProc TclFileTempDirCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileTemporaryCmd; MODULE_SCOPE void TclCreateLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); @@ -3072,9 +3070,9 @@ MODULE_SCOPE void TclInitLimitSupport(Tcl_Interp *interp); MODULE_SCOPE void TclInitNamespaceSubsystem(void); MODULE_SCOPE void TclInitNotifier(void); MODULE_SCOPE void TclInitObjSubsystem(void); -MODULE_SCOPE void TclInitSubsystems(void); MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp); MODULE_SCOPE int TclIsSpaceProc(int byte); +MODULE_SCOPE int TclIsDigitProc(int byte); MODULE_SCOPE int TclIsBareword(int byte); MODULE_SCOPE Tcl_Obj * TclJoinPath(int elements, Tcl_Obj * const objv[], int forceRelative); @@ -3241,17 +3239,6 @@ MODULE_SCOPE const char*TclGetCommandTypeName(Tcl_Command command); MODULE_SCOPE void TclRegisterCommandTypeName( Tcl_ObjCmdProc *implementationProc, const char *nameStr); -#if (TCL_UTF_MAX > 4) && (defined(__CYGWIN__) || defined(_WIN32)) -MODULE_SCOPE int TclUtfToWChar(const char *src, WCHAR *chPtr); -MODULE_SCOPE char * TclWCharToUtfDString(const WCHAR *uniStr, - int uniLength, Tcl_DString *dsPtr); -MODULE_SCOPE WCHAR * TclUtfToWCharDString(const char *src, - int length, Tcl_DString *dsPtr); -#else -# define TclUtfToWChar TclUtfToUniChar -# define TclWCharToUtfDString Tcl_UniCharToUtfDString -# define TclUtfToWCharDString Tcl_UtfToUniCharDString -#endif MODULE_SCOPE int TclUtfCmp(const char *cs, const char *ct); MODULE_SCOPE int TclUtfCasecmp(const char *cs, const char *ct); MODULE_SCOPE int TclUtfCount(int ch); @@ -3271,6 +3258,13 @@ MODULE_SCOPE void TclInitThreadStorage(void); MODULE_SCOPE void TclFinalizeThreadDataThread(void); MODULE_SCOPE void TclFinalizeThreadStorage(void); +/* TclWideMUInt -- wide integer used for measurement calculations: */ +#if (!defined(_WIN32) || !defined(_MSC_VER) || (_MSC_VER >= 1400)) +# define TclWideMUInt Tcl_WideUInt +#else +/* older MSVS may not allow conversions between unsigned __int64 and double) */ +# define TclWideMUInt Tcl_WideInt +#endif #ifdef TCL_WIDE_CLICKS MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void); MODULE_SCOPE double TclpWideClicksToNanoseconds(Tcl_WideInt clicks); @@ -4028,42 +4022,36 @@ MODULE_SCOPE int TclDivOpCmd(ClientData clientData, MODULE_SCOPE int TclCompileDivOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); -MODULE_SCOPE int TclLessOpCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileLessOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); -MODULE_SCOPE int TclLeqOpCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileLeqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); -MODULE_SCOPE int TclGreaterOpCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileGreaterOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); -MODULE_SCOPE int TclGeqOpCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileGeqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); -MODULE_SCOPE int TclEqOpCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileEqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); -MODULE_SCOPE int TclStreqOpCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileStreqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); +MODULE_SCOPE int TclCompileStrLtOpCmd(Tcl_Interp *interp, + Tcl_Parse *parsePtr, Command *cmdPtr, + struct CompileEnv *envPtr); +MODULE_SCOPE int TclCompileStrLeOpCmd(Tcl_Interp *interp, + Tcl_Parse *parsePtr, Command *cmdPtr, + struct CompileEnv *envPtr); +MODULE_SCOPE int TclCompileStrGtOpCmd(Tcl_Interp *interp, + Tcl_Parse *parsePtr, Command *cmdPtr, + struct CompileEnv *envPtr); +MODULE_SCOPE int TclCompileStrGeOpCmd(Tcl_Interp *interp, + Tcl_Parse *parsePtr, Command *cmdPtr, + struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, @@ -4142,7 +4130,6 @@ MODULE_SCOPE int TclObjCallVarTraces(Interp *iPtr, Var *arrayPtr, */ MODULE_SCOPE int TclCompareObjKeys(void *keyPtr, Tcl_HashEntry *hPtr); -MODULE_SCOPE void TclFreeObj(Tcl_Obj *objPtr); MODULE_SCOPE void TclFreeObjEntry(Tcl_HashEntry *hPtr); MODULE_SCOPE TCL_HASH_TYPE TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr); @@ -4203,7 +4190,6 @@ MODULE_SCOPE int TclIndexDecode(int encoded, int endValue); /* Constants used in index value encoding routines. */ #define TCL_INDEX_END (-2) -#define TCL_INDEX_NONE (-1) /* Index out of range or END+1 */ #define TCL_INDEX_START (0) /* @@ -4233,7 +4219,6 @@ MODULE_SCOPE int TclIndexDecode(int encoded, int endValue); #ifdef USE_DTRACE #ifndef _TCLDTRACE_H -typedef const char *TclDTraceStr; #include "tclDTrace.h" #endif #define TCL_DTRACE_OBJ_CREATE(objPtr) TCL_OBJ_CREATE(objPtr) @@ -4534,8 +4519,8 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, #define TclUnpackBignum(objPtr, bignum) \ do { \ - register Tcl_Obj *bignumObj = (objPtr); \ - register int bignumPayload = \ + Tcl_Obj *bignumObj = (objPtr); \ + int bignumPayload = \ PTR2INT(bignumObj->internalRep.twoPtrValue.ptr2); \ if (bignumPayload == -1) { \ (bignum) = *((mp_int *) bignumObj->internalRep.twoPtrValue.ptr1); \ @@ -4630,10 +4615,17 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, *---------------------------------------------------------------- */ +#if TCL_UTF_MAX > 4 #define TclUtfToUniChar(str, chPtr) \ ((((unsigned char) *(str)) < 0x80) ? \ ((*(chPtr) = (unsigned char) *(str)), 1) \ : Tcl_UtfToUniChar(str, chPtr)) +#else +#define TclUtfToUniChar(str, chPtr) \ + ((((unsigned char) *(str)) < 0x80) ? \ + ((*(chPtr) = (unsigned char) *(str)), 1) \ + : Tcl_UtfToChar16(str, chPtr)) +#endif /* *---------------------------------------------------------------- @@ -4886,15 +4878,16 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; #endif /* - * ---------------------------------------------------------------------- - * Macro to use to find the offset of a field in a structure. Computes number - * of bytes from beginning of structure to a given field. + * Macro to use to find the offset of a field in astructure. + * Computes number of bytes from beginning of structure to a given field. */ -#ifdef offsetof -#define TclOffset(type, field) ((int) offsetof(type, field)) -#else -#define TclOffset(type, field) ((int) ((char *) &((type *) 0)->field)) +#ifndef TCL_NO_DEPRECATED +# define TclOffset(type, field) ((int) offsetof(type, field)) +#endif +/* Workaround for platforms missing offsetof(), e.g. VC++ 6.0 */ +#ifndef offsetof +# define offsetof(type, field) ((size_t) ((char *) &((type *) 0)->field)) #endif /* @@ -5085,7 +5078,6 @@ typedef struct NRE_callback { #include "tclIntDecls.h" #include "tclIntPlatDecls.h" -#include "tclTomMathDecls.h" #if !defined(USE_TCL_STUBS) && !defined(TCL_MEM_DEBUG) #define Tcl_AttemptAlloc(size) TclpAlloc(size) diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h index eddbcb3..16bcdf8 100644 --- a/generic/tclIntDecls.h +++ b/generic/tclIntDecls.h @@ -28,6 +28,7 @@ #endif #if !defined(TCL_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) +# define tclGetIntForIndex tcl_GetIntForIndex /* Those macro's are especially for Itcl 3.4 compatibility */ # define tclCreateNamespace tcl_CreateNamespace # define tclDeleteNamespace tcl_DeleteNamespace @@ -129,7 +130,8 @@ EXTERN int TclGetFrame(Tcl_Interp *interp, const char *str, CallFrame **framePtrPtr); /* Slot 33 is reserved */ /* 34 */ -EXTERN int TclGetIntForIndex(Tcl_Interp *interp, +TCL_DEPRECATED("Use Tcl_GetIntForIndex") +int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* Slot 35 is reserved */ /* Slot 36 is reserved */ @@ -653,6 +655,9 @@ EXTERN void TclStaticPackage(Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); +/* 258 */ +EXTERN Tcl_Obj * TclpCreateTemporaryDirectory(Tcl_Obj *dirObj, + Tcl_Obj *basenameObj); typedef struct TclIntStubs { int magic; @@ -692,7 +697,7 @@ typedef struct TclIntStubs { const char * (*tclGetExtension) (const char *name); /* 31 */ int (*tclGetFrame) (Tcl_Interp *interp, const char *str, CallFrame **framePtrPtr); /* 32 */ void (*reserved33)(void); - int (*tclGetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* 34 */ + TCL_DEPRECATED_API("Use Tcl_GetIntForIndex") int (*tclGetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* 34 */ void (*reserved35)(void); void (*reserved36)(void); int (*tclGetLoadedPackages) (Tcl_Interp *interp, const char *targetName); /* 37 */ @@ -916,6 +921,7 @@ typedef struct TclIntStubs { int (*tclPtrObjMakeUpvar) (Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 255 */ int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 256 */ void (*tclStaticPackage) (Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 257 */ + Tcl_Obj * (*tclpCreateTemporaryDirectory) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* 258 */ } TclIntStubs; extern const TclIntStubs *tclIntStubsPtr; @@ -1359,6 +1365,8 @@ extern const TclIntStubs *tclIntStubsPtr; (tclIntStubsPtr->tclPtrUnsetVar) /* 256 */ #define TclStaticPackage \ (tclIntStubsPtr->tclStaticPackage) /* 257 */ +#define TclpCreateTemporaryDirectory \ + (tclIntStubsPtr->tclpCreateTemporaryDirectory) /* 258 */ #endif /* defined(USE_TCL_STUBS) */ @@ -1375,6 +1383,7 @@ extern const TclIntStubs *tclIntStubsPtr; # undef TclBackgroundException # undef TclSetStartupScript # undef TclGetStartupScript +# undef TclGetIntForIndex # undef TclCreateNamespace # undef TclDeleteNamespace # undef TclAppendExportList diff --git a/generic/tclInterp.c b/generic/tclInterp.c index 92c6159..bd786f3 100644 --- a/generic/tclInterp.c +++ b/generic/tclInterp.c @@ -3291,7 +3291,7 @@ Tcl_MakeSafe( * No env array in a safe slave. */ - Tcl_UnsetVar(interp, "env", TCL_GLOBAL_ONLY); + Tcl_UnsetVar2(interp, "env", NULL, TCL_GLOBAL_ONLY); /* * Remove unsafe parts of tcl_platform @@ -3307,9 +3307,9 @@ Tcl_MakeSafe( * nameofexecutable]) */ - Tcl_UnsetVar(interp, "tclDefaultLibrary", TCL_GLOBAL_ONLY); - Tcl_UnsetVar(interp, "tcl_library", TCL_GLOBAL_ONLY); - Tcl_UnsetVar(interp, "tcl_pkgPath", TCL_GLOBAL_ONLY); + Tcl_UnsetVar2(interp, "tclDefaultLibrary", NULL, TCL_GLOBAL_ONLY); + Tcl_UnsetVar2(interp, "tcl_library", NULL, TCL_GLOBAL_ONLY); + Tcl_UnsetVar2(interp, "tcl_pkgPath", NULL, TCL_GLOBAL_ONLY); /* * Remove the standard channels from the interpreter; safe interpreters do @@ -3362,7 +3362,7 @@ int Tcl_LimitExceeded( Tcl_Interp *interp) { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; return iPtr->limit.exceeded != 0; } @@ -3393,10 +3393,10 @@ int Tcl_LimitReady( Tcl_Interp *interp) { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; if (iPtr->limit.active != 0) { - register int ticker = ++iPtr->limit.granularityTicker; + int ticker = ++iPtr->limit.granularityTicker; if ((iPtr->limit.active & TCL_LIMIT_COMMANDS) && ((iPtr->limit.cmdGranularity == 1) || @@ -3440,7 +3440,7 @@ Tcl_LimitCheck( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; - register int ticker = iPtr->limit.granularityTicker; + int ticker = iPtr->limit.granularityTicker; if (Tcl_InterpDeleted(interp)) { return TCL_OK; diff --git a/generic/tclLink.c b/generic/tclLink.c index 030e471..8fbe540 100644 --- a/generic/tclLink.c +++ b/generic/tclLink.c @@ -16,7 +16,7 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tclTomMath.h" #include <math.h> /* @@ -533,11 +533,11 @@ GetUWide( Tcl_WideUInt value; unsigned char bytes[sizeof(Tcl_WideUInt)]; } scratch; - unsigned long numBytes = sizeof(Tcl_WideUInt); + size_t numBytes; unsigned char *bytes = scratch.bytes; - if (numPtr->sign || (MP_OKAY != mp_to_unsigned_bin_n(numPtr, - bytes, &numBytes))) { + if (numPtr->sign || (MP_OKAY != mp_to_ubin(numPtr, + bytes, sizeof(Tcl_WideUInt), &numBytes))) { /* * If the sign bit is set (a negative value) or if the value * can't possibly fit in the bits of an unsigned wide, there's diff --git a/generic/tclListObj.c b/generic/tclListObj.c index ad64971..d4dec9b 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -557,14 +557,14 @@ TclListObjRange( int Tcl_ListObjGetElements( Tcl_Interp *interp, /* Used to report errors if not NULL. */ - register Tcl_Obj *listPtr, /* List object for which an element array is + Tcl_Obj *listPtr, /* List object for which an element array is * to be returned. */ int *objcPtr, /* Where to store the count of objects * referenced by objv. */ Tcl_Obj ***objvPtr) /* Where to store the pointer to an array of * pointers to the list's objects. */ { - register List *listRepPtr; + List *listRepPtr; ListGetIntRep(listPtr, listRepPtr); @@ -614,7 +614,7 @@ Tcl_ListObjGetElements( int Tcl_ListObjAppendList( Tcl_Interp *interp, /* Used to report errors if not NULL. */ - register Tcl_Obj *listPtr, /* List object to append elements to. */ + Tcl_Obj *listPtr, /* List object to append elements to. */ Tcl_Obj *elemListPtr) /* List obj with elements to append. */ { int objc; @@ -673,7 +673,7 @@ Tcl_ListObjAppendElement( Tcl_Obj *listPtr, /* List object to append objPtr to. */ Tcl_Obj *objPtr) /* Object to append to listPtr's list. */ { - register List *listRepPtr, *newPtr = NULL; + List *listRepPtr, *newPtr = NULL; int numElems, numRequired, needGrow, isShared, attempt; if (Tcl_IsShared(listPtr)) { @@ -844,11 +844,11 @@ Tcl_ListObjAppendElement( int Tcl_ListObjIndex( Tcl_Interp *interp, /* Used to report errors if not NULL. */ - register Tcl_Obj *listPtr, /* List object to index into. */ - register int index, /* Index of element to return. */ + Tcl_Obj *listPtr, /* List object to index into. */ + int index, /* Index of element to return. */ Tcl_Obj **objPtrPtr) /* The resulting Tcl_Obj* is stored here. */ { - register List *listRepPtr; + List *listRepPtr; ListGetIntRep(listPtr, listRepPtr); if (listRepPtr == NULL) { @@ -900,10 +900,10 @@ Tcl_ListObjIndex( int Tcl_ListObjLength( Tcl_Interp *interp, /* Used to report errors if not NULL. */ - register Tcl_Obj *listPtr, /* List object whose #elements to return. */ - register int *intPtr) /* The resulting int is stored here. */ + Tcl_Obj *listPtr, /* List object whose #elements to return. */ + int *intPtr) /* The resulting int is stored here. */ { - register List *listRepPtr; + List *listRepPtr; ListGetIntRep(listPtr, listRepPtr); if (listRepPtr == NULL) { @@ -974,7 +974,7 @@ Tcl_ListObjReplace( * insert. */ { List *listRepPtr; - register Tcl_Obj **elemPtrs; + Tcl_Obj **elemPtrs; int needGrow, numElems, numRequired, numAfterLast, start, i, j, isShared; if (Tcl_IsShared(listPtr)) { diff --git a/generic/tclLiteral.c b/generic/tclLiteral.c index 464f565..5982cc8 100644 --- a/generic/tclLiteral.c +++ b/generic/tclLiteral.c @@ -58,7 +58,7 @@ static void RebuildLiteralTable(LiteralTable *tablePtr); void TclInitLiteralTable( - register LiteralTable *tablePtr) + LiteralTable *tablePtr) /* Pointer to table structure, which is * supplied by the caller. */ { @@ -104,7 +104,7 @@ TclDeleteLiteralTable( { LiteralEntry *entryPtr, *nextPtr; Tcl_Obj *objPtr; - int i; + size_t i; /* * Release remaining literals in the table. Note that releasing a literal @@ -209,7 +209,7 @@ TclCreateLiteral( */ int objLength; - char *objBytes = TclGetStringFromObj(objPtr, &objLength); + const char *objBytes = TclGetStringFromObj(objPtr, &objLength); if ((objLength == length) && ((length == 0) || ((objBytes[0] == bytes[0]) @@ -227,7 +227,9 @@ TclCreateLiteral( if (flags & LITERAL_ON_HEAP) { ckfree(bytes); } - globalPtr->refCount++; + if (globalPtr->refCount != (unsigned) -1) { + globalPtr->refCount++; + } return objPtr; } } @@ -296,7 +298,8 @@ TclCreateLiteral( TclVerifyGlobalLiteralTable(iPtr); { LiteralEntry *entryPtr; - int found, i; + int found; + size_t i; found = 0; for (i=0 ; i<globalTablePtr->numBuckets ; i++) { @@ -386,7 +389,7 @@ int TclRegisterLiteral( void *ePtr, /* Points to the CompileEnv in whose object * array an object is found or created. */ - register const char *bytes, /* Points to string for which to find or + const char *bytes, /* Points to string for which to find or * create an object in CompileEnv's object * array. */ int length, /* Number of bytes in the string. If < 0, the @@ -405,7 +408,7 @@ TclRegisterLiteral( Tcl_Obj *objPtr; unsigned hash; unsigned int localHash; - int objIndex, new; + int objIndex, isNew; Namespace *nsPtr; if (length < 0) { @@ -459,12 +462,12 @@ TclRegisterLiteral( */ globalPtr = NULL; - objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &new, nsPtr, flags, + objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &isNew, nsPtr, flags, &globalPtr); objIndex = AddLocalLiteralEntry(envPtr, objPtr, localHash); #ifdef TCL_COMPILE_DEBUG - if (globalPtr != NULL && globalPtr->refCount < 1) { + if (globalPtr != NULL && globalPtr->refCount + 1 < 2) { Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d", "TclRegisterLiteral", (length>60? 60 : length), bytes, globalPtr->refCount); @@ -496,13 +499,13 @@ static LiteralEntry * LookupLiteralEntry( Tcl_Interp *interp, /* Interpreter for which objPtr was created to * hold a literal. */ - register Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal + Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal * that was previously created by a call to * TclRegisterLiteral. */ { Interp *iPtr = (Interp *) interp; LiteralTable *globalTablePtr = &iPtr->literalTable; - register LiteralEntry *entryPtr; + LiteralEntry *entryPtr; const char *bytes; int length, globalHash; @@ -542,7 +545,7 @@ void TclHideLiteral( Tcl_Interp *interp, /* Interpreter for which objPtr was created to * hold a literal. */ - register CompileEnv *envPtr,/* Points to CompileEnv whose literal array + CompileEnv *envPtr,/* Points to CompileEnv whose literal array * contains the entry being hidden. */ int index) /* The index of the entry in the literal * array. */ @@ -606,14 +609,14 @@ TclHideLiteral( int TclAddLiteralObj( - register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array + CompileEnv *envPtr,/* Points to CompileEnv in whose literal array * the object is to be inserted. */ Tcl_Obj *objPtr, /* The object to insert into the array. */ LiteralEntry **litPtrPtr) /* The location where the pointer to the new * literal entry should be stored. May be * NULL. */ { - register LiteralEntry *lPtr; + LiteralEntry *lPtr; int objIndex; if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) { @@ -625,7 +628,7 @@ TclAddLiteralObj( lPtr = &envPtr->literalArrayPtr[objIndex]; lPtr->objPtr = objPtr; Tcl_IncrRefCount(objPtr); - lPtr->refCount = (size_t)-1; /* i.e., unused */ + lPtr->refCount = (unsigned) -1; /* i.e., unused */ lPtr->nextPtr = NULL; if (litPtrPtr) { @@ -655,12 +658,12 @@ TclAddLiteralObj( static int AddLocalLiteralEntry( - register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array + CompileEnv *envPtr,/* Points to CompileEnv in whose literal array * the object is to be inserted. */ Tcl_Obj *objPtr, /* The literal to add to the CompileEnv. */ int localHash) /* Hash value for the literal's string. */ { - register LiteralTable *localTablePtr = &envPtr->localLitTable; + LiteralTable *localTablePtr = &envPtr->localLitTable; LiteralEntry *localPtr; int objIndex; @@ -687,7 +690,8 @@ AddLocalLiteralEntry( TclVerifyLocalLiteralTable(envPtr); { char *bytes; - int length, found, i; + int length, found; + size_t i; found = 0; for (i=0 ; i<localTablePtr->numBuckets ; i++) { @@ -732,7 +736,7 @@ AddLocalLiteralEntry( static void ExpandLocalLiteralArray( - register CompileEnv *envPtr)/* Points to the CompileEnv whose object array + CompileEnv *envPtr)/* Points to the CompileEnv whose object array * must be enlarged. */ { /* @@ -741,15 +745,15 @@ ExpandLocalLiteralArray( */ LiteralTable *localTablePtr = &envPtr->localLitTable; - int currElems = envPtr->literalArrayNext; + size_t currElems = envPtr->literalArrayNext; size_t currBytes = (currElems * sizeof(LiteralEntry)); LiteralEntry *currArrayPtr = envPtr->literalArrayPtr; LiteralEntry *newArrayPtr; - int i; - unsigned int newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX; + size_t i; + size_t newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX; if (currBytes == newSize) { - Tcl_Panic("max size of Tcl literal array (%d literals) exceeded", + Tcl_Panic("max size of Tcl literal array (%" TCL_Z_MODIFIER "u literals) exceeded", currElems); } @@ -814,13 +818,13 @@ void TclReleaseLiteral( Tcl_Interp *interp, /* Interpreter for which objPtr was created to * hold a literal. */ - register Tcl_Obj *objPtr) /* Points to a literal object that was + Tcl_Obj *objPtr) /* Points to a literal object that was * previously created by a call to * TclRegisterLiteral. */ { Interp *iPtr = (Interp *) interp; LiteralTable *globalTablePtr; - register LiteralEntry *entryPtr, *prevPtr; + LiteralEntry *entryPtr, *prevPtr; const char *bytes; int length; unsigned int index; @@ -848,7 +852,7 @@ TclReleaseLiteral( * literal table entry (decrement the ref count of the object). */ - if (entryPtr->refCount-- <= 1) { + if ((entryPtr->refCount != (unsigned)-1) && (entryPtr->refCount-- <= 1)) { if (prevPtr == NULL) { globalTablePtr->buckets[index] = entryPtr->nextPtr; } else { @@ -894,10 +898,10 @@ TclReleaseLiteral( static unsigned HashString( - register const char *string, /* String for which to compute hash value. */ + const char *string, /* String for which to compute hash value. */ int length) /* Number of bytes in the string. */ { - register unsigned int result = 0; + unsigned int result = 0; /* * I tried a zillion different hash functions and asked many other people @@ -958,12 +962,12 @@ HashString( static void RebuildLiteralTable( - register LiteralTable *tablePtr) + LiteralTable *tablePtr) /* Local or global table to enlarge. */ { LiteralEntry **oldBuckets; - register LiteralEntry **oldChainPtr, **newChainPtr; - register LiteralEntry *entryPtr; + LiteralEntry **oldChainPtr, **newChainPtr; + LiteralEntry *entryPtr; LiteralEntry **bucketPtr; const char *bytes; unsigned int oldSize, index; @@ -1090,9 +1094,11 @@ TclLiteralStats( LiteralTable *tablePtr) /* Table for which to produce stats. */ { #define NUM_COUNTERS 10 - int count[NUM_COUNTERS], overflow, i, j; + size_t count[NUM_COUNTERS]; + int overflow; + size_t i, j; double average, tmp; - register LiteralEntry *entryPtr; + LiteralEntry *entryPtr; char *result, *p; /* @@ -1129,7 +1135,7 @@ TclLiteralStats( tablePtr->numEntries, tablePtr->numBuckets); p = result + strlen(result); for (i=0 ; i<NUM_COUNTERS ; i++) { - sprintf(p, "number of buckets with %d entries: %d\n", + sprintf(p, "number of buckets with %" TCL_Z_MODIFIER "u entries: %" TCL_Z_MODIFIER "u\n", i, count[i]); p += strlen(p); } @@ -1163,20 +1169,20 @@ TclVerifyLocalLiteralTable( CompileEnv *envPtr) /* Points to CompileEnv whose literal table is * to be validated. */ { - register LiteralTable *localTablePtr = &envPtr->localLitTable; - register LiteralEntry *localPtr; + LiteralTable *localTablePtr = &envPtr->localLitTable; + LiteralEntry *localPtr; char *bytes; - register int i; - int length, count; + size_t i, count; + int length; count = 0; for (i=0 ; i<localTablePtr->numBuckets ; i++) { for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL; localPtr=localPtr->nextPtr) { count++; - if (localPtr->refCount != -1) { + if (localPtr->refCount != (unsigned)-1) { bytes = TclGetStringFromObj(localPtr->objPtr, &length); - Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %d", + Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %u", "TclVerifyLocalLiteralTable", (length>60? 60 : length), bytes, localPtr->refCount); } @@ -1187,7 +1193,7 @@ TclVerifyLocalLiteralTable( } } if (count != localTablePtr->numEntries) { - Tcl_Panic("%s: local literal table had %d entries, should be %d", + Tcl_Panic("%s: local literal table had %" TCL_Z_MODIFIER "u entries, should be %u", "TclVerifyLocalLiteralTable", count, localTablePtr->numEntries); } @@ -1214,18 +1220,18 @@ TclVerifyGlobalLiteralTable( Interp *iPtr) /* Points to interpreter whose global literal * table is to be validated. */ { - register LiteralTable *globalTablePtr = &iPtr->literalTable; - register LiteralEntry *globalPtr; + LiteralTable *globalTablePtr = &iPtr->literalTable; + LiteralEntry *globalPtr; char *bytes; - register int i; - int length, count; + size_t i, count; + int length; count = 0; for (i=0 ; i<globalTablePtr->numBuckets ; i++) { for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL; globalPtr=globalPtr->nextPtr) { count++; - if (globalPtr->refCount < 1) { + if (globalPtr->refCount + 1 < 2) { bytes = TclGetStringFromObj(globalPtr->objPtr, &length); Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d", "TclVerifyGlobalLiteralTable", @@ -1238,7 +1244,7 @@ TclVerifyGlobalLiteralTable( } } if (count != globalTablePtr->numEntries) { - Tcl_Panic("%s: global literal table had %d entries, should be %d", + Tcl_Panic("%s: global literal table had %" TCL_Z_MODIFIER "u entries, should be %u", "TclVerifyGlobalLiteralTable", count, globalTablePtr->numEntries); } diff --git a/generic/tclMain.c b/generic/tclMain.c index 4b8fa8c..05d3787 100644 --- a/generic/tclMain.c +++ b/generic/tclMain.c @@ -17,21 +17,11 @@ */ /* - * On Windows, this file needs to be compiled twice, once with TCL_ASCII_MAIN - * defined. This way both Tcl_Main and Tcl_MainExW can be implemented, sharing - * the same source code. + * On Windows, this file needs to be compiled twice, once with UNICODE and + * _UNICODE defined. This way both Tcl_Main and Tcl_MainExW can be + * implemented, sharing the same source code. */ -#if defined(TCL_ASCII_MAIN) -# ifdef UNICODE -# undef UNICODE -# undef _UNICODE -# else -# define UNICODE -# define _UNICODE -# endif -#endif - #include "tclInt.h" /* @@ -53,33 +43,20 @@ # define _tcscmp strcmp #endif -/* - * Further on, in UNICODE mode we just use Tcl_NewUnicodeObj, otherwise - * NewNativeObj is needed (which provides proper conversion from native - * encoding to UTF-8). - */ - -#if defined(UNICODE) && (TCL_UTF_MAX <= 4) -# define NewNativeObj Tcl_NewUnicodeObj -#else /* !UNICODE || (TCL_UTF_MAX > 4) */ static inline Tcl_Obj * NewNativeObj( - TCHAR *string, - int length) + TCHAR *string) { Tcl_DString ds; #ifdef UNICODE - if (length > 0) { - length *= sizeof(WCHAR); - } - Tcl_WinTCharToUtf(string, length, &ds); + Tcl_DStringInit(&ds); + Tcl_WCharToUtfDString(string, -1, &ds); #else - Tcl_ExternalToUtfDString(NULL, (char *) string, length, &ds); + Tcl_ExternalToUtfDString(NULL, (char *) string, -1, &ds); #endif return TclDStringToObj(&ds); } -#endif /* !UNICODE || (TCL_UTF_MAX > 4) */ /* * Declarations for various library functions and variables (don't want to @@ -141,7 +118,7 @@ static void Prompt(Tcl_Interp *interp, InteractiveState *isPtr); static void StdinProc(ClientData clientData, int mask); static void FreeMainInterp(ClientData clientData); -#ifndef TCL_ASCII_MAIN +#if !defined(_WIN32) || defined(UNICODE) static Tcl_ThreadDataKey dataKey; /* @@ -286,7 +263,7 @@ Tcl_SourceRCFile( Tcl_DStringFree(&temp); } } -#endif /* !TCL_ASCII_MAIN */ +#endif /* !UNICODE */ /*---------------------------------------------------------------------- * @@ -348,14 +325,14 @@ Tcl_MainEx( if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1])) && ('-' != argv[3][0])) { - Tcl_Obj *value = NewNativeObj(argv[2], -1); - Tcl_SetStartupScript(NewNativeObj(argv[3], -1), + Tcl_Obj *value = NewNativeObj(argv[2]); + Tcl_SetStartupScript(NewNativeObj(argv[3]), Tcl_GetString(value)); Tcl_DecrRefCount(value); argc -= 3; argv += 3; } else if ((argc > 1) && ('-' != argv[1][0])) { - Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL); + Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL); argc--; argv++; } @@ -363,7 +340,7 @@ Tcl_MainEx( path = Tcl_GetStartupScript(&encodingName); if (path == NULL) { - appName = NewNativeObj(argv[0], -1); + appName = NewNativeObj(argv[0]); } else { appName = path; } @@ -375,7 +352,7 @@ Tcl_MainEx( argvPtr = Tcl_NewListObj(0, NULL); while (argc--) { - Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++, -1)); + Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++)); } Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY); @@ -642,7 +619,7 @@ Tcl_MainEx( Tcl_Exit(exitCode); } -#ifndef TCL_ASCII_MAIN +#if !defined(_WIN32) || defined(UNICODE) /* *--------------------------------------------------------------- @@ -733,7 +710,7 @@ TclFullFinalizationRequested(void) return finalize; #endif /* PURIFY */ } -#endif /* !TCL_ASCII_MAIN */ +#endif /* UNICODE */ /* *---------------------------------------------------------------------- diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index bbe357d..9f28661 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -240,7 +240,7 @@ TclInitNamespaceSubsystem(void) Tcl_Namespace * Tcl_GetCurrentNamespace( - register Tcl_Interp *interp)/* Interpreter whose current namespace is + Tcl_Interp *interp)/* Interpreter whose current namespace is * being queried. */ { return TclGetCurrentNamespace(interp); @@ -264,7 +264,7 @@ Tcl_GetCurrentNamespace( Tcl_Namespace * Tcl_GetGlobalNamespace( - register Tcl_Interp *interp)/* Interpreter whose global namespace should + Tcl_Interp *interp)/* Interpreter whose global namespace should * be returned. */ { return TclGetGlobalNamespace(interp); @@ -316,8 +316,8 @@ Tcl_PushCallFrame( * variables. */ { Interp *iPtr = (Interp *) interp; - register CallFrame *framePtr = (CallFrame *) callFramePtr; - register Namespace *nsPtr; + CallFrame *framePtr = (CallFrame *) callFramePtr; + Namespace *nsPtr; if (namespacePtr == NULL) { nsPtr = (Namespace *) TclGetCurrentNamespace(interp); @@ -393,8 +393,8 @@ void Tcl_PopCallFrame( Tcl_Interp *interp) /* Interpreter with call frame to pop. */ { - register Interp *iPtr = (Interp *) interp; - register CallFrame *framePtr = iPtr->framePtr; + Interp *iPtr = (Interp *) interp; + CallFrame *framePtr = iPtr->framePtr; Namespace *nsPtr; /* @@ -679,7 +679,7 @@ Tcl_CreateNamespace( * function should be called. */ { Interp *iPtr = (Interp *) interp; - register Namespace *nsPtr, *ancestorPtr; + Namespace *nsPtr, *ancestorPtr; Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr; Namespace *globalNsPtr = iPtr->globalNsPtr; const char *simpleName; @@ -848,7 +848,7 @@ Tcl_CreateNamespace( for (ancestorPtr = nsPtr; ancestorPtr != NULL; ancestorPtr = ancestorPtr->parentPtr) { if (ancestorPtr != globalNsPtr) { - register Tcl_DString *tempPtr = namePtr; + Tcl_DString *tempPtr = namePtr; TclDStringAppendLiteral(buffPtr, "::"); Tcl_DStringAppend(buffPtr, ancestorPtr->name, -1); @@ -922,7 +922,7 @@ void Tcl_DeleteNamespace( Tcl_Namespace *namespacePtr)/* Points to the namespace to delete. */ { - register Namespace *nsPtr = (Namespace *) namespacePtr; + Namespace *nsPtr = (Namespace *) namespacePtr; Interp *iPtr = (Interp *) nsPtr->interp; Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace((Tcl_Interp *) iPtr); @@ -1118,11 +1118,11 @@ TclNamespaceDeleted( void TclTeardownNamespace( - register Namespace *nsPtr) /* Points to the namespace to be dismantled + Namespace *nsPtr) /* Points to the namespace to be dismantled * and unlinked from its parent. */ { Interp *iPtr = (Interp *) nsPtr->interp; - register Tcl_HashEntry *entryPtr; + Tcl_HashEntry *entryPtr; Tcl_HashSearch search; int i; @@ -1311,7 +1311,7 @@ TclTeardownNamespace( static void NamespaceFree( - register Namespace *nsPtr) /* Points to the namespace to free. */ + Namespace *nsPtr) /* Points to the namespace to free. */ { /* * Most of the namespace's contents are freed when the namespace is @@ -1586,7 +1586,7 @@ Tcl_Import( { Namespace *nsPtr, *importNsPtr, *dummyPtr; const char *simplePattern; - register Tcl_HashEntry *hPtr; + Tcl_HashEntry *hPtr; Tcl_HashSearch search; /* @@ -1865,7 +1865,7 @@ Tcl_ForgetImport( Namespace *nsPtr, *sourceNsPtr, *dummyPtr; const char *simplePattern; char *cmdName; - register Tcl_HashEntry *hPtr; + Tcl_HashEntry *hPtr; Tcl_HashSearch search; /* @@ -1992,7 +1992,7 @@ TclGetOriginalCommand( Tcl_Command command) /* The imported command for which the original * command should be returned. */ { - register Command *cmdPtr = (Command *) command; + Command *cmdPtr = (Command *) command; ImportedCmdData *dataPtr; if (cmdPtr->deleteProc != DeleteImportedCmd) { @@ -2081,7 +2081,7 @@ DeleteImportedCmd( ImportedCmdData *dataPtr = clientData; Command *realCmdPtr = dataPtr->realCmdPtr; Command *selfPtr = dataPtr->selfPtr; - register ImportRef *refPtr, *prevPtr; + ImportRef *refPtr, *prevPtr; prevPtr = NULL; for (refPtr = realCmdPtr->importRefPtr; refPtr != NULL; @@ -2501,7 +2501,7 @@ Tcl_FindNamespace( * points to namespace in which to resolve * name; if NULL, look up name in the current * namespace. */ - register int flags) /* Flags controlling namespace lookup: an OR'd + int flags) /* Flags controlling namespace lookup: an OR'd * combination of TCL_GLOBAL_ONLY and * TCL_LEAVE_ERR_MSG flags. */ { @@ -2572,8 +2572,8 @@ Tcl_FindCommand( { Interp *iPtr = (Interp *) interp; Namespace *cxtNsPtr; - register Tcl_HashEntry *entryPtr; - register Command *cmdPtr; + Tcl_HashEntry *entryPtr; + Command *cmdPtr; const char *simpleName; int result; @@ -2684,7 +2684,7 @@ Tcl_FindCommand( } } else { Namespace *nsPtr[2]; - register int search; + int search; TclGetNamespaceForQualName(interp, name, cxtNsPtr, flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName); @@ -2758,7 +2758,7 @@ TclResetShadowedCmdRefs( { char *cmdName; Tcl_HashEntry *hPtr; - register Namespace *nsPtr; + Namespace *nsPtr; Namespace *trailNsPtr, *shadowNsPtr; Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp); int found, i; @@ -3008,7 +3008,7 @@ NamespaceChildrenCmd( Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp); const char *pattern = NULL; Tcl_DString buffer; - register Tcl_HashEntry *entryPtr; + Tcl_HashEntry *entryPtr; Tcl_HashSearch search; Tcl_Obj *listPtr, *elemPtr; @@ -3134,7 +3134,7 @@ NamespaceCodeCmd( { Namespace *currNsPtr; Tcl_Obj *listPtr, *objPtr; - register const char *arg; + const char *arg; int length; if (objc != 2) { @@ -3213,7 +3213,7 @@ NamespaceCurrentCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register Namespace *currNsPtr; + Namespace *currNsPtr; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -3278,7 +3278,7 @@ NamespaceDeleteCmd( { Tcl_Namespace *namespacePtr; const char *name; - register int i; + int i; if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?name name...?"); @@ -3633,7 +3633,7 @@ NamespaceForgetCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { const char *pattern; - register int i, result; + int i, result; if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?pattern pattern...?"); @@ -3699,7 +3699,7 @@ NamespaceImportCmd( { int allowOverwrite = 0; const char *string, *pattern; - register int i, result; + int i, result; int firstArg; if (objc < 1) { @@ -3852,7 +3852,7 @@ NRNamespaceInscopeCmd( cmdObjPtr = objv[2]; } else { Tcl_Obj *concatObjv[2]; - register Tcl_Obj *listPtr; + Tcl_Obj *listPtr; listPtr = Tcl_NewListObj(0, NULL); for (i = 3; i < objc; i++) { @@ -4253,7 +4253,7 @@ NamespaceQualifiersCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register const char *name, *p; + const char *name, *p; int length; if (objc != 2) { @@ -4508,7 +4508,7 @@ NamespaceTailCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register const char *name, *p; + const char *name, *p; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "string"); @@ -4711,7 +4711,7 @@ NamespaceWhichCmd( static void FreeNsNameInternalRep( - register Tcl_Obj *objPtr) /* nsName object with internal representation + Tcl_Obj *objPtr) /* nsName object with internal representation * to free. */ { ResolvedNsName *resNamePtr; @@ -4758,7 +4758,7 @@ FreeNsNameInternalRep( static void DupNsNameInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ + Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { ResolvedNsName *resNamePtr; @@ -4794,11 +4794,11 @@ SetNsNameFromAny( Tcl_Interp *interp, /* Points to the namespace in which to resolve * name. Also used for error reporting if not * NULL. */ - register Tcl_Obj *objPtr) /* The object to convert. */ + Tcl_Obj *objPtr) /* The object to convert. */ { const char *dummy; Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr; - register ResolvedNsName *resNamePtr; + ResolvedNsName *resNamePtr; const char *name; if (interp == NULL) { @@ -4921,7 +4921,7 @@ TclLogCommandInfo( Tcl_Obj **tosPtr) /* Current stack of bytecode execution * context */ { - register const char *p; + const char *p; Interp *iPtr = (Interp *) interp; int overflow, limit = 150; Var *varPtr, *arrayPtr; diff --git a/generic/tclOO.c b/generic/tclOO.c index e9cc0f0..af5ea50 100644 --- a/generic/tclOO.c +++ b/generic/tclOO.c @@ -175,7 +175,7 @@ MODULE_SCOPE const TclOOStubs tclOOStubs; * ROOT_CLASS respectively. */ -#define Deleted(oPtr) ((oPtr)->flags & OBJECT_DELETED) +#define Destructing(oPtr) ((oPtr)->flags & OBJECT_DESTRUCTING) #define IsRootObject(ocPtr) ((ocPtr)->flags & ROOT_OBJECT) #define IsRootClass(ocPtr) ((ocPtr)->flags & ROOT_CLASS) #define IsRoot(ocPtr) ((ocPtr)->flags & (ROOT_OBJECT|ROOT_CLASS)) @@ -789,7 +789,7 @@ MyDeleted( ClientData clientData) /* Reference to the object whose [my] has been * squelched. */ { - register Object *oPtr = clientData; + Object *oPtr = clientData; oPtr->myCommand = NULL; } @@ -840,7 +840,7 @@ ObjectRenamedTrace( * 2950259]. */ - if (!Deleted(oPtr)) { + if (!Destructing(oPtr)) { Tcl_DeleteNamespace(oPtr->namespacePtr); } oPtr->command = NULL; @@ -880,7 +880,7 @@ TclOODeleteDescendants( * clsPtr */ - if (!Deleted(mixinSubclassPtr->thisPtr) + if (!Destructing(mixinSubclassPtr->thisPtr) && !(mixinSubclassPtr->thisPtr->flags & DONT_DELETE)) { Tcl_DeleteCommandFromToken(interp, mixinSubclassPtr->thisPtr->command); @@ -900,7 +900,7 @@ TclOODeleteDescendants( if (clsPtr->subclasses.num > 0) { while (clsPtr->subclasses.num > 0) { subclassPtr = clsPtr->subclasses.list[clsPtr->subclasses.num - 1]; - if (!Deleted(subclassPtr->thisPtr) && !IsRoot(subclassPtr) + if (!Destructing(subclassPtr->thisPtr) && !IsRoot(subclassPtr) && !(subclassPtr->thisPtr->flags & DONT_DELETE)) { Tcl_DeleteCommandFromToken(interp, subclassPtr->thisPtr->command); @@ -926,7 +926,7 @@ TclOODeleteDescendants( * This condition also covers the case where instancePtr == oPtr */ - if (!Deleted(instancePtr) && !IsRoot(instancePtr) && + if (!Destructing(instancePtr) && !IsRoot(instancePtr) && !(instancePtr->flags & DONT_DELETE)) { Tcl_DeleteCommandFromToken(interp, instancePtr->command); } @@ -968,7 +968,7 @@ TclOOReleaseClassContents( * Sanity check! */ - if (!Deleted(oPtr)) { + if (!Destructing(oPtr)) { if (IsRootClass(oPtr)) { Tcl_Panic("deleting class structure for non-deleted %s", "::oo::class"); @@ -1087,7 +1087,7 @@ TclOOReleaseClassContents( ckfree(clsPtr->privateVariables.list); } - if (IsRootClass(oPtr) && !Deleted(fPtr->objectCls->thisPtr)) { + if (IsRootClass(oPtr) && !Destructing(fPtr->objectCls->thisPtr)) { Tcl_DeleteCommandFromToken(interp, fPtr->objectCls->thisPtr->command); } } @@ -1120,7 +1120,7 @@ ObjectNamespaceDeleted( Tcl_Interp *interp = oPtr->fPtr->interp; int i; - if (Deleted(oPtr)) { + if (Destructing(oPtr)) { /* * TODO: Can ObjectNamespaceDeleted ever be called twice? If not, * this guard could be removed. @@ -1135,7 +1135,7 @@ ObjectNamespaceDeleted( * records. This is the flag that */ - oPtr->flags |= OBJECT_DELETED; + oPtr->flags |= OBJECT_DESTRUCTING; /* * Let the dominoes fall! @@ -1280,7 +1280,7 @@ ObjectNamespaceDeleted( * sometimes not go away automatically; we force it here. [Bug 2962664] */ - if (IsRootObject(oPtr) && !Deleted(fPtr->classCls->thisPtr) + if (IsRootObject(oPtr) && !Destructing(fPtr->classCls->thisPtr) && !Tcl_InterpDeleted(interp)) { Tcl_DeleteCommandFromToken(interp, fPtr->classCls->thisPtr->command); } @@ -1331,6 +1331,20 @@ TclOODecrRefCount( /* * ---------------------------------------------------------------------- * + * TclOOObjectDestroyed -- + * + * Returns TCL_OK if an object is entirely deleted, i.e. the destruction + * sequence has completed. + * + * ---------------------------------------------------------------------- + */ +int TclOOObjectDestroyed(Object *oPtr) { + return (oPtr->namespacePtr == NULL); +} + +/* + * ---------------------------------------------------------------------- + * * TclOORemoveFromInstances -- * * Utility function to remove an object from the list of instances within @@ -1473,7 +1487,7 @@ TclOOAddToSubclasses( * is assumed that the class is not already * present as a subclass in the superclass. */ { - if (Deleted(superPtr->thisPtr)) { + if (Destructing(superPtr->thisPtr)) { return; } if (superPtr->subclasses.num >= superPtr->subclasses.size) { @@ -1538,7 +1552,7 @@ TclOOAddToMixinSubs( * is assumed that the class is not already * present as a subclass in the superclass. */ { - if (Deleted(superPtr->thisPtr)) { + if (Destructing(superPtr->thisPtr)) { return; } if (superPtr->mixinSubs.num >= superPtr->mixinSubs.size) { @@ -1652,7 +1666,7 @@ Tcl_NewObjectInstance( int skip) /* Number of arguments to _not_ pass to the * constructor. */ { - register Class *classPtr = (Class *) cls; + Class *classPtr = (Class *) cls; Object *oPtr; ClientData clientData[4]; @@ -1722,7 +1736,7 @@ TclNRNewObjectInstance( Tcl_Object *objectPtr) /* Place to write the object reference upon * successful allocation. */ { - register Class *classPtr = (Class *) cls; + Class *classPtr = (Class *) cls; CallContext *contextPtr; Tcl_InterpState state; Object *oPtr; @@ -1847,7 +1861,7 @@ FinalizeAlloc( * want to lose errors by accident. [Bug 2903011] */ - if (result != TCL_ERROR && Deleted(oPtr)) { + if (result != TCL_ERROR && Destructing(oPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "object deleted in constructor", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "STILLBORN", NULL); @@ -1862,7 +1876,7 @@ FinalizeAlloc( * command before we delete it. [Bug 9dd1bd7a74] */ - if (!Deleted(oPtr)) { + if (!Destructing(oPtr)) { (void) TclOOObjectName(interp, oPtr); Tcl_DeleteCommandFromToken(interp, oPtr->command); } @@ -2007,7 +2021,7 @@ Tcl_CopyObjectInstance( */ o2Ptr->flags = oPtr->flags & ~( - OBJECT_DELETED | ROOT_OBJECT | ROOT_CLASS | FILTER_HANDLING); + OBJECT_DESTRUCTING | ROOT_OBJECT | ROOT_CLASS | FILTER_HANDLING); /* * Copy the object's metadata. @@ -2656,7 +2670,7 @@ TclOOObjectCmdCore( methodNamePtr = objv[1]; if (oPtr->mapMethodNameProc != NULL) { - register Class **startClsPtr = &startCls; + Class **startClsPtr = &startCls; Tcl_Obj *mappedMethodName = Tcl_DuplicateObj(methodNamePtr); result = oPtr->mapMethodNameProc(interp, (Tcl_Object) oPtr, @@ -2715,7 +2729,7 @@ TclOOObjectCmdCore( if (startCls != NULL) { for (; contextPtr->index < contextPtr->callPtr->numChain; contextPtr->index++) { - register struct MInvoke *miPtr = + struct MInvoke *miPtr = &contextPtr->callPtr->chain[contextPtr->index]; if (miPtr->isFilter) { @@ -2853,7 +2867,7 @@ TclNRObjectContextInvokeNext( Tcl_Obj *const *objv, int skip) { - register CallContext *contextPtr = (CallContext *) context; + CallContext *contextPtr = (CallContext *) context; if (contextPtr->index + 1 >= contextPtr->callPtr->numChain) { /* diff --git a/generic/tclOOBasic.c b/generic/tclOOBasic.c index 13c98f4..6de7513 100644 --- a/generic/tclOOBasic.c +++ b/generic/tclOOBasic.c @@ -426,7 +426,7 @@ TclOO_Object_Eval( { CallContext *contextPtr = (CallContext *) context; Tcl_Object object = Tcl_ObjectContextObject(context); - register const int skip = Tcl_ObjectContextSkippedArgs(context); + const int skip = Tcl_ObjectContextSkippedArgs(context); CallFrame *framePtr, **framePtrPtr = &framePtr; Tcl_Obj *scriptPtr; CmdFrame *invoker; @@ -1122,7 +1122,7 @@ TclOOSelfObjCmd( Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", NULL); return TCL_ERROR; } else { - register struct MInvoke *miPtr = &CurrentlyInvoked(contextPtr); + struct MInvoke *miPtr = &CurrentlyInvoked(contextPtr); Object *oPtr; const char *type; diff --git a/generic/tclOOCall.c b/generic/tclOOCall.c index c0d2e64..423a41e 100644 --- a/generic/tclOOCall.c +++ b/generic/tclOOCall.c @@ -168,7 +168,7 @@ void TclOODeleteContext( CallContext *contextPtr) { - register Object *oPtr = contextPtr->oPtr; + Object *oPtr = contextPtr->oPtr; TclOODeleteChain(contextPtr->callPtr); if (oPtr != NULL) { @@ -314,7 +314,7 @@ TclOOInvokeContext( int objc, /* The number of arguments. */ Tcl_Obj *const objv[]) /* The arguments as actually seen. */ { - register CallContext *const contextPtr = clientData; + CallContext *const contextPtr = clientData; Method *const mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; const int isFilter = contextPtr->callPtr->chain[contextPtr->index].isFilter; @@ -968,7 +968,7 @@ AddMethodToCallChain( * looking to add things from a mixin and have * not passed a mixin. */ { - register CallChain *callPtr = cbPtr->callChainPtr; + CallChain *callPtr = cbPtr->callChainPtr; int i; /* @@ -1656,7 +1656,7 @@ AddPrivatesFromClassChainToCallContext( (char *) methodName); if (hPtr != NULL) { - register Method *mPtr = Tcl_GetHashValue(hPtr); + Method *mPtr = Tcl_GetHashValue(hPtr); if (IS_PRIVATE(mPtr)) { AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl, @@ -1677,6 +1677,7 @@ AddPrivatesFromClassChainToCallContext( return 1; } } + /* FALLTHRU */ case 0: return 0; } @@ -1740,7 +1741,7 @@ AddSimpleClassChainToCallContext( privateDanger |= 1; } if (hPtr != NULL) { - register Method *mPtr = Tcl_GetHashValue(hPtr); + Method *mPtr = Tcl_GetHashValue(hPtr); if (!IS_PRIVATE(mPtr)) { if (!(flags & KNOWN_STATE)) { @@ -1768,6 +1769,7 @@ AddSimpleClassChainToCallContext( privateDanger |= AddSimpleClassChainToCallContext(superPtr, methodNameObj, cbPtr, doneFilters, flags, filterDecl); } + /* FALLTHRU */ case 0: return privateDanger; } diff --git a/generic/tclOODefineCmds.c b/generic/tclOODefineCmds.c index 6a00018..f259954 100644 --- a/generic/tclOODefineCmds.c +++ b/generic/tclOODefineCmds.c @@ -779,7 +779,7 @@ FindCommand( { int length; const char *nameStr, *string = TclGetStringFromObj(stringObj, &length); - register Namespace *const nsPtr = (Namespace *) namespacePtr; + Namespace *const nsPtr = (Namespace *) namespacePtr; FOREACH_HASH_DECLS; Tcl_Command cmd, cmd2; @@ -1244,7 +1244,7 @@ TclOODefineSelfObjCmd( { Tcl_Namespace *nsPtr; Object *oPtr; - int result, private; + int result, isPrivate; oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { @@ -1256,7 +1256,7 @@ TclOODefineSelfObjCmd( return TCL_OK; } - private = IsPrivateDefine(interp); + isPrivate = IsPrivateDefine(interp); /* * Make the oo::objdefine namespace the current namespace and evaluate the @@ -1267,7 +1267,7 @@ TclOODefineSelfObjCmd( if (InitDefineContext(interp, nsPtr, oPtr, objc, objv) != TCL_OK) { return TCL_ERROR; } - if (private) { + if (isPrivate) { ((Interp *) interp)->varFramePtr->isProcCallFrame = PRIVATE_FRAME; } diff --git a/generic/tclOOInfo.c b/generic/tclOOInfo.c index fefeb0f..99918ae 100644 --- a/generic/tclOOInfo.c +++ b/generic/tclOOInfo.c @@ -809,7 +809,7 @@ InfoObjectVariablesCmd( { Object *oPtr; Tcl_Obj *resultObj; - int i, private = 0; + int i, isPrivate = 0; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "objName ?-private?"); @@ -819,7 +819,7 @@ InfoObjectVariablesCmd( if (strcmp("-private", Tcl_GetString(objv[2])) != 0) { return TCL_ERROR; } - private = 1; + isPrivate = 1; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { @@ -827,7 +827,7 @@ InfoObjectVariablesCmd( } resultObj = Tcl_NewObj(); - if (private) { + if (isPrivate) { PrivateVariableMapping *privatePtr; FOREACH_STRUCT(privatePtr, oPtr->privateVariables) { @@ -1588,7 +1588,7 @@ InfoClassVariablesCmd( { Class *clsPtr; Tcl_Obj *resultObj; - int i, private = 0; + int i, isPrivate = 0; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className ?-private?"); @@ -1598,7 +1598,7 @@ InfoClassVariablesCmd( if (strcmp("-private", Tcl_GetString(objv[2])) != 0) { return TCL_ERROR; } - private = 1; + isPrivate = 1; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { @@ -1606,7 +1606,7 @@ InfoClassVariablesCmd( } resultObj = Tcl_NewObj(); - if (private) { + if (isPrivate) { PrivateVariableMapping *privatePtr; FOREACH_STRUCT(privatePtr, clsPtr->privateVariables) { diff --git a/generic/tclOOInt.h b/generic/tclOOInt.h index c1a9010..ca984d0 100644 --- a/generic/tclOOInt.h +++ b/generic/tclOOInt.h @@ -213,14 +213,11 @@ typedef struct Object { * command. */ } Object; -#define OBJECT_DELETED 1 /* Flag to say that an object has been - * destroyed. */ -#define DESTRUCTOR_CALLED 2 /* Flag to say that the destructor has been - * called. */ -#define CLASS_GONE 4 /* Obsolete. Indicates that the class of this - * object has been deleted, and so the object - * should not attempt to remove itself from its - * class. */ +#define OBJECT_DESTRUCTING 1 /* Indicates that an object is being or has + * been destroyed */ +#define DESTRUCTOR_CALLED 2 /* Indicates that evaluation of destructor script for the + object has began */ +#define OO_UNUSED_4 4 /* No longer used. */ #define ROOT_OBJECT 0x1000 /* Flag to say that this object is the root of * the class hierarchy and should be treated * specially during teardown. */ @@ -563,6 +560,7 @@ MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp, const char *nameStr, const char *nsNameStr); MODULE_SCOPE int TclOODecrRefCount(Object *oPtr); +MODULE_SCOPE int TclOOObjectDestroyed(Object *oPtr); MODULE_SCOPE int TclOODefineSlots(Foundation *fPtr); MODULE_SCOPE void TclOODeleteChain(CallChain *callPtr); MODULE_SCOPE void TclOODeleteChainCache(Tcl_HashTable *tablePtr); @@ -671,7 +669,7 @@ MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr); #undef DUPLICATE /* prevent possible conflict with definition in WINAPI nb30.h */ #define DUPLICATE(target,source,type) \ do { \ - register unsigned len = sizeof(type) * ((target).num=(source).num);\ + size_t len = sizeof(type) * ((target).num=(source).num);\ if (len != 0) { \ memcpy(((target).list=(type*)ckalloc(len)), (source).list, len); \ } else { \ diff --git a/generic/tclOOMethod.c b/generic/tclOOMethod.c index db31795..01b47ff 100644 --- a/generic/tclOOMethod.c +++ b/generic/tclOOMethod.c @@ -121,7 +121,7 @@ static const Tcl_MethodType fwdMethodType = { #define TclVarTable(contextNs) \ ((Tcl_HashTable *) (&((Namespace *) (contextNs))->varTable)) #define TclVarHashGetValue(hPtr) \ - ((Tcl_Var) ((char *)hPtr - TclOffset(VarInHash, entry))) + ((Tcl_Var) ((char *)hPtr - offsetof(VarInHash, entry))) /* * ---------------------------------------------------------------------- @@ -149,8 +149,8 @@ Tcl_NewInstanceMethod( void *clientData) /* Some data associated with the particular * method to be created. */ { - register Object *oPtr = (Object *) object; - register Method *mPtr; + Object *oPtr = (Object *) object; + Method *mPtr; Tcl_HashEntry *hPtr; int isNew; @@ -221,8 +221,8 @@ Tcl_NewMethod( void *clientData) /* Some data associated with the particular * method to be created. */ { - register Class *clsPtr = (Class *) cls; - register Method *mPtr; + Class *clsPtr = (Class *) cls; + Method *mPtr; Tcl_HashEntry *hPtr; int isNew; @@ -344,7 +344,7 @@ TclOONewProcInstanceMethod( * interested. */ { int argsLen; - register ProcedureMethod *pmPtr; + ProcedureMethod *pmPtr; Tcl_Method method; if (Tcl_ListObjLength(interp, argsObj, &argsLen) != TCL_OK) { @@ -396,7 +396,7 @@ TclOONewProcMethod( * interested. */ { int argsLen; /* -1 => delete argsObj before exit */ - register ProcedureMethod *pmPtr; + ProcedureMethod *pmPtr; const char *procName; Tcl_Method method; @@ -679,11 +679,13 @@ InvokeProcedureMethod( * call frame's lifetime). */ /* - * If the interpreter was deleted, we just skip to the next thing in the - * chain. + * If the object namespace (or interpreter) were deleted, we just skip to + * the next thing in the chain. */ - if (Tcl_InterpDeleted(interp)) { + if (TclOOObjectDestroyed(((CallContext *)context)->oPtr) || + Tcl_InterpDeleted(interp) + ) { return TclNRObjectContextInvokeNext(interp, context, objc, objv, Tcl_ObjectContextSkippedArgs(context)); } @@ -796,7 +798,7 @@ PushMethodCallFrame( * frame. */ { Namespace *nsPtr = (Namespace *) contextPtr->oPtr->namespacePtr; - register int result; + int result; const char *namePtr; CallFrame **framePtrPtr = &fdPtr->framePtr; ByteCode *codePtr; @@ -829,7 +831,7 @@ PushMethodCallFrame( */ if (pmPtr->flags & USE_DECLARER_NS) { - register Method *mPtr = + Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; if (mPtr->declaringClassPtr != NULL) { @@ -900,7 +902,7 @@ PushMethodCallFrame( fdPtr->efi.fields[1].proc = pmPtr->gfivProc; fdPtr->efi.fields[1].clientData = pmPtr; } else { - register Tcl_Method method = + Tcl_Method method = Tcl_ObjectContextMethod((Tcl_ObjectContext) contextPtr); if (Tcl_MethodDeclarerObject(method) != NULL) { @@ -1294,7 +1296,7 @@ static void DeleteProcedureMethod( void *clientData) { - register ProcedureMethod *pmPtr = clientData; + ProcedureMethod *pmPtr = clientData; if (pmPtr->refCount-- <= 1) { DeleteProcedureMethodRecord(pmPtr); @@ -1387,7 +1389,7 @@ TclOONewForwardInstanceMethod( * prefix to forward to. */ { int prefixLen; - register ForwardMethod *fmPtr; + ForwardMethod *fmPtr; if (Tcl_ListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) { return NULL; @@ -1426,7 +1428,7 @@ TclOONewForwardMethod( * prefix to forward to. */ { int prefixLen; - register ForwardMethod *fmPtr; + ForwardMethod *fmPtr; if (Tcl_ListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) { return NULL; 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 d329aba..eb9334e 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -15,7 +15,7 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tclTomMath.h" #include <math.h> #include <assert.h> @@ -811,7 +811,7 @@ TclThreadFinalizeContLines( * * Tcl_RegisterObjType -- * - * This function is called to register a new Tcl object type in the table + * This function is called to a new Tcl object type in the table * of all object types supported by Tcl. * * Results: @@ -870,7 +870,7 @@ Tcl_AppendAllObjTypes( * name of each registered type is appended as * a list element. */ { - register Tcl_HashEntry *hPtr; + Tcl_HashEntry *hPtr; Tcl_HashSearch search; int numElems; @@ -918,7 +918,7 @@ const Tcl_ObjType * Tcl_GetObjType( const char *typeName) /* Name of Tcl object type to look up. */ { - register Tcl_HashEntry *hPtr; + Tcl_HashEntry *hPtr; const Tcl_ObjType *typePtr = NULL; Tcl_MutexLock(&tableMutex); @@ -1048,10 +1048,10 @@ TclDbDumpActiveObjects( #ifdef TCL_MEM_DEBUG void TclDbInitNewObj( - register Tcl_Obj *objPtr, - register const char *file, /* The name of the source file calling this + Tcl_Obj *objPtr, + const char *file, /* The name of the source file calling this * function; used for debugging. */ - register int line) /* Line number in the source file; used for + int line) /* Line number in the source file; used for * debugging. */ { objPtr->refCount = 0; @@ -1135,7 +1135,7 @@ Tcl_NewObj(void) Tcl_Obj * Tcl_NewObj(void) { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; /* * Use the macro defined in tclInt.h - it will use the correct allocator. @@ -1177,12 +1177,12 @@ Tcl_NewObj(void) Tcl_Obj * Tcl_DbNewObj( - register const char *file, /* The name of the source file calling this + const char *file, /* The name of the source file calling this * function; used for debugging. */ - register int line) /* Line number in the source file; used for + int line) /* Line number in the source file; used for * debugging. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; /* * Use the macro defined in tclInt.h - it will use the correct allocator. @@ -1232,8 +1232,8 @@ TclAllocateFreeObjects(void) { size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * sizeof(Tcl_Obj)); char *basePtr; - register Tcl_Obj *prevPtr, *objPtr; - register int i; + Tcl_Obj *prevPtr, *objPtr; + int i; /* * This has been noted by Purify to be a potential leak. The problem is @@ -1284,9 +1284,9 @@ TclAllocateFreeObjects(void) #ifdef TCL_MEM_DEBUG void TclFreeObj( - register Tcl_Obj *objPtr) /* The object to be freed. */ + Tcl_Obj *objPtr) /* The object to be freed. */ { - register const Tcl_ObjType *typePtr = objPtr->typePtr; + const Tcl_ObjType *typePtr = objPtr->typePtr; /* * This macro declares a variable, so must come here... @@ -1409,7 +1409,7 @@ TclFreeObj( void TclFreeObj( - register Tcl_Obj *objPtr) /* The object to be freed. */ + Tcl_Obj *objPtr) /* The object to be freed. */ { /* * Invalidate the string rep first so we can use the bytes value for our @@ -1618,7 +1618,7 @@ TclSetDuplicateObj( char * Tcl_GetString( - register Tcl_Obj *objPtr) /* Object whose string rep byte pointer should + Tcl_Obj *objPtr) /* Object whose string rep byte pointer should * be returned. */ { if (objPtr->bytes == NULL) { @@ -1674,9 +1674,9 @@ Tcl_GetString( char * Tcl_GetStringFromObj( - register Tcl_Obj *objPtr, /* Object whose string rep byte pointer should + Tcl_Obj *objPtr, /* Object whose string rep byte pointer should * be returned. */ - register int *lengthPtr) /* If non-NULL, the location where the string + int *lengthPtr) /* If non-NULL, the location where the string * rep's byte array length should * be stored. * If NULL, no length is stored. */ { @@ -1816,7 +1816,7 @@ Tcl_InitStringRep( void Tcl_InvalidateStringRep( - register Tcl_Obj *objPtr) /* Object whose string rep byte pointer should + Tcl_Obj *objPtr) /* Object whose string rep byte pointer should * be freed. */ { TclInvalidateStringRep(objPtr); @@ -1961,7 +1961,7 @@ Tcl_FreeIntRep( Tcl_Obj * Tcl_NewBooleanObj( - register int boolValue) /* Boolean used to initialize new object. */ + int boolValue) /* Boolean used to initialize new object. */ { return Tcl_DbNewWideIntObj(boolValue!=0, "unknown", 0); } @@ -1970,9 +1970,9 @@ Tcl_NewBooleanObj( Tcl_Obj * Tcl_NewBooleanObj( - register int boolValue) /* Boolean used to initialize new object. */ + int boolValue) /* Boolean used to initialize new object. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclNewIntObj(objPtr, boolValue!=0); return objPtr; @@ -2011,13 +2011,13 @@ Tcl_NewBooleanObj( Tcl_Obj * Tcl_DbNewBooleanObj( - register int boolValue, /* Boolean used to initialize new object. */ + int boolValue, /* Boolean used to initialize new object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); /* Optimized TclInvalidateStringRep() */ @@ -2032,7 +2032,7 @@ Tcl_DbNewBooleanObj( Tcl_Obj * Tcl_DbNewBooleanObj( - register int boolValue, /* Boolean used to initialize new object. */ + int boolValue, /* Boolean used to initialize new object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for @@ -2063,8 +2063,8 @@ Tcl_DbNewBooleanObj( #undef Tcl_SetBooleanObj void Tcl_SetBooleanObj( - register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ - register int boolValue) /* Boolean used to set object's value. */ + Tcl_Obj *objPtr, /* Object whose internal rep to init. */ + int boolValue) /* Boolean used to set object's value. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj"); @@ -2096,8 +2096,8 @@ Tcl_SetBooleanObj( int Tcl_GetBooleanFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr, /* The object from which to get boolean. */ - register int *boolPtr) /* Place to store resulting boolean. */ + Tcl_Obj *objPtr, /* The object from which to get boolean. */ + int *boolPtr) /* Place to store resulting boolean. */ { do { if (objPtr->typePtr == &tclIntType) { @@ -2162,7 +2162,7 @@ Tcl_GetBooleanFromObj( int TclSetBooleanFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr) /* The object to convert. */ + Tcl_Obj *objPtr) /* The object to convert. */ { /* * For some "pure" numeric Tcl_ObjTypes (no string rep), we can determine @@ -2208,7 +2208,7 @@ TclSetBooleanFromAny( static int ParseBoolean( - register Tcl_Obj *objPtr) /* The object to parse/convert. */ + Tcl_Obj *objPtr) /* The object to parse/convert. */ { int newBool; char lowerCase[6]; @@ -2350,7 +2350,7 @@ ParseBoolean( Tcl_Obj * Tcl_NewDoubleObj( - register double dblValue) /* Double used to initialize the object. */ + double dblValue) /* Double used to initialize the object. */ { return Tcl_DbNewDoubleObj(dblValue, "unknown", 0); } @@ -2359,9 +2359,9 @@ Tcl_NewDoubleObj( Tcl_Obj * Tcl_NewDoubleObj( - register double dblValue) /* Double used to initialize the object. */ + double dblValue) /* Double used to initialize the object. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclNewDoubleObj(objPtr, dblValue); return objPtr; @@ -2398,13 +2398,13 @@ Tcl_NewDoubleObj( Tcl_Obj * Tcl_DbNewDoubleObj( - register double dblValue, /* Double used to initialize the object. */ + double dblValue, /* Double used to initialize the object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); /* Optimized TclInvalidateStringRep() */ @@ -2419,7 +2419,7 @@ Tcl_DbNewDoubleObj( Tcl_Obj * Tcl_DbNewDoubleObj( - register double dblValue, /* Double used to initialize the object. */ + double dblValue, /* Double used to initialize the object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for @@ -2449,8 +2449,8 @@ Tcl_DbNewDoubleObj( void Tcl_SetDoubleObj( - register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ - register double dblValue) /* Double used to set the object's value. */ + Tcl_Obj *objPtr, /* Object whose internal rep to init. */ + double dblValue) /* Double used to set the object's value. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetDoubleObj"); @@ -2482,8 +2482,8 @@ Tcl_SetDoubleObj( int Tcl_GetDoubleFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr, /* The object from which to get a double. */ - register double *dblPtr) /* Place to store resulting double. */ + Tcl_Obj *objPtr, /* The object from which to get a double. */ + double *dblPtr) /* Place to store resulting double. */ { do { if (objPtr->typePtr == &tclDoubleType) { @@ -2537,7 +2537,7 @@ Tcl_GetDoubleFromObj( static int SetDoubleFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr) /* The object to convert. */ + Tcl_Obj *objPtr) /* The object to convert. */ { return TclParseNumber(interp, objPtr, "floating-point number", NULL, -1, NULL, 0); @@ -2566,7 +2566,7 @@ SetDoubleFromAny( static void UpdateStringOfDouble( - register Tcl_Obj *objPtr) /* Double obj with string rep to update. */ + Tcl_Obj *objPtr) /* Double obj with string rep to update. */ { char *dst = Tcl_InitStringRep(objPtr, NULL, TCL_DOUBLE_SPACE); @@ -2612,7 +2612,7 @@ UpdateStringOfDouble( Tcl_Obj * Tcl_NewIntObj( - register int intValue) /* Int used to initialize the new object. */ + int intValue) /* Int used to initialize the new object. */ { return Tcl_DbNewWideIntObj((long)intValue, "unknown", 0); } @@ -2621,9 +2621,9 @@ Tcl_NewIntObj( Tcl_Obj * Tcl_NewIntObj( - register int intValue) /* Int used to initialize the new object. */ + int intValue) /* Int used to initialize the new object. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclNewIntObj(objPtr, intValue); return objPtr; @@ -2652,8 +2652,8 @@ Tcl_NewIntObj( #undef Tcl_SetIntObj void Tcl_SetIntObj( - register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ - register int intValue) /* Integer used to set object's value. */ + Tcl_Obj *objPtr, /* Object whose internal rep to init. */ + int intValue) /* Integer used to set object's value. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetIntObj"); @@ -2692,8 +2692,8 @@ Tcl_SetIntObj( int Tcl_GetIntFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr, /* The object from which to get a int. */ - register int *intPtr) /* Place to store resulting int. */ + Tcl_Obj *objPtr, /* The object from which to get a int. */ + int *intPtr) /* Place to store resulting int. */ { #if (LONG_MAX == INT_MAX) return TclGetLongFromObj(interp, objPtr, (long *) intPtr); @@ -2763,7 +2763,7 @@ SetIntFromAny( static void UpdateStringOfInt( - register Tcl_Obj *objPtr) /* Int object whose string rep to update. */ + Tcl_Obj *objPtr) /* Int object whose string rep to update. */ { char *dst = Tcl_InitStringRep( objPtr, NULL, TCL_INTEGER_SPACE); @@ -2775,7 +2775,7 @@ UpdateStringOfInt( #if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG) static void UpdateStringOfOldInt( - register Tcl_Obj *objPtr) /* Int object whose string rep to update. */ + Tcl_Obj *objPtr) /* Int object whose string rep to update. */ { char *dst = Tcl_InitStringRep( objPtr, NULL, TCL_INTEGER_SPACE); @@ -2821,7 +2821,7 @@ UpdateStringOfOldInt( Tcl_Obj * Tcl_NewLongObj( - register long longValue) /* Long integer used to initialize the + long longValue) /* Long integer used to initialize the * new object. */ { return Tcl_DbNewWideIntObj(longValue, "unknown", 0); @@ -2831,10 +2831,10 @@ Tcl_NewLongObj( Tcl_Obj * Tcl_NewLongObj( - register long longValue) /* Long integer used to initialize the + long longValue) /* Long integer used to initialize the * new object. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclNewIntObj(objPtr, longValue); return objPtr; @@ -2880,14 +2880,14 @@ Tcl_NewLongObj( Tcl_Obj * Tcl_DbNewLongObj( - register long longValue, /* Long integer used to initialize the new + long longValue, /* Long integer used to initialize the new * object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); /* Optimized TclInvalidateStringRep */ @@ -2902,7 +2902,7 @@ Tcl_DbNewLongObj( Tcl_Obj * Tcl_DbNewLongObj( - register long longValue, /* Long integer used to initialize the new + long longValue, /* Long integer used to initialize the new * object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ @@ -2936,8 +2936,8 @@ Tcl_DbNewLongObj( #undef Tcl_SetLongObj void Tcl_SetLongObj( - register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ - register long longValue) /* Long integer used to initialize the + Tcl_Obj *objPtr, /* Object whose internal rep to init. */ + long longValue) /* Long integer used to initialize the * object's value. */ { if (Tcl_IsShared(objPtr)) { @@ -2972,8 +2972,8 @@ Tcl_SetLongObj( int Tcl_GetLongFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr, /* The object from which to get a long. */ - register long *longPtr) /* Place to store resulting long. */ + Tcl_Obj *objPtr, /* The object from which to get a long. */ + long *longPtr) /* Place to store resulting long. */ { do { #ifdef TCL_WIDE_INT_IS_LONG @@ -3019,11 +3019,12 @@ Tcl_GetLongFromObj( */ mp_int big; - unsigned long scratch, value = 0, numBytes = sizeof(unsigned long); + unsigned long scratch, value = 0; unsigned char *bytes = (unsigned char *) &scratch; + size_t numBytes; TclUnpackBignum(objPtr, big); - if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) { + if (mp_to_ubin(&big, bytes, sizeof(long), &numBytes) == MP_OKAY) { while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } @@ -3086,7 +3087,7 @@ Tcl_GetLongFromObj( Tcl_Obj * Tcl_NewWideIntObj( - register Tcl_WideInt wideValue) + Tcl_WideInt wideValue) /* Wide integer used to initialize the new * object. */ { @@ -3097,11 +3098,11 @@ Tcl_NewWideIntObj( Tcl_Obj * Tcl_NewWideIntObj( - register Tcl_WideInt wideValue) + Tcl_WideInt wideValue) /* Wide integer used to initialize the new * object. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclNewObj(objPtr); TclSetIntObj(objPtr, wideValue); @@ -3145,7 +3146,7 @@ Tcl_NewWideIntObj( Tcl_Obj * Tcl_DbNewWideIntObj( - register Tcl_WideInt wideValue, + Tcl_WideInt wideValue, /* Wide integer used to initialize the new * object. */ const char *file, /* The name of the source file calling this @@ -3153,7 +3154,7 @@ Tcl_DbNewWideIntObj( int line) /* Line number in the source file; used for * debugging. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); TclSetIntObj(objPtr, wideValue); @@ -3164,7 +3165,7 @@ Tcl_DbNewWideIntObj( Tcl_Obj * Tcl_DbNewWideIntObj( - register Tcl_WideInt wideValue, + Tcl_WideInt wideValue, /* Long integer used to initialize the new * object. */ const char *file, /* The name of the source file calling this @@ -3196,8 +3197,8 @@ Tcl_DbNewWideIntObj( void Tcl_SetWideIntObj( - register Tcl_Obj *objPtr, /* Object w. internal rep to init. */ - register Tcl_WideInt wideValue) + Tcl_Obj *objPtr, /* Object w. internal rep to init. */ + Tcl_WideInt wideValue) /* Wide integer used to initialize the * object's value. */ { @@ -3232,8 +3233,8 @@ Tcl_SetWideIntObj( int Tcl_GetWideIntFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr, /* Object from which to get a wide int. */ - register Tcl_WideInt *wideIntPtr) + Tcl_Obj *objPtr, /* Object from which to get a wide int. */ + Tcl_WideInt *wideIntPtr) /* Place to store resulting long. */ { do { @@ -3258,12 +3259,12 @@ Tcl_GetWideIntFromObj( mp_int big; Tcl_WideUInt value = 0; - unsigned long numBytes = sizeof(Tcl_WideInt); + size_t numBytes; Tcl_WideInt scratch; unsigned char *bytes = (unsigned char *) &scratch; TclUnpackBignum(objPtr, big); - if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) { + if (mp_to_ubin(&big, bytes, sizeof(Tcl_WideInt), &numBytes) == MP_OKAY) { while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } @@ -3339,12 +3340,12 @@ TclGetWideBitsFromObj( mp_int big; Tcl_WideUInt value = 0, scratch; - unsigned long numBytes = sizeof(Tcl_WideInt); + size_t numBytes; unsigned char *bytes = (unsigned char *) &scratch; Tcl_GetBignumFromObj(NULL, objPtr, &big); mp_mod_2d(&big, (int) (CHAR_BIT * sizeof(Tcl_WideInt)), &big); - mp_to_unsigned_bin_n(&big, bytes, &numBytes); + mp_to_ubin(&big, bytes, sizeof(Tcl_WideInt), &numBytes); while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } @@ -3464,7 +3465,7 @@ UpdateStringOfBignum( stringVal = Tcl_InitStringRep(objPtr, NULL, size - 1); TclOOM(stringVal, size); - if (MP_OKAY != mp_toradix_n(&bignumVal, stringVal, 10, size)) { + if (MP_OKAY != mp_to_radix(&bignumVal, stringVal, size, NULL, 10)) { Tcl_Panic("conversion failure in UpdateStringOfBignum"); } (void) Tcl_InitStringRep(objPtr, NULL, size - 1); @@ -3603,7 +3604,7 @@ GetBignumFromObj( return TCL_OK; } if (objPtr->typePtr == &tclIntType) { - TclInitBignumFromWideInt(bignumValue, + mp_init_i64(bignumValue, objPtr->internalRep.wideValue); return TCL_OK; } @@ -3713,14 +3714,14 @@ Tcl_SetBignumObj( mp_int *bignumValue) /* Value to store */ { Tcl_WideUInt value = 0; - unsigned long numBytes = sizeof(Tcl_WideUInt); + size_t numBytes; Tcl_WideUInt scratch; unsigned char *bytes = (unsigned char *) &scratch; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj"); } - if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) { + if (mp_to_ubin(bignumValue, bytes, sizeof(Tcl_WideUInt), &numBytes) != MP_OKAY) { goto tooLargeForWide; } while (numBytes-- > 0) { @@ -3925,7 +3926,7 @@ Tcl_IsShared( void Tcl_DbIncrRefCount( - register Tcl_Obj *objPtr, /* The object we are registering a reference + Tcl_Obj *objPtr, /* The object we are registering a reference * to. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ @@ -3988,7 +3989,7 @@ Tcl_DbIncrRefCount( void Tcl_DbDecrRefCount( - register Tcl_Obj *objPtr, /* The object we are releasing a reference + Tcl_Obj *objPtr, /* The object we are releasing a reference * to. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ @@ -4054,7 +4055,7 @@ Tcl_DbDecrRefCount( int Tcl_DbIsShared( - register Tcl_Obj *objPtr, /* The object to test for being shared. */ + Tcl_Obj *objPtr, /* The object to test for being shared. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for @@ -4126,7 +4127,7 @@ Tcl_DbIsShared( void Tcl_InitObjHashTable( - register Tcl_HashTable *tablePtr) + Tcl_HashTable *tablePtr) /* Pointer to table record, which is supplied * by the caller. */ { @@ -4189,8 +4190,8 @@ TclCompareObjKeys( { Tcl_Obj *objPtr1 = keyPtr; Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue; - register const char *p1, *p2; - register size_t l1, l2; + const char *p1, *p2; + size_t l1, l2; /* * If the object pointers are the same then they match. @@ -4347,13 +4348,13 @@ Tcl_Command Tcl_GetCommandFromObj( Tcl_Interp *interp, /* The interpreter in which to resolve the * command and to report errors. */ - register Tcl_Obj *objPtr) /* The object containing the command's name. + Tcl_Obj *objPtr) /* The object containing the command's name. * If the name starts with "::", will be * looked up in global namespace. Else, looked * up first in the current namespace, then in * global namespace. */ { - register ResolvedCmdName *resPtr; + ResolvedCmdName *resPtr; /* * Get the internal representation, converting to a command type if @@ -4376,12 +4377,12 @@ Tcl_GetCommandFromObj( resPtr = objPtr->internalRep.twoPtrValue.ptr1; if (objPtr->typePtr == &tclCmdNameType) { - register Command *cmdPtr = resPtr->cmdPtr; + Command *cmdPtr = resPtr->cmdPtr; if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch) && (interp == cmdPtr->nsPtr->interp) && !(cmdPtr->nsPtr->flags & NS_DYING)) { - register Namespace *refNsPtr = (Namespace *) + Namespace *refNsPtr = (Namespace *) TclGetCurrentNamespace(interp); if ((resPtr->refNsPtr == NULL) @@ -4483,12 +4484,12 @@ void TclSetCmdNameObj( Tcl_Interp *interp, /* Points to interpreter containing command * that should be cached in objPtr. */ - register Tcl_Obj *objPtr, /* Points to Tcl object to be changed to a + Tcl_Obj *objPtr, /* Points to Tcl object to be changed to a * CmdName object. */ Command *cmdPtr) /* Points to Command structure that the * CmdName object should refer to. */ { - register ResolvedCmdName *resPtr; + ResolvedCmdName *resPtr; if (objPtr->typePtr == &tclCmdNameType) { resPtr = objPtr->internalRep.twoPtrValue.ptr1; @@ -4523,10 +4524,10 @@ TclSetCmdNameObj( static void FreeCmdNameInternalRep( - register Tcl_Obj *objPtr) /* CmdName object with internal + Tcl_Obj *objPtr) /* CmdName object with internal * representation to free. */ { - register ResolvedCmdName *resPtr = objPtr->internalRep.twoPtrValue.ptr1; + ResolvedCmdName *resPtr = objPtr->internalRep.twoPtrValue.ptr1; /* * Decrement the reference count of the ResolvedCmdName structure. If @@ -4571,9 +4572,9 @@ FreeCmdNameInternalRep( static void DupCmdNameInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ + Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { - register ResolvedCmdName *resPtr = srcPtr->internalRep.twoPtrValue.ptr1; + ResolvedCmdName *resPtr = srcPtr->internalRep.twoPtrValue.ptr1; copyPtr->internalRep.twoPtrValue.ptr1 = resPtr; copyPtr->internalRep.twoPtrValue.ptr2 = NULL; @@ -4605,11 +4606,11 @@ DupCmdNameInternalRep( static int SetCmdNameFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr) /* The object to convert. */ + Tcl_Obj *objPtr) /* The object to convert. */ { const char *name; - register Command *cmdPtr; - register ResolvedCmdName *resPtr; + Command *cmdPtr; + ResolvedCmdName *resPtr; if (interp == NULL) { return TCL_ERROR; diff --git a/generic/tclPanic.c b/generic/tclPanic.c index e8c1e7f..4fce082 100644 --- a/generic/tclPanic.c +++ b/generic/tclPanic.c @@ -58,7 +58,7 @@ Tcl_SetPanicProc( else #endif panicProc = proc; - TclInitSubsystems(); + Tcl_InitSubsystems(); } /* diff --git a/generic/tclParse.c b/generic/tclParse.c index 164905a..6143cb7 100644 --- a/generic/tclParse.c +++ b/generic/tclParse.c @@ -195,19 +195,19 @@ Tcl_ParseCommand( * NULL, then no error message is provided. */ const char *start, /* First character of string containing one or * more Tcl commands. */ - register int numBytes, /* Total number of bytes in string. If < 0, + int numBytes, /* Total number of bytes in string. If < 0, * the script consists of all bytes up to the * first null character. */ int nested, /* Non-zero means this is a nested command: * close bracket should be considered a * command terminator. If zero, then close * bracket has no special meaning. */ - register Tcl_Parse *parsePtr) + Tcl_Parse *parsePtr) /* Structure to fill in with information about * the parsed command; any previous * information in the structure is ignored. */ { - register const char *src; /* Points to current character in the + const char *src; /* Points to current character in the * command. */ char type; /* Result returned by CHAR_TYPE(*src). */ Tcl_Token *tokenPtr; /* Pointer to token being filled in. */ @@ -620,14 +620,14 @@ TclIsBareword( static int ParseWhiteSpace( const char *src, /* First character to parse. */ - register int numBytes, /* Max number of bytes to scan. */ + int numBytes, /* Max number of bytes to scan. */ int *incompletePtr, /* Set this boolean memory to true if parsing * indicates an incomplete command. */ char *typePtr) /* Points to location to store character type * of character that ends run of whitespace */ { - register char type = TYPE_NORMAL; - register const char *p = src; + char type = TYPE_NORMAL; + const char *p = src; while (1) { while (numBytes && ((type = CHAR_TYPE(*p)) & TYPE_SPACE)) { @@ -729,7 +729,7 @@ TclParseHex( * conversion is to be written. */ { int result = 0; - register const char *p = src; + const char *p = src; while (numBytes--) { unsigned char digit = UCHAR(*p); @@ -784,10 +784,9 @@ TclParseBackslash( * of bytes scanned should be written. */ char *dst) /* NULL, or points to buffer where the UTF-8 * encoding of the backslash sequence is to be - * written. At most TCL_UTF_MAX bytes will be - * written there. */ + * written. At most 4 bytes will be written there. */ { - register const char *p = src+1; + const char *p = src+1; Tcl_UniChar unichar = 0; int result; int count; @@ -817,7 +816,7 @@ TclParseBackslash( count = 2; switch (*p) { /* - * Note: in the conversions below, use absolute values (e.g., 0xa) + * Note: in the conversions below, use absolute values (e.g., 0xA) * rather than symbolic values (e.g. \n) that get converted by the * compiler. It's possible that compilers on some platforms will do * the symbolic conversions differently, which could result in @@ -831,19 +830,19 @@ TclParseBackslash( result = 0x8; break; case 'f': - result = 0xc; + result = 0xC; break; case 'n': - result = 0xa; + result = 0xA; break; case 'r': - result = 0xd; + result = 0xD; break; case 't': result = 0x9; break; case 'v': - result = 0xb; + result = 0xB; break; case 'x': count += TclParseHex(p+1, (numBytes > 3) ? 2 : numBytes-2, &result); @@ -867,6 +866,16 @@ TclParseBackslash( * No hexdigits -> This is just "u". */ result = 'u'; + } else if (((result & 0xDC00) == 0xD800) && (count == 6) + && (p[5] == '\\') && (p[6] == 'u') && (numBytes >= 10)) { + /* If high surrogate is immediately followed by a low surrogate + * escape, combine them into one character. */ + int low; + int count2 = TclParseHex(p+7, 4, &low); + if ((count2 == 4) && ((low & 0xDC00) == 0xDC00)) { + result = ((result & 0x3FF)<<10 | (low & 0x3FF)) + 0x10000; + count += count2 + 2; + } } break; case 'U': @@ -876,6 +885,9 @@ TclParseBackslash( * No hexdigits -> This is just "U". */ result = 'U'; + } else if ((result | 0x7FF) == 0xDFFF) { + /* Upper or lower surrogate, not allowed in this syntax. */ + result = 0xFFFD; } break; case '\n': @@ -967,12 +979,12 @@ TclParseBackslash( static int ParseComment( const char *src, /* First character to parse. */ - register int numBytes, /* Max number of bytes to scan. */ + int numBytes, /* Max number of bytes to scan. */ Tcl_Parse *parsePtr) /* Information about parse in progress. * Updated if parsing indicates an incomplete * command. */ { - register const char *p = src; + const char *p = src; int incomplete = parsePtr->incomplete; while (numBytes) { @@ -1039,8 +1051,8 @@ ParseComment( static int ParseTokens( - register const char *src, /* First character to parse. */ - register int numBytes, /* Max number of bytes to scan. */ + const char *src, /* First character to parse. */ + int numBytes, /* Max number of bytes to scan. */ int mask, /* Specifies when to stop parsing. The parse * stops at the first unquoted character whose * CHAR_TYPE contains any of the bits in @@ -1318,7 +1330,7 @@ Tcl_ParseVarName( * NULL, then no error message is provided. */ const char *start, /* Start of variable substitution string. * First character must be "$". */ - register int numBytes, /* Total number of bytes in string. If < 0, + int numBytes, /* Total number of bytes in string. If < 0, * the string consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr, /* Structure to fill in with information about @@ -1329,7 +1341,7 @@ Tcl_ParseVarName( * reinitialize it. */ { Tcl_Token *tokenPtr; - register const char *src; + const char *src; int varIndex; unsigned array; @@ -1511,13 +1523,13 @@ Tcl_ParseVarName( const char * Tcl_ParseVar( Tcl_Interp *interp, /* Context for looking up variable. */ - register const char *start, /* Start of variable substitution. First + const char *start, /* Start of variable substitution. First * character must be "$". */ const char **termPtr) /* If non-NULL, points to word to fill in with * character just after last one in the * variable specifier. */ { - register Tcl_Obj *objPtr; + Tcl_Obj *objPtr; int code; Tcl_Parse *parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); @@ -1596,10 +1608,10 @@ Tcl_ParseBraces( * NULL, then no error message is provided. */ const char *start, /* Start of string enclosed in braces. The * first character must be {'. */ - register int numBytes, /* Total number of bytes in string. If < 0, + int numBytes, /* Total number of bytes in string. If < 0, * the string consists of all bytes up to the * first null character. */ - register Tcl_Parse *parsePtr, + Tcl_Parse *parsePtr, /* Structure to fill in with information about * the string. */ int append, /* Non-zero means append tokens to existing @@ -1612,7 +1624,7 @@ Tcl_ParseBraces( * successful. */ { Tcl_Token *tokenPtr; - register const char *src; + const char *src; int startIndex, level, length; if ((numBytes == 0) || (start == NULL)) { @@ -1738,7 +1750,7 @@ Tcl_ParseBraces( */ { - register int openBrace = 0; + int openBrace = 0; while (--src > start) { switch (*src) { @@ -1798,10 +1810,10 @@ Tcl_ParseQuotedString( * NULL, then no error message is provided. */ const char *start, /* Start of the quoted string. The first * character must be '"'. */ - register int numBytes, /* Total number of bytes in string. If < 0, + int numBytes, /* Total number of bytes in string. If < 0, * the string consists of all bytes up to the * first null character. */ - register Tcl_Parse *parsePtr, + Tcl_Parse *parsePtr, /* Structure to fill in with information about * the string. */ int append, /* Non-zero means append tokens to existing diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c index 3703aaf..13b7768 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) { @@ -2053,6 +2017,7 @@ Tcl_FSGetInternalRep( nativePathPtr = proc(pathPtr); srcFsPathPtr = PATHOBJ(pathPtr); srcFsPathPtr->nativePathPtr = nativePathPtr; + srcFsPathPtr->filesystemEpoch = TclFSEpoch(); } return srcFsPathPtr->nativePathPtr; @@ -2063,15 +2028,15 @@ Tcl_FSGetInternalRep( * * TclFSEnsureEpochOk -- * - * This will ensure the pathPtr is up to date and can be converted into a - * "path" type, and that we are able to generate a complete normalized - * path which is used to determine the filesystem match. + * Ensure that the path is a valid path, and that it has a + * fsPathType internal representation that is not stale. * * Results: - * Standard Tcl return code. + * A standard Tcl return code. * * Side effects: - * An attempt may be made to convert the object. + * The internal representation of fsPtrPtr is converted to fsPathType if + * possible. * *--------------------------------------------------------------------------- */ @@ -2089,14 +2054,11 @@ TclFSEnsureEpochOk( srcFsPathPtr = PATHOBJ(pathPtr); - /* - * Check if the filesystem has changed in some way since this object's - * internal representation was calculated. - */ - if (!TclFSEpochOk(srcFsPathPtr->filesystemEpoch)) { /* - * We have to discard the stale representation and recalculate it. + * The filesystem has changed in some way since the internal + * representation for this object was calculated. Discard the stale + * representation and recalculate it. */ TclGetString(pathPtr); @@ -2107,11 +2069,10 @@ TclFSEnsureEpochOk( srcFsPathPtr = PATHOBJ(pathPtr); } - /* - * Check whether the object is already assigned to a fs. - */ - if (srcFsPathPtr->fsPtr != NULL) { + /* + * There is already a filesystem assigned to this path. + */ *fsPtrPtr = srcFsPathPtr->fsPtr; } return TCL_OK; @@ -2219,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. @@ -2242,7 +2204,7 @@ SetFsPathFromAny( int len; FsPath *fsPathPtr; Tcl_Obj *transPtr; - char *name; + const char *name; if (TclHasIntRep(pathPtr, &fsPathType)) { return TCL_OK; @@ -2307,7 +2269,7 @@ SetFsPathFromAny( Tcl_DStringFree(&dirString); } else { /* - * We have a user name '~user' + * There is a '~user' */ const char *expandedUser; @@ -2501,7 +2463,7 @@ DupFsPathInternalRep( static void UpdateStringOfFsPath( - register Tcl_Obj *pathPtr) /* path obj with string rep to update. */ + Tcl_Obj *pathPtr) /* path obj with string rep to update. */ { FsPath *fsPathPtr = PATHOBJ(pathPtr); int cwdLen; diff --git a/generic/tclPipe.c b/generic/tclPipe.c index 63fd2fa..70774e7 100644 --- a/generic/tclPipe.c +++ b/generic/tclPipe.c @@ -183,7 +183,7 @@ Tcl_DetachPids( * array pointed to by pidPtr. */ Tcl_Pid *pidPtr) /* Array of pids to detach. */ { - register Detached *detPtr; + Detached *detPtr; int i; Tcl_MutexLock(&pipeMutex); @@ -219,7 +219,7 @@ Tcl_DetachPids( void Tcl_ReapDetachedProcs(void) { - register Detached *detPtr; + Detached *detPtr; Detached *nextPtr, *prevPtr; int status, code; @@ -413,7 +413,7 @@ TclCreatePipeline( * at *inPipePtr. NULL means command specified * its own input source. */ TclFile *outPipePtr, /* If non-NULL, output to the pipeline goes to - * a pipe, unless overriden by redirection in + * a pipe, unless overridden by redirection in * the command. The file id with which to read * frome this pipe is stored at *outPipePtr. * NULL means command specified its own output diff --git a/generic/tclPkg.c b/generic/tclPkg.c index ed5c57a..6727715 100644 --- a/generic/tclPkg.c +++ b/generic/tclPkg.c @@ -280,11 +280,11 @@ TclPkgFileSeen( if (pkgFiles && pkgFiles->names) { const char *name = pkgFiles->names->name; Tcl_HashTable *table = &pkgFiles->table; - int new; - Tcl_HashEntry *entry = Tcl_CreateHashEntry(table, name, &new); + int isNew; + Tcl_HashEntry *entry = Tcl_CreateHashEntry(table, name, &isNew); Tcl_Obj *list; - if (new) { + if (isNew) { list = Tcl_NewObj(); Tcl_SetHashValue(entry, list); Tcl_IncrRefCount(list); diff --git a/generic/tclPlatDecls.h b/generic/tclPlatDecls.h index abc8ee8..edf1ba3 100644 --- a/generic/tclPlatDecls.h +++ b/generic/tclPlatDecls.h @@ -117,6 +117,16 @@ extern const TclPlatStubs *tclPlatStubsPtr; #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT -#endif /* _TCLPLATDECLS */ - +#if defined(USE_TCL_STUBS) && (defined(_WIN32) || defined(__CYGWIN__))\ + && (defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8) +#undef Tcl_WinUtfToTChar +#undef Tcl_WinTCharToUtf +#ifdef _WIN32 +#define Tcl_WinUtfToTChar(string, len, dsPtr) (Tcl_DStringInit(dsPtr), \ + (TCHAR *)Tcl_UtfToChar16DString((string), (len), (dsPtr))) +#define Tcl_WinTCharToUtf(string, len, dsPtr) (Tcl_DStringInit(dsPtr), \ + (char *)Tcl_Char16ToUtfDString((const unsigned short *)(string), ((((len) + 2) >> 1) - 1), (dsPtr))) +#endif +#endif +#endif /* _TCLPLATDECLS */ diff --git a/generic/tclProc.c b/generic/tclProc.c index f24dae8..85d6531 100644 --- a/generic/tclProc.c +++ b/generic/tclProc.c @@ -157,7 +157,7 @@ Tcl_ProcObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; Proc *procPtr; const char *procName; const char *simpleName, *procArgs, *procBody; @@ -405,9 +405,9 @@ TclCreateProc( { Interp *iPtr = (Interp *) interp; - register Proc *procPtr = NULL; + Proc *procPtr = NULL; int i, result, numArgs; - register CompiledLocal *localPtr = NULL; + CompiledLocal *localPtr = NULL; Tcl_Obj **argArray; int precompiled = 0; @@ -634,7 +634,7 @@ TclCreateProc( * local variables for the argument. */ - localPtr = ckalloc(TclOffset(CompiledLocal, name) + fieldValues[0]->length +1); + localPtr = ckalloc(offsetof(CompiledLocal, name) + fieldValues[0]->length +1); if (procPtr->firstLocalPtr == NULL) { procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr; } else { @@ -761,7 +761,7 @@ TclObjGetFrame( CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if * global frame indicated). */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; int curLevel, level, result; const Tcl_ObjIntRep *irPtr; const char *name = NULL; @@ -808,7 +808,7 @@ TclObjGetFrame( } else { result = -1; } - } else if (TclGetWideBitsFromObj(interp, objPtr, &w) == TCL_OK) { + } else if (TclGetWideBitsFromObj(NULL, objPtr, &w) == TCL_OK) { /* * If this were an integer, we'd have succeeded already. * Docs say we have to treat this as a 'bad level' error. @@ -817,10 +817,16 @@ TclObjGetFrame( } } - if (result == 0) { - level = curLevel - 1; - } if (result != -1) { + /* if relative current level */ + if (result == 0) { + if (!curLevel) { + /* we are in top-level, so simply generate bad level */ + name = "1"; + goto badLevel; + } + level = curLevel - 1; + } if (level >= 0) { CallFrame *framePtr; for (framePtr = iPtr->varFramePtr; framePtr != NULL; @@ -832,9 +838,9 @@ TclObjGetFrame( } } } - +badLevel: if (name == NULL) { - name = TclGetString(objPtr); + name = objPtr ? TclGetString(objPtr) : "1" ; } Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad level \"%s\"", name)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", name, NULL); @@ -898,7 +904,7 @@ TclNRUplevelObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; CmdFrame *invoker = NULL; int word = 0; int result; @@ -1038,7 +1044,7 @@ ProcWrongNumArgs( int skip) { CallFrame *framePtr = ((Interp *)interp)->varFramePtr; - register Proc *procPtr = framePtr->procPtr; + Proc *procPtr = framePtr->procPtr; int localCt = procPtr->numCompiledLocals, numArgs, i; Tcl_Obj **desiredObjs; const char *final = NULL; @@ -1063,7 +1069,7 @@ ProcWrongNumArgs( Tcl_IncrRefCount(desiredObjs[0]); if (localCt > 0) { - register Var *defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt); + Var *defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt); for (i=1 ; i<=numArgs ; i++, defPtr++) { Tcl_Obj *argObj; @@ -1254,7 +1260,7 @@ InitResolvedLocals( resVarInfo = localPtr->resolveInfo; if (resVarInfo && resVarInfo->fetchProc) { - register Var *resolvedVarPtr = (Var *) + Var *resolvedVarPtr = (Var *) resVarInfo->fetchProc(interp, resVarInfo); if (resolvedVarPtr) { @@ -1277,7 +1283,7 @@ TclFreeLocalCache( Tcl_Obj **namePtrPtr = &localCachePtr->varName0; for (i = 0; i < localCachePtr->numVars; i++, namePtrPtr++) { - register Tcl_Obj *objPtr = *namePtrPtr; + Tcl_Obj *objPtr = *namePtrPtr; if (objPtr) { /* TclReleaseLiteral calls Tcl_DecrRefCount for us */ @@ -1300,7 +1306,7 @@ InitLocalCache( Var *varPtr; LocalCache *localCachePtr; CompiledLocal *localPtr; - int new; + int isNew; ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); @@ -1323,7 +1329,7 @@ InitLocalCache( } else { *namePtr = TclCreateLiteral(iPtr, localPtr->name, localPtr->nameLength, /* hash */ (unsigned int) -1, - &new, /* nsPtr */ NULL, 0, NULL); + &isNew, /* nsPtr */ NULL, 0, NULL); Tcl_IncrRefCount(*namePtr); } @@ -1363,16 +1369,16 @@ InitLocalCache( static int InitArgsAndLocals( - register Tcl_Interp *interp,/* Interpreter in which procedure was + Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ Tcl_Obj *procNameObj, /* Procedure name for error reporting. */ int skip) /* Number of initial arguments to be skipped, * i.e., words in the "command name". */ { CallFrame *framePtr = ((Interp *)interp)->varFramePtr; - register Proc *procPtr = framePtr->procPtr; + Proc *procPtr = framePtr->procPtr; ByteCode *codePtr; - register Var *varPtr, *defPtr; + Var *varPtr, *defPtr; int localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax; Tcl_Obj *const *argObjs; @@ -1530,7 +1536,7 @@ int TclPushProcCallFrame( ClientData clientData, /* Record describing procedure to be * interpreted. */ - register Tcl_Interp *interp,/* Interpreter in which procedure was + Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ int objc, /* Count of number of arguments to this * procedure. */ @@ -1622,7 +1628,7 @@ int TclObjInterpProc( ClientData clientData, /* Record describing procedure to be * interpreted. */ - register Tcl_Interp *interp,/* Interpreter in which procedure was + Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ int objc, /* Count of number of arguments to this * procedure. */ @@ -1639,7 +1645,7 @@ int TclNRInterpProc( ClientData clientData, /* Record describing procedure to be * interpreted. */ - register Tcl_Interp *interp,/* Interpreter in which procedure was + Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ int objc, /* Count of number of arguments to this * procedure. */ @@ -1674,7 +1680,7 @@ TclNRInterpProc( int TclNRInterpProcCore( - register Tcl_Interp *interp,/* Interpreter in which procedure was + Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ Tcl_Obj *procNameObj, /* Procedure name for error reporting. */ int skip, /* Number of initial arguments to be skipped, @@ -1683,7 +1689,7 @@ TclNRInterpProcCore( * results of the overall procedure. */ { Interp *iPtr = (Interp *) interp; - register Proc *procPtr = iPtr->varFramePtr->procPtr; + Proc *procPtr = iPtr->varFramePtr->procPtr; int result; CallFrame *freePtr; ByteCode *codePtr; @@ -1700,8 +1706,8 @@ TclNRInterpProcCore( #if defined(TCL_COMPILE_DEBUG) if (tclTraceExec >= 1) { - register CallFrame *framePtr = iPtr->varFramePtr; - register int i; + CallFrame *framePtr = iPtr->varFramePtr; + int i; if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) { fprintf(stdout, "Calling lambda "); @@ -1847,9 +1853,7 @@ InterpProcNR2( Tcl_SetErrorCode(interp, "TCL", "RESULT", "UNEXPECTED", NULL); result = TCL_ERROR; - /* - * Fall through to the TCL_ERROR handling code. - */ + /* FALLTHRU */ case TCL_ERROR: /* @@ -2119,9 +2123,9 @@ TclProcDeleteProc( void TclProcCleanupProc( - register Proc *procPtr) /* Procedure to be deleted. */ + Proc *procPtr) /* Procedure to be deleted. */ { - register CompiledLocal *localPtr; + CompiledLocal *localPtr; Tcl_Obj *bodyPtr = procPtr->bodyPtr; Tcl_Obj *defPtr; Tcl_ResolvedVarInfo *resVarInfo; @@ -2370,7 +2374,7 @@ ProcBodyFree( static void DupLambdaInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ + Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { Proc *procPtr; Tcl_Obj *nsObjPtr; @@ -2385,7 +2389,7 @@ DupLambdaInternalRep( static void FreeLambdaInternalRep( - register Tcl_Obj *objPtr) /* CmdName object with internal representation + Tcl_Obj *objPtr) /* CmdName object with internal representation * to free. */ { Proc *procPtr; @@ -2403,7 +2407,7 @@ FreeLambdaInternalRep( static int SetLambdaFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr) /* The object to convert. */ + Tcl_Obj *objPtr) /* The object to convert. */ { Interp *iPtr = (Interp *) interp; const char *name; diff --git a/generic/tclRegexp.c b/generic/tclRegexp.c index 804b117..b4fd811 100644 --- a/generic/tclRegexp.c +++ b/generic/tclRegexp.c @@ -263,7 +263,7 @@ Tcl_RegExpRange( if ((size_t) index > regexpPtr->re.re_nsub) { *startPtr = *endPtr = NULL; - } else if (regexpPtr->matches[index].rm_so < 0) { + } else if (regexpPtr->matches[index].rm_so == TCL_INDEX_NONE) { *startPtr = *endPtr = NULL; } else { if (regexpPtr->objPtr) { @@ -364,7 +364,7 @@ TclRegExpRangeUniChar( * passed to Tcl_RegExpExec. */ int index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching - * subrange, -1 means the range of the + * subrange, TCL_INDEX_NONE means the range of the * rm_extend field. */ int *startPtr, /* Store address of first character in * (sub-)range here. */ @@ -373,12 +373,12 @@ TclRegExpRangeUniChar( { TclRegexp *regexpPtr = (TclRegexp *) re; - if ((regexpPtr->flags®_EXPECT) && index == -1) { + if ((regexpPtr->flags®_EXPECT) && (index == TCL_INDEX_NONE)) { *startPtr = regexpPtr->details.rm_extend.rm_so; *endPtr = regexpPtr->details.rm_extend.rm_eo; } else if ((size_t) index > regexpPtr->re.re_nsub) { - *startPtr = -1; - *endPtr = -1; + *startPtr = TCL_INDEX_NONE; + *endPtr = TCL_INDEX_NONE; } else { *startPtr = regexpPtr->matches[index].rm_so; *endPtr = regexpPtr->matches[index].rm_eo; @@ -725,12 +725,12 @@ TclRegError( const char *p; Tcl_ResetResult(interp); - n = TclReError(status, NULL, buf, sizeof(buf)); + n = TclReError(status, buf, sizeof(buf)); p = (n > sizeof(buf)) ? "..." : ""; Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s%s%s", msg, buf, p)); sprintf(cbuf, "%d", status); - (void) TclReError(REG_ITOA, NULL, cbuf, sizeof(cbuf)); + (void) TclReError(REG_ITOA, cbuf, sizeof(cbuf)); Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, NULL); } diff --git a/generic/tclResult.c b/generic/tclResult.c index 4d14f01..3c856d3 100644 --- a/generic/tclResult.c +++ b/generic/tclResult.c @@ -414,14 +414,14 @@ void Tcl_SetResult( Tcl_Interp *interp, /* Interpreter with which to associate the * return value. */ - register char *result, /* Value to be returned. If NULL, the result + char *result, /* Value to be returned. If NULL, the result * is set to an empty string. */ Tcl_FreeProc *freeProc) /* Gives information about the string: * TCL_STATIC, TCL_VOLATILE, or the address of * a Tcl_FreeProc such as free. */ { Interp *iPtr = (Interp *) interp; - register Tcl_FreeProc *oldFreeProc = iPtr->freeProc; + Tcl_FreeProc *oldFreeProc = iPtr->freeProc; char *oldResult = iPtr->result; if (result == NULL) { @@ -484,7 +484,7 @@ Tcl_SetResult( const char * Tcl_GetStringResult( - register Tcl_Interp *interp)/* Interpreter whose result to return. */ + Tcl_Interp *interp)/* Interpreter whose result to return. */ { Interp *iPtr = (Interp *) interp; /* @@ -523,11 +523,11 @@ void Tcl_SetObjResult( Tcl_Interp *interp, /* Interpreter with which to associate the * return object value. */ - register Tcl_Obj *objPtr) /* Tcl object to be returned. If NULL, the obj + Tcl_Obj *objPtr) /* Tcl object to be returned. If NULL, the obj * result is made an empty string object. */ { - register Interp *iPtr = (Interp *) interp; - register Tcl_Obj *oldObjResult = iPtr->objResultPtr; + Interp *iPtr = (Interp *) interp; + Tcl_Obj *oldObjResult = iPtr->objResultPtr; iPtr->objResultPtr = objPtr; Tcl_IncrRefCount(objPtr); /* since interp result is a reference */ @@ -582,7 +582,7 @@ Tcl_Obj * Tcl_GetObjResult( Tcl_Interp *interp) /* Interpreter whose result to return. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; #ifndef TCL_NO_DEPRECATED Tcl_Obj *objResultPtr; int length; @@ -832,19 +832,19 @@ SetupAppendBuffer( totalSpace = newSpace + iPtr->appendUsed; if (totalSpace >= iPtr->appendAvl) { - char *new; + char *newSpace; if (totalSpace < 100) { totalSpace = 200; } else { totalSpace *= 2; } - new = ckalloc(totalSpace); - strcpy(new, iPtr->result); + newSpace = ckalloc(totalSpace); + strcpy(newSpace, iPtr->result); if (iPtr->appendResult != NULL) { ckfree(iPtr->appendResult); } - iPtr->appendResult = new; + iPtr->appendResult = newSpace; iPtr->appendAvl = totalSpace; } else if (iPtr->result != iPtr->appendResult) { strcpy(iPtr->appendResult, iPtr->result); @@ -879,9 +879,9 @@ SetupAppendBuffer( void Tcl_FreeResult( - register Tcl_Interp *interp)/* Interpreter for which to free result. */ + Tcl_Interp *interp)/* Interpreter for which to free result. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; #ifndef TCL_NO_DEPRECATED if (iPtr->freeProc != NULL) { @@ -918,9 +918,9 @@ Tcl_FreeResult( void Tcl_ResetResult( - register Tcl_Interp *interp)/* Interpreter for which to clear result. */ + Tcl_Interp *interp)/* Interpreter for which to clear result. */ { - register Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *) interp; ResetObjResult(iPtr); #ifndef TCL_NO_DEPRECATED @@ -983,10 +983,10 @@ Tcl_ResetResult( static void ResetObjResult( - register Interp *iPtr) /* Points to the interpreter whose result + Interp *iPtr) /* Points to the interpreter whose result * object should be reset. */ { - register Tcl_Obj *objResultPtr = iPtr->objResultPtr; + Tcl_Obj *objResultPtr = iPtr->objResultPtr; if (Tcl_IsShared(objResultPtr)) { TclDecrRefCount(objResultPtr); diff --git a/generic/tclScan.c b/generic/tclScan.c index 74ec2da..0d869b7 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -10,7 +10,7 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tclTomMath.h" /* * Flag values used by Tcl_ScanObjCmd. @@ -261,11 +261,11 @@ ValidateFormat( Tcl_UniChar ch = 0; int objIndex, xpgSize, nspace = numVars; int *nassign = TclStackAlloc(interp, nspace * sizeof(int)); - char buf[TCL_UTF_MAX + 1] = ""; Tcl_Obj *errorMsg; /* Place to build an error messages. Note that * these are messy operations because we do * not want to use the formatting engine; * we're inside there! */ + char buf[TCL_UTF_MAX + 1] = ""; /* * Initialize an array that records the number of times a variable is @@ -363,8 +363,10 @@ ValidateFormat( format += TclUtfToUniChar(format, &ch); break; } + /* FALLTHRU */ case 'L': flags |= SCAN_LONGER; + /* FALLTHRU */ case 'h': format += TclUtfToUniChar(format, &ch); } @@ -386,9 +388,7 @@ ValidateFormat( Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", NULL); goto error; } - /* - * Fall through! - */ + /* FALLTHRU */ case 'n': case 's': if (flags & (SCAN_LONGER|SCAN_BIG)) { @@ -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, @@ -703,11 +700,10 @@ Tcl_ScanObjCmd( format += TclUtfToUniChar(format, &ch); break; } + /* FALLTHRU */ case 'L': flags |= SCAN_LONGER; - /* - * Fall through so we skip to the next character. - */ + /* FALLTHRU */ case 'h': format += TclUtfToUniChar(format, &ch); } @@ -932,8 +928,15 @@ 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_u64(&big, (Tcl_WideUInt)wideValue) != MP_OKAY) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "insufficient memory to create bignum", -1)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + return TCL_ERROR; + } else { + Tcl_SetBignumObj(objPtr, &big); + } } else { TclSetIntObj(objPtr, wideValue); } @@ -943,7 +946,7 @@ Tcl_ScanObjCmd( int code = Tcl_GetBignumFromObj(interp, objPtr, &big); if (code == TCL_OK) { - if (big.sign != MP_ZPOS) { + if (mp_isneg(&big)) { code = TCL_ERROR; } mp_clear(&big); @@ -970,8 +973,19 @@ 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_u64(&big, (unsigned long)value) != MP_OKAY) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "insufficient memory to create bignum", -1)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + return TCL_ERROR; + } else { + 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 e7cb2c5..236fe59 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -14,7 +14,7 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tclTomMath.h" #include <math.h> /* @@ -145,7 +145,7 @@ typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); #define QUICK_MAX 14 /* floor((FP_PRECISION-1)*log(2)/log(10))-1 */ #define BLETCH 0x10 /* Highest power of two that is greater than * DBL_MAX_10_EXP, divided by 16. */ -#define DIGIT_GROUP 8 /* floor(DIGIT_BIT*log(2)/log(10)) */ +#define DIGIT_GROUP 8 /* floor(MP_DIGIT_BIT*log(2)/log(10)) */ /* * Union used to dismantle floating point numbers. @@ -289,10 +289,10 @@ static const Tcl_WideUInt wuipow5[27] = { static int AccumulateDecimalDigit(unsigned, int, Tcl_WideUInt *, mp_int *, int); static double MakeHighPrecisionDouble(int signum, - mp_int *significand, int nSigDigs, int exponent); + mp_int *significand, int nSigDigs, long exponent); static double MakeLowPrecisionDouble(int signum, Tcl_WideUInt significand, int nSigDigs, - int exponent); + long exponent); #ifdef IEEE_FLOATING_POINT static double MakeNaN(int signum, Tcl_WideUInt tag); #endif @@ -711,7 +711,7 @@ TclParseNumber( || (octalSignificandWide > ((Tcl_WideUInt)-1 >> shift)))) { octalSignificandOverflow = 1; - TclInitBignumFromWideUInt(&octalSignificandBig, + mp_init_u64(&octalSignificandBig, octalSignificandWide); } } @@ -828,7 +828,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - TclInitBignumFromWideUInt(&significandBig, + mp_init_u64(&significandBig, significandWide); } } @@ -847,6 +847,7 @@ TclParseNumber( acceptState = state; acceptPoint = p; acceptLen = len; + /* FALLTHRU */ case ZERO_B: zerob: if (c == '0') { @@ -869,7 +870,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - TclInitBignumFromWideUInt(&significandBig, + mp_init_u64(&significandBig, significandWide); } } @@ -1214,7 +1215,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - TclInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_u64(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { @@ -1235,7 +1236,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - TclInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_u64(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { @@ -1256,7 +1257,7 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || octalSignificandWide > (MOST_BITS + signum) >> shift)) { octalSignificandOverflow = 1; - TclInitBignumFromWideUInt(&octalSignificandBig, + mp_init_u64(&octalSignificandBig, octalSignificandWide); } if (shift) { @@ -1269,7 +1270,7 @@ TclParseNumber( } if (!octalSignificandOverflow) { if (octalSignificandWide > (MOST_BITS + signum)) { - TclInitBignumFromWideUInt(&octalSignificandBig, + mp_init_u64(&octalSignificandBig, octalSignificandWide); octalSignificandOverflow = 1; } else { @@ -1285,7 +1286,7 @@ TclParseNumber( } if (octalSignificandOverflow) { if (signum) { - mp_neg(&octalSignificandBig, &octalSignificandBig); + (void)mp_neg(&octalSignificandBig, &octalSignificandBig); } TclSetBignumIntRep(objPtr, &octalSignificandBig); } @@ -1297,12 +1298,12 @@ TclParseNumber( &significandWide, &significandBig, significandOverflow); if (!significandOverflow && (significandWide > MOST_BITS+signum)){ significandOverflow = 1; - TclInitBignumFromWideUInt(&significandBig, significandWide); + mp_init_u64(&significandBig, significandWide); } returnInteger: if (!significandOverflow) { if (significandWide > MOST_BITS+signum) { - TclInitBignumFromWideUInt(&significandBig, + mp_init_u64(&significandBig, significandWide); significandOverflow = 1; } else { @@ -1318,7 +1319,7 @@ TclParseNumber( } if (significandOverflow) { if (signum) { - mp_neg(&significandBig, &significandBig); + (void)mp_neg(&significandBig, &significandBig); } TclSetBignumIntRep(objPtr, &significandBig); } @@ -1337,16 +1338,45 @@ TclParseNumber( objPtr->typePtr = &tclDoubleType; if (exponentSignum) { + /* + * At this point exponent>=0, so the following calculation + * cannot underflow. + */ exponent = -exponent; } + + /* + * Adjust the exponent for the number of trailing zeros that + * have not been accumulated, and the number of digits after + * the decimal point. Pin any overflow to LONG_MAX/LONG_MIN + * respectively. + */ + + if (exponent >= 0) { + if (exponent - numDigitsAfterDp > LONG_MAX - numTrailZeros) { + exponent = LONG_MAX; + } else { + exponent = exponent - numDigitsAfterDp + numTrailZeros; + } + } else { + if (exponent + numTrailZeros < LONG_MIN + numDigitsAfterDp) { + exponent = LONG_MIN; + } else { + exponent = exponent + numTrailZeros - numDigitsAfterDp; + } + } + + /* + * The desired number is now significandWide * 10**exponent + * or significandBig * 10**exponent, depending on whether + * the significand has overflowed a wide int. + */ if (!significandOverflow) { objPtr->internalRep.doubleValue = MakeLowPrecisionDouble( - signum, significandWide, numSigDigs, - numTrailZeros + exponent - numDigitsAfterDp); + signum, significandWide, numSigDigs, exponent); } else { objPtr->internalRep.doubleValue = MakeHighPrecisionDouble( - signum, &significandBig, numSigDigs, - numTrailZeros + exponent - numDigitsAfterDp); + signum, &significandBig, numSigDigs, exponent); } break; @@ -1457,7 +1487,7 @@ AccumulateDecimalDigit( * bignum and fall through into the bignum case. */ - TclInitBignumFromWideUInt(bignumRepPtr, w); + mp_init_u64(bignumRepPtr, w); } else { /* * Wide multiplication. @@ -1485,9 +1515,9 @@ AccumulateDecimalDigit( * More than single digit multiplication. Multiply by the appropriate * small powers of 5, and then shift. Large strings of zeroes are * eaten 256 at a time; this is less efficient than it could be, but - * seems implausible. We presume that DIGIT_BIT is at least 27. The + * seems implausible. We presume that MP_DIGIT_BIT is at least 27. The * first multiplication, by up to 10**7, is done with a one-DIGIT - * multiply (this presumes that DIGIT_BIT >= 24). + * multiply (this presumes that MP_DIGIT_BIT >= 24). */ n = numZeros + 1; @@ -1530,9 +1560,9 @@ AccumulateDecimalDigit( static double MakeLowPrecisionDouble( int signum, /* 1 if the number is negative, 0 otherwise */ - Tcl_WideUInt significand, /* Significand of the number. */ - int numSigDigs, /* Number of digits in the significand. */ - int exponent) /* Power of ten. */ + Tcl_WideUInt significand, /* Significand of the number */ + int numSigDigs, /* Number of digits in the significand */ + long exponent) /* Power of ten */ { double retval; /* Value of the number. */ mp_int significandBig; /* Significand expressed as a bignum. */ @@ -1551,6 +1581,9 @@ MakeLowPrecisionDouble( * Test for the easy cases. */ + if (significand == 0) { + return copysign(0.0, -signum); + } if (numSigDigs <= QUICK_MAX) { if (exponent >= 0) { if (exponent <= mmaxpow) { @@ -1600,7 +1633,7 @@ MakeLowPrecisionDouble( * call MakeHighPrecisionDouble to do it the hard way. */ - TclInitBignumFromWideUInt(&significandBig, significand); + mp_init_u64(&significandBig, significand); retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs, exponent); mp_clear(&significandBig); @@ -1643,10 +1676,10 @@ MakeLowPrecisionDouble( static double MakeHighPrecisionDouble( - int signum, /* 1=negative, 0=nonnegative. */ - mp_int *significand, /* Exact significand of the number. */ - int numSigDigs, /* Number of significant digits. */ - int exponent) /* Power of 10 by which to multiply. */ + int signum, /* 1=negative, 0=nonnegative */ + mp_int *significand, /* Exact significand of the number */ + int numSigDigs, /* Number of significant digits */ + long exponent) /* Power of 10 by which to multiply */ { double retval; int machexp; /* Machine exponent of a power of 10. */ @@ -1662,15 +1695,18 @@ MakeHighPrecisionDouble( TCL_IEEE_DOUBLE_ROUNDING; /* - * Quick checks for over/underflow. + * Quick checks for zero, and over/underflow. Be careful to avoid + * integer overflow when calculating with 'exponent'. */ - if (numSigDigs+exponent-1 > maxDigits) { + if (mp_iszero(significand)) { + return copysign(0.0, -signum); + } + if (exponent >= 0 && exponent-1 > maxDigits-numSigDigs) { retval = HUGE_VAL; goto returnValue; - } - if (numSigDigs+exponent-1 < minDigits) { - retval = 0; + } else if (exponent < 0 && numSigDigs+exponent < minDigits+1) { + retval = 0.0; goto returnValue; } @@ -1805,6 +1841,9 @@ RefineApproximation( * "round to even" functionality */ double rteSignificand; /* Significand of the round-to-even result */ int rteExponent; /* Exponent of the round-to-even result */ + int shift; /* Shift count for converting numerator + * and denominator of corrector to floating + * point */ Tcl_WideInt rteSigWide; /* Wide integer version of the significand * for testing evenness */ int i; @@ -1817,13 +1856,22 @@ RefineApproximation( if (approxResult == HUGE_VAL) { return approxResult; } + significand = frexp(approxResult, &binExponent); /* - * Find a common denominator for the decimal and binary fractions. The - * common denominator will be 2**M2 + 5**M5. + * We are trying to compute a corrector term that, when added to the + * approximate result, will yield close to the exact result. + * The exact result is exactSignificand * 10**exponent. + * The approximate result is significand * 2**binExponent + * If exponent<0, we need to multiply the exact value by 10**-exponent + * to make it an integer, plus another factor of 2 to decide on rounding. + * Similarly if binExponent<FP_PRECISION, we need + * to multiply by 2**FP_PRECISION to make the approximate value an integer. + * + * Let M = 2**M2 * 5**M5 be the least common multiple of these two + * multipliers. */ - significand = frexp(approxResult, &binExponent); i = mantBits - binExponent; if (i < 0) { M2 = 0; @@ -1840,24 +1888,21 @@ RefineApproximation( } /* - * The floating point number is significand*2**binExponent. Compute the - * large integer significand*2**(binExponent+M2+1). The 2**-1 bit of the - * significand (the most significant) corresponds to the - * 2**(binExponent+M2 + 1) bit of 2*M2*v. Allocate enough digits to hold - * that quantity, then convert the significand to a large integer, scaled - * appropriately. Then multiply by the appropriate power of 5. + * Compute twoMv as 2*M*v, where v is the approximate value. + * This is done by bit-whacking to calculate 2**(M2+1)*significand, + * and then multiplying by 5**M5. */ msb = binExponent + M2; /* 1008 */ - nDigits = msb / DIGIT_BIT + 1; + nDigits = msb / MP_DIGIT_BIT + 1; mp_init_size(&twoMv, nDigits); - i = (msb % DIGIT_BIT + 1); + i = (msb % MP_DIGIT_BIT + 1); twoMv.used = nDigits; significand *= SafeLdExp(1.0, i); while (--nDigits >= 0) { twoMv.dp[nDigits] = (mp_digit) significand; significand -= (mp_digit) significand; - significand = SafeLdExp(significand, DIGIT_BIT); + significand = SafeLdExp(significand, MP_DIGIT_BIT); } for (i = 0; i <= 8; ++i) { if (M5 & (1 << i)) { @@ -1866,10 +1911,9 @@ RefineApproximation( } /* - * Collect the decimal significand as a high precision integer. The least - * significant bit corresponds to bit M2+exponent+1 so it will need to be - * shifted left by that many bits after being multiplied by - * 5**(M5+exponent). + * Compute twoMd as 2*M*d, where d is the exact value. + * This is done by multiplying by 5**(M5+exponent) and then multiplying + * by 2**(M5+exponent+1), which is, of couse, a left shift. */ mp_init_copy(&twoMd, exactSignificand); @@ -1879,17 +1923,23 @@ RefineApproximation( } } mp_mul_2d(&twoMd, M2+exponent+1, &twoMd); + + /* + * Now let twoMd = twoMd - twoMv, the difference between the exact and + * approximate values. + */ + mp_sub(&twoMd, &twoMv, &twoMd); /* * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction * term. Because 2M may well overflow a double, we need to scale the - * denominator by a factor of 2**binExponent-mantBits. + * denominator by a factor of 2**binExponent-mantBits. Place that factor + * times 1/2 ULP into twoMd. */ scale = binExponent - mantBits - 1; - - mp_set(&twoMv, 1); + mp_set_u64(&twoMv, 1); for (i=0; i<=8; ++i) { if (M5 & (1 << i)) { mp_mul(&twoMv, pow5+i, &twoMv); @@ -1902,25 +1952,36 @@ RefineApproximation( mp_div_2d(&twoMv, -multiplier, &twoMv, NULL); } + /* + * Will the eventual correction term be less than, equal to, or + * greater than 1/2 ULP? + */ + switch (mp_cmp_mag(&twoMd, &twoMv)) { case MP_LT: /* - * If the result is less than unity, the error is less than 1/2 unit in - * the last place, so there's no correction to make. + * If the error is less than 1/2 ULP, there's no correction to make. */ mp_clear(&twoMd); mp_clear(&twoMv); return approxResult; case MP_EQ: /* - * If the result is exactly unity, we need to round to even. + * If the error is exactly 1/2 ULP, we need to round to even. */ roundToEven = 1; break; case MP_GT: + /* + * We need to correct the result if the error exceeds 1/2 ULP. + */ break; } + /* + * If we're in the 'round to even' case, and the significand is already + * even, we're done. Return the approximate result. + */ if (roundToEven) { rteSignificand = frexp(approxResult, &rteExponent); rteSigWide = (Tcl_WideInt) ldexp(rteSignificand, FP_PRECISION); @@ -1931,6 +1992,16 @@ RefineApproximation( } } + /* + * Reduce the numerator and denominator of the corrector term so that + * they will fit in the floating point precision. + */ + shift = mp_count_bits(&twoMv) - FP_PRECISION - 1; + if (shift > 0) { + mp_div_2d(&twoMv, shift, &twoMv, NULL); + mp_div_2d(&twoMd, shift, &twoMd, NULL); + } + /* * Convert the numerator and denominator of the corrector term accurately * to floating point numbers. @@ -2724,7 +2795,7 @@ QuickConversion( int k, /* floor(log10(d)), approximately. */ int k_check, /* 0 if k is exact, 1 if it may be too high */ int flags, /* Flags passed to dtoa: - * TCL_DD_SHORTEN_FLAG */ + * TCL_DD_SHORTEST */ int len, /* Length of the return value. */ int ilim, /* Number of digits to store. */ int ilim1, /* Number of digits to store if we misguessed @@ -2795,7 +2866,7 @@ QuickConversion( * Format the digit string. */ - if (flags & TCL_DD_SHORTEN_FLAG) { + if (flags & TCL_DD_SHORTEST) { end = ShorteningQuickFormat(d, k, ilim, eps.d, retval, decpt); } else { end = StrictQuickFormat(d, k, ilim, eps.d, retval, decpt); @@ -3129,7 +3200,7 @@ StrictInt64Conversion( * * Test whether bankers' rounding should round a digit up. Assumption is * made that the denominator of the fraction being tested is a power of - * 2**DIGIT_BIT. + * 2**MP_DIGIT_BIT. * * Results: * Returns 1 iff the fraction is more than 1/2, or if the fraction is @@ -3141,11 +3212,11 @@ StrictInt64Conversion( static inline int ShouldBankerRoundUpPowD( mp_int *b, /* Numerator of the fraction. */ - int sd, /* Denominator is 2**(sd*DIGIT_BIT). */ + int sd, /* Denominator is 2**(sd*MP_DIGIT_BIT). */ int isodd) /* 1 if the digit is odd, 0 if even. */ { int i; - static const mp_digit topbit = ((mp_digit)1) << (DIGIT_BIT - 1); + static const mp_digit topbit = ((mp_digit)1) << (MP_DIGIT_BIT - 1); if (b->used < sd || (b->dp[sd-1] & topbit) == 0) { return 0; @@ -3180,7 +3251,7 @@ static inline int ShouldBankerRoundUpToNextPowD( mp_int *b, /* Numerator of the fraction. */ mp_int *m, /* Numerator of the rounding tolerance. */ - int sd, /* Common denominator is 2**(sd*DIGIT_BIT). */ + int sd, /* Common denominator is 2**(sd*MP_DIGIT_BIT). */ int isodd, /* 1 if the integer significand is odd. */ mp_int *temp) /* Work area for the calculation. */ { @@ -3189,7 +3260,7 @@ ShouldBankerRoundUpToNextPowD( /* * Compare B and S-m - which is the same as comparing B+m and S - which we * do by computing b+m and doing a bitwhack compare against - * 2**(DIGIT_BIT*sd) + * 2**(MP_DIGIT_BIT*sd) */ mp_add(b, m, temp); @@ -3217,7 +3288,7 @@ ShouldBankerRoundUpToNextPowD( * Converts a double-precision number to the shortest string of digits * that reconverts exactly to the given number, or to 'ilim' digits if * that will yield a shorter result. The denominator in David Gay's - * conversion algorithm is known to be a power of 2**DIGIT_BIT, and hence + * conversion algorithm is known to be a power of 2**MP_DIGIT_BIT, and hence * the division in the main loop may be replaced by a digit shift and * mask. * @@ -3267,8 +3338,8 @@ ShorteningBignumConversionPowD( * mminus = 5**m5 */ - TclInitBignumFromWideUInt(&b, bw); - mp_init_set_int(&mminus, 1); + mp_init_u64(&b, bw); + mp_init_set(&mminus, 1); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); @@ -3297,7 +3368,7 @@ ShorteningBignumConversionPowD( mp_init(&temp); /* - * Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT) + * Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT) * by mp_digit extraction. */ @@ -3409,7 +3480,7 @@ ShorteningBignumConversionPowD( * Converts a double-precision number to a fixed-lengt string of 'ilim' * digits (or 'ilim1' if log10(d) has been overestimated). The * denominator in David Gay's conversion algorithm is known to be a power - * of 2**DIGIT_BIT, and hence the division in the main loop may be + * of 2**MP_DIGIT_BIT, and hence the division in the main loop may be * replaced by a digit shift and mask. * * Results: @@ -3451,7 +3522,7 @@ StrictBignumConversionPowD( * b = bw * 2**b2 * 5**b5 */ - TclInitBignumFromWideUInt(&b, bw); + mp_init_u64(&b, bw); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); @@ -3466,7 +3537,7 @@ StrictBignumConversionPowD( } /* - * Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT) + * Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT) * by mp_digit extraction. */ @@ -3651,9 +3722,9 @@ ShorteningBignumConversion( * S = 2**s2 * 5*s5 */ - TclInitBignumFromWideUInt(&b, bw); + mp_init_u64(&b, bw); mp_mul_2d(&b, b2, &b); - mp_init_set_int(&S, 1); + mp_init_set(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); /* @@ -3671,7 +3742,7 @@ ShorteningBignumConversion( * mminus = 2**m2minus * 5**m5 */ - mp_init_set_int(&mminus, minit); + mp_init_set(&mminus, minit); mp_mul_2d(&mminus, m2minus, &mminus); if (m2plus > m2minus) { mp_init_copy(&mplus, &mminus); @@ -3860,9 +3931,9 @@ StrictBignumConversion( */ mp_init_multi(&dig, NULL); - TclInitBignumFromWideUInt(&b, bw); + mp_init_u64(&b, bw); mp_mul_2d(&b, b2, &b); - mp_init_set_int(&S, 1); + mp_init_set(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); /* @@ -4008,7 +4079,7 @@ StrictBignumConversion( * choosing the one that is closest to the given number (and * resolving ties with 'round to even'). It is allowed to return * fewer than 'ndigits' if the number converts exactly; if the - * TCL_DD_E_FORMAT|TCL_DD_SHORTEN_FLAG is supplied instead, it + * TCL_DD_E_FORMAT|TCL_DD_SHORTEST is supplied instead, it * also returns fewer digits if the shorter string will still * reconvert without loss to the given input number. In any case, * strings of trailing zeroes are suppressed. @@ -4019,7 +4090,7 @@ StrictBignumConversion( * string if the number is sufficiently small. Again, it is * permissible for TCL_DD_F_FORMAT to return fewer digits for a * number that converts exactly, and changing the argument to - * TCL_DD_F_FORMAT|TCL_DD_SHORTEN_FLAG will allow the routine + * TCL_DD_F_FORMAT|TCL_DD_SHORTEST will allow the routine * also to return fewer digits if the shorter string will still * reconvert without loss to the given input number. Strings of * trailing zeroes are suppressed. @@ -4156,7 +4227,7 @@ TclDoubleDigits( * denominator. */ - if (flags & TCL_DD_SHORTEN_FLAG) { + if (flags & TCL_DD_SHORTEST) { int m2minus = b2; int m2plus; int m5 = b5; @@ -4208,14 +4279,14 @@ TclDoubleDigits( } else if (s5 == 0) { /* * The denominator is a power of 2, so we can replace division by - * digit shifts. First we round up s2 to a multiple of DIGIT_BIT, + * digit shifts. First we round up s2 to a multiple of MP_DIGIT_BIT, * and adjust m2 and b2 accordingly. Then we launch into a version * of the comparison that's specialized for the 'power of mp_digit * in the denominator' case. */ - if (s2 % DIGIT_BIT != 0) { - int delta = DIGIT_BIT - (s2 % DIGIT_BIT); + if (s2 % MP_DIGIT_BIT != 0) { + int delta = MP_DIGIT_BIT - (s2 % MP_DIGIT_BIT); b2 += delta; m2plus += delta; @@ -4223,7 +4294,7 @@ TclDoubleDigits( s2 += delta; } return ShorteningBignumConversionPowD(&d, bw, b2, b5, - m2plus, m2minus, m5, s2/DIGIT_BIT, k, len, ilim, ilim1, + m2plus, m2minus, m5, s2/MP_DIGIT_BIT, k, len, ilim, ilim1, decpt, endPtr); } else { /* @@ -4264,20 +4335,20 @@ TclDoubleDigits( } else if (s5 == 0) { /* * The denominator is a power of 2, so we can replace division by - * digit shifts. First we round up s2 to a multiple of DIGIT_BIT, + * digit shifts. First we round up s2 to a multiple of MP_DIGIT_BIT, * and adjust m2 and b2 accordingly. Then we launch into a version * of the comparison that's specialized for the 'power of mp_digit * in the denominator' case. */ - if (s2 % DIGIT_BIT != 0) { - int delta = DIGIT_BIT - (s2 % DIGIT_BIT); + if (s2 % MP_DIGIT_BIT != 0) { + int delta = MP_DIGIT_BIT - (s2 % MP_DIGIT_BIT); b2 += delta; s2 += delta; } return StrictBignumConversionPowD(&d, bw, b2, b5, - s2/DIGIT_BIT, k, len, ilim, ilim1, decpt, endPtr); + s2/MP_DIGIT_BIT, k, len, ilim, ilim1, decpt, endPtr); } else { /* * There are no helpful special cases, but at least we know in @@ -4381,11 +4452,11 @@ TclInitDoubleConversion(void) for (i=0; i<9; ++i) { mp_init(pow5 + i); } - mp_set(pow5, 5); + mp_set_u64(pow5, 5); for (i=0; i<8; ++i) { mp_sqr(pow5+i, pow5+i+1); } - mp_init_set_int(pow5_13, 1220703125); + mp_init_u64(pow5_13, 1220703125); for (i = 1; i < 5; ++i) { mp_init(pow5_13 + i); mp_sqr(pow5_13 + i - 1, pow5_13 + i); @@ -4402,7 +4473,7 @@ TclInitDoubleConversion(void) + 0.5 * log(10.)) / log(10.)); minDigits = (int) floor((DBL_MIN_EXP - DBL_MANT_DIG) * log((double) FLT_RADIX) / log(10.)); - log10_DIGIT_MAX = (int) floor(DIGIT_BIT * log(2.) / log(10.)); + log10_DIGIT_MAX = (int) floor(MP_DIGIT_BIT * log(2.) / log(10.)); /* * Nokia 770's software-emulated floating point is "middle endian": the @@ -4503,7 +4574,7 @@ Tcl_InitBignumFromDouble( Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits); int shift = expt - mantBits; - TclInitBignumFromWideInt(b, w); + mp_init_i64(b, w); if (shift < 0) { mp_div_2d(b, -shift, b, NULL); } else if (shift > 0) { @@ -4545,10 +4616,10 @@ TclBignumToDouble( bits = mp_count_bits(a); if (bits > DBL_MAX_EXP*log2FLT_RADIX) { errno = ERANGE; - if (a->sign == MP_ZPOS) { - return HUGE_VAL; - } else { + if (mp_isneg(a)) { return -HUGE_VAL; + } else { + return HUGE_VAL; } } shift = mantBits - bits; @@ -4577,11 +4648,11 @@ TclBignumToDouble( */ mp_div_2d(a, -shift, &b, NULL); - if (mp_get_bit(&b, 0)) { - if (b.sign == MP_ZPOS) { - mp_add_d(&b, 1, &b); - } else { + if (mp_isodd(&b)) { + if (mp_isneg(&b)) { mp_sub_d(&b, 1, &b); + } else { + mp_add_d(&b, 1, &b); } } } else { @@ -4591,10 +4662,10 @@ TclBignumToDouble( */ mp_div_2d(a, -1-shift, &b, NULL); - if (b.sign == MP_ZPOS) { - mp_add_d(&b, 1, &b); - } else { + if (mp_isneg(&b)) { mp_sub_d(&b, 1, &b); + } else { + mp_add_d(&b, 1, &b); } mp_div_2d(&b, 1, &b, NULL); } @@ -4606,7 +4677,7 @@ TclBignumToDouble( r = 0.0; for (i=b.used-1 ; i>=0 ; --i) { - r = ldexp(r, DIGIT_BIT) + b.dp[i]; + r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; } mp_clear(&b); @@ -4620,10 +4691,10 @@ TclBignumToDouble( * Return the result with the appropriate sign. */ - if (a->sign == MP_ZPOS) { - return r; - } else { + if (mp_isneg(a)) { return -r; + } else { + return r; } } @@ -4649,7 +4720,7 @@ TclCeil( mp_int b; mp_init(&b); - if (a->sign != MP_ZPOS) { + if (mp_isneg(a)) { mp_neg(a, &b); r = -TclFloor(&b); } else { @@ -4675,7 +4746,7 @@ TclCeil( mp_add_d(&b, 1, &b); } for (i=b.used-1 ; i>=0 ; --i) { - r = ldexp(r, DIGIT_BIT) + b.dp[i]; + r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; } r = ldexp(r, bits - mantBits); } @@ -4706,7 +4777,7 @@ TclFloor( mp_int b; mp_init(&b); - if (a->sign != MP_ZPOS) { + if (mp_isneg(a)) { mp_neg(a, &b); r = -TclCeil(&b); } else { @@ -4725,7 +4796,7 @@ TclFloor( mp_copy(a, &b); } for (i=b.used-1 ; i>=0 ; --i) { - r = ldexp(r, DIGIT_BIT) + b.dp[i]; + r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; } r = ldexp(r, bits - mantBits); } @@ -4787,7 +4858,7 @@ BignumToBiasedFrExp( r = 0.0; for (i=b.used-1; i>=0; --i) { - r = ldexp(r, DIGIT_BIT) + b.dp[i]; + r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; } mp_clear(&b); @@ -4796,7 +4867,7 @@ BignumToBiasedFrExp( */ *machexp = bits - mantBits + 2; - return ((a->sign == MP_ZPOS) ? r : -r); + return (mp_isneg(a) ? -r : r); } /* diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 6652f15..eed49b1 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -35,7 +35,7 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tclTomMath.h" #include "tclStringRep.h" #include "assert.h" @@ -2059,6 +2059,7 @@ Tcl_AppendFormatToObj( } case 'u': + /* FALLTHRU */ case 'd': case 'o': case 'p': @@ -2270,11 +2271,11 @@ Tcl_AppendFormatToObj( } #endif } else if (useBig && big.used) { - int leftover = (big.used * DIGIT_BIT) % numBits; - mp_digit mask = (~(mp_digit)0) << (DIGIT_BIT-leftover); + int leftover = (big.used * MP_DIGIT_BIT) % numBits; + mp_digit mask = (~(mp_digit)0) << (MP_DIGIT_BIT-leftover); numDigits = 1 + - (((Tcl_WideInt) big.used * DIGIT_BIT) / numBits); + (((Tcl_WideInt) big.used * MP_DIGIT_BIT) / numBits); while ((mask & big.dp[big.used-1]) == 0) { numDigits--; mask >>= numBits; @@ -2310,9 +2311,9 @@ Tcl_AppendFormatToObj( if (useBig && big.used) { if (index < big.used && (size_t) shift < - CHAR_BIT*sizeof(Tcl_WideUInt) - DIGIT_BIT) { + CHAR_BIT*sizeof(Tcl_WideUInt) - MP_DIGIT_BIT) { bits |= ((Tcl_WideUInt) big.dp[index++]) << shift; - shift += DIGIT_BIT; + shift += MP_DIGIT_BIT; } shift -= numBits; } @@ -2718,6 +2719,7 @@ AppendPrintfToObjVA( break; case 'h': size = -1; + /* FALLTHRU */ default: p++; } @@ -3563,7 +3565,7 @@ TclStringFirst( } if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) { - unsigned char *end, *try, *bh; + unsigned char *end, *check, *bh; unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln); /* Find bytes in bytes */ @@ -3574,25 +3576,25 @@ TclStringFirst( } end = bh + lh; - try = bh + start; - while (try + ln <= end) { + check = bh + start; + while (check + ln <= end) { /* * Look for the leading byte of the needle in the haystack - * starting at try and stopping when there's not enough room + * starting at check and stopping when there's not enough room * for the needle left. */ - try = memchr(try, bn[0], (end + 1 - ln) - try); - if (try == NULL) { + check = memchr(check, bn[0], (end + 1 - ln) - check); + if (check == NULL) { /* Leading byte not found -> needle cannot be found. */ return -1; } /* Leading byte found, check rest of needle. */ - if (0 == memcmp(try+1, bn+1, ln-1)) { + if (0 == memcmp(check+1, bn+1, ln-1)) { /* Checks! Return the successful index. */ - return (try - bh); + return (check - bh); } /* Rest of needle match failed; Iterate to continue search. */ - try++; + check++; } return -1; } @@ -3610,7 +3612,7 @@ TclStringFirst( */ { - Tcl_UniChar *try, *end, *uh; + Tcl_UniChar *check, *end, *uh; Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln); uh = Tcl_GetUnicodeFromObj(haystack, &lh); @@ -3620,10 +3622,10 @@ TclStringFirst( } end = uh + lh; - for (try = uh + start; try + ln <= end; try++) { - if ((*try == *un) && (0 == - memcmp(try + 1, un + 1, (ln-1) * sizeof(Tcl_UniChar)))) { - return (try - uh); + for (check = uh + start; check + ln <= end; check++) { + if ((*check == *un) && (0 == + memcmp(check + 1, un + 1, (ln-1) * sizeof(Tcl_UniChar)))) { + return (check - uh); } } return -1; @@ -3667,7 +3669,7 @@ TclStringLast( } if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) { - unsigned char *try, *bh = Tcl_GetByteArrayFromObj(haystack, &lh); + unsigned char *check, *bh = Tcl_GetByteArrayFromObj(haystack, &lh); unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln); if (last >= lh) { @@ -3677,20 +3679,20 @@ TclStringLast( /* Don't start the loop if there cannot be a valid answer */ return -1; } - try = bh + last + 1 - ln; + check = bh + last + 1 - ln; - while (try >= bh) { - if ((*try == bn[0]) - && (0 == memcmp(try+1, bn+1, ln-1))) { - return (try - bh); + while (check >= bh) { + if ((*check == bn[0]) + && (0 == memcmp(check+1, bn+1, ln-1))) { + return (check - bh); } - try--; + check--; } return -1; } { - Tcl_UniChar *try, *uh = Tcl_GetUnicodeFromObj(haystack, &lh); + Tcl_UniChar *check, *uh = Tcl_GetUnicodeFromObj(haystack, &lh); Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln); if (last >= lh) { @@ -3700,13 +3702,13 @@ TclStringLast( /* Don't start the loop if there cannot be a valid answer */ return -1; } - try = uh + last + 1 - ln; - while (try >= uh) { - if ((*try == un[0]) - && (0 == memcmp(try+1, un+1, (ln-1)*sizeof(Tcl_UniChar)))) { - return (try - uh); + check = uh + last + 1 - ln; + while (check >= uh) { + if ((*check == un[0]) + && (0 == memcmp(check+1, un+1, (ln-1)*sizeof(Tcl_UniChar)))) { + return (check - uh); } - try--; + check--; } return -1; } diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 8945e0b..6983113 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -10,7 +10,8 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tommath_private.h" +#include "tclTomMath.h" #ifdef __CYGWIN__ # include <wchar.h> @@ -57,9 +58,75 @@ #undef TclWinSetSockOpt #undef TclWinNToHS #undef TclStaticPackage -#undef TclBNInitBignumFromLong #undef Tcl_BackgroundError #define TclStaticPackage Tcl_StaticPackage +#undef Tcl_UniCharToUtfDString +#undef Tcl_UtfToUniCharDString +#undef Tcl_UtfToUniChar + +#define TclBN_mp_add mp_add +#define TclBN_mp_and mp_and +#define TclBN_mp_clamp mp_clamp +#define TclBN_mp_clear mp_clear +#define TclBN_mp_clear_multi mp_clear_multi +#define TclBN_mp_cmp mp_cmp +#define TclBN_mp_cmp_mag mp_cmp_mag +#define TclBN_mp_cnt_lsb mp_cnt_lsb +#define TclBN_mp_copy mp_copy +#define TclBN_mp_count_bits mp_count_bits +#define TclBN_mp_div mp_div +#define TclBN_mp_div_2 mp_div_2 +#define TclBN_mp_div_2d mp_div_2d +#define TclBN_mp_exch mp_exch +#define TclBN_mp_get_mag_u64 mp_get_mag_u64 +#define TclBN_mp_grow mp_grow +#define TclBN_mp_init mp_init +#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_i64 mp_init_i64 +#define TclBN_mp_init_u64 mp_init_u64 +#define TclBN_mp_lshd mp_lshd +#define TclBN_mp_mod mp_mod +#define TclBN_mp_mod_2d mp_mod_2d +#define TclBN_mp_mul mp_mul +#define TclBN_mp_mul_2 mp_mul_2 +#define TclBN_mp_mul_2d mp_mul_2d +#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_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 TclBN_mp_and +#define TclBN_mp_tc_div_2d mp_signed_rsh +#define TclBN_mp_tc_or TclBN_mp_or +#define TclBN_mp_tc_xor TclBN_mp_xor +#define TclBN_mp_to_radix mp_to_radix +#define TclBN_mp_to_ubin mp_to_ubin +#define TclBN_mp_ubin_size mp_ubin_size +#define TclBN_mp_xor mp_xor +#define TclBN_mp_zero mp_zero +#define TclBN_s_mp_add s_mp_add +#define TclBN_s_mp_balance_mul mp_balance_mul +#define TclBN_mp_karatsuba_mul s_mp_karatsuba_mul +#define TclBN_mp_karatsuba_sqr s_mp_karatsuba_sqr +#define TclBN_s_mp_mul_digs s_mp_mul_digs +#define TclBN_s_mp_mul_digs_fast s_mp_mul_digs_fast +#define TclBN_s_mp_reverse s_mp_reverse +#define TclBN_s_mp_sqr s_mp_sqr +#define TclBN_s_mp_sqr_fast s_mp_sqr_fast +#define TclBN_s_mp_sub s_mp_sub +#define TclBN_mp_toom_mul s_mp_toom_mul +#define TclBN_mp_toom_sqr s_mp_toom_sqr + /* See bug 510001: TclSockMinimumBuffers needs plat imp */ #if defined(_WIN64) || defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 @@ -72,7 +139,72 @@ static int TclSockMinimumBuffersOld(int sock, int size) } #endif +mp_err TclBN_mp_set_int(mp_int *a, unsigned long i) +{ + TclBN_mp_set_u64(a, i); + return MP_OKAY; +} + +static mp_err TclBN_mp_set_long(mp_int *a, unsigned long i) +{ + TclBN_mp_set_u64(a, i); + return MP_OKAY; +} + +#define TclBN_mp_set_ul (void (*)(mp_int *a, unsigned long i))TclBN_mp_set_long + +mp_err MP_WUR TclBN_mp_expt_u32(const mp_int *a, unsigned int b, mp_int *c) { + return mp_expt_u32(a, b, c); +} +mp_err TclBN_mp_add_d(const mp_int *a, unsigned int b, mp_int *c) { + return mp_add_d(a, b, c); +} +mp_err TclBN_mp_cmp_d(const mp_int *a, unsigned int b) { + return mp_cmp_d(a, b); +} +mp_err TclBN_mp_sub_d(const mp_int *a, unsigned int b, mp_int *c) { + return mp_sub_d(a, b, c); +} +mp_err TclBN_mp_div_d(const mp_int *a, unsigned int b, mp_int *c, unsigned int *d) { + mp_digit d2; + mp_err result = mp_div_d(a, b, c, (d ? &d2 : NULL)); + if (d) { + *d = d2; + } + return result; +} +mp_err TclBN_mp_div_ld(const mp_int *a, uint64_t b, mp_int *c, uint64_t *d) { + mp_err result; + mp_digit d2; + + if ((b | (mp_digit)-1) != (mp_digit)-1) { + return MP_VAL; + } + result = mp_div_d(a, b, c, (d ? &d2 : NULL)); + if (d) { + *d = d2; + } + return result; +} +mp_err TclBN_mp_init_set(mp_int *a, unsigned int b) { + return mp_init_set(a, b); +} +mp_err TclBN_mp_mul_d(const mp_int *a, unsigned int b, mp_int *c) { + return mp_mul_d(a, b, c); +} + #if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 +# define TclBN_mp_expt_d_ex 0 +# define TclBN_mp_to_unsigned_bin 0 +# define TclBN_mp_to_unsigned_bin_n 0 +# define TclBN_mp_toradix_n 0 +# undef TclBN_mp_sqr +# define TclBN_mp_sqr 0 +# undef TclBN_mp_div_3 +# define TclBN_mp_div_3 0 +# define TclBN_mp_init_l 0 +# define TclBN_mp_init_ul 0 +# define TclBN_mp_set 0 # define TclSetStartupScriptPath 0 # define TclGetStartupScriptPath 0 # define TclSetStartupScriptFileName 0 @@ -87,9 +219,6 @@ static int TclSockMinimumBuffersOld(int sock, int size) # 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 @@ -104,11 +233,65 @@ static int TclSockMinimumBuffersOld(int sock, int size) # define Tcl_DbNewLongObj 0 # define Tcl_BackgroundError 0 #else -#define TclBNInitBignumFromLong initBignumFromLong -static void TclBNInitBignumFromLong(mp_int *a, long b) + +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 TclBN_mp_expt_u32(a, b, c); +} + +mp_err TclBN_mp_to_unsigned_bin(const mp_int *a, unsigned char *b) +{ + 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) { - TclInitBignumFromWideInt(a, b); + size_t n = TclBN_mp_ubin_size(a); + if (*outlen < (unsigned long)n) { + return MP_VAL; + } + *outlen = (unsigned long)n; + return TclBN_mp_to_ubin(a, b, n, NULL); +} + +void TclBN_reverse(unsigned char *s, int len) +{ + if (len > 0) { + TclBN_s_mp_reverse(s, (size_t)len); + } +} + +mp_err TclBN_mp_init_ul(mp_int *a, unsigned long b) +{ + return TclBN_mp_init_u64(a,b); +} + +mp_err TclBN_mp_init_l(mp_int *a, long b) +{ + return TclBN_mp_init_i64(a,b); +} + +void TclBN_mp_set(mp_int *a, unsigned int b) { + TclBN_mp_set_u64(a, b); +} + +mp_err TclBN_mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) +{ + if (maxlen < 0) { + return MP_VAL; + } + return TclBN_mp_to_radix(a, str, (size_t)maxlen, NULL, radix); } + #define TclSetStartupScriptPath setStartupScriptPath static void TclSetStartupScriptPath(Tcl_Obj *path) { @@ -157,8 +340,6 @@ TclWinGetPlatformId(void) #define TclWinResetInterfaces doNothing #define TclWinSetInterfaces (void (*) (int)) doNothing #endif -# define TclBNInitBignumFromWideUInt TclInitBignumFromWideUInt -# define TclBNInitBignumFromWideInt TclInitBignumFromWideInt #endif /* TCL_NO_DEPRECATED */ #ifdef _WIN32 @@ -189,7 +370,7 @@ void *TclWinGetTclInstance() { void *hInstance = NULL; GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (const char *)&TclpIsAtty, &hInstance); + (const wchar_t *)&TclpIsAtty, &hInstance); return hInstance; } @@ -238,6 +419,8 @@ TclpGetPid(Tcl_Pid pid) return (int) (size_t) pid; } +#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 +#undef Tcl_WinUtfToTChar char * Tcl_WinUtfToTChar( const char *string, @@ -245,12 +428,9 @@ Tcl_WinUtfToTChar( Tcl_DString *dsPtr) { Tcl_DStringInit(dsPtr); - if (!string) { - return NULL; - } - return (char *)TclUtfToWCharDString(string, len, dsPtr); + return (char *)Tcl_UtfToChar16DString(string, len, dsPtr); } - +#undef Tcl_WinTCharToUtf char * Tcl_WinTCharToUtf( const char *string, @@ -258,16 +438,9 @@ Tcl_WinTCharToUtf( Tcl_DString *dsPtr) { Tcl_DStringInit(dsPtr); - if (!string) { - return NULL; - } - if (len < 0) { - len = wcslen((wchar_t *)string); - } else { - len /= 2; - } - return TclWCharToUtfDString((const WCHAR *)string, len, dsPtr); + return Tcl_Char16ToUtfDString((const unsigned short *)string, len >> 1, dsPtr); } +#endif /* !defined(TCL_NO_DEPRECATED) */ #if defined(TCL_WIDE_INT_IS_LONG) /* On Cygwin64, long is 64-bit while on Win64 long is 32-bit. Therefore @@ -387,6 +560,7 @@ static int uniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsig # define TclpReaddir 0 # define TclSetStartupScript 0 # define TclGetStartupScript 0 +# define TclGetIntForIndex 0 # define TclCreateNamespace 0 # define TclDeleteNamespace 0 # define TclAppendExportList 0 @@ -417,19 +591,28 @@ static int uniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsig # define Tcl_SetPanicProc 0 # define Tcl_FindExecutable 0 # define Tcl_GetUnicode 0 -# define TclOldFreeObj 0 # undef Tcl_StringMatch # define Tcl_StringMatch 0 # define TclBN_reverse 0 -# define TclBN_fast_s_mp_mul_digs 0 -# define TclBN_fast_s_mp_sqr 0 +# undef TclBN_s_mp_mul_digs_fast +# define TclBN_s_mp_mul_digs_fast 0 +# undef TclBN_s_mp_sqr_fast +# define TclBN_s_mp_sqr_fast 0 +# undef TclBN_mp_karatsuba_mul # define TclBN_mp_karatsuba_mul 0 +# undef TclBN_mp_karatsuba_sqr # define TclBN_mp_karatsuba_sqr 0 +# undef TclBN_mp_toom_mul # define TclBN_mp_toom_mul 0 +# undef TclBN_mp_toom_sqr # define TclBN_mp_toom_sqr 0 +# undef TclBN_s_mp_add # define TclBN_s_mp_add 0 +# undef TclBN_s_mp_mul_digs # define TclBN_s_mp_mul_digs 0 +# undef TclBN_s_mp_sqr # define TclBN_s_mp_sqr 0 +# undef TclBN_s_mp_sub # define TclBN_s_mp_sub 0 #else /* TCL_NO_DEPRECATED */ # define Tcl_SeekOld seekOld @@ -437,6 +620,7 @@ static int uniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsig # define TclBackgroundException Tcl_BackgroundException # define TclSetStartupScript Tcl_SetStartupScript # define TclGetStartupScript Tcl_GetStartupScript +# define TclGetIntForIndex Tcl_GetIntForIndex # define TclCreateNamespace Tcl_CreateNamespace # define TclDeleteNamespace Tcl_DeleteNamespace # define TclAppendExportList Tcl_AppendExportList @@ -451,7 +635,6 @@ static int uniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsig # define TclGetCommandFullName Tcl_GetCommandFullName # define TclpLocaltime_unix TclpLocaltime # define TclpGmtime_unix TclpGmtime -# define TclOldFreeObj TclFreeObj static int seekOld( @@ -470,6 +653,11 @@ tellOld( } #endif /* !TCL_NO_DEPRECATED */ +#if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 +#define Tcl_WinUtfToTChar 0 +#define Tcl_WinTCharToUtf 0 +#endif + /* * WARNING: The contents of this file is automatically generated by the * tools/genStubs.tcl script. Any modifications to the function declarations @@ -751,6 +939,7 @@ static const TclIntStubs tclIntStubs = { TclPtrObjMakeUpvar, /* 255 */ TclPtrUnsetVar, /* 256 */ TclStaticPackage, /* 257 */ + TclpCreateTemporaryDirectory, /* 258 */ }; static const TclIntPlatStubs tclIntPlatStubs = { @@ -892,7 +1081,7 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_mp_div_2d, /* 16 */ TclBN_mp_div_3, /* 17 */ TclBN_mp_exch, /* 18 */ - TclBN_mp_expt_d, /* 19 */ + TclBN_mp_expt_u32, /* 19 */ TclBN_mp_grow, /* 20 */ TclBN_mp_init, /* 21 */ TclBN_mp_init_copy, /* 22 */ @@ -920,12 +1109,12 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_mp_to_unsigned_bin, /* 44 */ TclBN_mp_to_unsigned_bin_n, /* 45 */ TclBN_mp_toradix_n, /* 46 */ - TclBN_mp_unsigned_bin_size, /* 47 */ + TclBN_mp_ubin_size, /* 47 */ TclBN_mp_xor, /* 48 */ TclBN_mp_zero, /* 49 */ TclBN_reverse, /* 50 */ - TclBN_fast_s_mp_mul_digs, /* 51 */ - TclBN_fast_s_mp_sqr, /* 52 */ + TclBN_s_mp_mul_digs_fast, /* 51 */ + TclBN_s_mp_sqr_fast, /* 52 */ TclBN_mp_karatsuba_mul, /* 53 */ TclBN_mp_karatsuba_sqr, /* 54 */ TclBN_mp_toom_mul, /* 55 */ @@ -934,23 +1123,26 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_s_mp_mul_digs, /* 58 */ TclBN_s_mp_sqr, /* 59 */ TclBN_s_mp_sub, /* 60 */ - TclBN_mp_init_set_int, /* 61 */ - TclBN_mp_set_int, /* 62 */ + 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_long_long, /* 68 */ - TclBN_mp_get_long_long, /* 69 */ - TclBN_mp_set_long, /* 70 */ - TclBN_mp_get_long, /* 71 */ - TclBN_mp_get_int, /* 72 */ + TclBN_mp_set_u64, /* 68 */ + TclBN_mp_get_mag_u64, /* 69 */ + TclBN_mp_set_i64, /* 70 */ + 0, /* 71 */ + 0, /* 72 */ TclBN_mp_tc_and, /* 73 */ TclBN_mp_tc_or, /* 74 */ TclBN_mp_tc_xor, /* 75 */ - TclBN_mp_tc_div_2d, /* 76 */ - TclBN_mp_get_bit, /* 77 */ + TclBN_mp_signed_rsh, /* 76 */ + 0, /* 77 */ + TclBN_mp_to_ubin, /* 78 */ + TclBN_mp_div_ld, /* 79 */ + TclBN_mp_to_radix, /* 80 */ }; static const TclStubHooks tclStubHooks = { @@ -1008,7 +1200,7 @@ const TclStubs tclStubs = { Tcl_DbNewObj, /* 27 */ Tcl_DbNewStringObj, /* 28 */ Tcl_DuplicateObj, /* 29 */ - TclOldFreeObj, /* 30 */ + TclFreeObj, /* 30 */ Tcl_GetBoolean, /* 31 */ Tcl_GetBooleanFromObj, /* 32 */ Tcl_GetByteArrayFromObj, /* 33 */ @@ -1322,7 +1514,7 @@ const TclStubs tclStubs = { Tcl_UtfToExternalDString, /* 333 */ Tcl_UtfToLower, /* 334 */ Tcl_UtfToTitle, /* 335 */ - Tcl_UtfToUniChar, /* 336 */ + Tcl_UtfToChar16, /* 336 */ Tcl_UtfToUpper, /* 337 */ Tcl_WriteChars, /* 338 */ Tcl_WriteObj, /* 339 */ @@ -1340,8 +1532,8 @@ const TclStubs tclStubs = { Tcl_UniCharIsWordChar, /* 351 */ Tcl_UniCharLen, /* 352 */ Tcl_UniCharNcmp, /* 353 */ - Tcl_UniCharToUtfDString, /* 354 */ - Tcl_UtfToUniCharDString, /* 355 */ + Tcl_Char16ToUtfDString, /* 354 */ + Tcl_UtfToChar16DString, /* 355 */ Tcl_GetRegExpFromObj, /* 356 */ Tcl_EvalTokens, /* 357 */ Tcl_FreeParse, /* 358 */ @@ -1631,6 +1823,10 @@ const TclStubs tclStubs = { Tcl_DecrRefCount, /* 642 */ Tcl_IsShared, /* 643 */ Tcl_LinkArray, /* 644 */ + Tcl_GetIntForIndex, /* 645 */ + Tcl_UtfToUniChar, /* 646 */ + Tcl_UniCharToUtfDString, /* 647 */ + Tcl_UtfToUniCharDString, /* 648 */ }; /* !END!: Do not edit above this line. */ diff --git a/generic/tclTest.c b/generic/tclTest.c index 8476ecb..403b0a9 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -20,6 +20,7 @@ # define USE_TCL_STUBS #endif #include "tclInt.h" +#include "tclTomMath.h" #include "tclOO.h" #include <math.h> @@ -29,11 +30,6 @@ #include "tclRegexp.h" /* - * Required for TestlocaleCmd - */ -#include <locale.h> - -/* * Required for the TestChannelCmd and TestChannelEventCmd */ #include "tclIO.h" @@ -225,6 +221,9 @@ static void SpecialFree(char *blockPtr); static int StaticInitProc(Tcl_Interp *interp); static int TestasyncCmd(void *dummy, Tcl_Interp *interp, int argc, const char **argv); +static int TestbumpinterpepochObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); static int TestbytestringObjCmd(void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); @@ -389,6 +388,12 @@ static int TestSimpleFilesystemObjCmd( Tcl_Obj *const objv[]); static void TestReport(const char *cmd, Tcl_Obj *arg1, Tcl_Obj *arg2); +static int TestgetencpathObjCmd(void *dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int TestsetencpathObjCmd(void *dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); static Tcl_Obj * TestReportGetNativePath(Tcl_Obj *pathPtr); static Tcl_FSStatProc TestReportStat; static Tcl_FSAccessProc TestReportAccess; @@ -601,6 +606,8 @@ Tcltest_Init( Tcl_CreateObjCommand(interp, "testgetindexfromobjstruct", TestGetIndexFromObjStructObjCmd, NULL, NULL); Tcl_CreateCommand(interp, "testasync", TestasyncCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "testbumpinterpepoch", + TestbumpinterpepochObjCmd, NULL, NULL); Tcl_CreateCommand(interp, "testchannel", TestChannelCmd, NULL, NULL); Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd, @@ -731,6 +738,10 @@ Tcltest_Init( NULL, NULL); Tcl_CreateObjCommand(interp, "testinterpresolver", TestInterpResolverCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "testgetencpath", TestgetencpathObjCmd, + NULL, NULL); + Tcl_CreateObjCommand(interp, "testsetencpath", TestsetencpathObjCmd, + NULL, NULL); if (TclObjTest_Init(interp) != TCL_OK) { return TCL_ERROR; @@ -1041,6 +1052,22 @@ AsyncThreadProc( } #endif +static int +TestbumpinterpepochObjCmd( + ClientData dummy, /* Not used. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + Interp *iPtr = (Interp *)interp; + if (objc != 1) { + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + iPtr->compileEpoch++; + return TCL_OK; +} + /* *---------------------------------------------------------------------- * @@ -1777,7 +1804,7 @@ TestdoubledigitsObjCmd(void *unused, Tcl_SetObjResult(interp, Tcl_NewStringObj("bad flag", -1)); return TCL_ERROR; } - type |= TCL_DD_SHORTEN_FLAG; + type |= TCL_DD_SHORTEST; } str = TclDoubleDigits(d, ndigits, type, &decpt, &signum, &endPtr); strObj = Tcl_NewStringObj(str, endPtr-str); @@ -2404,11 +2431,11 @@ ExitProcOdd( void *clientData) /* Integer value to print. */ { char buf[16 + TCL_INTEGER_SPACE]; - size_t len; + int len; - sprintf(buf, "odd %" TCL_Z_MODIFIER "d\n", (size_t)PTR2INT(clientData)); + sprintf(buf, "odd %d\n", (int)PTR2INT(clientData)); len = strlen(buf); - if (len != (size_t) write(1, buf, len)) { + if (len != (int) write(1, buf, len)) { Tcl_Panic("ExitProcOdd: unable to write to stdout"); } } @@ -2418,11 +2445,11 @@ ExitProcEven( void *clientData) /* Integer value to print. */ { char buf[16 + TCL_INTEGER_SPACE]; - size_t len; + int len; - sprintf(buf, "even %" TCL_Z_MODIFIER "d\n", (size_t)PTR2INT(clientData)); + sprintf(buf, "even %d\n", (int)PTR2INT(clientData)); len = strlen(buf); - if (len != (size_t) write(1, buf, len)) { + if (len != (int) write(1, buf, len)) { Tcl_Panic("ExitProcEven: unable to write to stdout"); } } @@ -4417,7 +4444,7 @@ TesttranslatefilenameCmd( * * TestupvarCmd -- * - * This procedure implements the "testupvar2" command. It is used + * This procedure implements the "testupvar" command. It is used * to test Tcl_UpVar and Tcl_UpVar2. * * Results: @@ -5176,7 +5203,7 @@ TestbytestringObjCmd( static int TestsetCmd( void *data, /* Additional flags for Get/SetVar2. */ - register Tcl_Interp *interp,/* Current interpreter. */ + Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { @@ -5208,7 +5235,7 @@ TestsetCmd( static int Testset2Cmd( void *data, /* Additional flags for Get/SetVar2. */ - register Tcl_Interp *interp,/* Current interpreter. */ + Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { @@ -5259,7 +5286,7 @@ Testset2Cmd( static int TestsaveresultCmd( void *dummy, /* Not used. */ - register Tcl_Interp *interp,/* Current interpreter. */ + Tcl_Interp *interp,/* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { @@ -5390,7 +5417,7 @@ TestsaveresultFree( static int TestmainthreadCmd( void *dummy, /* Not used. */ - register Tcl_Interp *interp,/* Current interpreter. */ + Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { @@ -5451,7 +5478,7 @@ MainLoop(void) static int TestsetmainloopCmd( void *dummy, /* Not used. */ - register Tcl_Interp *interp,/* Current interpreter. */ + Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { @@ -5480,7 +5507,7 @@ TestsetmainloopCmd( static int TestexitmainloopCmd( void *dummy, /* Not used. */ - register Tcl_Interp *interp,/* Current interpreter. */ + Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { @@ -7525,6 +7552,72 @@ TestconcatobjCmd( /* *---------------------------------------------------------------------- * + * TestgetencpathObjCmd -- + * + * This function implements the "testgetencpath" command. It is used to + * test Tcl_GetEncodingSearchPath(). + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TestgetencpathObjCmd( + ClientData clientData, /* Not used. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const *objv) /* Argument strings. */ +{ + if (objc != 1) { + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath()); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TestsetencpathCmd -- + * + * This function implements the "testsetencpath" command. It is used to + * test Tcl_SetDefaultEncodingDir(). + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TestsetencpathObjCmd( + ClientData clientData, /* Not used. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const *objv) /* Argument strings. */ +{ + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "defaultDir"); + return TCL_ERROR; + } + + Tcl_SetEncodingSearchPath(objv[1]); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * TestparseargsCmd -- * * This procedure implements the "testparseargs" command. It is used to @@ -7710,7 +7803,7 @@ MyCompiledVarFree( } #define TclVarHashGetValue(hPtr) \ - ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry))) + ((Var *) ((char *)hPtr - offsetof(VarInHash, entry))) static Tcl_Var MyCompiledVarFetch( diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index a289e32..e616433 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -18,7 +18,11 @@ # define USE_TCL_STUBS #endif #include "tclInt.h" -#include "tommath.h" +#ifdef TCL_WITH_EXTERNAL_TOMMATH +# include "tommath.h" +#else +# include "tclTomMath.h" +#endif #include "tclStringRep.h" @@ -53,7 +57,7 @@ static int TeststringobjCmd(ClientData dummy, Tcl_Interp *interp, static void VarPtrDeleteProc(ClientData clientData, Tcl_Interp *interp) { - register int i; + int i; Tcl_Obj **varPtr = (Tcl_Obj **) clientData; for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { if (varPtr[i]) Tcl_DecrRefCount(varPtr[i]); @@ -91,7 +95,7 @@ int TclObjTest_Init( Tcl_Interp *interp) { - register int i; + int i; /* * An array of Tcl_Obj pointers used in the commands that operate on or get * the values of Tcl object-valued variables. varPtr[i] is the i-th variable's @@ -131,7 +135,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: @@ -290,9 +294,9 @@ TestbignumobjCmd( return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetIntObj(varPtr[varIndex], !mp_get_bit(&bignumValue, 0)); + Tcl_SetIntObj(varPtr[varIndex], !mp_isodd(&bignumValue)); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(!mp_get_bit(&bignumValue, 0))); + SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(!mp_isodd(&bignumValue))); } mp_clear(&bignumValue); break; @@ -1178,8 +1182,8 @@ TeststringobjCmd( Tcl_Obj **varPtr; static const char *const options[] = { "append", "appendstrings", "get", "get2", "length", "length2", - "set", "set2", "setlength", "maxchars", "getunicode", - "appendself", "appendself2", NULL + "set", "set2", "setlength", "maxchars", "appendself", + "appendself2", NULL }; if (objc < 3) { @@ -1344,13 +1348,7 @@ TeststringobjCmd( } Tcl_SetIntObj(Tcl_GetObjResult(interp), length); break; - case 10: /* getunicode */ - if (objc != 3) { - goto wrongNumArgs; - } - Tcl_GetUnicode(varPtr[varIndex]); - break; - case 11: /* appendself */ + case 10: /* appendself */ if (objc != 4) { goto wrongNumArgs; } @@ -1381,7 +1379,7 @@ TeststringobjCmd( Tcl_AppendToObj(varPtr[varIndex], string + i, length - i); Tcl_SetObjResult(interp, varPtr[varIndex]); break; - case 12: /* appendself2 */ + case 11: /* appendself2 */ if (objc != 4) { goto wrongNumArgs; } diff --git a/generic/tclTestProcBodyObj.c b/generic/tclTestProcBodyObj.c index 913b253..11e841f 100644 --- a/generic/tclTestProcBodyObj.c +++ b/generic/tclTestProcBodyObj.c @@ -51,7 +51,7 @@ static int ProcBodyTestCheckObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ProcBodyTestInitInternal(Tcl_Interp *interp, int isSafe); static int RegisterCommand(Tcl_Interp* interp, - const char *namespace, const CmdTable *cmdTablePtr); + const char *namesp, const CmdTable *cmdTablePtr); /* * List of commands to create when the package is loaded; must go after the @@ -139,7 +139,7 @@ static int RegisterCommand( Tcl_Interp* interp, /* the Tcl interpreter for which the operation * is performed */ - const char *namespace, /* the namespace in which the command is + const char *namesp, /* the namespace in which the command is * registered */ const CmdTable *cmdTablePtr)/* the command to register */ { @@ -147,13 +147,13 @@ RegisterCommand( if (cmdTablePtr->exportIt) { sprintf(buf, "namespace eval %s { namespace export %s }", - namespace, cmdTablePtr->cmdName); + namesp, cmdTablePtr->cmdName); if (Tcl_EvalEx(interp, buf, -1, 0) != TCL_OK) { return TCL_ERROR; } } - sprintf(buf, "%s::%s", namespace, cmdTablePtr->cmdName); + sprintf(buf, "%s::%s", namesp, cmdTablePtr->cmdName); Tcl_CreateObjCommand(interp, buf, cmdTablePtr->proc, 0, 0); return TCL_OK; } diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index 3f1abc2..8dfe014 100644 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -248,7 +248,7 @@ TclFreeAllocCache( { Cache *cachePtr = arg; Cache **nextPtrPtr; - register unsigned int bucket; + unsigned int bucket; /* * Flush blocks. @@ -305,7 +305,7 @@ TclpAlloc( { Cache *cachePtr; Block *blockPtr; - register int bucket; + int bucket; size_t size; #ifndef __LP64__ @@ -537,8 +537,8 @@ TclpRealloc( Tcl_Obj * TclThreadAllocObj(void) { - register Cache *cachePtr; - register Tcl_Obj *objPtr; + Cache *cachePtr; + Tcl_Obj *objPtr; GETCACHE(cachePtr); @@ -548,7 +548,7 @@ TclThreadAllocObj(void) */ if (cachePtr->numObjects == 0) { - register int numMove; + int numMove; Tcl_MutexLock(objLockPtr); numMove = sharedPtr->numObjects; @@ -709,7 +709,7 @@ MoveObjs( Cache *toPtr, int numMove) { - register Tcl_Obj *objPtr = fromPtr->firstObjPtr; + Tcl_Obj *objPtr = fromPtr->firstObjPtr; Tcl_Obj *fromFirstObjPtr = objPtr; toPtr->numObjects += numMove; @@ -810,7 +810,7 @@ Block2Ptr( int bucket, unsigned int reqSize) { - register void *ptr; + void *ptr; blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; blockPtr->sourceBucket = bucket; @@ -826,7 +826,7 @@ static Block * Ptr2Block( char *ptr) { - register Block *blockPtr; + Block *blockPtr; blockPtr = (((Block *) ptr) - 1); if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) { @@ -960,8 +960,8 @@ GetBlocks( Cache *cachePtr, int bucket) { - register Block *blockPtr; - register int n; + Block *blockPtr; + int n; /* * First, atttempt to move blocks from the shared cache. Note the @@ -1006,7 +1006,7 @@ GetBlocks( } if (cachePtr->buckets[bucket].numFree == 0) { - register size_t size; + size_t size; /* * If no blocks could be moved from shared, first look for a larger @@ -1062,7 +1062,7 @@ GetBlocks( * TclInitThreadAlloc -- * * Initializes the allocator cache-maintenance structures. - * It is done early and protected during the TclInitSubsystems(). + * It is done early and protected during the Tcl_InitSubsystems(). * * Results: * None. diff --git a/generic/tclTimer.c b/generic/tclTimer.c index ea80320..7e04b3e 100644 --- a/generic/tclTimer.c +++ b/generic/tclTimer.c @@ -217,7 +217,7 @@ TimerExitProc( Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, NULL); if (tsdPtr != NULL) { - register TimerHandler *timerHandlerPtr; + TimerHandler *timerHandlerPtr; timerHandlerPtr = tsdPtr->firstTimerHandlerPtr; while (timerHandlerPtr != NULL) { @@ -294,7 +294,7 @@ TclCreateAbsoluteTimerHandler( Tcl_TimerProc *proc, ClientData clientData) { - register TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr; + TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr; ThreadSpecificData *tsdPtr = InitTimer(); timerHandlerPtr = ckalloc(sizeof(TimerHandler)); @@ -355,7 +355,7 @@ Tcl_DeleteTimerHandler( Tcl_TimerToken token) /* Result previously returned by * Tcl_DeleteTimerHandler. */ { - register TimerHandler *timerHandlerPtr, *prevPtr; + TimerHandler *timerHandlerPtr, *prevPtr; ThreadSpecificData *tsdPtr = InitTimer(); if (token == NULL) { @@ -621,7 +621,7 @@ Tcl_DoWhenIdle( Tcl_IdleProc *proc, /* Function to invoke. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { - register IdleHandler *idlePtr; + IdleHandler *idlePtr; Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); @@ -665,7 +665,7 @@ Tcl_CancelIdleCall( Tcl_IdleProc *proc, /* Function that was previously registered. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { - register IdleHandler *idlePtr, *prevPtr; + IdleHandler *idlePtr, *prevPtr; IdleHandler *nextPtr; ThreadSpecificData *tsdPtr = InitTimer(); @@ -892,7 +892,7 @@ Tcl_AfterObjCmd( if (objc == 3) { commandPtr = objv[2]; } else { - commandPtr = Tcl_ConcatObj(objc-2, objv+2);; + commandPtr = Tcl_ConcatObj(objc-2, objv+2); } command = TclGetStringFromObj(commandPtr, &length); for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL; diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index 7221dcf..9d6eb1c 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -23,20 +23,20 @@ scspec EXTERN # Declare each of the functions in the Tcl tommath interface declare 0 { - int TclBN_epoch(void) + int MP_WUR TclBN_epoch(void) } declare 1 { - int TclBN_revision(void) + int MP_WUR TclBN_revision(void) } declare 2 { - int TclBN_mp_add(const mp_int *a, const mp_int *b, mp_int *c) + mp_err MP_WUR TclBN_mp_add(const mp_int *a, const mp_int *b, mp_int *c) } declare 3 { - int TclBN_mp_add_d(const mp_int *a, mp_digit b, mp_int *c) + mp_err MP_WUR TclBN_mp_add_d(const mp_int *a, unsigned int b, mp_int *c) } declare 4 { - int TclBN_mp_and(const mp_int *a, const mp_int *b, mp_int *c) + mp_err MP_WUR TclBN_mp_and(const mp_int *a, const mp_int *b, mp_int *c) } declare 5 { void TclBN_mp_clamp(mp_int *a) @@ -48,128 +48,128 @@ declare 7 { void TclBN_mp_clear_multi(mp_int *a, ...) } declare 8 { - int TclBN_mp_cmp(const mp_int *a, const mp_int *b) + mp_ord MP_WUR TclBN_mp_cmp(const mp_int *a, const mp_int *b) } declare 9 { - int TclBN_mp_cmp_d(const mp_int *a, mp_digit b) + mp_ord MP_WUR TclBN_mp_cmp_d(const mp_int *a, unsigned int b) } declare 10 { - int TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b) + mp_ord MP_WUR TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b) } declare 11 { - int TclBN_mp_copy(const mp_int *a, mp_int *b) + mp_err MP_WUR TclBN_mp_copy(const mp_int *a, mp_int *b) } declare 12 { - int TclBN_mp_count_bits(const mp_int *a) + int MP_WUR TclBN_mp_count_bits(const mp_int *a) } declare 13 { - int TclBN_mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) + mp_err MP_WUR TclBN_mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) } declare 14 { - int TclBN_mp_div_d(const mp_int *a, mp_digit b, mp_int *q, mp_digit *r) + mp_err MP_WUR TclBN_mp_div_d(const mp_int *a, unsigned int b, mp_int *q, unsigned int *r) } declare 15 { - int TclBN_mp_div_2(const mp_int *a, mp_int *q) + mp_err MP_WUR TclBN_mp_div_2(const mp_int *a, mp_int *q) } declare 16 { - int TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r) + mp_err MP_WUR TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r) } -declare 17 { - int TclBN_mp_div_3(const mp_int *a, mp_int *q, mp_digit *r) +declare 17 {deprecated {is private function in libtommath}} { + mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, unsigned int *r) } declare 18 { void TclBN_mp_exch(mp_int *a, mp_int *b) } declare 19 { - int TclBN_mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) + mp_err MP_WUR TclBN_mp_expt_u32(const mp_int *a, unsigned int b, mp_int *c) } declare 20 { - int TclBN_mp_grow(mp_int *a, int size) + mp_err MP_WUR TclBN_mp_grow(mp_int *a, int size) } declare 21 { - int TclBN_mp_init(mp_int *a) + mp_err MP_WUR TclBN_mp_init(mp_int *a) } declare 22 { - int TclBN_mp_init_copy(mp_int *a, const mp_int *b) + mp_err MP_WUR TclBN_mp_init_copy(mp_int *a, const mp_int *b) } declare 23 { - int TclBN_mp_init_multi(mp_int *a, ...) + mp_err MP_WUR TclBN_mp_init_multi(mp_int *a, ...) } declare 24 { - int TclBN_mp_init_set(mp_int *a, mp_digit b) + mp_err MP_WUR TclBN_mp_init_set(mp_int *a, unsigned int b) } declare 25 { - int TclBN_mp_init_size(mp_int *a, int size) + mp_err MP_WUR TclBN_mp_init_size(mp_int *a, int size) } declare 26 { - int TclBN_mp_lshd(mp_int *a, int shift) + mp_err MP_WUR TclBN_mp_lshd(mp_int *a, int shift) } declare 27 { - int TclBN_mp_mod(const mp_int *a, const mp_int *b, mp_int *r) + mp_err MP_WUR TclBN_mp_mod(const mp_int *a, const mp_int *b, mp_int *r) } declare 28 { - int TclBN_mp_mod_2d(const mp_int *a, int b, mp_int *r) + mp_err MP_WUR TclBN_mp_mod_2d(const mp_int *a, int b, mp_int *r) } declare 29 { - int TclBN_mp_mul(const mp_int *a, const mp_int *b, mp_int *p) + mp_err MP_WUR TclBN_mp_mul(const mp_int *a, const mp_int *b, mp_int *p) } declare 30 { - int TclBN_mp_mul_d(const mp_int *a, mp_digit b, mp_int *p) + mp_err MP_WUR TclBN_mp_mul_d(const mp_int *a, unsigned int b, mp_int *p) } declare 31 { - int TclBN_mp_mul_2(const mp_int *a, mp_int *p) + mp_err MP_WUR TclBN_mp_mul_2(const mp_int *a, mp_int *p) } declare 32 { - int TclBN_mp_mul_2d(const mp_int *a, int d, mp_int *p) + mp_err MP_WUR TclBN_mp_mul_2d(const mp_int *a, int d, mp_int *p) } declare 33 { - int TclBN_mp_neg(const mp_int *a, mp_int *b) + mp_err MP_WUR TclBN_mp_neg(const mp_int *a, mp_int *b) } declare 34 { - int TclBN_mp_or(const mp_int *a, const mp_int *b, mp_int *c) + mp_err MP_WUR TclBN_mp_or(const mp_int *a, const mp_int *b, mp_int *c) } declare 35 { - int TclBN_mp_radix_size(const mp_int *a, int radix, int *size) + mp_err MP_WUR TclBN_mp_radix_size(const mp_int *a, int radix, int *size) } declare 36 { - int TclBN_mp_read_radix(mp_int *a, const char *str, int radix) + mp_err MP_WUR TclBN_mp_read_radix(mp_int *a, const char *str, int radix) } declare 37 { void TclBN_mp_rshd(mp_int *a, int shift) } declare 38 { - int TclBN_mp_shrink(mp_int *a) + mp_err MP_WUR TclBN_mp_shrink(mp_int *a) } -declare 39 { - void TclBN_mp_set(mp_int *a, mp_digit b) +declare 39 {deprecated {macro calling mp_set_u64}} { + void TclBN_mp_set(mp_int *a, unsigned int b) } -declare 40 { - int TclBN_mp_sqr(const mp_int *a, mp_int *b) +declare 40 {nostub {is private function in libtommath}} { + mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b) } declare 41 { - int TclBN_mp_sqrt(const mp_int *a, mp_int *b) + mp_err MP_WUR TclBN_mp_sqrt(const mp_int *a, mp_int *b) } declare 42 { - int TclBN_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) + mp_err MP_WUR TclBN_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) } declare 43 { - int TclBN_mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) + mp_err MP_WUR TclBN_mp_sub_d(const mp_int *a, unsigned int b, mp_int *c) } -declare 44 { - int TclBN_mp_to_unsigned_bin(const mp_int *a, unsigned char *b) +declare 44 {deprecated {Use mp_to_ubin}} { + mp_err TclBN_mp_to_unsigned_bin(const mp_int *a, unsigned char *b) } -declare 45 { - int TclBN_mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, +declare 45 {deprecated {Use mp_to_ubin}} { + mp_err TclBN_mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen) } -declare 46 { - int TclBN_mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) +declare 46 {deprecated {Use mp_to_radix}} { + mp_err TclBN_mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) } declare 47 { - int TclBN_mp_unsigned_bin_size(const mp_int *a) + size_t TclBN_mp_ubin_size(const mp_int *a) } declare 48 { - int TclBN_mp_xor(const mp_int *a, const mp_int *b, mp_int *c) + mp_err MP_WUR TclBN_mp_xor(const mp_int *a, const mp_int *b, mp_int *c) } declare 49 { void TclBN_mp_zero(mp_int *a) @@ -182,93 +182,92 @@ declare 50 {deprecated {is private function in libtommath}} { void TclBN_reverse(unsigned char *s, int len) } declare 51 {deprecated {is private function in libtommath}} { - int TclBN_fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) + mp_err TclBN_s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) } declare 52 {deprecated {is private function in libtommath}} { - int TclBN_fast_s_mp_sqr(const mp_int *a, mp_int *b) + mp_err TclBN_s_mp_sqr_fast(const mp_int *a, mp_int *b) } declare 53 {deprecated {is private function in libtommath}} { - int TclBN_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) + mp_err TclBN_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) } declare 54 {deprecated {is private function in libtommath}} { - int TclBN_mp_karatsuba_sqr(const mp_int *a, mp_int *b) + mp_err TclBN_mp_karatsuba_sqr(const mp_int *a, mp_int *b) } declare 55 {deprecated {is private function in libtommath}} { - int TclBN_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) + mp_err TclBN_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) } declare 56 {deprecated {is private function in libtommath}} { - int TclBN_mp_toom_sqr(const mp_int *a, mp_int *b) + mp_err TclBN_mp_toom_sqr(const mp_int *a, mp_int *b) } declare 57 {deprecated {is private function in libtommath}} { - int TclBN_s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) + mp_err TclBN_s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) } declare 58 {deprecated {is private function in libtommath}} { - int TclBN_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) + mp_err TclBN_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) } declare 59 {deprecated {is private function in libtommath}} { - int TclBN_s_mp_sqr(const mp_int *a, mp_int *b) + mp_err TclBN_s_mp_sqr(const mp_int *a, mp_int *b) } declare 60 {deprecated {is private function in libtommath}} { - int TclBN_s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) + mp_err TclBN_s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) } -declare 61 { - int TclBN_mp_init_set_int(mp_int *a, unsigned long i) +declare 61 {deprecated {macro calling mp_init_u64}} { + mp_err TclBN_mp_init_ul(mp_int *a, unsigned long i) } -declare 62 { - int TclBN_mp_set_int(mp_int *a, unsigned long i) +declare 62 {deprecated {macro calling mp_set_u64}} { + void TclBN_mp_set_ul(mp_int *a, unsigned long i) } declare 63 { - int TclBN_mp_cnt_lsb(const mp_int *a) + 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_long_long()}} { - void TclBNInitBignumFromLong(mp_int *bignum, long initVal) +declare 64 {deprecated {macro calling mp_init_i64}} { + int TclBN_mp_init_l(mp_int *bignum, long initVal) } -declare 65 {deprecated {Use mp_init() + mp_set_long_long()}} { - 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_long_long()}} { - 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 -declare 67 { - int TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) +declare 67 {deprecated {Use mp_expt_u32}} { + mp_err TclBN_mp_expt_d_ex(const mp_int *a, unsigned int b, mp_int *c, int fast) } # Added in libtommath 1.0.1 declare 68 { - int TclBN_mp_set_long_long(mp_int *a, Tcl_WideUInt i) + void TclBN_mp_set_u64(mp_int *a, uint64_t i) } declare 69 { - Tcl_WideUInt TclBN_mp_get_long_long(const mp_int *a) + uint64_t MP_WUR TclBN_mp_get_mag_u64(const mp_int *a) } declare 70 { - int TclBN_mp_set_long(mp_int *a, unsigned long i) -} -declare 71 { - unsigned long TclBN_mp_get_long(const mp_int *a) -} -declare 72 { - unsigned long TclBN_mp_get_int(const mp_int *a) + void TclBN_mp_set_i64(mp_int *a, int64_t i) } # Added in libtommath 1.1.0 -declare 73 { - int TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) +declare 73 {deprecated {merged with mp_and}} { + mp_err TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) } -declare 74 { - int TclBN_mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c) +declare 74 {deprecated {merged with mp_or}} { + mp_err TclBN_mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c) } -declare 75 { - int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) +declare 75 {deprecated {merged with mp_xor}} { + mp_err TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) } declare 76 { - int TclBN_mp_tc_div_2d(const mp_int *a, int b, mp_int *c) + mp_err MP_WUR TclBN_mp_signed_rsh(const mp_int *a, int b, mp_int *c) +} + +# Added in libtommath 1.2.0 +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 77 { - int TclBN_mp_get_bit(const mp_int *a, int b) +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 26eef26..e9257a0 100644 --- a/generic/tclTomMath.h +++ b/generic/tclTomMath.h @@ -1,829 +1,14 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is a library that provides multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library was designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * SPDX-License-Identifier: Unlicense - */ -#ifndef BN_H_ -#define BN_H_ +#ifndef BN_TCL_H_ +#define BN_TCL_H_ -#include "tclTomMathDecls.h" -#ifndef MODULE_SCOPE -#define MODULE_SCOPE extern -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - -/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */ -#if defined(_WIN32) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__) -# define MP_32BIT -#endif - -/* detect 64-bit mode if possible */ -#if defined(NEVER) -# if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT)) -# if defined(__GNUC__) -/* we support 128bit integers only via: __attribute__((mode(TI))) */ -# define MP_64BIT -# else -/* otherwise we fall back to MP_32BIT even on 64bit platforms */ -# define MP_32BIT -# endif -# endif -#endif - -/* some default configurations. - * - * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits - * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits - * - * At the very least a mp_digit must be able to hold 7 bits - * [any size beyond that is ok provided it doesn't overflow the data type] - */ -#ifdef MP_8BIT -#ifndef MP_DIGIT_DECLARED -typedef unsigned char mp_digit; -#define MP_DIGIT_DECLARED -#endif -#ifndef MP_WORD_DECLARED -typedef unsigned short mp_word; -#define MP_WORD_DECLARED -#endif -# define MP_SIZEOF_MP_DIGIT 1 -# ifdef DIGIT_BIT -# error You must not define DIGIT_BIT when using MP_8BIT -# endif -#elif defined(MP_16BIT) -#ifndef MP_DIGIT_DECLARED -typedef unsigned short mp_digit; -#define MP_DIGIT_DECLARED -#endif -#ifndef MP_WORD_DECLARED -typedef unsigned int mp_word; -#define MP_WORD_DECLARED -#endif -# define MP_SIZEOF_MP_DIGIT 2 -# ifdef DIGIT_BIT -# error You must not define DIGIT_BIT when using MP_16BIT -# endif -#elif defined(MP_64BIT) -/* for GCC only on supported platforms */ -#ifndef MP_DIGIT_DECLARED -typedef unsigned long long mp_digit; -#define MP_DIGIT_DECLARED -#endif -typedef unsigned long mp_word __attribute__((mode(TI))); -# define DIGIT_BIT 60 +#ifdef MP_NO_STDINT +#ifdef HAVE_STDINT_H +# include <stdint.h> #else -/* this is the default case, 28-bit digits */ - -/* this is to make porting into LibTomCrypt easier :-) */ -#ifndef MP_DIGIT_DECLARED -typedef unsigned int mp_digit; -#define MP_DIGIT_DECLARED -#endif -#ifndef MP_WORD_DECLARED -typedef unsigned long long mp_word; -#define MP_WORD_DECLARED +# include "../compat/stdint.h" #endif - -# ifdef MP_31BIT -/* this is an extension that uses 31-bit digits */ -# define DIGIT_BIT 31 -# else -/* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ -# define DIGIT_BIT 28 -# define MP_28BIT -# endif -#endif - -/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ -#ifndef DIGIT_BIT -# define DIGIT_BIT (((CHAR_BIT * MP_SIZEOF_MP_DIGIT) - 1)) /* bits per digit */ -#endif - -#define MP_DIGIT_BIT DIGIT_BIT -#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) -#define MP_DIGIT_MAX MP_MASK - -/* equalities */ -#define MP_LT -1 /* less than */ -#define MP_EQ 0 /* equal to */ -#define MP_GT 1 /* greater than */ - -#define MP_ZPOS 0 /* positive integer */ -#define MP_NEG 1 /* negative */ - -#define MP_OKAY 0 /* ok result */ -#define MP_MEM -2 /* out of mem */ -#define MP_VAL -3 /* invalid input */ -#define MP_RANGE MP_VAL -#define MP_ITER -4 /* Max. iterations reached */ - -#define MP_YES 1 /* yes response */ -#define MP_NO 0 /* no response */ - -/* Primality generation flags */ -#define LTM_PRIME_BBS 0x0001 /* BBS style prime */ -#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ -#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ - -typedef int mp_err; - -/* define this to use lower memory usage routines (exptmods mostly) */ -/* #define MP_LOW_MEM */ - -/* default precision */ -#ifndef MP_PREC -# ifndef MP_LOW_MEM -# define MP_PREC 32 /* default digits of precision */ -# else -# define MP_PREC 8 /* default digits of precision */ -# endif -#endif - -/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ -#define MP_WARRAY (1u << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT)) + 1)) - -/* the infamous mp_int structure */ -#ifndef MP_INT_DECLARED -#define MP_INT_DECLARED -typedef struct mp_int mp_int; -#endif -struct mp_int { - int used, alloc, sign; - mp_digit *dp; -}; - -/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */ -typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); - - -#define USED(m) ((m)->used) -#define DIGIT(m, k) ((m)->dp[(k)]) -#define SIGN(m) ((m)->sign) - -/* error code to char* string */ -const char *mp_error_to_string(int code); - -/* ---> init and deinit bignum functions <--- */ -/* init a bignum */ -/* -int mp_init(mp_int *a); -*/ - -/* free a bignum */ -/* -void mp_clear(mp_int *a); -*/ - -/* init a null terminated series of arguments */ -/* -int mp_init_multi(mp_int *mp, ...); -*/ - -/* clear a null terminated series of arguments */ -/* -void mp_clear_multi(mp_int *mp, ...); -*/ - -/* exchange two ints */ -/* -void mp_exch(mp_int *a, mp_int *b); -*/ - -/* shrink ram required for a bignum */ -/* -int mp_shrink(mp_int *a); -*/ - -/* grow an int to a given size */ -/* -int mp_grow(mp_int *a, int size); -*/ - -/* init to a given number of digits */ -/* -int mp_init_size(mp_int *a, int size); -*/ - -/* ---> Basic Manipulations <--- */ -#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) -#define mp_iseven(a) (!mp_get_bit((a),0)) -#define mp_isodd(a) mp_get_bit((a),0) -#define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO) - -/* set to zero */ -/* -void mp_zero(mp_int *a); -*/ - -/* set to a digit */ -/* -void mp_set(mp_int *a, mp_digit b); -*/ - -/* set a 32-bit const */ -/* -int mp_set_int(mp_int *a, unsigned long b); -*/ - -/* set a platform dependent unsigned long value */ -/* -int mp_set_long(mp_int *a, unsigned long b); -*/ - -/* set a platform dependent unsigned long long value */ -/* -int mp_set_long_long(mp_int *a, unsigned long long b); -*/ - -/* get a 32-bit value */ -/* -unsigned long mp_get_int(const mp_int *a); -*/ - -/* get a platform dependent unsigned long value */ -/* -unsigned long mp_get_long(const mp_int *a); -*/ - -/* get a platform dependent unsigned long long value */ -/* -unsigned long long mp_get_long_long(const mp_int *a); -*/ - -/* initialize and set a digit */ -/* -int mp_init_set(mp_int *a, mp_digit b); -*/ - -/* initialize and set 32-bit value */ -/* -int mp_init_set_int(mp_int *a, unsigned long b); -*/ - -/* copy, b = a */ -/* -int mp_copy(const mp_int *a, mp_int *b); -*/ - -/* inits and copies, a = b */ -/* -int mp_init_copy(mp_int *a, const mp_int *b); -*/ - -/* trim unused digits */ -/* -void mp_clamp(mp_int *a); -*/ - -/* import binary data */ -/* -int mp_import(mp_int *rop, size_t count, int order, size_t size, int endian, size_t nails, const void *op); -*/ - -/* export binary data */ -/* -int mp_export(void *rop, size_t *countp, int order, size_t size, int endian, size_t nails, const mp_int *op); -*/ - -/* ---> digit manipulation <--- */ - -/* right shift by "b" digits */ -/* -void mp_rshd(mp_int *a, int b); -*/ - -/* left shift by "b" digits */ -/* -int mp_lshd(mp_int *a, int b); -*/ - -/* c = a / 2**b, implemented as c = a >> b */ -/* -int mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d); -*/ - -/* b = a/2 */ -/* -int mp_div_2(const mp_int *a, mp_int *b); -*/ - -/* c = a * 2**b, implemented as c = a << b */ -/* -int mp_mul_2d(const mp_int *a, int b, mp_int *c); -*/ - -/* b = a*2 */ -/* -int mp_mul_2(const mp_int *a, mp_int *b); -*/ - -/* c = a mod 2**b */ -/* -int mp_mod_2d(const mp_int *a, int b, mp_int *c); -*/ - -/* computes a = 2**b */ -/* -int mp_2expt(mp_int *a, int b); -*/ - -/* Counts the number of lsbs which are zero before the first zero bit */ -/* -int mp_cnt_lsb(const mp_int *a); -*/ - -/* I Love Earth! */ - -/* makes a pseudo-random mp_int of a given size */ -/* -int mp_rand(mp_int *a, int digits); -*/ -/* makes a pseudo-random small int of a given size */ -/* -int mp_rand_digit(mp_digit *r); -*/ - -#ifdef MP_PRNG_ENABLE_LTM_RNG -/* A last resort to provide random data on systems without any of the other - * implemented ways to gather entropy. - * It is compatible with `rng_get_bytes()` from libtomcrypt so you could - * provide that one and then set `ltm_rng = rng_get_bytes;` */ -extern unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); -extern void (*ltm_rng_callback)(void); -#endif - -/* ---> binary operations <--- */ -/* c = a XOR b */ -/* -int mp_xor(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = a OR b */ -/* -int mp_or(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = a AND b */ -/* -int mp_and(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = a XOR b (two complement) */ -/* -int mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = a OR b (two complement) */ -/* -int mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = a AND b (two complement) */ -/* -int mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* right shift (two complement) */ -/* -int mp_tc_div_2d(const mp_int *a, int b, mp_int *c); -*/ - -/* ---> Basic arithmetic <--- */ - -/* b = ~a */ -/* -int mp_complement(const mp_int *a, mp_int *b); -*/ - -/* b = -a */ -/* -int mp_neg(const mp_int *a, mp_int *b); -*/ - -/* b = |a| */ -/* -int mp_abs(const mp_int *a, mp_int *b); -*/ - -/* compare a to b */ -/* -int mp_cmp(const mp_int *a, const mp_int *b); -*/ - -/* compare |a| to |b| */ -/* -int mp_cmp_mag(const mp_int *a, const mp_int *b); -*/ - -/* c = a + b */ -/* -int mp_add(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = a - b */ -/* -int mp_sub(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = a * b */ -/* -int mp_mul(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* b = a*a */ -/* -int mp_sqr(const mp_int *a, mp_int *b); -*/ - -/* a/b => cb + d == a */ -/* -int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d); -*/ - -/* c = a mod b, 0 <= c < b */ -/* -int mp_mod(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* ---> single digit functions <--- */ - -/* compare against a single digit */ -/* -int mp_cmp_d(const mp_int *a, mp_digit b); -*/ - -/* c = a + b */ -/* -int mp_add_d(const mp_int *a, mp_digit b, mp_int *c); -*/ - -/* c = a - b */ -/* -int mp_sub_d(const mp_int *a, mp_digit b, mp_int *c); -*/ - -/* c = a * b */ -/* -int mp_mul_d(const mp_int *a, mp_digit b, mp_int *c); -*/ - -/* a/b => cb + d == a */ -/* -int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d); -*/ - -/* a/3 => 3c + d == a */ -/* -int mp_div_3(const mp_int *a, mp_int *c, mp_digit *d); -*/ - -/* c = a**b */ -/* -int mp_expt_d(const mp_int *a, mp_digit b, mp_int *c); -*/ -/* -int mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast); -*/ - -/* c = a mod b, 0 <= c < b */ -/* -int mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c); -*/ - -/* ---> number theory <--- */ - -/* d = a + b (mod c) */ -/* -int mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); -*/ - -/* d = a - b (mod c) */ -/* -int mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); -*/ - -/* d = a * b (mod c) */ -/* -int mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); -*/ - -/* c = a * a (mod b) */ -/* -int mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = 1/a (mod b) */ -/* -int mp_invmod(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* c = (a, b) */ -/* -int mp_gcd(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* produces value such that U1*a + U2*b = U3 */ -/* -int mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3); -*/ - -/* c = [a, b] or (a*b)/(a, b) */ -/* -int mp_lcm(const mp_int *a, const mp_int *b, mp_int *c); -*/ - -/* finds one of the b'th root of a, such that |c|**b <= |a| - * - * returns error if a < 0 and b is even - */ -/* -int mp_n_root(const mp_int *a, mp_digit b, mp_int *c); -*/ -/* -int mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast); -*/ - -/* special sqrt algo */ -/* -int mp_sqrt(const mp_int *arg, mp_int *ret); -*/ - -/* special sqrt (mod prime) */ -/* -int mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret); -*/ - -/* is number a square? */ -/* -int mp_is_square(const mp_int *arg, int *ret); -*/ - -/* computes the jacobi c = (a | n) (or Legendre if b is prime) */ -/* -int mp_jacobi(const mp_int *a, const mp_int *n, int *c); -*/ - -/* used to setup the Barrett reduction for a given modulus b */ -/* -int mp_reduce_setup(mp_int *a, const mp_int *b); -*/ - -/* Barrett Reduction, computes a (mod b) with a precomputed value c - * - * Assumes that 0 < x <= m*m, note if 0 > x > -(m*m) then you can merely - * compute the reduction as -1 * mp_reduce(mp_abs(x)) [pseudo code]. - */ -/* -int mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu); -*/ - -/* setups the montgomery reduction */ -/* -int mp_montgomery_setup(const mp_int *n, mp_digit *rho); -*/ - -/* computes a = B**n mod b without division or multiplication useful for - * normalizing numbers in a Montgomery system. - */ -/* -int mp_montgomery_calc_normalization(mp_int *a, const mp_int *b); -*/ - -/* computes x/R == x (mod N) via Montgomery Reduction */ -/* -int mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho); -*/ - -/* returns 1 if a is a valid DR modulus */ -/* -int mp_dr_is_modulus(const mp_int *a); -*/ - -/* sets the value of "d" required for mp_dr_reduce */ -/* -void mp_dr_setup(const mp_int *a, mp_digit *d); -*/ - -/* reduces a modulo n using the Diminished Radix method */ -/* -int mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k); -*/ - -/* returns true if a can be reduced with mp_reduce_2k */ -/* -int mp_reduce_is_2k(const mp_int *a); -*/ - -/* determines k value for 2k reduction */ -/* -int mp_reduce_2k_setup(const mp_int *a, mp_digit *d); -*/ - -/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ -/* -int mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d); -*/ - -/* returns true if a can be reduced with mp_reduce_2k_l */ -/* -int mp_reduce_is_2k_l(const mp_int *a); -*/ - -/* determines k value for 2k reduction */ -/* -int mp_reduce_2k_setup_l(const mp_int *a, mp_int *d); -*/ - -/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ -/* -int mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d); -*/ - -/* Y = G**X (mod P) */ -/* -int mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y); -*/ - -/* ---> Primes <--- */ - -/* number of primes */ -#ifdef MP_8BIT -# define PRIME_SIZE 31 -#else -# define PRIME_SIZE 256 -#endif - -/* table of first PRIME_SIZE primes */ -#if defined(BUILD_tcl) || !defined(_WIN32) -MODULE_SCOPE const mp_digit ltm_prime_tab[PRIME_SIZE]; -#endif - -/* result=1 if a is divisible by one of the first PRIME_SIZE primes */ -/* -int mp_prime_is_divisible(const mp_int *a, int *result); -*/ - -/* performs one Fermat test of "a" using base "b". - * Sets result to 0 if composite or 1 if probable prime - */ -/* -int mp_prime_fermat(const mp_int *a, const mp_int *b, int *result); -*/ - -/* performs one Miller-Rabin test of "a" using base "b". - * Sets result to 0 if composite or 1 if probable prime - */ -/* -int mp_prime_miller_rabin(const mp_int *a, const mp_int *b, int *result); -*/ - -/* This gives [for a given bit size] the number of trials required - * such that Miller-Rabin gives a prob of failure lower than 2^-96 - */ -/* -int mp_prime_rabin_miller_trials(int size); -*/ - -/* performs t random rounds of Miller-Rabin on "a" additional to - * bases 2 and 3. Also performs an initial sieve of trial - * division. Determines if "a" is prime with probability - * of error no more than (1/4)**t. - * Both a strong Lucas-Selfridge to complete the BPSW test - * and a separate Frobenius test are available at compile time. - * With t<0 a deterministic test is run for primes up to - * 318665857834031151167461. With t<13 (abs(t)-13) additional - * tests with sequential small primes are run starting at 43. - * Is Fips 186.4 compliant if called with t as computed by - * mp_prime_rabin_miller_trials(); - * - * Sets result to 1 if probably prime, 0 otherwise - */ -/* -int mp_prime_is_prime(const mp_int *a, int t, int *result); -*/ - -/* finds the next prime after the number "a" using "t" trials - * of Miller-Rabin. - * - * bbs_style = 1 means the prime must be congruent to 3 mod 4 - */ -/* -int mp_prime_next_prime(mp_int *a, int t, int bbs_style); -*/ - -/* makes a truly random prime of a given size (bytes), - * call with bbs = 1 if you want it to be congruent to 3 mod 4 - * - * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can - * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself - * so it can be NULL - * - * The prime generated will be larger than 2^(8*size). - */ -#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) - -/* makes a truly random prime of a given size (bits), - * - * Flags are as follows: - * - * LTM_PRIME_BBS - make prime congruent to 3 mod 4 - * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) - * LTM_PRIME_2MSB_ON - make the 2nd highest bit one - * - * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can - * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself - * so it can be NULL - * - */ -/* -int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat); -*/ - -/* ---> radix conversion <--- */ -/* -int mp_count_bits(const mp_int *a); -*/ - -/* -int mp_unsigned_bin_size(const mp_int *a); -*/ -/* -int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c); -*/ -/* -int mp_to_unsigned_bin(const mp_int *a, unsigned char *b); -*/ -/* -int mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen); -*/ - -/* -int mp_signed_bin_size(const mp_int *a); -*/ -/* -int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c); -*/ -/* -int mp_to_signed_bin(const mp_int *a, unsigned char *b); -*/ -/* -int mp_to_signed_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen); -*/ - -/* -int mp_read_radix(mp_int *a, const char *str, int radix); -*/ -/* -int mp_toradix(const mp_int *a, char *str, int radix); -*/ -/* -int mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen); -*/ -/* -int mp_radix_size(const mp_int *a, int radix, int *size); -*/ - -#ifndef LTM_NO_FILE -/* -int mp_fread(mp_int *a, int radix, FILE *stream); -*/ -/* -int mp_fwrite(const mp_int *a, int radix, FILE *stream); -*/ -#endif - -#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) -#define mp_raw_size(mp) mp_signed_bin_size(mp) -#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) -#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) -#define mp_mag_size(mp) mp_unsigned_bin_size(mp) -#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) - -#define mp_tobinary(M, S) mp_toradix((M), (S), 2) -#define mp_tooctal(M, S) mp_toradix((M), (S), 8) -#define mp_todecimal(M, S) mp_toradix((M), (S), 10) -#define mp_tohex(M, S) mp_toradix((M), (S), 16) - -#ifdef __cplusplus -} #endif +#include "tommath.h" +#include "tclTomMathDecls.h" #endif - - -/* ref: $Format:%D$ */ -/* git commit: $Format:%H$ */ -/* commit time: $Format:%ai$ */ - diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index 165e3b7..52ac5da 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -16,6 +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 @@ -32,91 +36,127 @@ /* MODULE_SCOPE void* TclBNAlloc( size_t ); */ #define TclBNAlloc(s) ((void*)ckalloc((size_t)(s))) +/* MODULE_SCOPE void* TclBNCalloc( size_t, size_t ); */ +#define TclBNCalloc(m,s) memset(ckalloc((size_t)(m)*(size_t)(s)),0,(size_t)(m)*(size_t)(s)) /* MODULE_SCOPE void* TclBNRealloc( void*, size_t ); */ #define TclBNRealloc(x,s) ((void*)ckrealloc((char*)(x),(size_t)(s))) /* MODULE_SCOPE void TclBNFree( void* ); */ #define TclBNFree(x) (ckfree((char*)(x))) -#define XMALLOC(size) TclBNAlloc(size) -#define XFREE(mem, size) TclBNFree(mem) -#define XREALLOC(mem, oldsize, newsize) TclBNRealloc(mem, newsize) +#undef MP_MALLOC +#undef MP_CALLOC +#undef MP_REALLOC +#undef MP_FREE +#define MP_MALLOC(size) TclBNAlloc(size) +#define MP_CALLOC(nmemb, size) TclBNCalloc(nmemb, size) +#define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc(mem, newsize) +#define MP_FREE(mem, size) TclBNFree(mem) + +#ifndef MODULE_SCOPE +# define MODULE_SCOPE extern +#endif + +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_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 *b); +MODULE_SCOPE mp_err TclBN_s_mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c); +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_reverse(unsigned char *s, size_t len); +MODULE_SCOPE void TclBN_s_mp_set(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); /* Rename the global symbols in libtommath to avoid linkage conflicts */ +#ifndef TCL_WITH_EXTERNAL_TOMMATH #define bn_reverse TclBN_reverse -#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs -#define fast_s_mp_sqr TclBN_fast_s_mp_sqr #define mp_add TclBN_mp_add -#define mp_add_d TclBN_mp_add_d +#define mp_add_d TclBN_s_mp_add_d #define mp_and TclBN_mp_and #define mp_clamp TclBN_mp_clamp #define mp_clear TclBN_mp_clear #define mp_clear_multi TclBN_mp_clear_multi #define mp_cmp TclBN_mp_cmp -#define mp_cmp_d TclBN_mp_cmp_d +#define mp_cmp_d TclBN_s_mp_cmp_d #define mp_cmp_mag TclBN_mp_cmp_mag #define mp_cnt_lsb TclBN_mp_cnt_lsb #define mp_copy TclBN_mp_copy #define mp_count_bits TclBN_mp_count_bits #define mp_div TclBN_mp_div +#define mp_div_d TclBN_s_mp_div_d #define mp_div_2 TclBN_mp_div_2 +#define mp_div_3 TclBN_s_mp_div_3 #define mp_div_2d TclBN_mp_div_2d -#define mp_div_3 TclBN_mp_div_3 -#define mp_div_d TclBN_mp_div_d #define mp_exch TclBN_mp_exch #define mp_expt_d TclBN_mp_expt_d #define mp_expt_d_ex TclBN_mp_expt_d_ex -#define mp_get_bit TclBN_mp_get_bit -#define mp_get_int TclBN_mp_get_int -#define mp_get_long TclBN_mp_get_long -#define mp_get_long_long TclBN_mp_get_long_long +#define mp_expt_u32 TclBN_s_mp_expt_u32 +#define mp_get_mag_u64 TclBN_mp_get_mag_u64 #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_multi TclBN_mp_init_multi -#define mp_init_set TclBN_mp_init_set -#define mp_init_set_int TclBN_mp_init_set_int +#define mp_init_set TclBN_s_mp_init_set #define mp_init_size TclBN_mp_init_size -#define mp_karatsuba_mul TclBN_mp_karatsuba_mul -#define mp_karatsuba_sqr TclBN_mp_karatsuba_sqr +#define mp_init_u64 TclBN_mp_init_u64 #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_d TclBN_s_mp_mul_d #define mp_mul_2 TclBN_mp_mul_2 #define mp_mul_2d TclBN_mp_mul_2d -#define mp_mul_d TclBN_mp_mul_d #define mp_neg TclBN_mp_neg #define mp_or TclBN_mp_or #define mp_radix_size TclBN_mp_radix_size #define mp_read_radix TclBN_mp_read_radix #define mp_rshd TclBN_mp_rshd -#define mp_set TclBN_mp_set -#define mp_set_int TclBN_mp_set_int -#define mp_set_long TclBN_mp_set_long -#define mp_set_long_long TclBN_mp_set_long_long +#define mp_s_rmap TclBN_mp_s_rmap +#define mp_s_rmap_reverse TclBN_mp_s_rmap_reverse +#define mp_s_rmap_reverse_sz TclBN_mp_s_rmap_reverse_sz +#define mp_set TclBN_s_mp_set +#define mp_set_i64 TclBN_mp_set_i64 +#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_sub_d TclBN_mp_sub_d -#define mp_tc_and TclBN_mp_tc_and -#define mp_tc_div_2d TclBN_mp_tc_div_2d -#define mp_tc_or TclBN_mp_tc_or -#define mp_tc_xor TclBN_mp_tc_xor +#define mp_sub_d TclBN_s_mp_sub_d +#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_toom_mul TclBN_mp_toom_mul -#define mp_toom_sqr TclBN_mp_toom_sqr #define mp_toradix_n TclBN_mp_toradix_n -#define mp_unsigned_bin_size TclBN_mp_unsigned_bin_size +#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_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,b) (MP_DEPRECATED_PRAGMA("replaced by mp_init_ul") TclBN_mp_init_u64(a,(unsigned int)(b))) +#define mp_set_int(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_ul") (TclBN_mp_set_u64((a),((unsigned int)(b))),MP_OKAY)) +#define mp_set_long(a,b) (MP_DEPRECATED_PRAGMA("replaced by mp_set_ul") (TclBN_mp_set_u64((a),(long)(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_unsigned_bin_size(mp) (MP_DEPRECATED_PRAGMA("replaced by mp_ubin_size") (int)TclBN_mp_ubin_size(mp)) #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl @@ -146,18 +186,18 @@ extern "C" { */ /* 0 */ -EXTERN int TclBN_epoch(void); +EXTERN int TclBN_epoch(void) MP_WUR; /* 1 */ -EXTERN int TclBN_revision(void); +EXTERN int TclBN_revision(void) MP_WUR; /* 2 */ -EXTERN int TclBN_mp_add(const mp_int *a, const mp_int *b, - mp_int *c); +EXTERN mp_err TclBN_mp_add(const mp_int *a, const mp_int *b, + mp_int *c) MP_WUR; /* 3 */ -EXTERN int TclBN_mp_add_d(const mp_int *a, mp_digit b, - mp_int *c); +EXTERN mp_err TclBN_mp_add_d(const mp_int *a, unsigned int b, + mp_int *c) MP_WUR; /* 4 */ -EXTERN int TclBN_mp_and(const mp_int *a, const mp_int *b, - mp_int *c); +EXTERN mp_err TclBN_mp_and(const mp_int *a, const mp_int *b, + mp_int *c) MP_WUR; /* 5 */ EXTERN void TclBN_mp_clamp(mp_int *a); /* 6 */ @@ -165,104 +205,109 @@ EXTERN void TclBN_mp_clear(mp_int *a); /* 7 */ EXTERN void TclBN_mp_clear_multi(mp_int *a, ...); /* 8 */ -EXTERN int TclBN_mp_cmp(const mp_int *a, const mp_int *b); +EXTERN mp_ord TclBN_mp_cmp(const mp_int *a, const mp_int *b) MP_WUR; /* 9 */ -EXTERN int TclBN_mp_cmp_d(const mp_int *a, mp_digit b); +EXTERN mp_ord TclBN_mp_cmp_d(const mp_int *a, unsigned int b) MP_WUR; /* 10 */ -EXTERN int TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b); +EXTERN mp_ord TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b) MP_WUR; /* 11 */ -EXTERN int TclBN_mp_copy(const mp_int *a, mp_int *b); +EXTERN mp_err TclBN_mp_copy(const mp_int *a, mp_int *b) MP_WUR; /* 12 */ -EXTERN int TclBN_mp_count_bits(const mp_int *a); +EXTERN int TclBN_mp_count_bits(const mp_int *a) MP_WUR; /* 13 */ -EXTERN int TclBN_mp_div(const mp_int *a, const mp_int *b, - mp_int *q, mp_int *r); +EXTERN mp_err TclBN_mp_div(const mp_int *a, const mp_int *b, + mp_int *q, mp_int *r) MP_WUR; /* 14 */ -EXTERN int TclBN_mp_div_d(const mp_int *a, mp_digit b, - mp_int *q, mp_digit *r); +EXTERN mp_err TclBN_mp_div_d(const mp_int *a, unsigned int b, + mp_int *q, unsigned int *r) MP_WUR; /* 15 */ -EXTERN int TclBN_mp_div_2(const mp_int *a, mp_int *q); +EXTERN mp_err TclBN_mp_div_2(const mp_int *a, mp_int *q) MP_WUR; /* 16 */ -EXTERN int TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, - mp_int *r); +EXTERN mp_err TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, + mp_int *r) MP_WUR; /* 17 */ -EXTERN int TclBN_mp_div_3(const mp_int *a, mp_int *q, - mp_digit *r); +TCL_DEPRECATED("is private function in libtommath") +mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, + unsigned int *r); /* 18 */ EXTERN void TclBN_mp_exch(mp_int *a, mp_int *b); /* 19 */ -EXTERN int TclBN_mp_expt_d(const mp_int *a, mp_digit b, - mp_int *c); +EXTERN mp_err TclBN_mp_expt_u32(const mp_int *a, unsigned int b, + mp_int *c) MP_WUR; /* 20 */ -EXTERN int TclBN_mp_grow(mp_int *a, int size); +EXTERN mp_err TclBN_mp_grow(mp_int *a, int size) MP_WUR; /* 21 */ -EXTERN int TclBN_mp_init(mp_int *a); +EXTERN mp_err TclBN_mp_init(mp_int *a) MP_WUR; /* 22 */ -EXTERN int TclBN_mp_init_copy(mp_int *a, const mp_int *b); +EXTERN mp_err TclBN_mp_init_copy(mp_int *a, const mp_int *b) MP_WUR; /* 23 */ -EXTERN int TclBN_mp_init_multi(mp_int *a, ...); +EXTERN mp_err TclBN_mp_init_multi(mp_int *a, ...) MP_WUR; /* 24 */ -EXTERN int TclBN_mp_init_set(mp_int *a, mp_digit b); +EXTERN mp_err TclBN_mp_init_set(mp_int *a, unsigned int b) MP_WUR; /* 25 */ -EXTERN int TclBN_mp_init_size(mp_int *a, int size); +EXTERN mp_err TclBN_mp_init_size(mp_int *a, int size) MP_WUR; /* 26 */ -EXTERN int TclBN_mp_lshd(mp_int *a, int shift); +EXTERN mp_err TclBN_mp_lshd(mp_int *a, int shift) MP_WUR; /* 27 */ -EXTERN int TclBN_mp_mod(const mp_int *a, const mp_int *b, - mp_int *r); +EXTERN mp_err TclBN_mp_mod(const mp_int *a, const mp_int *b, + mp_int *r) MP_WUR; /* 28 */ -EXTERN int TclBN_mp_mod_2d(const mp_int *a, int b, mp_int *r); +EXTERN mp_err TclBN_mp_mod_2d(const mp_int *a, int b, mp_int *r) MP_WUR; /* 29 */ -EXTERN int TclBN_mp_mul(const mp_int *a, const mp_int *b, - mp_int *p); +EXTERN mp_err TclBN_mp_mul(const mp_int *a, const mp_int *b, + mp_int *p) MP_WUR; /* 30 */ -EXTERN int TclBN_mp_mul_d(const mp_int *a, mp_digit b, - mp_int *p); +EXTERN mp_err TclBN_mp_mul_d(const mp_int *a, unsigned int b, + mp_int *p) MP_WUR; /* 31 */ -EXTERN int TclBN_mp_mul_2(const mp_int *a, mp_int *p); +EXTERN mp_err TclBN_mp_mul_2(const mp_int *a, mp_int *p) MP_WUR; /* 32 */ -EXTERN int TclBN_mp_mul_2d(const mp_int *a, int d, mp_int *p); +EXTERN mp_err TclBN_mp_mul_2d(const mp_int *a, int d, mp_int *p) MP_WUR; /* 33 */ -EXTERN int TclBN_mp_neg(const mp_int *a, mp_int *b); +EXTERN mp_err TclBN_mp_neg(const mp_int *a, mp_int *b) MP_WUR; /* 34 */ -EXTERN int TclBN_mp_or(const mp_int *a, const mp_int *b, - mp_int *c); +EXTERN mp_err TclBN_mp_or(const mp_int *a, const mp_int *b, + mp_int *c) MP_WUR; /* 35 */ -EXTERN int TclBN_mp_radix_size(const mp_int *a, int radix, - int *size); +EXTERN mp_err TclBN_mp_radix_size(const mp_int *a, int radix, + int *size) MP_WUR; /* 36 */ -EXTERN int TclBN_mp_read_radix(mp_int *a, const char *str, - int radix); +EXTERN mp_err TclBN_mp_read_radix(mp_int *a, const char *str, + int radix) MP_WUR; /* 37 */ EXTERN void TclBN_mp_rshd(mp_int *a, int shift); /* 38 */ -EXTERN int TclBN_mp_shrink(mp_int *a); +EXTERN mp_err TclBN_mp_shrink(mp_int *a) MP_WUR; /* 39 */ -EXTERN void TclBN_mp_set(mp_int *a, mp_digit b); +TCL_DEPRECATED("macro calling mp_set_u64") +void TclBN_mp_set(mp_int *a, unsigned int b); /* 40 */ -EXTERN int TclBN_mp_sqr(const mp_int *a, mp_int *b); +EXTERN mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b); /* 41 */ -EXTERN int TclBN_mp_sqrt(const mp_int *a, mp_int *b); +EXTERN mp_err TclBN_mp_sqrt(const mp_int *a, mp_int *b) MP_WUR; /* 42 */ -EXTERN int TclBN_mp_sub(const mp_int *a, const mp_int *b, - mp_int *c); +EXTERN mp_err TclBN_mp_sub(const mp_int *a, const mp_int *b, + mp_int *c) MP_WUR; /* 43 */ -EXTERN int TclBN_mp_sub_d(const mp_int *a, mp_digit b, - mp_int *c); +EXTERN mp_err TclBN_mp_sub_d(const mp_int *a, unsigned int b, + mp_int *c) MP_WUR; /* 44 */ -EXTERN int TclBN_mp_to_unsigned_bin(const mp_int *a, +TCL_DEPRECATED("Use mp_to_ubin") +mp_err TclBN_mp_to_unsigned_bin(const mp_int *a, unsigned char *b); /* 45 */ -EXTERN int TclBN_mp_to_unsigned_bin_n(const mp_int *a, +TCL_DEPRECATED("Use mp_to_ubin") +mp_err TclBN_mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen); /* 46 */ -EXTERN int TclBN_mp_toradix_n(const mp_int *a, char *str, +TCL_DEPRECATED("Use mp_to_radix") +mp_err TclBN_mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen); /* 47 */ -EXTERN int TclBN_mp_unsigned_bin_size(const mp_int *a); +EXTERN size_t TclBN_mp_ubin_size(const mp_int *a); /* 48 */ -EXTERN int TclBN_mp_xor(const mp_int *a, const mp_int *b, - mp_int *c); +EXTERN mp_err TclBN_mp_xor(const mp_int *a, const mp_int *b, + mp_int *c) MP_WUR; /* 49 */ EXTERN void TclBN_mp_zero(mp_int *a); /* 50 */ @@ -270,166 +315,178 @@ TCL_DEPRECATED("is private function in libtommath") void TclBN_reverse(unsigned char *s, int len); /* 51 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_fast_s_mp_mul_digs(const mp_int *a, +mp_err TclBN_s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs); /* 52 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_fast_s_mp_sqr(const mp_int *a, mp_int *b); +mp_err TclBN_s_mp_sqr_fast(const mp_int *a, mp_int *b); /* 53 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_mp_karatsuba_mul(const mp_int *a, +mp_err TclBN_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c); /* 54 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_mp_karatsuba_sqr(const mp_int *a, mp_int *b); +mp_err TclBN_mp_karatsuba_sqr(const mp_int *a, mp_int *b); /* 55 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_mp_toom_mul(const mp_int *a, const mp_int *b, +mp_err TclBN_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c); /* 56 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_mp_toom_sqr(const mp_int *a, mp_int *b); +mp_err TclBN_mp_toom_sqr(const mp_int *a, mp_int *b); /* 57 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_s_mp_add(const mp_int *a, const mp_int *b, +mp_err TclBN_s_mp_add(const mp_int *a, const mp_int *b, mp_int *c); /* 58 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_s_mp_mul_digs(const mp_int *a, const mp_int *b, +mp_err TclBN_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs); /* 59 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_s_mp_sqr(const mp_int *a, mp_int *b); +mp_err TclBN_s_mp_sqr(const mp_int *a, mp_int *b); /* 60 */ TCL_DEPRECATED("is private function in libtommath") -int TclBN_s_mp_sub(const mp_int *a, const mp_int *b, +mp_err TclBN_s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c); /* 61 */ -EXTERN int TclBN_mp_init_set_int(mp_int *a, unsigned long i); +TCL_DEPRECATED("macro calling mp_init_u64") +mp_err TclBN_mp_init_ul(mp_int *a, unsigned long i); /* 62 */ -EXTERN int TclBN_mp_set_int(mp_int *a, unsigned long i); +TCL_DEPRECATED("macro calling mp_set_u64") +void TclBN_mp_set_ul(mp_int *a, unsigned long i); /* 63 */ -EXTERN int TclBN_mp_cnt_lsb(const mp_int *a); +EXTERN int TclBN_mp_cnt_lsb(const mp_int *a) MP_WUR; /* 64 */ -TCL_DEPRECATED("Use mp_init() + mp_set_long_long()") -void TclBNInitBignumFromLong(mp_int *bignum, long initVal); +TCL_DEPRECATED("macro calling mp_init_i64") +int TclBN_mp_init_l(mp_int *bignum, long initVal); /* 65 */ -TCL_DEPRECATED("Use mp_init() + mp_set_long_long()") -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_long_long()") -void TclBNInitBignumFromWideUInt(mp_int *bignum, - Tcl_WideUInt initVal); +EXTERN int TclBN_mp_init_u64(mp_int *bignum, uint64_t initVal) MP_WUR; /* 67 */ -EXTERN int TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, +TCL_DEPRECATED("Use mp_expt_u32") +mp_err TclBN_mp_expt_d_ex(const mp_int *a, unsigned int b, mp_int *c, int fast); /* 68 */ -EXTERN int TclBN_mp_set_long_long(mp_int *a, Tcl_WideUInt i); +EXTERN void TclBN_mp_set_u64(mp_int *a, uint64_t i); /* 69 */ -EXTERN Tcl_WideUInt TclBN_mp_get_long_long(const mp_int *a); +EXTERN uint64_t TclBN_mp_get_mag_u64(const mp_int *a) MP_WUR; /* 70 */ -EXTERN int TclBN_mp_set_long(mp_int *a, unsigned long i); -/* 71 */ -EXTERN unsigned long TclBN_mp_get_long(const mp_int *a); -/* 72 */ -EXTERN unsigned long TclBN_mp_get_int(const mp_int *a); +EXTERN void TclBN_mp_set_i64(mp_int *a, int64_t i); +/* Slot 71 is reserved */ +/* Slot 72 is reserved */ /* 73 */ -EXTERN int TclBN_mp_tc_and(const mp_int *a, const mp_int *b, +TCL_DEPRECATED("merged with mp_and") +mp_err TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c); /* 74 */ -EXTERN int TclBN_mp_tc_or(const mp_int *a, const mp_int *b, +TCL_DEPRECATED("merged with mp_or") +mp_err TclBN_mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c); /* 75 */ -EXTERN int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, +TCL_DEPRECATED("merged with mp_xor") +mp_err TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c); /* 76 */ -EXTERN int TclBN_mp_tc_div_2d(const mp_int *a, int b, mp_int *c); -/* 77 */ -EXTERN int TclBN_mp_get_bit(const mp_int *a, int b); +EXTERN mp_err TclBN_mp_signed_rsh(const mp_int *a, int b, + mp_int *c) MP_WUR; +/* Slot 77 is reserved */ +/* 78 */ +EXTERN int TclBN_mp_to_ubin(const mp_int *a, unsigned char *buf, + size_t maxlen, size_t *written) MP_WUR; +/* 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; typedef struct TclTomMathStubs { int magic; void *hooks; - int (*tclBN_epoch) (void); /* 0 */ - int (*tclBN_revision) (void); /* 1 */ - int (*tclBN_mp_add) (const mp_int *a, const mp_int *b, mp_int *c); /* 2 */ - int (*tclBN_mp_add_d) (const mp_int *a, mp_digit b, mp_int *c); /* 3 */ - int (*tclBN_mp_and) (const mp_int *a, const mp_int *b, mp_int *c); /* 4 */ + int (*tclBN_epoch) (void) MP_WUR; /* 0 */ + int (*tclBN_revision) (void) MP_WUR; /* 1 */ + mp_err (*tclBN_mp_add) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 2 */ + mp_err (*tclBN_mp_add_d) (const mp_int *a, unsigned int b, mp_int *c) MP_WUR; /* 3 */ + mp_err (*tclBN_mp_and) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 4 */ void (*tclBN_mp_clamp) (mp_int *a); /* 5 */ void (*tclBN_mp_clear) (mp_int *a); /* 6 */ void (*tclBN_mp_clear_multi) (mp_int *a, ...); /* 7 */ - int (*tclBN_mp_cmp) (const mp_int *a, const mp_int *b); /* 8 */ - int (*tclBN_mp_cmp_d) (const mp_int *a, mp_digit b); /* 9 */ - int (*tclBN_mp_cmp_mag) (const mp_int *a, const mp_int *b); /* 10 */ - int (*tclBN_mp_copy) (const mp_int *a, mp_int *b); /* 11 */ - int (*tclBN_mp_count_bits) (const mp_int *a); /* 12 */ - int (*tclBN_mp_div) (const mp_int *a, const mp_int *b, mp_int *q, mp_int *r); /* 13 */ - int (*tclBN_mp_div_d) (const mp_int *a, mp_digit b, mp_int *q, mp_digit *r); /* 14 */ - int (*tclBN_mp_div_2) (const mp_int *a, mp_int *q); /* 15 */ - int (*tclBN_mp_div_2d) (const mp_int *a, int b, mp_int *q, mp_int *r); /* 16 */ - int (*tclBN_mp_div_3) (const mp_int *a, mp_int *q, mp_digit *r); /* 17 */ + mp_ord (*tclBN_mp_cmp) (const mp_int *a, const mp_int *b) MP_WUR; /* 8 */ + mp_ord (*tclBN_mp_cmp_d) (const mp_int *a, unsigned int b) MP_WUR; /* 9 */ + mp_ord (*tclBN_mp_cmp_mag) (const mp_int *a, const mp_int *b) MP_WUR; /* 10 */ + mp_err (*tclBN_mp_copy) (const mp_int *a, mp_int *b) MP_WUR; /* 11 */ + int (*tclBN_mp_count_bits) (const mp_int *a) MP_WUR; /* 12 */ + mp_err (*tclBN_mp_div) (const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) MP_WUR; /* 13 */ + mp_err (*tclBN_mp_div_d) (const mp_int *a, 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 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_mp_div_3) (const mp_int *a, mp_int *q, unsigned int *r); /* 17 */ void (*tclBN_mp_exch) (mp_int *a, mp_int *b); /* 18 */ - int (*tclBN_mp_expt_d) (const mp_int *a, mp_digit b, mp_int *c); /* 19 */ - int (*tclBN_mp_grow) (mp_int *a, int size); /* 20 */ - int (*tclBN_mp_init) (mp_int *a); /* 21 */ - int (*tclBN_mp_init_copy) (mp_int *a, const mp_int *b); /* 22 */ - int (*tclBN_mp_init_multi) (mp_int *a, ...); /* 23 */ - int (*tclBN_mp_init_set) (mp_int *a, mp_digit b); /* 24 */ - int (*tclBN_mp_init_size) (mp_int *a, int size); /* 25 */ - int (*tclBN_mp_lshd) (mp_int *a, int shift); /* 26 */ - int (*tclBN_mp_mod) (const mp_int *a, const mp_int *b, mp_int *r); /* 27 */ - int (*tclBN_mp_mod_2d) (const mp_int *a, int b, mp_int *r); /* 28 */ - int (*tclBN_mp_mul) (const mp_int *a, const mp_int *b, mp_int *p); /* 29 */ - int (*tclBN_mp_mul_d) (const mp_int *a, mp_digit b, mp_int *p); /* 30 */ - int (*tclBN_mp_mul_2) (const mp_int *a, mp_int *p); /* 31 */ - int (*tclBN_mp_mul_2d) (const mp_int *a, int d, mp_int *p); /* 32 */ - int (*tclBN_mp_neg) (const mp_int *a, mp_int *b); /* 33 */ - int (*tclBN_mp_or) (const mp_int *a, const mp_int *b, mp_int *c); /* 34 */ - int (*tclBN_mp_radix_size) (const mp_int *a, int radix, int *size); /* 35 */ - int (*tclBN_mp_read_radix) (mp_int *a, const char *str, int radix); /* 36 */ + mp_err (*tclBN_mp_expt_u32) (const mp_int *a, unsigned int b, mp_int *c) MP_WUR; /* 19 */ + mp_err (*tclBN_mp_grow) (mp_int *a, int size) MP_WUR; /* 20 */ + mp_err (*tclBN_mp_init) (mp_int *a) MP_WUR; /* 21 */ + mp_err (*tclBN_mp_init_copy) (mp_int *a, const mp_int *b) MP_WUR; /* 22 */ + mp_err (*tclBN_mp_init_multi) (mp_int *a, ...) MP_WUR; /* 23 */ + mp_err (*tclBN_mp_init_set) (mp_int *a, unsigned int b) MP_WUR; /* 24 */ + mp_err (*tclBN_mp_init_size) (mp_int *a, int size) MP_WUR; /* 25 */ + mp_err (*tclBN_mp_lshd) (mp_int *a, int shift) MP_WUR; /* 26 */ + mp_err (*tclBN_mp_mod) (const mp_int *a, const mp_int *b, mp_int *r) MP_WUR; /* 27 */ + mp_err (*tclBN_mp_mod_2d) (const mp_int *a, int b, mp_int *r) MP_WUR; /* 28 */ + mp_err (*tclBN_mp_mul) (const mp_int *a, const mp_int *b, mp_int *p) MP_WUR; /* 29 */ + mp_err (*tclBN_mp_mul_d) (const mp_int *a, unsigned int b, mp_int *p) MP_WUR; /* 30 */ + mp_err (*tclBN_mp_mul_2) (const mp_int *a, mp_int *p) MP_WUR; /* 31 */ + mp_err (*tclBN_mp_mul_2d) (const mp_int *a, int d, mp_int *p) MP_WUR; /* 32 */ + mp_err (*tclBN_mp_neg) (const mp_int *a, mp_int *b) MP_WUR; /* 33 */ + mp_err (*tclBN_mp_or) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 34 */ + mp_err (*tclBN_mp_radix_size) (const mp_int *a, int radix, int *size) MP_WUR; /* 35 */ + mp_err (*tclBN_mp_read_radix) (mp_int *a, const char *str, int radix) MP_WUR; /* 36 */ void (*tclBN_mp_rshd) (mp_int *a, int shift); /* 37 */ - int (*tclBN_mp_shrink) (mp_int *a); /* 38 */ - void (*tclBN_mp_set) (mp_int *a, mp_digit b); /* 39 */ - int (*tclBN_mp_sqr) (const mp_int *a, mp_int *b); /* 40 */ - int (*tclBN_mp_sqrt) (const mp_int *a, mp_int *b); /* 41 */ - int (*tclBN_mp_sub) (const mp_int *a, const mp_int *b, mp_int *c); /* 42 */ - int (*tclBN_mp_sub_d) (const mp_int *a, mp_digit b, mp_int *c); /* 43 */ - int (*tclBN_mp_to_unsigned_bin) (const mp_int *a, unsigned char *b); /* 44 */ - int (*tclBN_mp_to_unsigned_bin_n) (const mp_int *a, unsigned char *b, unsigned long *outlen); /* 45 */ - int (*tclBN_mp_toradix_n) (const mp_int *a, char *str, int radix, int maxlen); /* 46 */ - int (*tclBN_mp_unsigned_bin_size) (const mp_int *a); /* 47 */ - int (*tclBN_mp_xor) (const mp_int *a, const mp_int *b, mp_int *c); /* 48 */ + mp_err (*tclBN_mp_shrink) (mp_int *a) MP_WUR; /* 38 */ + TCL_DEPRECATED_API("macro calling mp_set_u64") void (*tclBN_mp_set) (mp_int *a, unsigned int b); /* 39 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_mp_sqr) (const mp_int *a, mp_int *b); /* 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 */ + TCL_DEPRECATED_API("Use mp_to_ubin") mp_err (*tclBN_mp_to_unsigned_bin) (const mp_int *a, unsigned char *b); /* 44 */ + TCL_DEPRECATED_API("Use mp_to_ubin") mp_err (*tclBN_mp_to_unsigned_bin_n) (const mp_int *a, unsigned char *b, unsigned long *outlen); /* 45 */ + TCL_DEPRECATED_API("Use mp_to_radix") mp_err (*tclBN_mp_toradix_n) (const mp_int *a, char *str, int radix, int maxlen); /* 46 */ + size_t (*tclBN_mp_ubin_size) (const mp_int *a); /* 47 */ + mp_err (*tclBN_mp_xor) (const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 48 */ void (*tclBN_mp_zero) (mp_int *a); /* 49 */ TCL_DEPRECATED_API("is private function in libtommath") void (*tclBN_reverse) (unsigned char *s, int len); /* 50 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_fast_s_mp_mul_digs) (const mp_int *a, const mp_int *b, mp_int *c, int digs); /* 51 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_fast_s_mp_sqr) (const mp_int *a, mp_int *b); /* 52 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_mp_karatsuba_mul) (const mp_int *a, const mp_int *b, mp_int *c); /* 53 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_mp_karatsuba_sqr) (const mp_int *a, mp_int *b); /* 54 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_mp_toom_mul) (const mp_int *a, const mp_int *b, mp_int *c); /* 55 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_mp_toom_sqr) (const mp_int *a, mp_int *b); /* 56 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_s_mp_add) (const mp_int *a, const mp_int *b, mp_int *c); /* 57 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_s_mp_mul_digs) (const mp_int *a, const mp_int *b, mp_int *c, int digs); /* 58 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_s_mp_sqr) (const mp_int *a, mp_int *b); /* 59 */ - TCL_DEPRECATED_API("is private function in libtommath") int (*tclBN_s_mp_sub) (const mp_int *a, const mp_int *b, mp_int *c); /* 60 */ - int (*tclBN_mp_init_set_int) (mp_int *a, unsigned long i); /* 61 */ - int (*tclBN_mp_set_int) (mp_int *a, unsigned long i); /* 62 */ - int (*tclBN_mp_cnt_lsb) (const mp_int *a); /* 63 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_long_long()") void (*tclBNInitBignumFromLong) (mp_int *bignum, long initVal); /* 64 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_long_long()") void (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ - TCL_DEPRECATED_API("Use mp_init() + mp_set_long_long()") void (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ - int (*tclBN_mp_expt_d_ex) (const mp_int *a, mp_digit b, mp_int *c, int fast); /* 67 */ - int (*tclBN_mp_set_long_long) (mp_int *a, Tcl_WideUInt i); /* 68 */ - Tcl_WideUInt (*tclBN_mp_get_long_long) (const mp_int *a); /* 69 */ - int (*tclBN_mp_set_long) (mp_int *a, unsigned long i); /* 70 */ - unsigned long (*tclBN_mp_get_long) (const mp_int *a); /* 71 */ - unsigned long (*tclBN_mp_get_int) (const mp_int *a); /* 72 */ - int (*tclBN_mp_tc_and) (const mp_int *a, const mp_int *b, mp_int *c); /* 73 */ - int (*tclBN_mp_tc_or) (const mp_int *a, const mp_int *b, mp_int *c); /* 74 */ - int (*tclBN_mp_tc_xor) (const mp_int *a, const mp_int *b, mp_int *c); /* 75 */ - int (*tclBN_mp_tc_div_2d) (const mp_int *a, int b, mp_int *c); /* 76 */ - int (*tclBN_mp_get_bit) (const mp_int *a, int b); /* 77 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_s_mp_mul_digs_fast) (const mp_int *a, const mp_int *b, mp_int *c, int digs); /* 51 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_s_mp_sqr_fast) (const mp_int *a, mp_int *b); /* 52 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_mp_karatsuba_mul) (const mp_int *a, const mp_int *b, mp_int *c); /* 53 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_mp_karatsuba_sqr) (const mp_int *a, mp_int *b); /* 54 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_mp_toom_mul) (const mp_int *a, const mp_int *b, mp_int *c); /* 55 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_mp_toom_sqr) (const mp_int *a, mp_int *b); /* 56 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_s_mp_add) (const mp_int *a, const mp_int *b, mp_int *c); /* 57 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_s_mp_mul_digs) (const mp_int *a, const mp_int *b, mp_int *c, int digs); /* 58 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_s_mp_sqr) (const mp_int *a, mp_int *b); /* 59 */ + TCL_DEPRECATED_API("is private function in libtommath") mp_err (*tclBN_s_mp_sub) (const mp_int *a, const mp_int *b, mp_int *c); /* 60 */ + TCL_DEPRECATED_API("macro calling mp_init_u64") mp_err (*tclBN_mp_init_ul) (mp_int *a, unsigned long i); /* 61 */ + TCL_DEPRECATED_API("macro calling mp_set_u64") 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("macro calling mp_init_i64") int (*tclBN_mp_init_l) (mp_int *bignum, long initVal); /* 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 */ + void (*tclBN_mp_set_i64) (mp_int *a, int64_t i); /* 70 */ + void (*reserved71)(void); + void (*reserved72)(void); + TCL_DEPRECATED_API("merged with mp_and") mp_err (*tclBN_mp_tc_and) (const mp_int *a, const mp_int *b, mp_int *c); /* 73 */ + TCL_DEPRECATED_API("merged with mp_or") mp_err (*tclBN_mp_tc_or) (const mp_int *a, const mp_int *b, mp_int *c); /* 74 */ + TCL_DEPRECATED_API("merged with mp_xor") mp_err (*tclBN_mp_tc_xor) (const mp_int *a, const mp_int *b, mp_int *c); /* 75 */ + mp_err (*tclBN_mp_signed_rsh) (const mp_int *a, int b, mp_int *c) MP_WUR; /* 76 */ + void (*reserved77)(void); + int (*tclBN_mp_to_ubin) (const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) MP_WUR; /* 78 */ + 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; extern const TclTomMathStubs *tclTomMathStubsPtr; @@ -482,8 +539,8 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_mp_div_3) /* 17 */ #define TclBN_mp_exch \ (tclTomMathStubsPtr->tclBN_mp_exch) /* 18 */ -#define TclBN_mp_expt_d \ - (tclTomMathStubsPtr->tclBN_mp_expt_d) /* 19 */ +#define TclBN_mp_expt_u32 \ + (tclTomMathStubsPtr->tclBN_mp_expt_u32) /* 19 */ #define TclBN_mp_grow \ (tclTomMathStubsPtr->tclBN_mp_grow) /* 20 */ #define TclBN_mp_init \ @@ -538,18 +595,18 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_mp_to_unsigned_bin_n) /* 45 */ #define TclBN_mp_toradix_n \ (tclTomMathStubsPtr->tclBN_mp_toradix_n) /* 46 */ -#define TclBN_mp_unsigned_bin_size \ - (tclTomMathStubsPtr->tclBN_mp_unsigned_bin_size) /* 47 */ +#define TclBN_mp_ubin_size \ + (tclTomMathStubsPtr->tclBN_mp_ubin_size) /* 47 */ #define TclBN_mp_xor \ (tclTomMathStubsPtr->tclBN_mp_xor) /* 48 */ #define TclBN_mp_zero \ (tclTomMathStubsPtr->tclBN_mp_zero) /* 49 */ #define TclBN_reverse \ (tclTomMathStubsPtr->tclBN_reverse) /* 50 */ -#define TclBN_fast_s_mp_mul_digs \ - (tclTomMathStubsPtr->tclBN_fast_s_mp_mul_digs) /* 51 */ -#define TclBN_fast_s_mp_sqr \ - (tclTomMathStubsPtr->tclBN_fast_s_mp_sqr) /* 52 */ +#define TclBN_s_mp_mul_digs_fast \ + (tclTomMathStubsPtr->tclBN_s_mp_mul_digs_fast) /* 51 */ +#define TclBN_s_mp_sqr_fast \ + (tclTomMathStubsPtr->tclBN_s_mp_sqr_fast) /* 52 */ #define TclBN_mp_karatsuba_mul \ (tclTomMathStubsPtr->tclBN_mp_karatsuba_mul) /* 53 */ #define TclBN_mp_karatsuba_sqr \ @@ -566,45 +623,126 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_s_mp_sqr) /* 59 */ #define TclBN_s_mp_sub \ (tclTomMathStubsPtr->tclBN_s_mp_sub) /* 60 */ -#define TclBN_mp_init_set_int \ - (tclTomMathStubsPtr->tclBN_mp_init_set_int) /* 61 */ -#define TclBN_mp_set_int \ - (tclTomMathStubsPtr->tclBN_mp_set_int) /* 62 */ +#define TclBN_mp_init_ul \ + (tclTomMathStubsPtr->tclBN_mp_init_ul) /* 61 */ +#define TclBN_mp_set_ul \ + (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_long_long \ - (tclTomMathStubsPtr->tclBN_mp_set_long_long) /* 68 */ -#define TclBN_mp_get_long_long \ - (tclTomMathStubsPtr->tclBN_mp_get_long_long) /* 69 */ -#define TclBN_mp_set_long \ - (tclTomMathStubsPtr->tclBN_mp_set_long) /* 70 */ -#define TclBN_mp_get_long \ - (tclTomMathStubsPtr->tclBN_mp_get_long) /* 71 */ -#define TclBN_mp_get_int \ - (tclTomMathStubsPtr->tclBN_mp_get_int) /* 72 */ +#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_set_i64 \ + (tclTomMathStubsPtr->tclBN_mp_set_i64) /* 70 */ +/* Slot 71 is reserved */ +/* Slot 72 is reserved */ #define TclBN_mp_tc_and \ (tclTomMathStubsPtr->tclBN_mp_tc_and) /* 73 */ #define TclBN_mp_tc_or \ (tclTomMathStubsPtr->tclBN_mp_tc_or) /* 74 */ #define TclBN_mp_tc_xor \ (tclTomMathStubsPtr->tclBN_mp_tc_xor) /* 75 */ -#define TclBN_mp_tc_div_2d \ - (tclTomMathStubsPtr->tclBN_mp_tc_div_2d) /* 76 */ -#define TclBN_mp_get_bit \ - (tclTomMathStubsPtr->tclBN_mp_get_bit) /* 77 */ +#define TclBN_mp_signed_rsh \ + (tclTomMathStubsPtr->tclBN_mp_signed_rsh) /* 76 */ +/* Slot 77 is reserved */ +#define TclBN_mp_to_ubin \ + (tclTomMathStubsPtr->tclBN_mp_to_ubin) /* 78 */ +#define TclBN_mp_div_ld \ + (tclTomMathStubsPtr->tclBN_mp_div_ld) /* 79 */ +#define TclBN_mp_to_radix \ + (tclTomMathStubsPtr->tclBN_mp_to_radix) /* 80 */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ +#if defined(USE_TCL_STUBS) +#undef mp_add_d +#define mp_add_d TclBN_mp_add_d +#undef mp_cmp_d +#define mp_cmp_d TclBN_mp_cmp_d +#undef mp_div_d +#ifdef MP_64BIT +#define mp_div_d TclBN_mp_div_ld +#else +#define mp_div_d TclBN_mp_div_d +#endif +#undef mp_sub_d +#define mp_sub_d TclBN_mp_sub_d +#undef mp_init_set +#define mp_init_set TclBN_mp_init_set +#undef mp_mul_d +#define mp_mul_d TclBN_mp_mul_d +#undef mp_set +#define mp_set TclBN_mp_set +#undef mp_expt_u32 +#define mp_expt_u32 TclBN_mp_expt_u32 +#endif /* USE_TCL_STUBS */ + +#define TclBNInitBignumFromLong(a,b) \ + do { \ + (a)->dp = NULL; \ + (void)mp_init_i64((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) +#undef mp_get_ll +#define mp_get_ll(a) ((long long)mp_get_i64(a)) +#undef mp_set_ll +#define mp_set_ll(a,b) mp_set_i64(a,b) +#undef mp_init_ll +#define mp_init_ll(a,b) mp_init_i64(a,b) +#undef mp_get_ull +#define mp_get_ull(a) ((unsigned long long)mp_get_i64(a)) +#undef mp_set_ull +#define mp_set_ull(a,b) mp_set_u64(a,b) +#undef mp_init_ull +#define mp_init_ull(a,b) mp_init_u64(a,b) +#undef mp_set +#define mp_set(a,b) mp_set_i64((a),(int32_t)(b)) +#define mp_set_i32(a,b) mp_set_i64((a),(int32_t)(b)) +#define mp_set_l(a,b) mp_set_i64((a),(long)(b)) +#define mp_set_u32(a,b) mp_set_u64((a),(uint32_t)(b)) +#define mp_set_ul(a,b) mp_set_u64((a),(unsigned long)(b)) +#define mp_init_i32(a,b) mp_init_i64((a),(int32_t)(b)) +#define mp_init_l(a,b) mp_init_i64((a),(long)(b)) +#define mp_init_u32(a,b) mp_init_u64((a),(uint32_t)(b)) +#define mp_init_ul(a,b) mp_init_u64((a),(unsigned long)(b)) +#undef mp_iseven +#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) +#undef mp_sqr +#define mp_sqr(a,b) mp_mul(a,a,b) + #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT diff --git a/generic/tclTomMathInterface.c b/generic/tclTomMathInterface.c index ae1eb7e..60ed123 100644 --- a/generic/tclTomMathInterface.c +++ b/generic/tclTomMathInterface.c @@ -13,7 +13,7 @@ */ #include "tclInt.h" -#include "tommath.h" +#include "tclTomMath.h" MODULE_SCOPE const TclTomMathStubs tclTomMathStubs; @@ -91,65 +91,6 @@ TclBN_revision(void) } /* - *---------------------------------------------------------------------- - * - * TclInitBignumFromWideInt -- - * - * Allocate and initialize a 'bignum' from a Tcl_WideInt - * - * Results: - * None. - * - * Side effects: - * The 'bignum' is constructed. - * - *---------------------------------------------------------------------- - */ - -void -TclInitBignumFromWideInt( - mp_int *a, /* Bignum to initialize */ - Tcl_WideInt v) /* Initial value */ -{ - if (mp_init(a) != MP_OKAY) { - Tcl_Panic("initialization failure in TclInitBignumFromWideInt"); - } - if (v < 0) { - mp_set_long_long(a, (Tcl_WideUInt)(-v)); - mp_neg(a, a); - } else { - mp_set_long_long(a, (Tcl_WideUInt)v); - } -} - -/* - *---------------------------------------------------------------------- - * - * TclInitBignumFromWideUInt -- - * - * Allocate and initialize a 'bignum' from a Tcl_WideUInt - * - * Results: - * None. - * - * Side effects: - * The 'bignum' is constructed. - * - *---------------------------------------------------------------------- - */ - -void -TclInitBignumFromWideUInt( - mp_int *a, /* Bignum to initialize */ - Tcl_WideUInt v) /* Initial value */ -{ - if (mp_init(a) != MP_OKAY) { - Tcl_Panic("initialization failure in TclInitBignumFromWideUInt"); - } - mp_set_long_long(a, v); -} - -/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/generic/tclTomMathStubLib.c b/generic/tclTomMathStubLib.c index 715904c..7bebe12 100644 --- a/generic/tclTomMathStubLib.c +++ b/generic/tclTomMathStubLib.c @@ -12,6 +12,7 @@ */ #include "tclInt.h" +#include "tclTomMath.h" MODULE_SCOPE const TclTomMathStubs *tclTomMathStubsPtr; diff --git a/generic/tclTrace.c b/generic/tclTrace.c index 8662d70..1106e37 100644 --- a/generic/tclTrace.c +++ b/generic/tclTrace.c @@ -135,7 +135,7 @@ static int StringTraceProc(ClientData clientData, static void StringTraceDeleteProc(ClientData clientData); static void DisposeTraceResult(int flags, char *result); static int TraceVarEx(Tcl_Interp *interp, const char *part1, - const char *part2, register VarTrace *tracePtr); + const char *part2, VarTrace *tracePtr); /* * The following structure holds the client data for string-based @@ -469,7 +469,7 @@ TraceExecutionObjCmd( length = (size_t) commandLength; if ((enum traceOptions) optionIndex == TRACE_ADD) { TraceCommandInfo *tcmdPtr = ckalloc( - TclOffset(TraceCommandInfo, command) + 1 + length); + offsetof(TraceCommandInfo, command) + 1 + length); tcmdPtr->flags = flags; tcmdPtr->stepTrace = NULL; @@ -706,7 +706,7 @@ TraceCommandObjCmd( length = (size_t) commandLength; if ((enum traceOptions) optionIndex == TRACE_ADD) { TraceCommandInfo *tcmdPtr = ckalloc( - TclOffset(TraceCommandInfo, command) + 1 + length); + offsetof(TraceCommandInfo, command) + 1 + length); tcmdPtr->flags = flags; tcmdPtr->stepTrace = NULL; @@ -909,7 +909,7 @@ TraceVariableObjCmd( length = (size_t) commandLength; if ((enum traceOptions) optionIndex == TRACE_ADD) { CombinedTraceVarInfo *ctvarPtr = ckalloc( - TclOffset(CombinedTraceVarInfo, traceCmdInfo.command) + offsetof(CombinedTraceVarInfo, traceCmdInfo.command) + 1 + length); ctvarPtr->traceCmdInfo.flags = flags; @@ -1048,7 +1048,7 @@ Tcl_CommandTraceInfo( * call will return the first trace. */ { Command *cmdPtr; - register CommandTrace *tracePtr; + CommandTrace *tracePtr; cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL, TCL_LEAVE_ERR_MSG); @@ -1113,7 +1113,7 @@ Tcl_TraceCommand( ClientData clientData) /* Arbitrary argument to pass to proc. */ { Command *cmdPtr; - register CommandTrace *tracePtr; + CommandTrace *tracePtr; cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL, TCL_LEAVE_ERR_MSG); @@ -1176,7 +1176,7 @@ Tcl_UntraceCommand( Tcl_CommandTraceProc *proc, /* Function assocated with trace. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { - register CommandTrace *tracePtr; + CommandTrace *tracePtr; CommandTrace *prevPtr; Command *cmdPtr; Interp *iPtr = (Interp *) interp; @@ -1671,13 +1671,13 @@ TclCheckInterpTraces( static int CallTraceFunction( Tcl_Interp *interp, /* The current interpreter. */ - register Trace *tracePtr, /* Describes the trace function to call. */ + Trace *tracePtr, /* Describes the trace function to call. */ Command *cmdPtr, /* Points to command's Command struct. */ const char *command, /* Points to the first character of the * command's source before substitutions. */ int numChars, /* The number of characters in the command's * source. */ - register int objc, /* Number of arguments for the command. */ + int objc, /* Number of arguments for the command. */ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */ { Interp *iPtr = (Interp *) interp; @@ -1919,7 +1919,7 @@ TraceExecutionProc( if ((flags & TCL_TRACE_ENTER_EXEC) && (tcmdPtr->stepTrace == NULL) && (tcmdPtr->flags & (TCL_TRACE_ENTER_DURING_EXEC | TCL_TRACE_LEAVE_DURING_EXEC))) { - register unsigned len = strlen(command) + 1; + size_t len = strlen(command) + 1; tcmdPtr->startLevel = level; tcmdPtr->startCmd = ckalloc(len); @@ -2064,7 +2064,7 @@ TraceVarProc( } } if (destroy && result != NULL) { - register Tcl_Obj *errMsgObj = (Tcl_Obj *) result; + Tcl_Obj *errMsgObj = (Tcl_Obj *) result; Tcl_DecrRefCount(errMsgObj); result = NULL; @@ -2141,8 +2141,8 @@ Tcl_CreateObjTrace( Tcl_CmdObjTraceDeleteProc *delProc) /* Function to call when trace is deleted */ { - register Trace *tracePtr; - register Interp *iPtr = (Interp *) interp; + Trace *tracePtr; + Interp *iPtr = (Interp *) interp; /* * Test if this trace allows inline compilation of commands. @@ -2341,7 +2341,7 @@ Tcl_DeleteTrace( { Interp *iPtr = (Interp *) interp; Trace *prevPtr, *tracePtr = (Trace *) trace; - register Trace **tracePtr2 = &iPtr->tracePtr; + Trace **tracePtr2 = &iPtr->tracePtr; ActiveInterpTrace *activePtr; /* @@ -2533,7 +2533,7 @@ TclCheckArrayTraces( int TclObjCallVarTraces( Interp *iPtr, /* Interpreter containing variable. */ - register Var *arrayPtr, /* Pointer to array variable that contains the + Var *arrayPtr, /* Pointer to array variable that contains the * variable, or NULL if the variable isn't an * element of an array. */ Var *varPtr, /* Variable whose traces are to be invoked. */ @@ -2570,7 +2570,7 @@ TclObjCallVarTraces( int TclCallVarTraces( Interp *iPtr, /* Interpreter containing variable. */ - register Var *arrayPtr, /* Pointer to array variable that contains the + Var *arrayPtr, /* Pointer to array variable that contains the * variable, or NULL if the variable isn't an * element of an array. */ Var *varPtr, /* Variable whose traces are to be invoked. */ @@ -2583,7 +2583,7 @@ TclCallVarTraces( * error, then leave an error message and * stack trace information in *iPTr. */ { - register VarTrace *tracePtr; + VarTrace *tracePtr; ActiveVarTrace active; char *result; const char *openParen, *p; @@ -2913,7 +2913,7 @@ Tcl_UntraceVar2( Tcl_VarTraceProc *proc, /* Function assocated with trace. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { - register VarTrace *tracePtr; + VarTrace *tracePtr; VarTrace *prevPtr, *nextPtr; Var *varPtr, *arrayPtr; Interp *iPtr = (Interp *) interp; @@ -3105,7 +3105,7 @@ Tcl_VarTraceInfo2( hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr); if (hPtr) { - register VarTrace *tracePtr = Tcl_GetHashValue(hPtr); + VarTrace *tracePtr = Tcl_GetHashValue(hPtr); if (prevClientData != NULL) { for (; tracePtr != NULL; tracePtr = tracePtr->nextPtr) { @@ -3203,7 +3203,7 @@ Tcl_TraceVar2( * invoked upon varName. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { - register VarTrace *tracePtr; + VarTrace *tracePtr; int result; tracePtr = ckalloc(sizeof(VarTrace)); @@ -3248,7 +3248,7 @@ TraceVarEx( const char *part2, /* Name of element within array; NULL means * trace applies to scalar variable or array * as-a-whole. */ - register VarTrace *tracePtr)/* Structure containing flags, traceProc and + VarTrace *tracePtr)/* Structure containing flags, traceProc and * clientData fields. Others should be left * blank. Will be ckfree()d (eventually) if * this function returns TCL_OK, and up to diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 86d1913..8bc4d49 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -221,22 +221,33 @@ three: *--------------------------------------------------------------------------- */ +#undef Tcl_UniCharToUtfDString char * Tcl_UniCharToUtfDString( - const Tcl_UniChar *uniStr, /* Unicode string to convert to UTF-8. */ - int uniLength, /* Length of Unicode string in Tcl_UniChars - * (must be >= 0). */ + const int *uniStr, /* Unicode string to convert to UTF-8. */ + int uniLength, /* Length of Unicode string. */ Tcl_DString *dsPtr) /* UTF-8 representation of string is appended * to this previously initialized DString. */ { - const Tcl_UniChar *w, *wEnd; + const int *w, *wEnd; char *p, *string; - int oldLength, len = 1; + int oldLength; /* * UTF-8 string length in bytes will be <= Unicode string length * 4. */ + if (uniStr == NULL) { + return NULL; + } + if (uniLength < 0) { + uniLength = 0; + w = uniStr; + while (*w != '\0') { + uniLength++; + w++; + } + } oldLength = Tcl_DStringLength(dsPtr); Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * 4); string = Tcl_DStringValue(dsPtr) + oldLength; @@ -244,45 +255,43 @@ Tcl_UniCharToUtfDString( p = string; wEnd = uniStr + uniLength; for (w = uniStr; w < wEnd; ) { - if (!len && ((*w & 0xFC00) != 0xDC00)) { - /* Special case for handling high surrogates. */ - p += Tcl_UniCharToUtf(-1, p); - } - len = Tcl_UniCharToUtf(*w, p); - p += len; - if ((*w >= 0xD800) && (len < 3)) { - len = 0; /* Indication that high surrogate was found */ - } + p += Tcl_UniCharToUtf(*w, p); w++; } - if (!len) { - /* Special case for handling high surrogates. */ - p += Tcl_UniCharToUtf(-1, p); - } Tcl_DStringSetLength(dsPtr, oldLength + (p - string)); return string; } -#if (TCL_UTF_MAX > 4) && (defined(__CYGWIN__) || defined(_WIN32)) char * -TclWCharToUtfDString( - const WCHAR *uniStr, /* WCHAR string to convert to UTF-8. */ - int uniLength, /* Length of WCHAR string in Tcl_UniChars - * (must be >= 0). */ +Tcl_Char16ToUtfDString( + const unsigned short *uniStr,/* Utf-16 string to convert to UTF-8. */ + int uniLength, /* Length of Utf-16 string. */ Tcl_DString *dsPtr) /* UTF-8 representation of string is appended * to this previously initialized DString. */ { - const WCHAR *w, *wEnd; + const unsigned short *w, *wEnd; char *p, *string; int oldLength, len = 1; /* - * UTF-8 string length in bytes will be <= Unicode string length * 4. + * UTF-8 string length in bytes will be <= Utf16 string length * 3. */ + if (uniStr == NULL) { + return NULL; + } + if (uniLength < 0) { + + uniLength = 0; + w = uniStr; + while (*w != '\0') { + uniLength++; + w++; + } + } oldLength = Tcl_DStringLength(dsPtr); - Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * 4); + Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * 3); string = Tcl_DStringValue(dsPtr) + oldLength; p = string; @@ -307,7 +316,6 @@ TclWCharToUtfDString( return string; } -#endif /* *--------------------------------------------------------------------------- * @@ -324,7 +332,7 @@ TclWCharToUtfDString( * Tcl_UtfCharComplete() before calling this routine to ensure that * enough bytes remain in the string. * - * Special handling of Surrogate pairs is handled as follows: + * If TCL_UTF_MAX <= 4, special handling of Surrogate pairs is done: * For any UTF-8 string containing a character outside of the BMP, the * first call to this function will fill *chPtr with the high surrogate * and generate a return value of 1. Calling Tcl_UtfToUniChar again @@ -350,13 +358,14 @@ static const unsigned short cp1252[32] = { 0x2DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x9D, 0x017E, 0x0178 }; +#undef Tcl_UtfToUniChar int Tcl_UtfToUniChar( - register const char *src, /* The UTF-8 string. */ - register Tcl_UniChar *chPtr)/* Filled with the Tcl_UniChar represented by + const char *src, /* The UTF-8 string. */ + int *chPtr)/* Filled with the unsigned int represented by * the UTF-8 string. */ { - Tcl_UniChar byte; + int byte; /* * Unroll 1 to 4 byte UTF-8 sequences. @@ -372,20 +381,6 @@ Tcl_UtfToUniChar( * characters representing themselves. */ -#if TCL_UTF_MAX <= 4 - /* If *chPtr contains a high surrogate (produced by a previous - * Tcl_UtfToUniChar() call) and the next 3 bytes are UTF-8 continuation - * bytes, then we must produce a follow-up low surrogate. We only - * do that if the high surrogate matches the bits we encounter. - */ - if ((byte >= 0x80) - && (((((byte - 0x10) << 2) & 0xFC) | 0xD800) == (*chPtr & 0xFCFC)) - && ((src[1] & 0xF0) == (((*chPtr << 4) & 0x30) | 0x80)) - && ((src[2] & 0xC0) == 0x80)) { - *chPtr = ((src[1] & 0x0F) << 6) + (src[2] & 0x3F) + 0xDC00; - return 3; - } -#endif if ((unsigned)(byte-0x80) < (unsigned)0x20) { *chPtr = cp1252[byte-0x80]; } else { @@ -431,23 +426,11 @@ Tcl_UtfToUniChar( /* * Four-byte-character lead byte followed by three trail bytes. */ -#if TCL_UTF_MAX <= 4 - Tcl_UniChar high = (((byte & 0x07) << 8) | ((src[1] & 0x3F) << 2) - | ((src[2] & 0x3F) >> 4)) - 0x40; - if (high >= 0x400) { - /* out of range, < 0x10000 or > 0x10ffff */ - } else { - /* produce high surrogate, advance source pointer */ - *chPtr = 0xD800 + high; - return 1; - } -#else *chPtr = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12) | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F)); if ((unsigned)(*chPtr - 0x10000) <= 0xFFFFF) { return 4; } -#endif } /* @@ -460,14 +443,13 @@ Tcl_UtfToUniChar( return 1; } -#if (TCL_UTF_MAX > 4) && (defined(__CYGWIN__) || defined(_WIN32)) int -TclUtfToWChar( +Tcl_UtfToChar16( const char *src, /* The UTF-8 string. */ - WCHAR *chPtr)/* Filled with the WCHAR represented by + unsigned short *chPtr)/* Filled with the unsigned short represented by * the UTF-8 string. */ { - WCHAR byte; + unsigned short byte; /* * Unroll 1 to 4 byte UTF-8 sequences. @@ -540,7 +522,7 @@ TclUtfToWChar( /* * Four-byte-character lead byte followed by three trail bytes. */ - WCHAR high = (((byte & 0x07) << 8) | ((src[1] & 0x3F) << 2) + unsigned short high = (((byte & 0x07) << 8) | ((src[1] & 0x3F) << 2) | ((src[2] & 0x3F) >> 4)) - 0x40; if (high >= 0x400) { /* out of range, < 0x10000 or > 0x10ffff */ @@ -560,7 +542,6 @@ TclUtfToWChar( *chPtr = byte; return 1; } -#endif /* *--------------------------------------------------------------------------- @@ -580,7 +561,8 @@ TclUtfToWChar( *--------------------------------------------------------------------------- */ -Tcl_UniChar * +#undef Tcl_UtfToUniCharDString +int * Tcl_UtfToUniCharDString( const char *src, /* UTF-8 string to convert to Unicode. */ int length, /* Length of UTF-8 string in bytes, or -1 for @@ -589,10 +571,13 @@ Tcl_UtfToUniCharDString( * appended to this previously initialized * DString. */ { - Tcl_UniChar ch = 0, *w, *wString; + int ch = 0, *w, *wString; const char *p, *end; int oldLength; + if (src == NULL) { + return NULL; + } if (length < 0) { length = strlen(src); } @@ -605,20 +590,20 @@ Tcl_UtfToUniCharDString( oldLength = Tcl_DStringLength(dsPtr); Tcl_DStringSetLength(dsPtr, - oldLength + (int) ((length + 1) * sizeof(Tcl_UniChar))); - wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength); + oldLength + ((length + 1) * sizeof(int))); + wString = (int *) (Tcl_DStringValue(dsPtr) + oldLength); w = wString; p = src; end = src + length - 4; while (p < end) { - p += TclUtfToUniChar(p, &ch); + p += Tcl_UtfToUniChar(p, &ch); *w++ = ch; } end += 4; while (p < end) { if (Tcl_UtfCharComplete(p, end-p)) { - p += TclUtfToUniChar(p, &ch); + p += Tcl_UtfToUniChar(p, &ch); } else { ch = UCHAR(*p++); } @@ -631,9 +616,8 @@ Tcl_UtfToUniCharDString( return wString; } -#if (TCL_UTF_MAX > 4) && (defined(__CYGWIN__) || defined(_WIN32)) -WCHAR * -TclUtfToWCharDString( +unsigned short * +Tcl_UtfToChar16DString( const char *src, /* UTF-8 string to convert to Unicode. */ int length, /* Length of UTF-8 string in bytes, or -1 for * strlen(). */ @@ -641,10 +625,14 @@ TclUtfToWCharDString( * appended to this previously initialized * DString. */ { - WCHAR ch = 0, *w, *wString; + unsigned short ch = 0; + unsigned short *w, *wString; const char *p, *end; int oldLength; + if (src == NULL) { + return NULL; + } if (length < 0) { length = strlen(src); } @@ -657,20 +645,20 @@ TclUtfToWCharDString( oldLength = Tcl_DStringLength(dsPtr); Tcl_DStringSetLength(dsPtr, - oldLength + (int) ((length + 1) * sizeof(WCHAR))); - wString = (WCHAR *) (Tcl_DStringValue(dsPtr) + oldLength); + oldLength + ((length + 1) * sizeof(unsigned short))); + wString = (unsigned short *) (Tcl_DStringValue(dsPtr) + oldLength); w = wString; p = src; end = src + length - 4; while (p < end) { - p += TclUtfToWChar(p, &ch); + p += Tcl_UtfToChar16(p, &ch); *w++ = ch; } end += 4; while (p < end) { if (Tcl_UtfCharComplete(p, end-p)) { - p += TclUtfToWChar(p, &ch); + p += Tcl_UtfToChar16(p, &ch); } else { ch = UCHAR(*p++); } @@ -682,7 +670,6 @@ TclUtfToWCharDString( return wString; } -#endif /* *--------------------------------------------------------------------------- * @@ -731,12 +718,12 @@ Tcl_UtfCharComplete( int Tcl_NumUtfChars( - register const char *src, /* The UTF-8 string to measure. */ + const char *src, /* The UTF-8 string to measure. */ int length) /* The length of the string in bytes, or -1 * for strlen(string). */ { Tcl_UniChar ch = 0; - register int i = 0; + int i = 0; /* * The separate implementations are faster. @@ -752,7 +739,7 @@ Tcl_NumUtfChars( } if (i < 0) i = INT_MAX; /* Bug [2738427] */ } else { - register const char *endPtr = src + length - 4; + const char *endPtr = src + length - 4; while (src < endPtr) { src += TclUtfToUniChar(src, &ch); @@ -801,7 +788,7 @@ Tcl_UtfFindFirst( len = TclUtfToUniChar(src, &find); fullchar = find; #if TCL_UTF_MAX <= 4 - if ((ch >= 0xD800) && (len < 3)) { + if ((fullchar != ch) && (find >= 0xD800) && (len < 3)) { len += TclUtfToUniChar(src + len, &find); fullchar = (((fullchar & 0x3ff) << 10) | (find & 0x3ff)) + 0x10000; } @@ -849,7 +836,7 @@ Tcl_UtfFindLast( len = TclUtfToUniChar(src, &find); fullchar = find; #if TCL_UTF_MAX <= 4 - if ((ch >= 0xD800) && (len < 3)) { + if ((fullchar != ch) && (find >= 0xD800) && (len < 3)) { len += TclUtfToUniChar(src + len, &find); fullchar = (((fullchar & 0x3ff) << 10) | (find & 0x3ff)) + 0x10000; } @@ -968,8 +955,8 @@ Tcl_UtfPrev( int Tcl_UniCharAtIndex( - register const char *src, /* The UTF-8 string to dereference. */ - register int index) /* The position of the desired character. */ + const char *src, /* The UTF-8 string to dereference. */ + int index) /* The position of the desired character. */ { Tcl_UniChar ch = 0; int fullchar = 0; @@ -1016,8 +1003,8 @@ Tcl_UniCharAtIndex( const char * Tcl_UtfAtIndex( - register const char *src, /* The UTF-8 string. */ - register int index) /* The position of the desired character. */ + const char *src, /* The UTF-8 string. */ + int index) /* The position of the desired character. */ { Tcl_UniChar ch = 0; int len = 0; @@ -1044,7 +1031,7 @@ Tcl_UtfAtIndex( * * Results: * Stores the bytes represented by the backslash sequence in dst and - * returns the number of bytes written to dst. At most TCL_UTF_MAX bytes + * returns the number of bytes written to dst. At most 4 bytes * are written to dst; dst must have been large enough to accept those * bytes. If readPtr isn't NULL then it is filled in with a count of the * number of bytes in the backslash sequence. @@ -1080,7 +1067,7 @@ Tcl_UtfBackslash( * We ate a whole line. Pay the price of a strlen() */ - result = TclParseBackslash(src, (int)strlen(src), &numRead, dst); + result = TclParseBackslash(src, strlen(src), &numRead, dst); } if (readPtr != NULL) { *readPtr = numRead; @@ -1323,7 +1310,7 @@ TclpUtfNcmp2( * fine in the strcmp manner. */ - register int result = 0; + int result = 0; for ( ; numBytes != 0; numBytes--, cs++, ct++) { if (*cs != *ct) { @@ -2151,7 +2138,7 @@ Tcl_UniCharCaseMatch( if ((p != '[') && (p != '?') && (p != '\\')) { if (nocase) { while (*uniStr && (p != *uniStr) - && (p != (Tcl_UniChar)Tcl_UniCharToLower(*uniStr))) { + && (p != Tcl_UniCharToLower(*uniStr))) { uniStr++; } } else { @@ -2191,13 +2178,13 @@ Tcl_UniCharCaseMatch( Tcl_UniChar startChar, endChar; uniPattern++; - ch1 = (nocase ? (Tcl_UniChar)Tcl_UniCharToLower(*uniStr) : *uniStr); + ch1 = (nocase ? Tcl_UniCharToLower(*uniStr) : *uniStr); uniStr++; while (1) { if ((*uniPattern == ']') || (*uniPattern == 0)) { return 0; } - startChar = (nocase ? (Tcl_UniChar)Tcl_UniCharToLower(*uniPattern) + startChar = (nocase ? Tcl_UniCharToLower(*uniPattern) : *uniPattern); uniPattern++; if (*uniPattern == '-') { @@ -2205,7 +2192,7 @@ Tcl_UniCharCaseMatch( if (*uniPattern == 0) { return 0; } - endChar = (nocase ? (Tcl_UniChar)Tcl_UniCharToLower(*uniPattern) + endChar = (nocase ? Tcl_UniCharToLower(*uniPattern) : *uniPattern); uniPattern++; if (((startChar <= ch1) && (ch1 <= endChar)) @@ -2343,7 +2330,7 @@ TclUniCharMatch( if ((p != '[') && (p != '?') && (p != '\\')) { if (nocase) { while ((string < stringEnd) && (p != *string) - && (p != (Tcl_UniChar)Tcl_UniCharToLower(*string))) { + && (p != Tcl_UniCharToLower(*string))) { string++; } } else { @@ -2384,20 +2371,20 @@ TclUniCharMatch( Tcl_UniChar ch1, startChar, endChar; pattern++; - ch1 = (nocase ? (Tcl_UniChar)Tcl_UniCharToLower(*string) : *string); + ch1 = (nocase ? Tcl_UniCharToLower(*string) : *string); string++; while (1) { if ((*pattern == ']') || (pattern == patternEnd)) { return 0; } - startChar = (nocase ? (Tcl_UniChar)Tcl_UniCharToLower(*pattern) : *pattern); + startChar = (nocase ? Tcl_UniCharToLower(*pattern) : *pattern); pattern++; if (*pattern == '-') { pattern++; if (pattern == patternEnd) { return 0; } - endChar = (nocase ? (Tcl_UniChar)Tcl_UniCharToLower(*pattern) + endChar = (nocase ? Tcl_UniCharToLower(*pattern) : *pattern); pattern++; if (((startChar <= ch1) && (ch1 <= endChar)) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 2889852..c9eb966 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -15,7 +15,7 @@ #include "tclInt.h" #include "tclParse.h" #include "tclStringTrim.h" -#include "tommath.h" +#include "tclTomMath.h" #include <math.h> /* @@ -121,7 +121,7 @@ static int FindElement(Tcl_Interp *interp, const char *string, /* * The following is the Tcl object type definition for an object that * represents a list index in the form, "end-offset". It is used as a - * performance optimization in TclGetIntForIndex. The internal rep is + * performance optimization in Tcl_GetIntForIndex. The internal rep is * stored directly in the wideValue, so no memory management is required * for it. This is a caching intrep, keeping the result of a parse * around. This type is only created from a pre-existing string, so an @@ -943,8 +943,8 @@ Tcl_SplitList( int Tcl_ScanElement( - register const char *src, /* String to convert to list element. */ - register int *flagPtr) /* Where to store information to guide + const char *src, /* String to convert to list element. */ + int *flagPtr) /* Where to store information to guide * Tcl_ConvertCountedElement. */ { return Tcl_ScanCountedElement(src, -1, flagPtr); @@ -1323,9 +1323,9 @@ TclScanElement( int Tcl_ConvertElement( - register const char *src, /* Source information for list element. */ - register char *dst, /* Place to put list-ified element. */ - register int flags) /* Flags produced by Tcl_ScanElement. */ + const char *src, /* Source information for list element. */ + char *dst, /* Place to put list-ified element. */ + int flags) /* Flags produced by Tcl_ScanElement. */ { return Tcl_ConvertCountedElement(src, -1, dst, flags); } @@ -1353,7 +1353,7 @@ Tcl_ConvertElement( int Tcl_ConvertCountedElement( - register const char *src, /* Source information for list element. */ + const char *src, /* Source information for list element. */ int length, /* Number of bytes in src, or -1. */ char *dst, /* Place to put list-ified element. */ int flags) /* Flags produced by Tcl_ScanElement. */ @@ -1386,7 +1386,7 @@ Tcl_ConvertCountedElement( int TclConvertElement( - register const char *src, /* Source information for list element. */ + const char *src, /* Source information for list element. */ int length, /* Number of bytes in src, or -1. */ char *dst, /* Place to put list-ified element. */ int flags) /* Flags produced by Tcl_ScanElement. */ @@ -2304,7 +2304,7 @@ Tcl_StringCaseMatch( if (nocase) { while (*str) { charLen = TclUtfToUniChar(str, &ch1); - if (ch2==ch1 || ch2==(Tcl_UniChar)Tcl_UniCharToLower(ch1)) { + if (ch2==ch1 || ch2==Tcl_UniCharToLower(ch1)) { break; } str += charLen; @@ -3345,13 +3345,13 @@ Tcl_PrintDouble( * the first (the recommended zero value for tcl_precision avoids the * problem entirely). * - * Uncomment TCL_DD_SHORTEN_FLAG in the next call to prefer the method + * Uncomment TCL_DD_SHORTEST in the next call to prefer the method * that allows floating point values to be shortened if it can be done * without loss of precision. */ digits = TclDoubleDigits(value, *precisionPtr, - TCL_DD_E_FORMAT /* | TCL_DD_SHORTEN_FLAG */, + TCL_DD_E_FORMAT /* | TCL_DD_SHORTEST */, &exponent, &signum, &end); } if (signum) { @@ -3615,49 +3615,25 @@ TclFormatInt( * formatted characters are written. */ Tcl_WideInt n) /* The integer to format. */ { - Tcl_WideInt intVal; - int i; + Tcl_WideUInt intVal; + int i = 0; int numFormatted, j; - const char *digits = "0123456789"; - - /* - * Check first whether "n" is zero. - */ - - if (n == 0) { - buffer[0] = '0'; - buffer[1] = 0; - return 1; - } - - /* - * Check whether "n" is the maximum negative value. This is -2^(m-1) for - * an m-bit word, and has no positive equivalent; negating it produces the - * same value. - */ - - intVal = -n; /* [Bug 3390638] Workaround for*/ - if (n == -n || intVal == n) { /* broken compiler optimizers. */ - return sprintf(buffer, "%" TCL_LL_MODIFIER "d", n); - } + static const char digits[] = "0123456789"; /* * Generate the characters of the result backwards in the buffer. */ - intVal = (n < 0? -n : n); - i = 0; - buffer[0] = '\0'; + intVal = (n < 0 ? -(Tcl_WideUInt)n : (Tcl_WideUInt)n); do { - i++; - buffer[i] = digits[intVal % 10]; - intVal = intVal/10; + buffer[i++] = digits[intVal % 10]; + intVal = intVal / 10; } while (intVal > 0); if (n < 0) { - i++; - buffer[i] = '-'; + buffer[i++] = '-'; } - numFormatted = i; + buffer[i] = '\0'; + numFormatted = i--; /* * Now reverse the characters. @@ -3728,7 +3704,7 @@ GetWideForIndex( /* objPtr holds an integer outside the signed wide range */ /* Truncate to the signed wide range. */ - *widePtr = (((mp_int *)cd)->sign != MP_ZPOS) ? WIDE_MIN : WIDE_MAX; + *widePtr = ((mp_isneg((mp_int *)cd)) ? WIDE_MIN : WIDE_MAX); return TCL_OK; } @@ -3841,7 +3817,7 @@ GetWideForIndex( } else { /* sum holds an integer outside the signed wide range */ /* Truncate to the signed wide range. */ - if (((mp_int *)cd)->sign != MP_ZPOS) { + if (mp_isneg((mp_int *)cd)) { *widePtr = WIDE_MIN; } else { *widePtr = WIDE_MAX; @@ -3872,7 +3848,7 @@ GetWideForIndex( /* *---------------------------------------------------------------------- * - * TclGetIntForIndex -- + * Tcl_GetIntForIndex -- * * This function returns an integer corresponding to the list index held * in a Tcl object. The Tcl object's value is expected to be in the @@ -3894,7 +3870,7 @@ GetWideForIndex( */ int -TclGetIntForIndex( +Tcl_GetIntForIndex( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, then no error message is left after * errors. */ @@ -3988,7 +3964,7 @@ GetEndOffsetFromObj( if (t == TCL_NUMBER_BIG) { /* Truncate to the signed wide range. */ - if (((mp_int *)cd)->sign != MP_ZPOS) { + if (mp_isneg((mp_int *)cd)) { offset = (bytes[3] == '-') ? WIDE_MAX : WIDE_MIN; } else { offset = (bytes[3] == '-') ? WIDE_MIN : WIDE_MAX; @@ -4192,7 +4168,7 @@ TclCheckBadOctal( * errors. */ const char *value) /* String to check. */ { - register const char *p = value; + const char *p = value; /* * A frequent mistake is invalid octal values due to an unwanted leading @@ -4399,7 +4375,7 @@ TclSetProcessGlobalValue( Tcl_IncrRefCount(newValue); cacheMap = GetThreadHash(&pgvPtr->key); ClearHash(cacheMap); - hPtr = Tcl_CreateHashEntry(cacheMap, (void *)(size_t)(pgvPtr->epoch), &dummy); + hPtr = Tcl_CreateHashEntry(cacheMap, INT2PTR(pgvPtr->epoch), &dummy); Tcl_SetHashValue(hPtr, newValue); Tcl_MutexUnlock(&pgvPtr->mutex); } @@ -4459,7 +4435,7 @@ TclGetProcessGlobalValue( } } cacheMap = GetThreadHash(&pgvPtr->key); - hPtr = Tcl_FindHashEntry(cacheMap, (void *)(size_t)epoch); + hPtr = Tcl_FindHashEntry(cacheMap, INT2PTR(epoch)); if (NULL == hPtr) { int dummy; @@ -4492,7 +4468,7 @@ TclGetProcessGlobalValue( value = Tcl_NewStringObj(pgvPtr->value, pgvPtr->numBytes); hPtr = Tcl_CreateHashEntry(cacheMap, - (void *)(size_t)(pgvPtr->epoch), &dummy); + INT2PTR(pgvPtr->epoch), &dummy); Tcl_MutexUnlock(&pgvPtr->mutex); Tcl_SetHashValue(hPtr, value); Tcl_IncrRefCount(value); diff --git a/generic/tclVar.c b/generic/tclVar.c index e400369..4849839 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -45,7 +45,7 @@ static inline Var * VarHashNextVar(Tcl_HashSearch *searchPtr); static inline void CleanupVar(Var *varPtr, Var *arrayPtr); #define VarHashGetValue(hPtr) \ - ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry))) + ((Var *) ((char *)hPtr - offsetof(VarInHash, entry))) /* * NOTE: VarHashCreateVar increments the recount of its key argument. @@ -532,7 +532,7 @@ TclLookupVar( Var * TclObjLookupVar( Tcl_Interp *interp, /* Interpreter to use for lookup. */ - register Tcl_Obj *part1Ptr, /* If part2 isn't NULL, this is the name of an + Tcl_Obj *part1Ptr, /* If part2 isn't NULL, this is the name of an * array. Otherwise, this is a full variable * name that could include a parenthesized * array element. */ @@ -605,7 +605,7 @@ TclObjLookupVarEx( { Interp *iPtr = (Interp *) interp; CallFrame *varFramePtr = iPtr->varFramePtr; - register Var *varPtr; /* Points to the variable's in-frame Var + Var *varPtr; /* Points to the variable's in-frame Var * structure. */ const char *errMsg = NULL; int index, parsed = 0; @@ -984,7 +984,7 @@ TclLookupSimpleVar( int localLen; for (i=0 ; i<localCt ; i++, objPtrPtr++) { - register Tcl_Obj *objPtr = *objPtrPtr; + Tcl_Obj *objPtr = *objPtrPtr; if (objPtr) { localNameStr = TclGetStringFromObj(objPtr, &localLen); @@ -1325,10 +1325,10 @@ Tcl_Obj * Tcl_ObjGetVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ - register Tcl_Obj *part1Ptr, /* Points to an object holding the name of an + Tcl_Obj *part1Ptr, /* Points to an object holding the name of an * array (if part2 is non-NULL) or the name of * a variable. */ - register Tcl_Obj *part2Ptr, /* If non-null, points to an object holding + Tcl_Obj *part2Ptr, /* If non-null, points to an object holding * the name of an element in the array * part1Ptr. */ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY and @@ -1423,7 +1423,7 @@ Tcl_Obj * TclPtrGetVarIdx( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ - register Var *varPtr, /* The variable to be read.*/ + Var *varPtr, /* The variable to be read.*/ Var *arrayPtr, /* NULL for scalar variables, pointer to the * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or @@ -1529,7 +1529,7 @@ TclPtrGetVarIdx( int Tcl_SetObjCmd( ClientData dummy, /* Not used. */ - register Tcl_Interp *interp,/* Current interpreter. */ + Tcl_Interp *interp,/* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { @@ -1753,10 +1753,10 @@ Tcl_Obj * Tcl_ObjSetVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to * be found. */ - register Tcl_Obj *part1Ptr, /* Points to an object holding the name of an + Tcl_Obj *part1Ptr, /* Points to an object holding the name of an * array (if part2 is non-NULL) or the name of * a variable. */ - register Tcl_Obj *part2Ptr, /* If non-NULL, points to an object holding + Tcl_Obj *part2Ptr, /* If non-NULL, points to an object holding * the name of an element in the array * part1Ptr. */ Tcl_Obj *newValuePtr, /* New value for variable. */ @@ -1993,7 +1993,7 @@ Tcl_Obj * TclPtrSetVarIdx( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ - register Var *varPtr, /* Reference to the variable to set. */ + Var *varPtr, /* Reference to the variable to set. */ Var *arrayPtr, /* Reference to the array containing the * variable, or NULL if the variable is a * scalar. */ @@ -2313,7 +2313,7 @@ TclPtrIncrObjVarIdx( * variable, or -1. Only used when part1Ptr is * NULL. */ { - register Tcl_Obj *varValuePtr; + Tcl_Obj *varValuePtr; if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; @@ -2574,7 +2574,7 @@ int TclPtrUnsetVarIdx( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ - register Var *varPtr, /* The variable to be unset. */ + Var *varPtr, /* The variable to be unset. */ Var *arrayPtr, /* NULL for scalar variables, pointer to the * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or @@ -2828,8 +2828,8 @@ Tcl_UnsetObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - register int i, flags = TCL_LEAVE_ERR_MSG; - register const char *name; + int i, flags = TCL_LEAVE_ERR_MSG; + const char *name; if (objc == 1) { /* @@ -2897,7 +2897,7 @@ Tcl_AppendObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { Var *varPtr, *arrayPtr; - register Tcl_Obj *varValuePtr = NULL; + Tcl_Obj *varValuePtr = NULL; /* Initialized to avoid compiler warning. */ int i; @@ -4953,7 +4953,7 @@ Tcl_GetVariableFullName( * variable's full name is appended. */ { Interp *iPtr = (Interp *) interp; - register Var *varPtr = (Var *) variable; + Var *varPtr = (Var *) variable; Tcl_Obj *namePtr; Namespace *nsPtr; @@ -5013,9 +5013,9 @@ Tcl_GlobalObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; - register Tcl_Obj *objPtr, *tailPtr; + Tcl_Obj *objPtr, *tailPtr; const char *varName; - register const char *tail; + const char *tail; int result, i; /* @@ -5410,7 +5410,7 @@ ParseSearchId( static void DeleteSearches( Interp *iPtr, - register Var *arrayVarPtr) /* Variable whose searches are to be + Var *arrayVarPtr) /* Variable whose searches are to be * deleted. */ { ArraySearch *searchPtr, *nextPtr; @@ -5552,7 +5552,7 @@ TclDeleteVars( { Tcl_Interp *interp = (Tcl_Interp *) iPtr; Tcl_HashSearch search; - register Var *varPtr; + Var *varPtr; int flags; Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp); @@ -5604,7 +5604,7 @@ TclDeleteCompiledLocalVars( CallFrame *framePtr) /* Procedure call frame containing compiler- * assigned local variables to delete. */ { - register Var *varPtr; + Var *varPtr; int numLocals, i; Tcl_Obj **namePtrPtr; @@ -5653,7 +5653,7 @@ DeleteArray( { Tcl_HashSearch search; Tcl_HashEntry *tPtr; - register Var *elPtr; + Var *elPtr; ActiveVarTrace *activePtr; Tcl_Obj *objPtr; VarTrace *tracePtr; @@ -5842,7 +5842,7 @@ static void FreeParsedVarName( Tcl_Obj *objPtr) { - register Tcl_Obj *arrayPtr, *elem; + Tcl_Obj *arrayPtr, *elem; int parsed; ParsedGetIntRep(objPtr, parsed, arrayPtr, elem); @@ -5859,7 +5859,7 @@ DupParsedVarName( Tcl_Obj *srcPtr, Tcl_Obj *dupPtr) { - register Tcl_Obj *arrayPtr, *elem; + Tcl_Obj *arrayPtr, *elem; int parsed; ParsedGetIntRep(srcPtr, parsed, arrayPtr, elem); @@ -5948,7 +5948,7 @@ ObjFindNamespaceVar( Namespace *nsPtr[2], *cxtNsPtr; const char *simpleName; Var *varPtr; - register int search; + int search; int result; Tcl_Var var; Tcl_Obj *simpleNamePtr; @@ -6600,8 +6600,8 @@ CompareVarKeys( { Tcl_Obj *objPtr1 = keyPtr; Tcl_Obj *objPtr2 = hPtr->key.objPtr; - register const char *p1, *p2; - register int l1, l2; + const char *p1, *p2; + int l1, l2; /* * If the object pointers are the same then they match. diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 3d1941c..393db5c 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -277,16 +277,17 @@ static struct { Tcl_HashTable zipHash; /* Mount to ZipFile mapping */ } ZipFS = { 0, 0, 0, DEFAULT_WRITE_MAX_SIZE, 0, + {0,{0,0,0,0},0,0,0,0,0,0,0,0,0}, + {0,{0,0,0,0},0,0,0,0,0,0,0,0,0} }; /* * For password rotation. */ -static const char pwrot[16] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 -}; +static const char pwrot[17] = + "\x00\x80\x40\xC0\x20\xA0\x60\xE0" + "\x10\x90\x50\xD0\x30\xB0\x70\xF0"; /* * Table to compute CRC32. @@ -400,9 +401,7 @@ static int ZipChannelWrite(void *instanceData, * Define the ZIP filesystem dispatch table. */ -MODULE_SCOPE const Tcl_Filesystem zipfsFilesystem; - -const Tcl_Filesystem zipfsFilesystem = { +static const Tcl_Filesystem zipfsFilesystem = { "zipfs", sizeof(Tcl_Filesystem), TCL_FILESYSTEM_VERSION_2, @@ -1882,7 +1881,7 @@ TclZipfs_Unmount( static int ZipFSMountObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -1916,7 +1915,7 @@ ZipFSMountObjCmd( static int ZipFSMountBufferObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -1968,7 +1967,7 @@ ZipFSMountBufferObjCmd( static int ZipFSRootObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -1995,7 +1994,7 @@ ZipFSRootObjCmd( static int ZipFSUnmountObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2026,7 +2025,7 @@ ZipFSUnmountObjCmd( static int ZipFSMkKeyObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2805,7 +2804,7 @@ ZipFSMkZipOrImgObjCmd( static int ZipFSMkZipObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2825,7 +2824,7 @@ ZipFSMkZipObjCmd( static int ZipFSLMkZipObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2862,7 +2861,7 @@ ZipFSLMkZipObjCmd( static int ZipFSMkImgObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2883,7 +2882,7 @@ ZipFSMkImgObjCmd( static int ZipFSLMkImgObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2920,7 +2919,7 @@ ZipFSLMkImgObjCmd( static int ZipFSCanonicalObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -2976,7 +2975,7 @@ ZipFSCanonicalObjCmd( static int ZipFSExistsObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -3029,7 +3028,7 @@ ZipFSExistsObjCmd( static int ZipFSInfoObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -3079,7 +3078,7 @@ ZipFSInfoObjCmd( static int ZipFSListObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -3179,7 +3178,7 @@ TclZipfs_TclLibrary(void) #ifdef _WIN32 HMODULE hModule; WCHAR wName[MAX_PATH + LIBRARY_SIZE]; - char dllName[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX]; + char dllName[(MAX_PATH + LIBRARY_SIZE) * 3]; #endif /* _WIN32 */ /* @@ -3276,7 +3275,7 @@ TclZipfs_TclLibrary(void) static int ZipFSTclLibraryObjCmd( - void *clientData, /* Not used. */ + void *dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -3311,7 +3310,7 @@ ZipFSTclLibraryObjCmd( static int ZipChannelClose( void *instanceData, - Tcl_Interp *interp) /* Current interpreter. */ + Tcl_Interp *dummy) /* Current interpreter. */ { ZipChannel *info = instanceData; @@ -4166,7 +4165,7 @@ ZipFSFilesystemSeparatorProc( static int ZipFSMatchInDirectoryProc( - Tcl_Interp *interp, /* Current interpreter. */ + Tcl_Interp *dummy, /* Current interpreter. */ Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, @@ -4357,7 +4356,7 @@ ZipFSMatchInDirectoryProc( static int ZipFSPathInFilesystemProc( Tcl_Obj *pathPtr, - void **clientDataPtr) + void **dummy) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; @@ -4730,7 +4729,7 @@ ZipFSLoadFile( *------------------------------------------------------------------------- */ -MODULE_SCOPE int +int TclZipfs_Init( Tcl_Interp *interp) /* Current interpreter. */ { @@ -4880,7 +4879,11 @@ TclZipfs_AppHook( { char *archive; +#ifdef _WIN32 + Tcl_FindExecutable(NULL); +#else /* !_WIN32 */ Tcl_FindExecutable((*argvPtr)[0]); +#endif /* _WIN32 */ archive = (char *) Tcl_GetNameOfExecutable(); TclZipfs_Init(NULL); @@ -4930,7 +4933,8 @@ TclZipfs_AppHook( #ifdef _WIN32 Tcl_DString ds; - archive = Tcl_WinTCharToUtf((*argvPtr)[1], -1, &ds); + Tcl_DStringInit(&ds); + archive = Tcl_WCharToUtfDString((*argvPtr)[1], -1, &ds); #else /* !_WIN32 */ archive = (*argvPtr)[1]; #endif /* _WIN32 */ diff --git a/generic/tommath.h b/generic/tommath.h deleted file mode 100644 index 028a84d..0000000 --- a/generic/tommath.h +++ /dev/null @@ -1 +0,0 @@ -#include "tclTomMathInt.h" |