From b30ba5a92be8e6597c0ff9e890d669f4d071d602 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 24 Aug 2011 07:50:13 +0000 Subject: Upcoming TIP implementation: Full support for Unicode 6.0 --- generic/tcl.decls | 10 +- generic/tcl.h | 2 +- generic/tclBinary.c | 13 +- generic/tclCmdMZ.c | 22 ++- generic/tclDecls.h | 20 +-- generic/tclEncoding.c | 49 ++++-- generic/tclExecute.c | 2 +- generic/tclParse.c | 13 +- generic/tclScan.c | 16 +- generic/tclStringObj.c | 8 +- generic/tclUniData.c | 437 ++++++++++++++++++++++++++++++++++++++++++++++++- generic/tclUtf.c | 258 ++++++++++++++++++++++------- tests/encoding.test | 9 +- tests/string.test | 8 +- tests/utf.test | 43 ++++- tools/uniParse.tcl | 40 +++-- 16 files changed, 795 insertions(+), 155 deletions(-) diff --git a/generic/tcl.decls b/generic/tcl.decls index 30a2aca..0d1dfdf 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -1148,16 +1148,16 @@ declare 319 { Tcl_QueuePosition position) } declare 320 { - Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index) + int Tcl_UniCharAtIndex(const char *src, int index) } declare 321 { - Tcl_UniChar Tcl_UniCharToLower(int ch) + int Tcl_UniCharToLower(int ch) } declare 322 { - Tcl_UniChar Tcl_UniCharToTitle(int ch) + int Tcl_UniCharToTitle(int ch) } declare 323 { - Tcl_UniChar Tcl_UniCharToUpper(int ch) + int Tcl_UniCharToUpper(int ch) } declare 324 { int Tcl_UniCharToUtf(int ch, char *buf) @@ -1351,7 +1351,7 @@ declare 380 { int Tcl_GetCharLength(Tcl_Obj *objPtr) } declare 381 { - Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index) + int Tcl_GetUniChar(Tcl_Obj *objPtr, int index) } declare 382 { Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj *objPtr) diff --git a/generic/tcl.h b/generic/tcl.h index 7370516..611e74e 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2162,7 +2162,7 @@ typedef struct Tcl_EncodingType { */ #ifndef TCL_UTF_MAX -#define TCL_UTF_MAX 3 +#define TCL_UTF_MAX 4 #endif /* diff --git a/generic/tclBinary.c b/generic/tclBinary.c index 0a340f2..6379fe8 100644 --- a/generic/tclBinary.c +++ b/generic/tclBinary.c @@ -425,7 +425,7 @@ SetByteArrayFromAny( const char *src, *srcEnd; unsigned char *dst; ByteArray *byteArrayPtr; - Tcl_UniChar ch; + Tcl_UniChar ch = 0; if (objPtr->typePtr != &tclByteArrayType) { src = TclGetStringFromObj(objPtr, &length); @@ -433,8 +433,11 @@ SetByteArrayFromAny( byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); for (dst = byteArrayPtr->bytes; src < srcEnd; ) { - src += Tcl_UtfToUniChar(src, &ch); - *dst++ = UCHAR(ch); + int n = Tcl_UtfToUniChar(src, &ch); + if (n) { + src += n; + *dst++ = UCHAR(ch); + } } byteArrayPtr->used = dst - byteArrayPtr->bytes; @@ -1209,7 +1212,7 @@ BinaryFormatCmd( badField: { - Tcl_UniChar ch; + Tcl_UniChar ch = 0; char buf[TCL_UTF_MAX + 1]; Tcl_UtfToUniChar(errorString, &ch); @@ -1578,7 +1581,7 @@ BinaryScanCmd( badField: { - Tcl_UniChar ch; + Tcl_UniChar ch = 0; char buf[TCL_UTF_MAX + 1]; Tcl_UtfToUniChar(errorString, &ch); diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index e7c7152..42b2847 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -283,7 +283,7 @@ Tcl_RegexpObjCmd( */ if ((offset == 0) || ((offset > 0) && - (Tcl_GetUniChar(objPtr, offset-1) == (Tcl_UniChar) '\n'))) { + (Tcl_GetUniChar(objPtr, offset-1) == '\n'))) { eflags = 0; } else { eflags = TCL_REG_NOTBOL; @@ -465,7 +465,7 @@ Tcl_RegsubObjCmd( Tcl_RegExp regExpr; Tcl_RegExpInfo info; Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL; - Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend; + Tcl_UniChar ch = 0, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend; static const char *const options[] = { "-all", "-nocase", "-expanded", @@ -1011,7 +1011,7 @@ Tcl_SplitObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar ch; + Tcl_UniChar ch = 0; int len; const char *splitChars; const char *stringPtr; @@ -1096,7 +1096,7 @@ Tcl_SplitObjCmd( } else { const char *element, *p, *splitEnd; int splitLen; - Tcl_UniChar splitChar; + Tcl_UniChar splitChar = 0; /* * Normal case: split on any of a given set of characters. Discard @@ -1425,7 +1425,7 @@ StringIsCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *end, *stop; - Tcl_UniChar ch; + Tcl_UniChar ch = 0; int (*chcomp)(int) = NULL; /* The UniChar comparison function. */ int i, failat = 0, result = 1, strict = 0, index, length1, length2; Tcl_Obj *objPtr, *failVarObj = NULL; @@ -1710,8 +1710,14 @@ StringIsCmd( } end = string1 + length1; for (; string1 < end; string1 += length2, failat++) { + int fullchar; length2 = TclUtfToUniChar(string1, &ch); - if (!chcomp(ch)) { + fullchar = ch; + if (!length2) { + length2 = TclUtfToUniChar(string1, &ch); + fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + if (!chcomp(fullchar)) { result = 0; break; } @@ -2363,7 +2369,7 @@ StringStartCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar ch; + Tcl_UniChar ch = 0; const char *p, *string; int cur, index, length, numChars; @@ -2424,7 +2430,7 @@ StringEndCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_UniChar ch; + Tcl_UniChar ch = 0; const char *p, *end, *string; int cur, index, length, numChars; diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 1df7e14..54e426b 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -945,13 +945,13 @@ EXTERN void Tcl_ThreadAlert(Tcl_ThreadId threadId); EXTERN void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 320 */ -EXTERN Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index); +EXTERN int Tcl_UniCharAtIndex(const char *src, int index); /* 321 */ -EXTERN Tcl_UniChar Tcl_UniCharToLower(int ch); +EXTERN int Tcl_UniCharToLower(int ch); /* 322 */ -EXTERN Tcl_UniChar Tcl_UniCharToTitle(int ch); +EXTERN int Tcl_UniCharToTitle(int ch); /* 323 */ -EXTERN Tcl_UniChar Tcl_UniCharToUpper(int ch); +EXTERN int Tcl_UniCharToUpper(int ch); /* 324 */ EXTERN int Tcl_UniCharToUtf(int ch, char *buf); /* 325 */ @@ -1103,7 +1103,7 @@ EXTERN void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, /* 380 */ EXTERN int Tcl_GetCharLength(Tcl_Obj *objPtr); /* 381 */ -EXTERN Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index); +EXTERN int Tcl_GetUniChar(Tcl_Obj *objPtr, int index); /* 382 */ EXTERN Tcl_UniChar * Tcl_GetUnicode(Tcl_Obj *objPtr); /* 383 */ @@ -2162,10 +2162,10 @@ typedef struct TclStubs { Tcl_Obj * (*tcl_SetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, Tcl_Obj *newValuePtr, int flags); /* 317 */ void (*tcl_ThreadAlert) (Tcl_ThreadId threadId); /* 318 */ void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 319 */ - Tcl_UniChar (*tcl_UniCharAtIndex) (const char *src, int index); /* 320 */ - Tcl_UniChar (*tcl_UniCharToLower) (int ch); /* 321 */ - Tcl_UniChar (*tcl_UniCharToTitle) (int ch); /* 322 */ - Tcl_UniChar (*tcl_UniCharToUpper) (int ch); /* 323 */ + int (*tcl_UniCharAtIndex) (const char *src, int index); /* 320 */ + int (*tcl_UniCharToLower) (int ch); /* 321 */ + int (*tcl_UniCharToTitle) (int ch); /* 322 */ + int (*tcl_UniCharToUpper) (int ch); /* 323 */ int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */ CONST84_RETURN char * (*tcl_UtfAtIndex) (const char *src, int index); /* 325 */ int (*tcl_UtfCharComplete) (const char *src, int length); /* 326 */ @@ -2223,7 +2223,7 @@ typedef struct TclStubs { Tcl_Obj * (*tcl_NewUnicodeObj) (const Tcl_UniChar *unicode, int numChars); /* 378 */ void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars); /* 379 */ int (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 380 */ - Tcl_UniChar (*tcl_GetUniChar) (Tcl_Obj *objPtr, int index); /* 381 */ + int (*tcl_GetUniChar) (Tcl_Obj *objPtr, int index); /* 381 */ Tcl_UniChar * (*tcl_GetUnicode) (Tcl_Obj *objPtr); /* 382 */ Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, int first, int last); /* 383 */ void (*tcl_AppendUnicodeToObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int length); /* 384 */ diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 15411d8..987d2ae 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -2261,8 +2261,11 @@ UtfToUtfProc( const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; int result, numChars; - Tcl_UniChar ch; + Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr; + if (flags & TCL_ENCODING_START) { + *chPtr = 0; + } result = TCL_OK; srcStart = src; @@ -2311,12 +2314,14 @@ UtfToUtfProc( * incomplete char its byts are made to represent themselves. */ - ch = (unsigned char) *src; + *chPtr = (unsigned char) *src; src += 1; - dst += Tcl_UniCharToUtf(ch, dst); + dst += Tcl_UniCharToUtf(*chPtr, dst); } else { - src += Tcl_UtfToUniChar(src, &ch); - dst += Tcl_UniCharToUtf(ch, dst); + int n = Tcl_UtfToUniChar(src, chPtr); + src += n; + if (!n) numChars--; + dst += Tcl_UniCharToUtf(*chPtr, dst); } } @@ -2372,8 +2377,11 @@ UnicodeToUtfProc( const char *srcStart, *srcEnd; const char *dstEnd, *dstStart; int result, numChars; - Tcl_UniChar ch; + Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr; + if (flags & TCL_ENCODING_START) { + *chPtr = 0; + } result = TCL_OK; if ((srcLen % sizeof(Tcl_UniChar)) != 0) { result = TCL_CONVERT_MULTIBYTE; @@ -2398,11 +2406,13 @@ UnicodeToUtfProc( * Tcl_UniChar-size data. */ - ch = *(Tcl_UniChar *)src; - if (ch && ch < 0x80) { - *dst++ = (ch & 0xFF); + *chPtr = *(Tcl_UniChar *)src; + if (*chPtr && *chPtr < 0x80) { + *dst++ = (*chPtr & 0xFF); } else { - dst += Tcl_UniCharToUtf(ch, dst); + int n = Tcl_UniCharToUtf(*chPtr, dst); + dst += n; + if (!n) --numChars;/* Don't count high surrogates */ } src += sizeof(Tcl_UniChar); } @@ -2459,8 +2469,11 @@ UtfToUnicodeProc( { const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd; int result, numChars; - Tcl_UniChar ch; + Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr; + if (flags & TCL_ENCODING_START) { + *chPtr = 0; + } srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; @@ -2486,7 +2499,7 @@ UtfToUnicodeProc( result = TCL_CONVERT_NOSPACE; break; } - src += TclUtfToUniChar(src, &ch); + src += TclUtfToUniChar(src, chPtr); /* * Need to handle this in a way that won't cause misalignment by @@ -2495,11 +2508,11 @@ UtfToUnicodeProc( */ #ifdef WORDS_BIGENDIAN - *dst++ = (ch >> 8); - *dst++ = (ch & 0xFF); + *dst++ = (*chPtr >> 8); + *dst++ = (*chPtr & 0xFF); #else - *dst++ = (ch & 0xFF); - *dst++ = (ch >> 8); + *dst++ = (*chPtr & 0xFF); + *dst++ = (*chPtr >> 8); #endif } *srcReadPtr = src - srcStart; @@ -2556,7 +2569,7 @@ TableToUtfProc( const char *srcStart, *srcEnd; const char *dstEnd, *dstStart, *prefixBytes; int result, byte, numChars; - Tcl_UniChar ch; + Tcl_UniChar ch = 0; const unsigned short *const *toUnicode; const unsigned short *pageZero; TableEncodingData *dataPtr = clientData; @@ -2665,7 +2678,7 @@ TableFromUtfProc( { const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd, *prefixBytes; - Tcl_UniChar ch; + Tcl_UniChar ch = 0; int result, len, word, numChars; TableEncodingData *dataPtr = clientData; const unsigned short *const *fromUnicode; diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 691c8d7..2df935b 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -4557,7 +4557,7 @@ TEBCresume( valuePtr->bytes+index, 1); } else { char buf[TCL_UTF_MAX]; - Tcl_UniChar ch = Tcl_GetUniChar(valuePtr, index); + int ch = Tcl_GetUniChar(valuePtr, index); /* * This could be: Tcl_NewUnicodeObj((const Tcl_UniChar *)&ch, 1) diff --git a/generic/tclParse.c b/generic/tclParse.c index 3c984bf..66a1575 100644 --- a/generic/tclParse.c +++ b/generic/tclParse.c @@ -808,7 +808,7 @@ TclParseBackslash( * written there. */ { register const char *p = src+1; - Tcl_UniChar unichar; + Tcl_UniChar unichar = 0; int result; int count; char buf[TCL_UTF_MAX]; @@ -958,6 +958,15 @@ TclParseBackslash( if (readPtr != NULL) { *readPtr = count; } + if ((result & 0xF800) == 0xD800) { + /* If result is a surrogate, Tcl_UniCharToUtf will try to + * handle that especially, but we don't want that here. + */ + dst[2] = (char) ((result | 0x80) & 0xBF); + dst[1] = (char) (((result >> 6) | 0x80) & 0xBF); + dst[0] = (char) ((result >> 12) | 0xE0); + return 3; + } return Tcl_UniCharToUtf(result, dst); } @@ -1356,7 +1365,7 @@ Tcl_ParseVarName( register const char *src; unsigned char c; int varIndex, offset; - Tcl_UniChar ch; + Tcl_UniChar ch = 0; unsigned array; if ((numBytes == 0) || (start == NULL)) { diff --git a/generic/tclScan.c b/generic/tclScan.c index d21bfaf..0a6f49f 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -72,7 +72,7 @@ BuildCharSet( CharSet *cset, const char *format) /* Points to first char of set. */ { - Tcl_UniChar ch, start; + Tcl_UniChar ch = 0, start; int offset, nranges; const char *end; @@ -257,7 +257,7 @@ ValidateFormat( { int gotXpg, gotSequential, value, i, flags; char *end; - Tcl_UniChar ch; + Tcl_UniChar ch = 0; int objIndex, xpgSize, nspace = numVars; int *nassign = TclStackAlloc(interp, nspace * sizeof(int)); char buf[TCL_UTF_MAX+1]; @@ -570,7 +570,7 @@ Tcl_ScanObjCmd( char op = 0; int width, underflow = 0; Tcl_WideInt wideValue; - Tcl_UniChar ch, sch; + Tcl_UniChar ch = 0, sch = 0; Tcl_Obj **objs = NULL, *objPtr = NULL; int flags; char buf[513]; /* Temporary buffer to hold scanned number @@ -870,9 +870,15 @@ Tcl_ScanObjCmd( * Scan a single Unicode character. */ - string += Tcl_UtfToUniChar(string, &sch); + offset = Tcl_UtfToUniChar(string, &sch); + i = (int)sch; + if (!offset) { + offset = Tcl_UtfToUniChar(string, &sch); + i = (((i<<10) & 0x0FFC00) + 0x10000) + (sch & 0x3FF); + } + string += offset; if (!(flags & SCAN_SUPPRESS)) { - objPtr = Tcl_NewIntObj((int)sch); + objPtr = Tcl_NewIntObj(i); Tcl_IncrRefCount(objPtr); CLANG_ASSERT(objs); objs[objIndex++] = objPtr; diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 993a694..5838c0f 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -531,7 +531,7 @@ Tcl_GetCharLength( *---------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_GetUniChar( Tcl_Obj *objPtr, /* The object to get the Unicode charater * from. */ @@ -548,7 +548,7 @@ Tcl_GetUniChar( if (TclIsPureByteArray(objPtr)) { unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, NULL); - return (Tcl_UniChar) bytes[index]; + return (int) bytes[index]; } /* @@ -572,7 +572,7 @@ Tcl_GetUniChar( FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } - return stringPtr->unicode[index]; + return (int) stringPtr->unicode[index]; } /* @@ -1708,6 +1708,7 @@ Tcl_AppendFormatToObj( const char *span = format, *msg, *errCode; int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; int originalLength, limit; + Tcl_UniChar ch = 0; static const char *mixedXPG = "cannot mix \"%\" and \"%n$\" conversion specifiers"; static const char *const badIndex[2] = { @@ -1732,7 +1733,6 @@ Tcl_AppendFormatToObj( int width, gotPrecision, precision, useShort, useWide, useBig; int newXpg, numChars, allocSegment = 0, segmentLimit, segmentNumBytes; Tcl_Obj *segment; - Tcl_UniChar ch; int step = Tcl_UtfToUniChar(format, &ch); format += step; diff --git a/generic/tclUniData.c b/generic/tclUniData.c index 6cff83a..c5343da 100644 --- a/generic/tclUniData.c +++ b/generic/tclUniData.c @@ -151,7 +151,247 @@ static const unsigned short pageMap[] = { 42, 42, 291, 42, 291, 42, 42, 292, 56, 293, 294, 295, 42, 42, 296, 297, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 298, 299, 42, 300, 42, 301, 302, 303, 304, 305, 306, 42, 42, 42, 307, 308, 2, 309, 310, 311, - 312, 313, 314 + 312, 313, 314, 315, 316, 317, 56, 42, 42, 42, 247, 318, 319, 320, 321, + 322, 56, 323, 324, 56, 56, 56, 56, 140, 42, 325, 56, 312, 326, 327, + 56, 328, 42, 329, 56, 330, 331, 332, 42, 333, 334, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 335, 336, 337, 56, 56, 56, 56, 56, 338, 339, 56, + 56, 56, 56, 56, 56, 340, 341, 342, 343, 56, 56, 56, 56, 42, 344, 345, + 346, 56, 56, 56, 56, 42, 42, 347, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 348, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 349, 350, 351, 352, 156, 353, 354, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 355, 56, 56, 56, 56, 320, 320, 320, 356, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 355, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 357, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 358, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 146, 146, 146, 146, + 146, 146, 146, 238, 146, 359, 146, 360, 361, 362, 363, 56, 146, 146, + 364, 56, 56, 56, 56, 56, 146, 146, 365, 366, 56, 56, 56, 56, 367, 368, + 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 367, 368, 380, + 370, 381, 382, 383, 374, 384, 385, 386, 387, 388, 389, 390, 391, 392, + 393, 394, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 146, 395, 146, 146, 237, 396, 397, 56, + 398, 399, 146, 400, 401, 56, 56, 402, 403, 401, 404, 56, 56, 56, 56, + 56, 146, 405, 146, 406, 237, 146, 407, 408, 146, 249, 409, 146, 146, + 146, 146, 410, 146, 363, 323, 411, 56, 56, 56, 412, 413, 414, 415, + 56, 146, 146, 416, 56, 146, 146, 146, 237, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 232, 56, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 123, 42, 42, + 42, 42, 42, 42, 333, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 333 }; /* @@ -723,7 +963,189 @@ static const unsigned char groupMap[] = { 46, 46, 46, 46, 46, 46, 0, 0, 46, 46, 46, 46, 46, 46, 0, 0, 46, 46, 46, 46, 46, 46, 0, 0, 46, 46, 46, 0, 0, 0, 4, 4, 7, 11, 14, 4, 4, 0, 14, 7, 7, 7, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 14, - 14, 0, 0 + 14, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 46, 46, 0, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 3, 3, 14, 0, 0, 0, 0, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 18, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 85, 0, 0, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 117, 46, 46, 46, 46, 46, 46, 46, 46, 117, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 3, 46, 46, 46, 46, 0, 0, + 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 3, 117, 117, 117, 117, 117, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 0, 0, 46, 0, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 0, 46, 46, 0, 0, 0, 46, 0, 0, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 0, 3, 18, 18, 18, 18, 18, 18, 18, 18, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 18, 18, 18, 18, 18, 18, 0, 0, 0, 3, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 0, 0, 0, 0, 0, 3, 46, 85, 85, 85, 0, 85, 85, 0, 0, 0, 0, 0, 85, + 85, 85, 85, 46, 46, 46, 46, 0, 46, 46, 46, 0, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 0, 0, 0, 0, 85, 85, 85, 0, 0, 0, 0, 85, 18, 18, 18, + 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 18, 18, 3, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, + 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 115, + 85, 115, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 115, 115, + 115, 85, 85, 85, 85, 115, 115, 85, 85, 3, 3, 17, 3, 3, 3, 3, 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, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 117, + 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, 0, + 0, 0, 0, 46, 46, 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, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 115, 115, 85, 85, 85, + 14, 14, 14, 115, 115, 115, 115, 115, 115, 17, 17, 17, 17, 17, 17, 17, + 17, 85, 85, 85, 85, 85, 85, 85, 85, 14, 14, 85, 85, 85, 85, 85, 85, + 85, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 85, 85, 85, + 85, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, + 14, 85, 85, 85, 14, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 99, 0, 99, 99, 0, 0, 99, 0, 0, 99, 99, 0, 0, 99, 99, 99, 99, 0, 99, + 99, 99, 99, 99, 99, 99, 99, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, + 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, + 99, 0, 99, 99, 99, 99, 0, 0, 99, 99, 99, 99, 99, 99, 99, 99, 0, 99, + 99, 99, 99, 99, 99, 99, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, + 99, 0, 99, 99, 99, 99, 0, 99, 99, 99, 99, 99, 0, 99, 0, 0, 0, 99, 99, + 99, 99, 99, 99, 99, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, 99, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 15, 15, 15, 15, 15, 15, 0, 0, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, + 15, 15, 15, 15, 15, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 7, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 7, 15, 15, 15, 15, 15, 15, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 15, 15, + 15, 15, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 7, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 7, 15, 15, 15, 15, 15, 15, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 15, 15, 15, 15, 99, + 15, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, + 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 0, + 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 0, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, + 14, 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, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 0, 14, 0, 14, + 0, 14, 0, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, + 14, 0, 14, 0, 0, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, + 14, 14, 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 }; /* @@ -767,7 +1189,7 @@ static const int groups[] = { 13, 14, -246316991, -274694079, -270729151, 917569, 917634, 524362, 524426, 852061, 852125, -352026559, -124977087, -351502271, 353730690, 353632386, -353238975, -352223167, -353337279, -353304511, -354385855, - 238026882, -1157758911, -1385430975, 18, 17 + 238026882, -1157758911, -1385430975, 18, 17, 1310785, 1310850 }; /* @@ -775,7 +1197,8 @@ static const int groups[] = { * Unicode character. */ -#define UNICODE_CATEGORY_MASK 0X1F +#define UNICODE_CATEGORY_MASK 0x1F +#define UNICODE_OUT_OF_RANGE 0x2FA20u enum { UNASSIGNED, @@ -817,13 +1240,13 @@ enum { */ #define GetCaseType(info) (((info) & 0xE0) >> 5) -#define GetCategory(info) ((info) & 0x1F) +#define GetCategory(ch) (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) #define GetDelta(info) (((info) > 0) ? ((info) >> 15) : (~(~((info)) >> 15))) /* * This macro extracts the information about a character from the - * Unicode character tables. + * Unicode character tables. It may only be used for (unsigned) ch < UNICODE_OUT_OF_RANGE */ -#define GetUniCharInfo(ch) (groups[groupMap[(pageMap[(((int)(ch)) & 0xffff) >> OFFSET_BITS] << OFFSET_BITS) | ((ch) & ((1 << OFFSET_BITS)-1))]]) +#define GetUniCharInfo(ch) (groups[groupMap[(pageMap[((int)(ch)) >> OFFSET_BITS] << OFFSET_BITS) | ((ch) & ((1 << OFFSET_BITS)-1))]]) diff --git a/generic/tclUtf.c b/generic/tclUtf.c index ab26779..5819bcd 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -122,6 +122,11 @@ UtfCount( return 3; } #if TCL_UTF_MAX > 3 +#if TCL_UTF_MAX == 4 + if (ch <= 0x10FFFF) { + return 4; + } +#else if (ch <= 0x1FFFFF) { return 4; } @@ -132,6 +137,7 @@ UtfCount( return 6; } #endif +#endif return 3; } @@ -173,6 +179,23 @@ Tcl_UniCharToUtf( return 2; } if (ch <= 0xFFFF) { +#if TCL_UTF_MAX == 4 + if ((ch & 0xF800) == 0xD800) { + if (ch & 0x0400) { + /* Low surrogate */ + buf[3] = (char) ((ch | 0x80) & 0xBF); + buf[2] |= (char) (((ch >> 6) | 0x80) & 0x8F); + return 4; + } else { + /* High surrogate */ + ch += 0x40; + buf[2] = (char) (((ch << 4) | 0x80) & 0xB0); + buf[1] = (char) (((ch >> 2) | 0x80) & 0xBF); + buf[0] = (char) (((ch >> 8) | 0xF0) & 0xF7); + return 0; + } + } +#endif three: buf[2] = (char) ((ch | 0x80) & 0xBF); buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF); @@ -181,6 +204,15 @@ Tcl_UniCharToUtf( } #if TCL_UTF_MAX > 3 +#if TCL_UTF_MAX == 4 + if (ch <= 0x10FFFF) { + buf[3] = (char) ((ch | 0x80) & 0xBF); + buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF); + buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF); + buf[0] = (char) ((ch >> 18) | 0xF0); + return 4; + } +#else if (ch <= 0x1FFFFF) { buf[3] = (char) ((ch | 0x80) & 0xBF); buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF); @@ -206,6 +238,7 @@ Tcl_UniCharToUtf( return 6; } #endif +#endif } ch = 0xFFFD; @@ -282,6 +315,16 @@ Tcl_UniCharToUtfDString( * *chPtr is filled with the Tcl_UniChar, and the return value is the * number of bytes from the UTF-8 string that were consumed. * + * If TCL_UTF_MAX == 4, special handling of Surrogate pairs is done: + * + * If the UTF-8 string represents 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 0. Calling Tcl_UtfToUniChar again + * will produce the low surrogate and a return value of 4. Because *chPtr + * is used to remember whether the high surrogate is already produced, it + * is recommended to initialize the variable it points to as 0 before + * the first call to Tcl_UtfToUniChar is done. + * * Side effects: * None. * @@ -345,8 +388,40 @@ Tcl_UtfToUniChar( *chPtr = (Tcl_UniChar) byte; return 1; +#if TCL_UTF_MAX == 4 + } else if (byte < 0xF8) { + if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80)) { + Tcl_UniChar surrogate; + /* + * Four-byte-character lead byte followed by three trail bytes. + */ + + byte = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12) + | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F)) - 0x10000; + surrogate = 0xD800 + (byte >> 10); + if (byte & 0x100000) { + /* out of range, < 0x10000 or > 0x10ffff */ + } else if (*chPtr != surrogate) { + /* produce high surrogate, but don't advance source pointer */ + *chPtr = surrogate; + return 0; + } else { + /* produce low surrogate, and advance source pointer */ + *chPtr = (Tcl_UniChar) (0xDC00 | (byte & 0x3FF)); + return 4; + } + } + + /* + * A four-byte-character lead-byte not followed by three trail-bytes + * or representing a character < 0x10000 or > 0x10ffff represents itself. + */ + + *chPtr = (Tcl_UniChar) byte; + return 1; +#endif } -#if TCL_UTF_MAX > 3 +#if TCL_UTF_MAX > 4 { int ch, total, trail; @@ -401,7 +476,7 @@ Tcl_UtfToUniCharDString( * appended to this previously initialized * DString. */ { - Tcl_UniChar *w, *wString; + Tcl_UniChar ch, *w, *wString; const char *p, *end; int oldLength; @@ -423,8 +498,8 @@ Tcl_UtfToUniCharDString( w = wString; end = src + length; for (p = src; p < end; ) { - p += TclUtfToUniChar(p, w); - w++; + p += TclUtfToUniChar(p, &ch); + *w++ = ch; } *w = '\0'; Tcl_DStringSetLength(dsPtr, @@ -488,7 +563,7 @@ Tcl_NumUtfChars( int length) /* The length of the string in bytes, or -1 * for strlen(string). */ { - Tcl_UniChar ch; + Tcl_UniChar ch = 0; register Tcl_UniChar *chPtr = &ch; register int i; @@ -548,7 +623,7 @@ Tcl_UtfFindFirst( int ch) /* The Tcl_UniChar to search for. */ { int len; - Tcl_UniChar find; + Tcl_UniChar find = 0; while (1) { len = TclUtfToUniChar(src, &find); @@ -587,7 +662,7 @@ Tcl_UtfFindLast( int ch) /* The Tcl_UniChar to search for. */ { int len; - Tcl_UniChar find; + Tcl_UniChar find = 0; const char *last; last = NULL; @@ -627,8 +702,7 @@ const char * Tcl_UtfNext( const char *src) /* The current location in the string. */ { - Tcl_UniChar ch; - + Tcl_UniChar ch = 0; return src + TclUtfToUniChar(src, &ch); } @@ -700,16 +774,25 @@ Tcl_UtfPrev( *--------------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_UniCharAtIndex( register const char *src, /* The UTF-8 string to dereference. */ register int index) /* The position of the desired character. */ { - Tcl_UniChar ch = 0; - - while (index >= 0) { - index--; - src += TclUtfToUniChar(src, &ch); + Tcl_UniChar unichar = 0; + int bytes; + int ch = 0; + + while (index-- >= 0) { + bytes = TclUtfToUniChar(src, &unichar); + ch = unichar; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &unichar); + /* Combine surrogates */ + ch = (((ch & 0x3ff) << 10) | (unichar & 0x3ff)) + 0x10000; + } + src += bytes; } return ch; } @@ -736,11 +819,16 @@ Tcl_UtfAtIndex( register const char *src, /* The UTF-8 string. */ register int index) /* The position of the desired character. */ { - Tcl_UniChar ch; + Tcl_UniChar ch = 0; + int len; while (index > 0) { - index--; - src += TclUtfToUniChar(src, &ch); + index--; + len = TclUtfToUniChar(src, &ch); + if (!len) { + len = TclUtfToUniChar(src, &ch); + } + src += len; } return src; } @@ -820,7 +908,8 @@ int Tcl_UtfToUpper( char *str) /* String to convert in place. */ { - Tcl_UniChar ch, upChar; + Tcl_UniChar ch = 0; + int upChar; char *src, *dst; int bytes; @@ -831,7 +920,14 @@ Tcl_UtfToUpper( src = dst = str; while (*src) { bytes = TclUtfToUniChar(src, &ch); - upChar = Tcl_UniCharToUpper(ch); + upChar = ch; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &ch); + /* Combine surrogates */ + upChar = (((upChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + upChar = Tcl_UniCharToUpper(upChar); /* * To keep badly formed Utf strings from getting inflated by the @@ -873,7 +969,8 @@ int Tcl_UtfToLower( char *str) /* String to convert in place. */ { - Tcl_UniChar ch, lowChar; + Tcl_UniChar ch = 0; + int lowChar; char *src, *dst; int bytes; @@ -884,7 +981,14 @@ Tcl_UtfToLower( src = dst = str; while (*src) { bytes = TclUtfToUniChar(src, &ch); - lowChar = Tcl_UniCharToLower(ch); + lowChar = ch; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &ch); + /* Combine surrogates */ + lowChar = (((lowChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + lowChar = Tcl_UniCharToLower(lowChar); /* * To keep badly formed Utf strings from getting inflated by the @@ -927,7 +1031,8 @@ int Tcl_UtfToTitle( char *str) /* String to convert in place. */ { - Tcl_UniChar ch, titleChar, lowChar; + Tcl_UniChar ch = 0; + int titleChar, lowChar; char *src, *dst; int bytes; @@ -940,7 +1045,14 @@ Tcl_UtfToTitle( if (*src) { bytes = TclUtfToUniChar(src, &ch); - titleChar = Tcl_UniCharToTitle(ch); + titleChar = ch; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &ch); + /* Combine surrogates */ + titleChar = (((titleChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + titleChar = Tcl_UniCharToTitle(titleChar); if (bytes < UtfCount(titleChar)) { memcpy(dst, src, (size_t) bytes); @@ -952,7 +1064,14 @@ Tcl_UtfToTitle( } while (*src) { bytes = TclUtfToUniChar(src, &ch); - lowChar = Tcl_UniCharToLower(ch); + lowChar = ch; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &ch); + /* Combine surrogates */ + lowChar = (((lowChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + lowChar = Tcl_UniCharToLower(lowChar); if (bytes < UtfCount(lowChar)) { memcpy(dst, src, (size_t) bytes); @@ -1036,7 +1155,7 @@ Tcl_UtfNcmp( const char *ct, /* UTF string cs is compared to. */ unsigned long numChars) /* Number of UTF chars to compare. */ { - Tcl_UniChar ch1, ch2; + Tcl_UniChar ch1 = 0, ch2 = 0; /* * Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the @@ -1084,7 +1203,7 @@ Tcl_UtfNcasecmp( const char *ct, /* UTF string cs is compared to. */ unsigned long numChars) /* Number of UTF chars to compare. */ { - Tcl_UniChar ch1, ch2; + Tcl_UniChar ch1 = 0, ch2 = 0; while (numChars-- > 0) { /* * n must be interpreted as chars, not bytes. @@ -1120,14 +1239,14 @@ Tcl_UtfNcasecmp( *---------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_UniCharToUpper( int ch) /* Unicode character to convert. */ { - int info = GetUniCharInfo(ch); + int info = (ch < UNICODE_OUT_OF_RANGE) ? GetUniCharInfo(ch) : 0; if (GetCaseType(info) & 0x04) { - return (Tcl_UniChar) (ch - GetDelta(info)); + return ch - GetDelta(info); } else { return ch; } @@ -1149,14 +1268,14 @@ Tcl_UniCharToUpper( *---------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_UniCharToLower( int ch) /* Unicode character to convert. */ { - int info = GetUniCharInfo(ch); + int info = (ch < UNICODE_OUT_OF_RANGE) ? GetUniCharInfo(ch) : 0; if (GetCaseType(info) & 0x02) { - return (Tcl_UniChar) (ch + GetDelta(info)); + return ch + GetDelta(info); } else { return ch; } @@ -1178,11 +1297,11 @@ Tcl_UniCharToLower( *---------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_UniCharToTitle( int ch) /* Unicode character to convert. */ { - int info = GetUniCharInfo(ch); + int info = (ch < UNICODE_OUT_OF_RANGE) ? GetUniCharInfo(ch) : 0; int mode = GetCaseType(info); if (mode & 0x1) { @@ -1192,7 +1311,7 @@ Tcl_UniCharToTitle( return (Tcl_UniChar) (ch + ((mode & 0x4) ? -1 : 1)); } else if (mode == 0x4) { - return (Tcl_UniChar) (ch - GetDelta(info)); + return ch - GetDelta(info); } else { return ch; } @@ -1329,9 +1448,10 @@ int Tcl_UniCharIsAlnum( int ch) /* Unicode character to test. */ { - register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); - - return (((ALPHA_BITS | DIGIT_BITS) >> category) & 1); + if (ch > UNICODE_OUT_OF_RANGE) { + return 0; + } + return (((ALPHA_BITS | DIGIT_BITS) >> GetCategory(ch)) & 1); } /* @@ -1354,8 +1474,10 @@ int Tcl_UniCharIsAlpha( int ch) /* Unicode character to test. */ { - register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); - return ((ALPHA_BITS >> category) & 1); + if (ch > UNICODE_OUT_OF_RANGE) { + return 0; + } + return ((ALPHA_BITS >> GetCategory(ch)) & 1); } /* @@ -1378,7 +1500,10 @@ int Tcl_UniCharIsControl( int ch) /* Unicode character to test. */ { - return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) == CONTROL); + if (ch > UNICODE_OUT_OF_RANGE) { + return 0; + } + return (GetCategory(ch) == CONTROL); } /* @@ -1401,7 +1526,10 @@ int Tcl_UniCharIsDigit( int ch) /* Unicode character to test. */ { - return (GetUniCharInfo(ch)&UNICODE_CATEGORY_MASK) == DECIMAL_DIGIT_NUMBER; + if (ch > UNICODE_OUT_OF_RANGE) { + return 0; + } + return (GetCategory(ch) == DECIMAL_DIGIT_NUMBER); } /* @@ -1424,8 +1552,10 @@ int Tcl_UniCharIsGraph( int ch) /* Unicode character to test. */ { - register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); - return (((PRINT_BITS >> category) & 1) && ((unsigned char) ch != ' ')); + if ((ch == ' ') || (ch > UNICODE_OUT_OF_RANGE)) { + return (ch >= 0xE0100u) && (ch <= 0xE01EFu); + } + return ((PRINT_BITS >> GetCategory(ch)) & 1); } /* @@ -1448,7 +1578,10 @@ int Tcl_UniCharIsLower( int ch) /* Unicode character to test. */ { - return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) == LOWERCASE_LETTER); + if (ch > UNICODE_OUT_OF_RANGE) { + return 0; + } + return (GetCategory(ch) == LOWERCASE_LETTER); } /* @@ -1471,8 +1604,10 @@ int Tcl_UniCharIsPrint( int ch) /* Unicode character to test. */ { - register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); - return ((PRINT_BITS >> category) & 1); + if (ch > UNICODE_OUT_OF_RANGE) { + return (ch >= 0xE0100u) && (ch <= 0xE01EFu); + } + return ((PRINT_BITS >> GetCategory(ch)) & 1); } /* @@ -1495,8 +1630,10 @@ int Tcl_UniCharIsPunct( int ch) /* Unicode character to test. */ { - register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); - return ((PUNCT_BITS >> category) & 1); + if (ch > UNICODE_OUT_OF_RANGE) { + return 0; + } + return ((PUNCT_BITS >> GetCategory(ch)) & 1); } /* @@ -1519,8 +1656,6 @@ int Tcl_UniCharIsSpace( int ch) /* Unicode character to test. */ { - register int category; - /* * If the character is within the first 127 characters, just use the * standard C function, otherwise consult the Unicode table. @@ -1528,9 +1663,10 @@ Tcl_UniCharIsSpace( if (ch < 0x80) { return TclIsSpaceProc((char)ch); + } else if (ch > UNICODE_OUT_OF_RANGE) { + return 0; } else { - category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); - return ((SPACE_BITS >> category) & 1); + return ((SPACE_BITS >> GetCategory(ch)) & 1); } } @@ -1554,7 +1690,10 @@ int Tcl_UniCharIsUpper( int ch) /* Unicode character to test. */ { - return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) == UPPERCASE_LETTER); + if (ch > UNICODE_OUT_OF_RANGE) { + return 0; + } + return (GetCategory(ch) == UPPERCASE_LETTER); } /* @@ -1577,9 +1716,10 @@ int Tcl_UniCharIsWordChar( int ch) /* Unicode character to test. */ { - register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK); - - return (((ALPHA_BITS | DIGIT_BITS | CONNECTOR_BITS) >> category) & 1); + if (ch > UNICODE_OUT_OF_RANGE) { + return 0; + } + return (((ALPHA_BITS | DIGIT_BITS | CONNECTOR_BITS) >> GetCategory(ch)) & 1); } /* @@ -1613,7 +1753,7 @@ Tcl_UniCharCaseMatch( * characters. */ int nocase) /* 0 for case sensitive, 1 for insensitive */ { - Tcl_UniChar ch1, p; + Tcl_UniChar ch1 = 0, p; while (1) { p = *uniPattern; diff --git a/tests/encoding.test b/tests/encoding.test index a4f8449..d14d8f0 100644 --- a/tests/encoding.test +++ b/tests/encoding.test @@ -327,9 +327,14 @@ test encoding-16.1 {UnicodeToUtfProc} { set val [encoding convertfrom unicode NN] list $val [format %x [scan $val %c]] } "\u4e4e 4e4e" +test encoding-16.2 {UnicodeToUtfProc} -constraints utf16 -body { + set val [encoding convertfrom unicode "\xd8\xd8\xdc\xdc"] + list $val [format %x [scan $val %c]] +} -result "\U460dc 460dc" -test encoding-17.1 {UtfToUnicodeProc} { -} {} +test encoding-17.1 {UtfToUnicodeProc} -constraints utf16 -body { + encoding convertto unicode "\U460dc" +} -result "\xd8\xd8\xdc\xdc" test encoding-18.1 {TableToUtfProc} { } {} diff --git a/tests/string.test b/tests/string.test index 1a62a66..73640bf 100644 --- a/tests/string.test +++ b/tests/string.test @@ -571,12 +571,12 @@ test string-6.85 {string is control} { } 0 test string-6.86 {string is graph} { ## graph is any print char, except space - list [string is gra -fail var "0123abc!@#\$\u0100 "] $var -} {0 12} + list [string is gra -fail var "0123abc!@#\$\u0100\UE0100\UE01EF "] $var +} {0 14} test string-6.87 {string is print} { ## basically any printable char - list [string is print -fail var "0123abc!@#\$\u0100 \u0010"] $var -} {0 13} + list [string is print -fail var "0123abc!@#\$\u0100 \UE0100\UE01EF\u0010"] $var +} {0 15} test string-6.88 {string is punct} { ## any graph char that isn't alnum list [string is punct -fail var "_!@#\u00beq0"] $var diff --git a/tests/utf.test b/tests/utf.test index 64b5cd4..04bf9f2 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -15,6 +15,10 @@ if {[lsearch [namespace children] ::tcltest] == -1} { catch {unset x} +# Some tests require support for utf16 + +testConstraint utf16 [expr {[format %c 0x010000] != [bytestring "\xef\xbf\xbd"]}] + test utf-1.1 {Tcl_UniCharToUtf: 1 byte sequences} { set x \x01 } [bytestring "\x01"] @@ -27,10 +31,13 @@ test utf-1.3 {Tcl_UniCharToUtf: 2 byte sequences} { test utf-1.4 {Tcl_UniCharToUtf: 3 byte sequences} { set x "\u4e4e" } [bytestring "\xe4\xb9\x8e"] -test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} { +test utf-1.5 {Tcl_UniCharToUtf: 4 byte sequences} -constraints utf16 -body { + set x "\U014e4e" +} -result [bytestring "\xf0\x94\xb9\x8e"] +test utf-1.6 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} { format %c 0x110000 } [bytestring "\xef\xbf\xbd"] -test utf-1.6 {Tcl_UniCharToUtf: negative Tcl_UniChar} { +test utf-1.7 {Tcl_UniCharToUtf: negative Tcl_UniChar} { format %c -1 } [bytestring "\xef\xbf\xbd"] @@ -55,9 +62,21 @@ test utf-2.6 {Tcl_UtfToUniChar: lead (3-byte) followed by 1 trail} { test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} { string length [bytestring "\xE4\xb9\x8e"] } {1} -test utf-2.8 {Tcl_UtfToUniChar: longer UTF sequences not supported} { - string length [bytestring "\xF4\xA2\xA2\xA2"] +test utf-2.8 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} -constraints utf16 -body { + string length [bytestring "\xF0\x90\x80\x80"] +} -result {1} +test utf-2.9 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} -constraints utf16 -body { + string length [bytestring "\xF4\x8F\xBF\xBF"] +} -result {1} +test utf-2.10 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, underflow} { + string length [bytestring "\xF0\x8F\xBF\xBF"] } {4} +test utf-2.11 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, overflow} { + string length [bytestring "\xF4\x90\x80\x80"] +} {4} +test utf-2.12 {Tcl_UtfToUniChar: longer UTF sequences not supported} { + string length [bytestring "\xF8\xA2\xA2\xA2\xA2"] +} {5} test utf-3.1 {Tcl_UtfCharComplete} { } {} @@ -190,8 +209,16 @@ bsCheck \Ua1 161 bsCheck \U4e21 20001 bsCheck \U004e21 20001 bsCheck \U00004e21 20001 -bsCheck \U00110000 65533 -bsCheck \Uffffffff 65533 +bsCheck \U0000004e21 78 +if {[testConstraint utf16]} { + bsCheck \U00110000 69632 + bsCheck \U01100000 69632 + bsCheck \U11000000 69632 + bsCheck \U0010FFFF 1114111 + bsCheck \U010FFFF0 1114111 + bsCheck \U10FFFF00 1114111 + bsCheck \UFFFFFFFF 1048575 +} test utf-11.1 {Tcl_UtfToUpper} { string toupper {} @@ -259,8 +286,8 @@ test utf-16.1 {Tcl_UniCharToLower, negative delta} { string tolower aA } aa test utf-16.2 {Tcl_UniCharToLower, positive delta} { - string tolower \u0178\u00ff\uA78D -} \u00ff\u00ff\u0265 + string tolower \u0178\u00ff\uA78D\U10400 +} \u00ff\u00ff\u0265\U10428 test utf-17.1 {Tcl_UniCharToLower, no delta} { string tolower ! diff --git a/tools/uniParse.tcl b/tools/uniParse.tcl index 8576f9d..cce2138 100644 --- a/tools/uniParse.tcl +++ b/tools/uniParse.tcl @@ -44,17 +44,17 @@ proc uni::getValue {items index} { # Extract character info set category [lindex $items 2] - if {[scan [lindex $items 12] %4x toupper] == 1} { + if {[scan [lindex $items 12] %6x toupper] == 1} { set toupper [expr {$index - $toupper}] } else { set toupper {} } - if {[scan [lindex $items 13] %4x tolower] == 1} { + if {[scan [lindex $items 13] %6x tolower] == 1} { set tolower [expr {$tolower - $index}] } else { set tolower {} } - if {[scan [lindex $items 14] %4x totitle] == 1} { + if {[scan [lindex $items 14] %6x totitle] == 1} { set totitle [expr {$index - $totitle}] } else { set totitle {} @@ -101,25 +101,30 @@ proc uni::buildTables {data} { variable pMap {} variable pages {} variable groups {{0,,,}} + variable next 0 set info {} ;# temporary page info set mask [expr {(1 << $shift) - 1}] - set next 0 - foreach line [split $data \n] { if {$line eq ""} { - set line "FFFF;;Cn;0;ON;;;;;N;;;;;\n" + if {!($next & $mask)} { + # next character is already on page boundary + continue + } + # fill remaining page + set line [format %X [expr {($next-1)|$mask}]] + append line ";;Cn;0;ON;;;;;N;;;;;\n" } set items [split $line \;] scan [lindex $items 0] %x index - if {$index > 0xFFFF} then { - # Ignore non-BMP characters, as long as Tcl doesn't support them + if {$index >= 0xE0000} then { + # Ignore those characters, as they don't have case variants anyway continue } - set index [format 0x%0.4x $index] + set index [format %d $index] set gIndex [getGroup [getValue $items $index]] @@ -167,6 +172,7 @@ proc uni::main {} { variable groups variable shift variable titleCount + variable next if {$argc != 2} { puts stderr "\nusage: $argv0 \n" @@ -178,7 +184,7 @@ proc uni::main {} { buildTables $data puts "X = [llength $pMap] Y= [llength $pages] A= [llength $groups]" - set size [expr {[llength $pMap] + [llength $pages]*(1<<$shift)}] + set size [expr {[llength $pMap]*2 + [llength $pages]*(1<<$shift)}] puts "shift = $shift, space = $size" puts "title case count = $titleCount" @@ -316,15 +322,17 @@ static const int groups\[\] = {" } } puts $f $line - puts $f "}; + puts -nonewline $f "}; /* * The following constants are used to determine the category of a * Unicode character. */ -#define UNICODE_CATEGORY_MASK 0X1F - +#define UNICODE_CATEGORY_MASK 0x1F +#define UNICODE_OUT_OF_RANGE " + puts $f [format 0x%Xu $next] + puts $f " enum { UNASSIGNED, UPPERCASE_LETTER, @@ -365,15 +373,15 @@ enum { */ #define GetCaseType(info) (((info) & 0xE0) >> 5) -#define GetCategory(info) ((info) & 0x1F) +#define GetCategory(ch) (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) #define GetDelta(info) (((info) > 0) ? ((info) >> 15) : (~(~((info)) >> 15))) /* * This macro extracts the information about a character from the - * Unicode character tables. + * Unicode character tables. It may only be used for (unsigned) ch < UNICODE_OUT_OF_RANGE */ -#define GetUniCharInfo(ch) (groups\[groupMap\[(pageMap\[(((int)(ch)) & 0xffff) >> OFFSET_BITS\] << OFFSET_BITS) | ((ch) & ((1 << OFFSET_BITS)-1))\]\]) +#define GetUniCharInfo(ch) (groups\[groupMap\[(pageMap\[((int)(ch)) >> OFFSET_BITS\] << OFFSET_BITS) | ((ch) & ((1 << OFFSET_BITS)-1))\]\]) " close $f -- cgit v0.12 From 39ad9eb8f353ef5355a28d18349f6319bf9fcc9c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 24 Aug 2011 08:32:39 +0000 Subject: fix tests utf-2.8 and utf-2.9 --- generic/tclUtf.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 5819bcd..14061df 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -564,8 +564,7 @@ Tcl_NumUtfChars( * for strlen(string). */ { Tcl_UniChar ch = 0; - register Tcl_UniChar *chPtr = &ch; - register int i; + register int i, n; /* * The separate implementations are faster. @@ -577,18 +576,23 @@ Tcl_NumUtfChars( i = 0; if (length < 0) { while (*src != '\0') { - src += TclUtfToUniChar(src, chPtr); + n = TclUtfToUniChar(src, &ch); + if (!n) { + n = Tcl_UtfToUniChar(src, &ch); + } + src += n; i++; } } else { - register int n; - while (length > 0) { if (UCHAR(*src) < 0xC0) { length--; src++; } else { - n = Tcl_UtfToUniChar(src, chPtr); + n = Tcl_UtfToUniChar(src, &ch); + if (!n) { + n = Tcl_UtfToUniChar(src, &ch); + } length -= n; src += n; } @@ -823,7 +827,7 @@ Tcl_UtfAtIndex( int len; while (index > 0) { - index--; + index--; len = TclUtfToUniChar(src, &ch); if (!len) { len = TclUtfToUniChar(src, &ch); -- cgit v0.12 From dd60d528143a4f125200655aee2defc814066401 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sat, 17 Jan 2015 18:40:19 +0000 Subject: apply contributed patch which fixes a segfault --- generic/tclCmdMZ.c | 4 ++++ generic/tclStringObj.c | 31 ++++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 4ed353e..58196a3 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1085,6 +1085,10 @@ Tcl_SplitObjCmd( for ( ; stringPtr < end; stringPtr += len) { len = TclUtfToUniChar(stringPtr, &ch); + + if (!len) { + continue; + } /* * Assume Tcl_UniChar is an integral type... diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 2df6dd8..0ae5a7c 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -672,6 +672,7 @@ Tcl_GetRange( { Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */ String *stringPtr; + int i, firstoffset = 0, lastoffset = 0; /* * Optimize the case where we're really dealing with a bytearray object @@ -716,7 +717,17 @@ Tcl_GetRange( stringPtr = GET_STRING(objPtr); } - return Tcl_NewUnicodeObj(stringPtr->unicode + first, last-first+1); + for (i = 0; i <= last + lastoffset + firstoffset; i++) { + if ((stringPtr->unicode[i] & 0xfc00) == 0xd800) { + if (i < first + firstoffset) { + firstoffset++; + } else { + lastoffset++; + } + } + } + + return Tcl_NewUnicodeObj(stringPtr->unicode + first + firstoffset, last-first+1 + lastoffset + firstoffset); } /* @@ -2866,8 +2877,8 @@ ExtendUnicodeRepWithString( int numAppendChars) { String *stringPtr = GET_STRING(objPtr); - int needed, numOrigChars = 0; - Tcl_UniChar *dst; + int incr, needed, numOrigChars = 0; + Tcl_UniChar *dst, unichar = 0; if (stringPtr->hasUnicode) { numOrigChars = stringPtr->numChars; @@ -2890,7 +2901,12 @@ ExtendUnicodeRepWithString( numAppendChars = 0; } for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) { - bytes += TclUtfToUniChar(bytes, dst); + bytes += (incr = TclUtfToUniChar(bytes, &unichar)); + *dst = unichar; + if (!incr) { + bytes += TclUtfToUniChar(bytes, &unichar); + *++dst = unichar; + } } *dst = 0; } @@ -3095,7 +3111,7 @@ ExtendStringRepWithUnicode( * Pre-condition: this is the "string" Tcl_ObjType. */ - int i, origLength, size = 0; + int incr, i, origLength, size = 0, offset = 0; char *dst, buf[TCL_UTF_MAX]; String *stringPtr = GET_STRING(objPtr); @@ -3121,8 +3137,9 @@ ExtendStringRepWithUnicode( goto copyBytes; } - for (i = 0; i < numChars && size >= 0; i++) { - size += Tcl_UniCharToUtf((int) unicode[i], buf); + for (i = 0; i < numChars + offset && size >= 0; i++) { + size += (incr = Tcl_UniCharToUtf((int) unicode[i], buf)); + if (!incr) offset++; } if (size < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); -- cgit v0.12 From adceea62b6fc04fb2a4d41dd0a31adb3011c3147 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 21 Jun 2015 22:29:11 +0000 Subject: Branch for androwish, as help to keep track on which android-specific changes could be included into the core without harm. --- Android.mk | 202 ++++ debian/changelog | 23 + debian/compat | 1 + debian/control | 37 + debian/copyright | 141 +++ debian/rules | 131 ++ debian/sdltcl8.6-dev.dirs | 2 + debian/sdltcl8.6-dev.files | 2 + debian/sdltcl8.6-doc.files | 2 + debian/sdltcl8.6.files | 18 + debian/shlibs.local | 1 + generic/tclEncoding.c | 10 + generic/tclIOUtil.c | 74 +- generic/tclInt.decls | 12 + generic/tclIntDecls.h | 19 + generic/tclMain.c | 146 ++- generic/tclPkgConfig.c | 20 + generic/tclStubInit.c | 9 + generic/zcrypt.h | 131 ++ generic/zipfs.c | 2867 ++++++++++++++++++++++++++++++++++++++++++++ generic/zipfs.h | 43 + pkgs/Android.mk | 1 + tcl-config.mk | 60 + unix/Makefile.in | 11 +- unix/tclLoadDl.c | 40 +- unix/tclUnixFCmd.c | 21 + unix/tclUnixInit.c | 5 + unix/tclUnixPort.h | 2 + unix/tclUnixTime.c | 5 +- win/Makefile.in | 5 +- 30 files changed, 4027 insertions(+), 14 deletions(-) create mode 100644 Android.mk create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100755 debian/rules create mode 100644 debian/sdltcl8.6-dev.dirs create mode 100644 debian/sdltcl8.6-dev.files create mode 100644 debian/sdltcl8.6-doc.files create mode 100644 debian/sdltcl8.6.files create mode 100644 debian/shlibs.local create mode 100644 generic/zcrypt.h create mode 100644 generic/zipfs.c create mode 100644 generic/zipfs.h create mode 100644 pkgs/Android.mk create mode 100644 tcl-config.mk diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..9d8ce27 --- /dev/null +++ b/Android.mk @@ -0,0 +1,202 @@ +LOCAL_PATH := $(call my-dir) + +########################### +# +# Tcl shared library +# +########################### + +include $(CLEAR_VARS) + +tcl_path := $(LOCAL_PATH) + +include $(tcl_path)/tcl-config.mk + +LOCAL_MODULE := tcl + +LOCAL_ARM_MODE := arm + +LOCAL_C_INCLUDES := $(tcl_includes) $(LOCAL_PATH)/libtommath + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) + +LOCAL_SRC_FILES := \ + libtommath/bncore.c \ + libtommath/bn_reverse.c \ + libtommath/bn_fast_s_mp_mul_digs.c \ + libtommath/bn_fast_s_mp_sqr.c \ + libtommath/bn_mp_add.c \ + libtommath/bn_mp_add_d.c \ + libtommath/bn_mp_and.c \ + libtommath/bn_mp_clamp.c \ + libtommath/bn_mp_clear.c \ + libtommath/bn_mp_clear_multi.c \ + libtommath/bn_mp_cmp.c \ + libtommath/bn_mp_cmp_d.c \ + libtommath/bn_mp_cmp_mag.c \ + libtommath/bn_mp_copy.c \ + libtommath/bn_mp_cnt_lsb.c \ + libtommath/bn_mp_count_bits.c \ + libtommath/bn_mp_div.c \ + libtommath/bn_mp_div_d.c \ + libtommath/bn_mp_div_2.c \ + libtommath/bn_mp_div_2d.c \ + libtommath/bn_mp_div_3.c \ + libtommath/bn_mp_exch.c \ + libtommath/bn_mp_expt_d.c \ + libtommath/bn_mp_grow.c \ + libtommath/bn_mp_init.c \ + libtommath/bn_mp_init_copy.c \ + libtommath/bn_mp_init_multi.c \ + libtommath/bn_mp_init_set.c \ + libtommath/bn_mp_init_set_int.c \ + libtommath/bn_mp_init_size.c \ + libtommath/bn_mp_karatsuba_mul.c \ + libtommath/bn_mp_karatsuba_sqr.c \ + libtommath/bn_mp_lshd.c \ + libtommath/bn_mp_mod.c \ + libtommath/bn_mp_mod_2d.c \ + libtommath/bn_mp_mul.c \ + libtommath/bn_mp_mul_2.c \ + libtommath/bn_mp_mul_2d.c \ + libtommath/bn_mp_mul_d.c \ + libtommath/bn_mp_neg.c \ + libtommath/bn_mp_or.c \ + libtommath/bn_mp_radix_size.c \ + libtommath/bn_mp_radix_smap.c \ + libtommath/bn_mp_read_radix.c \ + libtommath/bn_mp_rshd.c \ + libtommath/bn_mp_set.c \ + libtommath/bn_mp_set_int.c \ + libtommath/bn_mp_shrink.c \ + libtommath/bn_mp_sqr.c \ + libtommath/bn_mp_sqrt.c \ + libtommath/bn_mp_sub.c \ + libtommath/bn_mp_sub_d.c \ + libtommath/bn_mp_to_unsigned_bin.c \ + libtommath/bn_mp_to_unsigned_bin_n.c \ + libtommath/bn_mp_toom_mul.c \ + libtommath/bn_mp_toom_sqr.c \ + libtommath/bn_mp_toradix_n.c \ + libtommath/bn_mp_unsigned_bin_size.c \ + libtommath/bn_mp_xor.c \ + libtommath/bn_mp_zero.c \ + libtommath/bn_s_mp_add.c \ + libtommath/bn_s_mp_mul_digs.c \ + libtommath/bn_s_mp_sqr.c \ + libtommath/bn_s_mp_sub.c \ + generic/regcomp.c \ + generic/regexec.c \ + generic/regfree.c \ + generic/regerror.c \ + generic/tclAlloc.c \ + generic/tclAssembly.c \ + generic/tclAsync.c \ + generic/tclBasic.c \ + generic/tclBinary.c \ + generic/tclCkalloc.c \ + generic/tclClock.c \ + generic/tclCmdAH.c \ + generic/tclCmdIL.c \ + generic/tclCmdMZ.c \ + generic/tclCompCmds.c \ + generic/tclCompCmdsGR.c \ + generic/tclCompCmdsSZ.c \ + generic/tclCompExpr.c \ + generic/tclCompile.c \ + generic/tclConfig.c \ + generic/tclDate.c \ + generic/tclDictObj.c \ + generic/tclDisassemble.c \ + generic/tclEncoding.c \ + generic/tclEnsemble.c \ + generic/tclEnv.c \ + generic/tclEvent.c \ + generic/tclExecute.c \ + generic/tclFCmd.c \ + generic/tclFileName.c \ + generic/tclGet.c \ + generic/tclHash.c \ + generic/tclHistory.c \ + generic/tclIndexObj.c \ + generic/tclInterp.c \ + generic/tclIO.c \ + generic/tclIOCmd.c \ + generic/tclIOGT.c \ + generic/tclIOSock.c \ + generic/tclIOUtil.c \ + generic/tclIORChan.c \ + generic/tclIORTrans.c \ + generic/tclLink.c \ + generic/tclListObj.c \ + generic/tclLiteral.c \ + generic/tclLoad.c \ + generic/tclMain.c \ + generic/tclNamesp.c \ + generic/tclNotify.c \ + generic/tclObj.c \ + generic/tclOptimize.c \ + generic/tclPanic.c \ + generic/tclParse.c \ + generic/tclPathObj.c \ + generic/tclPipe.c \ + generic/tclPkg.c \ + generic/tclPkgConfig.c \ + generic/tclPosixStr.c \ + generic/tclPreserve.c \ + generic/tclProc.c \ + generic/tclRegexp.c \ + generic/tclResolve.c \ + generic/tclResult.c \ + generic/tclScan.c \ + generic/tclStubInit.c \ + generic/tclStringObj.c \ + generic/tclStrToD.c \ + generic/tclThread.c \ + generic/tclThreadAlloc.c \ + generic/tclThreadJoin.c \ + generic/tclThreadStorage.c \ + generic/tclTimer.c \ + generic/tclTomMathInterface.c \ + generic/tclTrace.c \ + generic/tclUtil.c \ + generic/tclUtf.c \ + generic/tclVar.c \ + generic/tclZlib.c \ + generic/tclOO.c \ + generic/tclOOBasic.c \ + generic/tclOOCall.c \ + generic/tclOODefineCmds.c \ + generic/tclOOInfo.c \ + generic/tclOOMethod.c \ + generic/tclOOStubInit.c \ + generic/tclStubLib.c \ + generic/tclTomMathStubLib.c \ + generic/tclOOStubLib.c \ + generic/zipfs.c \ + unix/tclAppInit.c \ + unix/tclLoadDl.c \ + unix/tclUnixChan.c \ + unix/tclUnixCompat.c \ + unix/tclUnixEvent.c \ + unix/tclUnixFCmd.c \ + unix/tclUnixFile.c \ + unix/tclUnixInit.c \ + unix/tclUnixNotfy.c \ + unix/tclUnixPipe.c \ + unix/tclUnixSock.c \ + unix/tclUnixTest.c \ + unix/tclUnixThrd.c \ + unix/tclUnixTime.c + +LOCAL_CFLAGS := $(tcl_cflags) \ + -DPACKAGE_NAME="\"tcl\"" \ + -DPACKAGE_VERSION="\"8.6\"" \ + -DBUILD_tcl=1 \ + -Dmain=tclsh \ + -O2 + +LOCAL_LDLIBS := -ldl -lz -llog + +include $(BUILD_SHARED_LIBRARY) + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..caad3ba --- /dev/null +++ b/debian/changelog @@ -0,0 +1,23 @@ +sdltcl8.6 (8.6.4-1) unstable; urgency=low + + * Update to 8.6.4 + + -- Christian Werner Thu, 12 Mar 2015 22:00:00 +0100 + +sdltcl8.6 (8.6.3-1) unstable; urgency=low + + * Update to 8.6.3 + + -- Christian Werner Wed, 12 Nov 2014 20:00:00 +0100 + +sdltcl8.6 (8.6.2-1) unstable; urgency=low + + * Update to 8.6.2 + + -- Christian Werner Thu, 28 Aug 2014 07:10:10 +0200 + +sdltcl8.6 (8.6.1-1) unstable; urgency=low + + * Initial packaging + + -- Christian Werner Sat, 05 Apr 2014 14:44:48 +0200 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..3434297 --- /dev/null +++ b/debian/control @@ -0,0 +1,37 @@ +Source: sdltcl8.6 +Section: libs +Priority: optional +Maintainer: +Build-Depends: debhelper (>= 5.0.0), quilt +Standards-Version: 3.8.3 +Homepage: http://www.tcl.tk/ + +Package: sdltcl8.6 +Section: interpreters +Priority: optional +Architecture: any +Depends: ${shlibs:Depends} +Description: Tcl (the Tool Command Language) v8.6 - run-time files + Tcl is a powerful, easy to use, embeddable, cross-platform interpreted + scripting language. This package contains everything you need to run + Tcl scripts and Tcl-enabled apps. This version includes thread support. + +Package: sdltcl8.6-doc +Section: doc +Priority: optional +Architecture: all +Suggests: sdltcl8.6 +Description: Tcl (the Tool Command Language) v8.6 - manual pages + Tcl is a powerful, easy-to-use, embeddable, cross-platform interpreted + scripting language. This package contains the man pages for Tcl commands. + +Package: sdltcl8.6-dev +Section: devel +Priority: optional +Architecture: any +Depends: sdltcl8.6 (= ${binary:Version}) +Suggests: sdltcl8.6-doc +Description: Tcl (the Tool Command Language) v8.6 - development files + Tcl is a powerful, easy-to-use, embeddable, cross-platform interpreted + scripting language. This package contains the headers and libraries + needed to embed or extend Tcl. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..075c312 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,141 @@ +This package was originally debianized by David Engel +from sources obtained at http://prdownloads.sourceforge.net/tcl + +List of copyright holders mentioned in individual files: + +Copyright 1983, 1988-1994 The Regents of the University of California +Copyright 1991-1999 Karl Lehenbauer and Mark Diekhans +Copyright 1992-1996 Free Software Foundation, Inc. +Copyright 1993-1994 Lockheed Missle & Space Company, AI Center +Copyright 1993-1997 Bell Labs Innovations for Lucent Technologies +Copyright 1993-1997 Lucent Technologies +Copyright 1994-1998 Sun Microsystems, Inc. +Copyright 1995 General Electric Company +Copyright 1995 Dave Nebinger +Copyright 1995-1997 Roger E. Critchlow Jr +Copyright 1996 Lucent Technologies and Jim Ingham +Copyright 1997-2000 Ajuba Solutions +Copyright 1998-2000 Scriptics Corporation +Copyright 1998-1999 Henry Spencer +Copyright 1998 Paul Duffin +Copyright 1998 Mark Harrison +Copyright 1999 America Online, Inc. +Copyright 1999-2000 Andreas Kupries +Copyright 2000-2001 ActiveState Corporation, et al +Copyright 2001 ActiveState Tool Corp. +Copyright 2001-2002 Apple Computer, Inc. +Copyright 2001-2002 ActiveState Corporation +Copyright 2001-2002 Vincent Darley +Copyright 2001-2002 Donal K. Fellows +Copyright 2001-2003 Kevin B. Kenny +Copyright 2001-2002 David Gravereaux +Contributions from Don Porter, NIST, 2002-2003. (not subject to US copyright) +Copyright 2005 Tcl Core Team +Copyright 2005 Daniel A. Steffen + +Copyright: + +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, +and other parties. The following terms apply to all files associated +with the software unless explicitly disclaimed in individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. + +Several files are distributed under other conditions: + +compat/strftime.c: +/* + * strftime.c -- + * + * This file contains a modified version of the BSD 4.4 strftime + * function. + * + * This file is a modified version of the strftime.c file from the BSD 4.4 + * source. See the copyright notice below for details on redistribution + * restrictions. The "license.terms" file does not apply to this file. + * + * Changes 2002 Copyright (c) 2002 ActiveState Corporation. + * + * RCS: @(#) $Id: strftime.c,v 1.10.2.3 2005/11/04 18:18:04 kennykb Exp $ + */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +compat/dlfcn.h and unix/tclLoadAix.c: + * This file is subject to the following copyright notice, which is + * different from the notice used elsewhere in Tcl but rougly + * equivalent in meaning. + * + * Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH + * Not derived from licensed software. + * + * Permission is granted to freely use, copy, modify, and redistribute + * this software, provided that the author is not construed to be liable + * for any results of using the software, alterations are clearly marked + * as such, and this notice is not modified. + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..7a0214c --- /dev/null +++ b/debian/rules @@ -0,0 +1,131 @@ +#!/usr/bin/make -f +# debian/rules that uses debhelper. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) + +export QUILT_PATCHES := debian/patches + +v = 8.6 + +ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) +CFLAGS=-g -O0 +else +# See bug #446335 +CFLAGS=-g -O2 -fno-unit-at-a-time +endif + +CFLAGS+=-DZIPFS_IN_TCL=1 + +unpatch: + dh_testdir + quilt pop -a || test $$? = 2 + rm -rf patch-stamp .pc + +patch: patch-stamp +patch-stamp: + dh_testdir + quilt push -a || test $$? = 2 + touch patch-stamp + +build: build-stamp +build-stamp: patch-stamp + dh_testdir +# So so ugly but it works... + touch generic/tclStubInit.c + cd unix && \ + CFLAGS="$(CFLAGS)" \ + ac_cv_func_strtod=yes \ + tcl_cv_strtod_buggy=1 \ + ./configure --host=$(DEB_HOST_GNU_TYPE) \ + --build=$(DEB_BUILD_GNU_TYPE) \ + --prefix=/opt/sdltk86 \ + --includedir=/opt/sdltk86/include \ + --enable-shared \ + --mandir=/opt/sdltk86/man \ + --enable-man-symlinks \ + --enable-man-compression=gzip \ + --enable-threads \ + --without-tzdata && \ + touch ../generic/tclStubInit.c && \ + $(MAKE) +# Build the static library. + cd unix && \ + ar cr libtcl$(v).a *.o && \ + ar d libtcl$(v).a tclAppInit.o && \ + ranlib libtcl$(v).a + touch build-stamp + +clean: clean-patched unpatch + dh_testdir + dh_testroot + dh_clean + +clean-patched: + dh_testdir + dh_testroot + rm -f build-stamp install-stamp + cd unix && [ ! -f Makefile ] || $(MAKE) distclean +# Remove forgotten files + rm -f tests/pkg/pkga.so unix/config.log unix/Tcltest.so + +install: install-stamp +install-stamp: build-stamp + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + cd unix && \ + GZIP=-9 \ + $(MAKE) INSTALL_ROOT=`pwd`/../debian/tmp \ + MAN_INSTALL_DIR=`pwd`/../debian/tmp/opt/sdltk86/man \ + install install-private-headers install-packages +# Fix up the libraries. + cp unix/libtcl$(v).a debian/tmp/opt/sdltk86/lib + touch install-stamp + +# Build architecture-independent files here. +binary-indep: build install + dh_testdir -i + dh_testroot -i + dh_movefiles -i + dh_installdocs -i + dh_installchangelogs -i ChangeLog + dh_compress -i + dh_fixperms -i + dh_installdeb -i + dh_gencontrol -i + dh_md5sums -i + dh_builddeb -i + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir -a + dh_testroot -a + dh_movefiles -a +# now, fix up file locations for .sh + mv debian/sdltcl$(v)/opt/sdltk86/lib/tclConfig.sh \ + debian/sdltcl$(v)-dev/opt/sdltk86/lib + dh_installdocs -a + dh_installmenu -a + dh_installchangelogs -a ChangeLog + dh_fixperms -a + dh_strip -a + dh_compress -a + dh_makeshlibs -a -V 'sdltcl$(v) (>= 8.6.2)' -XTcltest + dh_installdeb -a + dh_shlibdeps -a -ldebian/sdltcl$(v)/opt/sdltk86/lib + dh_gencontrol -a + dh_md5sums -a + dh_builddeb -a + +source diff: + @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false + +binary: binary-indep binary-arch + +.PHONY: patch unpatch clean-patched build clean binary-indep binary-arch binary install + diff --git a/debian/sdltcl8.6-dev.dirs b/debian/sdltcl8.6-dev.dirs new file mode 100644 index 0000000..4de4819 --- /dev/null +++ b/debian/sdltcl8.6-dev.dirs @@ -0,0 +1,2 @@ +opt/sdltk86/lib +opt/sdltk86/include diff --git a/debian/sdltcl8.6-dev.files b/debian/sdltcl8.6-dev.files new file mode 100644 index 0000000..5cd0878 --- /dev/null +++ b/debian/sdltcl8.6-dev.files @@ -0,0 +1,2 @@ +opt/sdltk86/include +opt/sdltk86/lib/*.a diff --git a/debian/sdltcl8.6-doc.files b/debian/sdltcl8.6-doc.files new file mode 100644 index 0000000..56ca7e7 --- /dev/null +++ b/debian/sdltcl8.6-doc.files @@ -0,0 +1,2 @@ +opt/sdltk86/man/man3 +opt/sdltk86/man/mann diff --git a/debian/sdltcl8.6.files b/debian/sdltcl8.6.files new file mode 100644 index 0000000..501d10a --- /dev/null +++ b/debian/sdltcl8.6.files @@ -0,0 +1,18 @@ +opt/sdltk86/bin +opt/sdltk86/lib/tcl8 +opt/sdltk86/lib/tcl8/* +opt/sdltk86/lib/tcl8.6 +opt/sdltk86/lib/tcl8.6/* +opt/sdltk86/lib/*.so +opt/sdltk86/lib/*.sh +opt/sdltk86/lib/itcl* +opt/sdltk86/lib/itcl*/* +opt/sdltk86/lib/pkgconfig +opt/sdltk86/lib/pkgconfig/* +opt/sdltk86/lib/sqlite* +opt/sdltk86/lib/sqlite*/* +opt/sdltk86/lib/tdbc* +opt/sdltk86/lib/tdbc*/* +opt/sdltk86/lib/thread* +opt/sdltk86/lib/thread*/* +opt/sdltk86/man/man1 diff --git a/debian/shlibs.local b/debian/shlibs.local new file mode 100644 index 0000000..7da5dd4 --- /dev/null +++ b/debian/shlibs.local @@ -0,0 +1 @@ +libtcl8.6 1 diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index a7ef199..35caf11 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -496,7 +496,11 @@ FillEncodingFileMap(void) Tcl_Obj *directory, *matchFileList = Tcl_NewObj(); Tcl_Obj **filev; Tcl_GlobTypeData readableFiles = { +#ifdef ZIPFS_IN_TCL + TCL_GLOB_TYPE_FILE | TCL_GLOB_TYPE_DIR, TCL_GLOB_PERM_R, NULL, NULL +#else TCL_GLOB_TYPE_FILE, TCL_GLOB_PERM_R, NULL, NULL +#endif }; Tcl_ListObjIndex(NULL, searchPath, i, &directory); @@ -508,7 +512,13 @@ FillEncodingFileMap(void) Tcl_ListObjGetElements(NULL, matchFileList, &numFiles, &filev); for (j=0; jnextPtr) { +#ifdef ZIPFS_IN_TCL + if (fsRecPtr->fsPtr == &zipfsFilesystem) { + ClientData clientData = NULL; + /* + * Allow mounted zipfs filesystem to overtake entire normalisation. + * This is needed on unix for mounts on symlinks right below root. + */ + + if (fsRecPtr->fsPtr->pathInFilesystemProc != NULL) { + if (fsRecPtr->fsPtr->pathInFilesystemProc(pathPtr, + &clientData)!=-1) { + TclFSSetPathDetails(pathPtr, fsRecPtr->fsPtr, clientData); + break; + } + } + continue; + } +#endif if (fsRecPtr->fsPtr != &tclNativeFilesystem) { continue; } @@ -1423,6 +1455,11 @@ TclFSNormalizeToUniquePath( if (fsRecPtr->fsPtr == &tclNativeFilesystem) { continue; } +#ifdef ZIPFS_IN_TCL + if (fsRecPtr->fsPtr == &zipfsFilesystem) { + continue; + } +#endif if (fsRecPtr->fsPtr->normalizePathProc != NULL) { startAt = fsRecPtr->fsPtr->normalizePathProc(interp, pathPtr, @@ -2890,15 +2927,32 @@ int Tcl_FSChdir( Tcl_Obj *pathPtr) { - const Tcl_Filesystem *fsPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); + const Tcl_Filesystem *fsPtr, *oldFsPtr = NULL; int retVal = -1; + if (tsdPtr->cwdPathPtr != NULL) { + oldFsPtr = Tcl_FSGetFileSystemForPath(tsdPtr->cwdPathPtr); + } if (Tcl_FSGetNormalizedPath(NULL, pathPtr) == NULL) { Tcl_SetErrno(ENOENT); return retVal; } fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); + + if ((fsPtr != NULL) && (fsPtr != &tclNativeFilesystem)) { + /* + * Watch out for tilde substitution. + * Only valid in native filesystem. + */ + char *name = Tcl_GetString(pathPtr); + + if ((name != NULL) && (*name == '~')) { + fsPtr = &tclNativeFilesystem; + } + } + if (fsPtr != NULL) { if (fsPtr->chdirProc != NULL) { /* @@ -3009,6 +3063,14 @@ Tcl_FSChdir( } else { FsUpdateCwd(normDirName, NULL); } + + /* + * If the filesystem changed between old and new cwd + * force filesystem refresh on path objects. + */ + if (oldFsPtr != NULL && fsPtr != oldFsPtr) { + Tcl_FSMountsChanged(NULL); + } } return retVal; diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 9f7b106..6298708 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -1012,6 +1012,18 @@ declare 251 { int TclRegisterLiteral(void *envPtr, char *bytes, int length, int flags) } + +declare 252 { + int Tclzipfs_Init(Tcl_Interp *interp) +} +declare 253 { + int Tclzipfs_Mount(Tcl_Interp *interp, const char *zipname, + const char *mntpt, const char *passwd) +} +declare 254 { + int Tclzipfs_Unmount(Tcl_Interp *interp, const char *zipname) +} + ############################################################################## diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h index f95f999..3e74bbb 100644 --- a/generic/tclIntDecls.h +++ b/generic/tclIntDecls.h @@ -617,6 +617,16 @@ EXTERN void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags, /* 251 */ EXTERN int TclRegisterLiteral(void *envPtr, char *bytes, int length, int flags); +/* 252 */ +EXTERN int Tclzipfs_Init(Tcl_Interp *interp); +/* 253 */ +EXTERN int Tclzipfs_Mount(Tcl_Interp *interp, + const char *zipname, const char *mntpt, + const char *passwd); +/* 254 */ +EXTERN int Tclzipfs_Unmount(Tcl_Interp *interp, + const char *zipname); + typedef struct TclIntStubs { int magic; @@ -874,6 +884,9 @@ typedef struct TclIntStubs { char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */ void (*tclSetSlaveCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */ int (*tclRegisterLiteral) (void *envPtr, char *bytes, int length, int flags); /* 251 */ + int (*tclzipfs_Init) (Tcl_Interp *interp); /* 252 */ + int (*tclzipfs_Mount) (Tcl_Interp *interp, const char *zipname, const char *mntpt, const char *passwd); /* 253 */ + int (*tclzipfs_Unmount) (Tcl_Interp *interp, const char *zipname); /* 254 */ } TclIntStubs; extern const TclIntStubs *tclIntStubsPtr; @@ -1305,6 +1318,12 @@ extern const TclIntStubs *tclIntStubsPtr; (tclIntStubsPtr->tclSetSlaveCancelFlags) /* 250 */ #define TclRegisterLiteral \ (tclIntStubsPtr->tclRegisterLiteral) /* 251 */ +#define Tclzipfs_Init \ + (tclIntStubsPtr->tclzipfs_Init) /* 252 */ +#define Tclzipfs_Mount \ + (tclIntStubsPtr->tclzipfs_Mount) /* 253 */ +#define Tclzipfs_Unmount \ + (tclIntStubsPtr->tclzipfs_Unmount) /* 254 */ #endif /* defined(USE_TCL_STUBS) */ diff --git a/generic/tclMain.c b/generic/tclMain.c index 360f5e9..2c40c3f 100644 --- a/generic/tclMain.c +++ b/generic/tclMain.c @@ -34,6 +34,10 @@ #include "tclInt.h" +#ifdef ZIPFS_IN_TCL +#include "zipfs.h" +#endif + /* * The default prompt used when the user has not overridden it. */ @@ -51,6 +55,7 @@ # define TCHAR char # define TEXT(arg) arg # define _tcscmp strcmp +# define _tcsncmp strncmp #endif /* @@ -308,10 +313,16 @@ Tcl_MainEx( { Tcl_Obj *path, *resultPtr, *argvPtr, *appName; const char *encodingName = NULL; - int code, exitCode = 0; + int code, length, exitCode = 0; Tcl_MainLoopProc *mainLoopProc; Tcl_Channel chan; InteractiveState is; + const char *zipFile = NULL; + Tcl_Obj *zipval = NULL; + int autoRun = 1; +#ifdef ZIPFS_IN_TCL + int zipOk = TCL_ERROR; +#endif TclpSetInitialEncodings(); TclpFindExecutable((const char *)argv[0]); @@ -344,6 +355,24 @@ Tcl_MainEx( Tcl_DecrRefCount(value); argc -= 3; argv += 3; + } else if (argc > 2) { + length = strlen((char *) argv[1]); + if ((length >= 2) && + (0 == _tcsncmp(TEXT("-zip"), argv[1], length))) { + argc--; + argv++; + if ((argc > 1) && (argv[1][0] != (TCHAR) '-')) { + zipval = NewNativeObj(argv[1], -1); + zipFile = Tcl_GetString(zipval); + autoRun = 0; + argc--; + argv++; + } + } else if ('-' != argv[1][0]) { + Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL); + argc--; + argv++; + } } else if ((argc > 1) && ('-' != argv[1][0])) { Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL); argc--; @@ -377,6 +406,51 @@ Tcl_MainEx( Tcl_SetVar2Ex(interp, "tcl_interactive", NULL, Tcl_NewIntObj(!path && is.tty), TCL_GLOBAL_ONLY); +#ifdef ZIPFS_IN_TCL + zipOk = Tclzipfs_Init(interp); + if (zipOk == TCL_OK) { + int relax = 0; + + if (zipFile == NULL) { + relax = 1; +#ifdef ANDROID + zipFile = getenv("PACKAGE_CODE_PATH"); + if (zipFile == NULL) { + zipFile = Tcl_GetNameOfExecutable(); + } +#else + zipFile = Tcl_GetNameOfExecutable(); +#endif + } + if (zipFile != NULL) { + zipOk = Tclzipfs_Mount(interp, zipFile, "", NULL); + if (!relax && (zipOk != TCL_OK)) { + exitCode = 1; + goto done; + } + } else { + zipOk = TCL_ERROR; + } + Tcl_ResetResult(interp); + } + if (zipOk == TCL_OK) { + char *tcl_lib = "/assets/tcl" TCL_VERSION; + char *tcl_pkg = "/assets"; + + Tcl_SetVar2(interp, "env", "TCL_LIBRARY", tcl_lib, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "tcl_libPath", tcl_lib, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "tcl_library", tcl_lib, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "tcl_pkgPath", tcl_pkg, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "auto_path", tcl_lib, + TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT); + + } +#endif + if (zipval != NULL) { + Tcl_DecrRefCount(zipval); + zipval = NULL; + } + /* * Invoke application-specific initialization. */ @@ -406,6 +480,76 @@ Tcl_MainEx( Tcl_CreateExitHandler(FreeMainInterp, interp); } +#ifdef ZIPFS_IN_TCL + /* + * Setup auto loading info to point to mounted ZIP file. + */ + + if (zipOk == TCL_OK) { + char *tcl_lib = "/assets/tcl" TCL_VERSION; + char *tcl_pkg = "/assets"; + + Tcl_SetVar(interp, "tcl_libPath", tcl_lib, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "tcl_library", tcl_lib, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "tcl_pkgPath", tcl_pkg, TCL_GLOBAL_ONLY); + + /* + * We need to re-init encoding (after initializing Tcl), + * otherwise "encoding system" will return "identity" + */ + + TclpSetInitialEncodings(); + } + + /* + * Set embedded application startup file, if any. + */ + + if ((zipOk == TCL_OK) && autoRun) { + char *filename; + Tcl_Channel chan; + + filename = "/assets/app/main.tcl"; + chan = Tcl_OpenFileChannel(NULL, filename, "r", 0); + if (chan != (Tcl_Channel) NULL) { + Tcl_Obj *arg; + + Tcl_Close(NULL, chan); + + /* + * Push back script file to argv, if any. + */ + if ((arg = Tcl_GetStartupScript(NULL)) != NULL) { + Tcl_Obj *v, *no; + + no = Tcl_NewStringObj("argv", 4); + v = Tcl_ObjGetVar2(interp, no, NULL, TCL_GLOBAL_ONLY); + if (v != NULL) { + Tcl_Obj **objv, *nv; + int objc, i; + + objc = 0; + Tcl_ListObjGetElements(NULL, v, &objc, &objv); + nv = Tcl_NewListObj(1, &arg); + for (i = 0; i < objc; i++) { + Tcl_ListObjAppendElement(NULL, nv, objv[i]); + } + Tcl_IncrRefCount(nv); + if (Tcl_ObjSetVar2(interp, no, NULL, nv, TCL_GLOBAL_ONLY) + != NULL) { + Tcl_GlobalEval(interp, "incr argc"); + } + Tcl_DecrRefCount(nv); + } + Tcl_DecrRefCount(no); + } + Tcl_SetStartupScript(Tcl_NewStringObj(filename, -1), NULL); + Tcl_SetVar(interp, "argv0", filename, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY); + } + } +#endif + /* * Invoke the script specified on the command line, if any. Must fetch it * again, as the appInitProc might have reset it. diff --git a/generic/tclPkgConfig.c b/generic/tclPkgConfig.c index 466d535..3f8178e 100644 --- a/generic/tclPkgConfig.c +++ b/generic/tclPkgConfig.c @@ -100,19 +100,35 @@ static Tcl_Config const cfg[] = { /* Runtime paths to various stuff */ +#ifdef ANDROID + {"libdir,runtime", ""}, + {"bindir,runtime", ""}, + {"scriptdir,runtime", ""}, + {"includedir,runtime", ""}, + {"docdir,runtime", ""}, +#else {"libdir,runtime", CFG_RUNTIME_LIBDIR}, {"bindir,runtime", CFG_RUNTIME_BINDIR}, {"scriptdir,runtime", CFG_RUNTIME_SCRDIR}, {"includedir,runtime", CFG_RUNTIME_INCDIR}, {"docdir,runtime", CFG_RUNTIME_DOCDIR}, +#endif /* Installation paths to various stuff */ +#ifdef ANDROID + {"libdir,install", ""}, + {"bindir,install", ""}, + {"scriptdir,install", ""}, + {"includedir,install", ""}, + {"docdir,install", ""}, +#else {"libdir,install", CFG_INSTALL_LIBDIR}, {"bindir,install", CFG_INSTALL_BINDIR}, {"scriptdir,install", CFG_INSTALL_SCRDIR}, {"includedir,install", CFG_INSTALL_INCDIR}, {"docdir,install", CFG_INSTALL_DOCDIR}, +#endif /* Last entry, closes the array */ {NULL, NULL} @@ -123,6 +139,10 @@ TclInitEmbeddedConfigurationInformation( Tcl_Interp *interp) /* Interpreter the configuration command is * registered in. */ { +#if defined(ANDROID) && !defined(TCL_CFGVAL_ENCODING) +#define TCL_CFGVAL_ENCODING "utf-8" +#endif + Tcl_RegisterConfig(interp, "tcl", cfg, TCL_CFGVAL_ENCODING); } diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 7a84cba..d3e0afa 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -560,6 +560,15 @@ static const TclIntStubs tclIntStubs = { TclDoubleDigits, /* 249 */ TclSetSlaveCancelFlags, /* 250 */ TclRegisterLiteral, /* 251 */ +#ifdef ZIPFS_IN_TCL + Tclzipfs_Init, /* 252 */ + Tclzipfs_Mount, /* 253 */ + Tclzipfs_Unmount, /* 254 */ +#else + 0, /* 252 */ + 0, /* 253 */ + 0, /* 254 */ +#endif }; static const TclIntPlatStubs tclIntPlatStubs = { diff --git a/generic/zcrypt.h b/generic/zcrypt.h new file mode 100644 index 0000000..eb9865b --- /dev/null +++ b/generic/zcrypt.h @@ -0,0 +1,131 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned int* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned int* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned int* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(const char* passwd, /* password string */ + unsigned char* buf, /* where to write header */ + int bufSize, + unsigned long* pkeys, + const unsigned int* pcrc_32_tab, + unsigned long crcForCrypting) +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/generic/zipfs.c b/generic/zipfs.c new file mode 100644 index 0000000..ec58d9f --- /dev/null +++ b/generic/zipfs.c @@ -0,0 +1,2867 @@ +#if !defined(_WIN32) && !defined(_WIN64) +#include +#endif +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ZLIB +#include "zlib.h" +#include "zcrypt.h" +#endif +#include "tclInt.h" +#include "tclFileSystem.h" +#include "zipfs.h" + +#ifdef HAVE_ZLIB + +#define ZIP_SIG_LEN 4 + +#define ZIP_LOCAL_HEADER_SIG 0x04034b50 +#define ZIP_LOCAL_HEADER_LEN 30 +#define ZIP_LOCAL_SIG_OFFS 0 +#define ZIP_LOCAL_VERSION_OFFS 4 +#define ZIP_LOCAL_FLAGS_OFFS 6 +#define ZIP_LOCAL_COMPMETH_OFFS 8 +#define ZIP_LOCAL_MTIME_OFFS 10 +#define ZIP_LOCAL_MDATE_OFFS 12 +#define ZIP_LOCAL_CRC32_OFFS 14 +#define ZIP_LOCAL_COMPLEN_OFFS 18 +#define ZIP_LOCAL_UNCOMPLEN_OFFS 22 +#define ZIP_LOCAL_PATHLEN_OFFS 26 +#define ZIP_LOCAL_EXTRALEN_OFFS 28 + +#define ZIP_CENTRAL_HEADER_SIG 0x02014b50 +#define ZIP_CENTRAL_HEADER_LEN 46 +#define ZIP_CENTRAL_SIG_OFFS 0 +#define ZIP_CENTRAL_VERSIONMADE_OFFS 4 +#define ZIP_CENTRAL_VERSION_OFFS 6 +#define ZIP_CENTRAL_FLAGS_OFFS 8 +#define ZIP_CENTRAL_COMPMETH_OFFS 10 +#define ZIP_CENTRAL_MTIME_OFFS 12 +#define ZIP_CENTRAL_MDATE_OFFS 14 +#define ZIP_CENTRAL_CRC32_OFFS 16 +#define ZIP_CENTRAL_COMPLEN_OFFS 20 +#define ZIP_CENTRAL_UNCOMPLEN_OFFS 24 +#define ZIP_CENTRAL_PATHLEN_OFFS 28 +#define ZIP_CENTRAL_EXTRALEN_OFFS 30 +#define ZIP_CENTRAL_FCOMMENTLEN_OFFS 32 +#define ZIP_CENTRAL_DISKFILE_OFFS 34 +#define ZIP_CENTRAL_IATTR_OFFS 36 +#define ZIP_CENTRAL_EATTR_OFFS 38 +#define ZIP_CENTRAL_LOCALHDR_OFFS 42 + +#define ZIP_CENTRAL_END_SIG 0x06054b50 +#define ZIP_CENTRAL_END_LEN 22 +#define ZIP_CENTRAL_END_SIG_OFFS 0 +#define ZIP_CENTRAL_DISKNO_OFFS 4 +#define ZIP_CENTRAL_DISKDIR_OFFS 6 +#define ZIP_CENTRAL_ENTS_OFFS 8 +#define ZIP_CENTRAL_TOTALENTS_OFFS 10 +#define ZIP_CENTRAL_DIRSIZE_OFFS 12 +#define ZIP_CENTRAL_DIRSTART_OFFS 16 +#define ZIP_CENTRAL_COMMENTLEN_OFFS 20 + +#define ZIP_MIN_VERSION 20 +#define ZIP_COMPMETH_STORED 0 +#define ZIP_COMPMETH_DEFLATED 8 + +#define ZIP_PASSWORD_END_SIG 0x5a5a4b50 + +#define zip_read_int(p) \ + ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24)) +#define zip_read_short(p) \ + ((p)[0] | ((p)[1] << 8)) + +#define zip_write_int(p, v) \ + (p)[0] = (v) & 0xff; (p)[1] = ((v) >> 8) & 0xff; \ + (p)[2] = ((v) >> 16) & 0xff; (p)[3] = ((v) >> 24) & 0xff; +#define zip_write_short(p, v) \ + (p)[0] = (v) & 0xff; (p)[1] = ((v) >> 8) & 0xff; + +#if defined(_WIN32) || defined(_WIN64) +static CONST char alpha[] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +#endif + +#if !defined(_WIN32) && !defined(_WIN64) +#ifndef HAVE_LOCALTIME_R +TCL_DECLARE_MUTEX(localtimeMutex) +#endif +#endif + +typedef struct ZipFile { + char *name; /* Archive name */ + Tcl_Channel chan; /* Channel handle or NULL */ + unsigned char *data; /* Memory mapped or malloc'ed file */ + long length; /* Length of memory mapped file */ + unsigned char *tofree; /* Non-NULL if malloc'ed file */ + int nfiles; /* Number of files in archive */ + int baseoffs; /* Archive start */ + int baseoffsp; /* Password start */ + int centoffs; /* Archive directory start */ + char pwbuf[264]; /* Password buffer */ +#if defined(_WIN32) || defined(_WIN64) + HANDLE mh; +#endif + int nopen; /* Number of open files on archive */ + struct ZipEntry *entries; /* List of files in archive */ + struct ZipEntry *topents; /* List of top-level dirs in archive */ + int mntptlen; /* Length of mount point */ + char mntpt[1]; /* Mount point */ +} ZipFile; + +typedef struct ZipEntry { + char *name; /* The full pathname of the virtual file */ + ZipFile *zipfile; /* The ZIP file holding this virtual file */ + long offset; /* Data offset into memory mapped ZIP file */ + int nbyte; /* Uncompressed size of the virtual file */ + int nbytecompr; /* Compressed size of the virtual file */ + int cmeth; /* Compress method */ + int isdir; /* Set to 1 if directory */ + int depth; /* Number of slashes in path. */ + int crc32; /* CRC-32 */ + int timestamp; /* Modification time */ + int isenc; /* True if data is encrypted */ + unsigned char *data; /* File data if written */ + struct ZipEntry *next; /* Next file in the same archive */ + struct ZipEntry *tnext; /* Next top-level dir in archive */ +} ZipEntry; + +typedef struct ZipChannel { + ZipFile *zipfile; /* The ZIP file holding this channel */ + ZipEntry *zipentry; /* Pointer back to virtual file */ + unsigned long nmax; /* Max. size for write */ + unsigned long nbyte; /* Number of bytes of uncompressed data */ + unsigned long nread; /* Pos of next byte to be read from the channel */ + unsigned char *ubuf; /* Pointer to the uncompressed data */ + int iscompr; /* True if data is compressed */ + int isdir; /* Set to 1 if directory */ + int isenc; /* True if data is encrypted */ + int iswr; /* True if open for writing */ + unsigned long keys[3]; /* Key for decryption */ +} ZipChannel; + +static struct { + int initialized; /* True when initialized */ + int lock; /* RW lock, see below */ + int waiters; /* RW lock, see below */ + int wrmax; /* Maximum write size of a file */ + Tcl_HashTable fileHash; /* File name to ZipEntry mapping */ + Tcl_HashTable zipHash; /* Mount to ZipFile mapping */ +} ZipFS = { + 0, 0, 0, 0, +}; + +/* POSIX like rwlock (multiple reader, single writer) */ + +TCL_DECLARE_MUTEX(ZipFSMutex) +static Tcl_Condition ZipFSCond; + +static void +ReadLock(void) +{ + Tcl_MutexLock(&ZipFSMutex); + while (ZipFS.lock < 0) { + ZipFS.waiters++; + Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, NULL); + ZipFS.waiters--; + } + ZipFS.lock++; + Tcl_MutexUnlock(&ZipFSMutex); +} + +static void +WriteLock(void) +{ + Tcl_MutexLock(&ZipFSMutex); + while (ZipFS.lock != 0) { + ZipFS.waiters++; + Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, NULL); + ZipFS.waiters--; + } + ZipFS.lock = -1; + Tcl_MutexUnlock(&ZipFSMutex); +} + +static void +Unlock(void) +{ + Tcl_MutexLock(&ZipFSMutex); + if (ZipFS.lock > 0) { + --ZipFS.lock; + } else if (ZipFS.lock < 0) { + ZipFS.lock = 0; + } + if ((ZipFS.lock == 0) && (ZipFS.waiters > 0)) { + Tcl_ConditionNotify(&ZipFSCond); + } + Tcl_MutexUnlock(&ZipFSMutex); +} + +static CONST char pwrot[16] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 +}; + +static CONST unsigned int crc32tab[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d, +}; + +static time_t +DosTimeDate(int dosDate, int dosTime) +{ + time_t now; + struct tm *tmp, tm; + + now = time(NULL); +#if defined(_WIN32) || defined(_WIN64) + tmp = localtime(&now); + tm = *tmp; +#else +#ifdef HAVE_LOCALTIME_R + tmp = &tm; + localtime_r(&now, tmp); +#else + Tcl_MutexLock(&localtimeMutex); + tmp = localtime(&now); + tm = *tmp; + Tcl_MutexUnlock(&localtimeMutex); +#endif +#endif + tm.tm_year = (((dosDate & 0xfe00) >> 9) + 80); + tm.tm_mon = ((dosDate & 0x1e0) >> 5) - 1; + tm.tm_mday = dosDate & 0x1f; + tm.tm_hour = (dosTime & 0xf800) >> 11; + tm.tm_min = (dosTime & 0x7e) >> 5; + tm.tm_sec = (dosTime & 0x1f) << 1; + return mktime(&tm); +} + +static int +ToDosTime(time_t when) +{ + struct tm *tmp, tm; + +#if defined(_WIN32) || defined(_WIN64) + tmp = localtime(&when); + tm = *tmp; +#else +#ifdef HAVE_LOCALTIME_R + tmp = &tm; + localtime_r(&when, tmp); +#else + Tcl_MutexLock(&localtimeMutex); + tmp = localtime(&when); + tm = *tmp; + Tcl_MutexUnlock(&localtimeMutex); +#endif +#endif + return (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec >> 1); +} + +static int +ToDosDate(time_t when) +{ + struct tm *tmp, tm; + +#if defined(_WIN32) || defined(_WIN64) + tmp = localtime(&when); + tm = *tmp; +#else +#ifdef HAVE_LOCALTIME_R + tmp = &tm; + localtime_r(&when, tmp); +#else + Tcl_MutexLock(&localtimeMutex); + tmp = localtime(&when); + tm = *tmp; + Tcl_MutexUnlock(&localtimeMutex); +#endif +#endif + return ((tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday; +} + +static int +CountSlashes(CONST char *string) +{ + int count = 0; + CONST char *p = string; + + while (*p != '\0') { + if (*p == '/') { + count++; + } + p++; + } + return count; +} + +static char * +CanonicalPath(CONST char *root, CONST char *tail, Tcl_DString *dsPtr) +{ + char *path; + int i, j, c, isunc = 0; + +#if defined(_WIN32) || defined(_WIN64) + if ((tail[0] != '\0') && (strchr(alpha, tail[0]) != NULL) && + (tail[1] == ':')) { + tail += 2; + } + /* UNC style path */ + if (tail[0] == '\\') { + root = ""; + ++tail; + } + if (tail[0] == '\\') { + root = "/"; + ++tail; + } +#endif + /* UNC style path */ + if ((root[0] == '/') && (root[1] == '/')) { + isunc = 1; + } + if (tail[0] == '/') { + root = ""; + ++tail; + isunc = 0; + } + if (tail[0] == '/') { + root = "/"; + ++tail; + isunc = 1; + } + i = strlen(root); + j = strlen(tail); + Tcl_DStringSetLength(dsPtr, i + j + 1); + path = Tcl_DStringValue(dsPtr); + memcpy(path, root, i); + path[i++] = '/'; + memcpy(path + i, tail, j); +#if defined(_WIN32) || defined(_WIN64) + for (i = 0; path[i] != '\0'; i++) { + if (path[i] == '\\') { + path[i] = '/'; + } + } +#endif + for (i = j = 0; (c = path[i]) != '\0'; i++) { + if (c == '/') { + int c2 = path[i + 1]; + + if (c2 == '/') { + continue; + } + if (c2 == '.') { + int c3 = path[i + 2]; + + if ((c3 == '/') || (c3 == '\0')) { + i++; + continue; + } + if ((c3 == '.') && + ((path[i + 3] == '/') || (path [i + 3] == '\0'))) { + i += 2; + while ((j > 0) && (path[j - 1] != '/')) { + j--; + } + if (j > isunc) { + --j; + while ((j > 1 + isunc) && (path[j - 2] == '/')) { + j--; + } + } + continue; + } + } + } + path[j++] = c; + } + if (j == 0) { + path[j++] = '/'; + } + path[j] = 0; + Tcl_DStringSetLength(dsPtr, j); + return Tcl_DStringValue(dsPtr); +} + +static char * +AbsolutePath(CONST char *path, Tcl_DString *dsPtr) +{ + char *result; + + if (*path == '~') { + Tcl_DStringAppend(dsPtr, path, -1); + return Tcl_DStringValue(dsPtr); + } + if ((*path != '/') +#if defined(_WIN32) || defined(_WIN64) + && (*path != '\\') && + (((*path != '\0') && (strchr(alpha, *path) == NULL)) || + (path[1] != ':')) +#endif + ) { + Tcl_DString pwd; + + /* relative path */ + Tcl_DStringInit(&pwd); + Tcl_GetCwd(NULL, &pwd); + result = Tcl_DStringValue(&pwd); +#if defined(_WIN32) || defined(_WIN64) + if ((result[0] != '\0') && (strchr(alpha, result[0]) != NULL) && + (result[1] == ':')) { + result += 2; + } +#endif + result = CanonicalPath(result, path, dsPtr); + Tcl_DStringFree(&pwd); + } else { + /* absolute path */ + result = CanonicalPath("", path, dsPtr); + } + return result; +} + +static ZipEntry * +ZipFSLookup(char *filename) +{ + char *realname; + Tcl_HashEntry *hPtr; + ZipEntry *z; + Tcl_DString ds; + + Tcl_DStringInit(&ds); + realname = AbsolutePath(filename, &ds); + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, realname); + z = hPtr ? (ZipEntry *) Tcl_GetHashValue(hPtr) : NULL; + Tcl_DStringFree(&ds); + return z; +} + +#ifdef NEVER_USED +static int +ZipFSLookupMount(char *filename) +{ + char *realname; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + ZipFile *zf; + Tcl_DString ds; + int match = 0; + + Tcl_DStringInit(&ds); + realname = AbsolutePath(filename, &ds); + hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); + while (hPtr != NULL) { + if ((zf = (ZipFile *) Tcl_GetHashValue(hPtr)) != NULL) { + if (strcmp(zf->mntpt, realname) == 0) { + match = 1; + break; + } + } + hPtr = Tcl_NextHashEntry(&search); + } + Tcl_DStringFree(&ds); + return match; +} +#endif + +static void +ZipFSCloseArchive(Tcl_Interp *interp, ZipFile *zf) +{ +#if defined(_WIN32) || defined(_WIN64) + if ((zf->data != NULL) && (zf->tofree == NULL)) { + UnmapViewOfFile(zf->data); + zf->data = NULL; + } + if (zf->mh != INVALID_HANDLE_VALUE) { + CloseHandle(zf->mh); + } +#else + if ((zf->data != MAP_FAILED) && (zf->tofree == NULL)) { + munmap(zf->data, zf->length); + zf->data = MAP_FAILED; + } +#endif + if (zf->tofree != NULL) { + Tcl_Free((char *) zf->tofree); + zf->tofree = NULL; + } + Tcl_Close(interp, zf->chan); + zf->chan = NULL; +} + +static int +ZipFSOpenArchive(Tcl_Interp *interp, CONST char *zipname, int needZip, + ZipFile *zf) +{ + int i; + ClientData handle; + unsigned char *p, *q; + +#if defined(_WIN32) || defined(_WIN64) + zf->data = NULL; + zf->mh = INVALID_HANDLE_VALUE; +#else + zf->data = MAP_FAILED; +#endif + zf->length = 0; + zf->nfiles = 0; + zf->baseoffs = zf->baseoffsp = 0; + zf->tofree = NULL; + zf->pwbuf[0] = 0; + zf->chan = Tcl_OpenFileChannel(interp, zipname, "r", 0); + if (zf->chan == NULL) { + return TCL_ERROR; + } + if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) != TCL_OK) { + if (Tcl_SetChannelOption(interp, zf->chan, "-translation", "binary") + != TCL_OK) { + goto error; + } + if (Tcl_SetChannelOption(interp, zf->chan, "-encoding", "binary") + != TCL_OK) { + goto error; + } + zf->length = Tcl_Seek(zf->chan, 0, SEEK_END); + if ((zf->length <= 0) || (zf->length > 64 * 1024 * 1024)) { + if (interp) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("illegal file size", -1)); + } + goto error; + } + Tcl_Seek(zf->chan, 0, SEEK_SET); + zf->tofree = zf->data = (unsigned char *) Tcl_Alloc(zf->length); + i = Tcl_Read(zf->chan, (char *) zf->data, zf->length); + if (i != zf->length) { + if (interp) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("file read error", -1)); + } + goto error; + } + Tcl_Close(interp, zf->chan); + zf->chan = NULL; + } else { +#if defined(_WIN32) || defined(_WIN64) + zf->length = GetFileSize((HANDLE) handle, 0); + if ((zf->length == INVALID_FILE_SIZE) || + (zf->length < ZIP_CENTRAL_END_LEN)) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("invalid file size", -1)); + } + goto error; + } + zf->mh = CreateFileMapping((HANDLE) handle, 0, PAGE_READONLY, 0, + zf->length, 0); + if (zf->mh == INVALID_HANDLE_VALUE) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("file mapping failed", -1)); + } + goto error; + } + zf->data = MapViewOfFile(zf->mh, FILE_MAP_READ, 0, 0, zf->length); + if (zf->data == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("file mapping failed", -1)); + } + goto error; + } +#else + zf->length = lseek((int) (long) handle, 0, SEEK_END); + if ((zf->length == -1) || (zf->length < ZIP_CENTRAL_END_LEN)) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("invalid file size", -1)); + } + goto error; + } + lseek((int) (long) handle, 0, SEEK_SET); + zf->data = (unsigned char *) mmap(0, zf->length, PROT_READ, + MAP_FILE | MAP_PRIVATE, + (int) (long) handle, 0); + if (zf->data == MAP_FAILED) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("file mapping failed", -1)); + } + goto error; + } +#endif + } + p = zf->data + zf->length - ZIP_CENTRAL_END_LEN; + while (p >= zf->data) { + if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) { + if (zip_read_int(p) == ZIP_CENTRAL_END_SIG) { + break; + } + p -= ZIP_SIG_LEN; + } else { + --p; + } + } + if (p < zf->data) { + if (!needZip) { + zf->baseoffs = zf->baseoffsp = zf->length; + return TCL_OK; + } + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("wrong end signature", -1)); + } + goto error; + } + zf->nfiles = zip_read_short(p + ZIP_CENTRAL_ENTS_OFFS); + if (zf->nfiles == 0) { + if (!needZip) { + zf->baseoffs = zf->baseoffsp = zf->length; + return TCL_OK; + } + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("empty archive", -1)); + } + goto error; + } + q = zf->data + zip_read_int(p + ZIP_CENTRAL_DIRSTART_OFFS); + p -= zip_read_int(p + ZIP_CENTRAL_DIRSIZE_OFFS); + if ((p < zf->data) || (p > (zf->data + zf->length)) || + (q < zf->data) || (q > (zf->data + zf->length))) { + if (!needZip) { + zf->baseoffs = zf->baseoffsp = zf->length; + return TCL_OK; + } + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("archive directory not found", -1)); + } + goto error; + } + zf->baseoffs = zf->baseoffsp = p - q; + zf->centoffs = p - zf->data; + q = p; + for (i = 0; i < zf->nfiles; i++) { + int pathlen, comlen, extra; + + if ((q + ZIP_CENTRAL_HEADER_LEN) > (zf->data + zf->length)) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("wrong header length", -1)); + } + goto error; + } + if (zip_read_int(q) != ZIP_CENTRAL_HEADER_SIG) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("wrong header signature", -1)); + } + goto error; + } + pathlen = zip_read_short(q + ZIP_CENTRAL_PATHLEN_OFFS); + comlen = zip_read_short(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); + extra = zip_read_short(q + ZIP_CENTRAL_EXTRALEN_OFFS); + q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; + } + q = zf->data + zf->baseoffs; + if ((zf->baseoffs >= 6) && + (zip_read_int(q - 4) == ZIP_PASSWORD_END_SIG)) { + i = q[-5]; + if (q - 5 - i > zf->data) { + zf->pwbuf[0] = i; + memcpy(zf->pwbuf + 1, q - 5 - i, i); + zf->baseoffsp -= i ? (5 + i) : 0; + } + } + return TCL_OK; + +error: + ZipFSCloseArchive(interp, zf); + return TCL_ERROR; +} + +int +Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, + CONST char *passwd) +{ + char *realname; + int i, pwlen, isNew; + ZipFile *zf, zf0; + ZipEntry *z; + Tcl_HashEntry *hPtr; + Tcl_DString ds, fpBuf; + unsigned char *q; + + ReadLock(); + if (!ZipFS.initialized) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("not initialized", -1)); + } + Unlock(); + return TCL_ERROR; + } + if (zipname == NULL) { + Tcl_HashSearch search; + int ret = TCL_OK; + + i = 0; + hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); + while (hPtr != NULL) { + if ((zf = (ZipFile *) Tcl_GetHashValue(hPtr)) != NULL) { + if (interp != NULL) { + Tcl_AppendElement(interp, zf->mntpt); + Tcl_AppendElement(interp, zf->name); + } + ++i; + } + hPtr = Tcl_NextHashEntry(&search); + } + if (interp == NULL) { + ret = (i > 0) ? TCL_OK : TCL_BREAK; + } + Unlock(); + return ret; + } + if (mntpt == NULL) { + if (interp == NULL) { + Unlock(); + return TCL_OK; + } + Tcl_DStringInit(&ds); + hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, AbsolutePath(zipname, &ds)); + if (hPtr != NULL) { + if ((zf = Tcl_GetHashValue(hPtr)) != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->mntpt, -1)); + } + } + Unlock(); + Tcl_DStringFree(&ds); + return TCL_OK; + } + Unlock(); + pwlen = 0; + if (passwd != NULL) { + pwlen = strlen(passwd); + if ((pwlen > 255) || (strchr(passwd, 0xff) != NULL)) { + if (interp) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("illegal password", -1)); + } + return TCL_ERROR; + } + } + if (ZipFSOpenArchive(interp, zipname, 1, &zf0) != TCL_OK) { + return TCL_ERROR; + } + Tcl_DStringInit(&ds); + realname = AbsolutePath(zipname, &ds); + WriteLock(); + hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, realname, &isNew); + Tcl_DStringSetLength(&ds, 0); + if (!isNew) { + zf = (ZipFile *) Tcl_GetHashValue(hPtr); + if (interp != NULL) { + Tcl_AppendResult(interp, "already mounted at ", zf->mntpt, + (char *) NULL); + } + goto error; + } + if (strcmp(mntpt, "/") == 0) { + mntpt = ""; + } + zf = (ZipFile *) Tcl_Alloc(sizeof (*zf) + strlen(mntpt) + 1); + *zf = zf0; + zf->name = Tcl_GetHashKey(&ZipFS.zipHash, hPtr); + strcpy(zf->mntpt, mntpt); + zf->mntptlen = strlen(zf->mntpt); + zf->entries = NULL; + zf->topents = NULL; + zf->nopen = 0; + Tcl_SetHashValue(hPtr, (ClientData) zf); + if ((zf->pwbuf[0] == 0) && pwlen) { + int k = 0; + + i = pwlen; + zf->pwbuf[k++] = i; + while (i > 0) { + zf->pwbuf[k] = (passwd[i - 1] & 0x0f) | + pwrot[(passwd[i - 1] >> 4) & 0x0f]; + k++; + i--; + } + zf->pwbuf[k] = '\0'; + } + if (mntpt[0] != '\0') { + z = (ZipEntry *) Tcl_Alloc(sizeof (*z)); + z->name = NULL; + z->tnext = NULL; + z->depth = CountSlashes(mntpt); + z->zipfile = zf; + z->isdir = 1; + z->isenc = 0; + z->offset = zf->baseoffs; + z->crc32 = 0; + z->timestamp = 0; + z->nbyte = z->nbytecompr = 0; + z->cmeth = ZIP_COMPMETH_STORED; + z->data = NULL; + hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, mntpt, &isNew); + if (!isNew) { + /* skip it */ + Tcl_Free((char *) z); + } else { + Tcl_SetHashValue(hPtr, (ClientData) z); + z->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + z->next = zf->entries; + zf->entries = z; + } + } + q = zf->data + zf->centoffs; + Tcl_DStringInit(&fpBuf); + for (i = 0; i < zf->nfiles; i++) { + int pathlen, comlen, extra, isdir = 0, dosTime, dosDate, nbcompr, offs; + unsigned char *lq, *gq = NULL; + char *fullpath, *path; + + pathlen = zip_read_short(q + ZIP_CENTRAL_PATHLEN_OFFS); + comlen = zip_read_short(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); + extra = zip_read_short(q + ZIP_CENTRAL_EXTRALEN_OFFS); + Tcl_DStringSetLength(&ds, 0); + Tcl_DStringAppend(&ds, (char *) q + ZIP_CENTRAL_HEADER_LEN, pathlen); + path = Tcl_DStringValue(&ds); + if ((pathlen > 0) && (path[pathlen - 1] == '/')) { + Tcl_DStringSetLength(&ds, pathlen - 1); + path = Tcl_DStringValue(&ds); + isdir = 1; + } + if ((strcmp(path, ".") == 0) || (strcmp(path, "..") == 0)) { + goto nextent; + } + lq = zf->data + zf->baseoffs + + zip_read_int(q + ZIP_CENTRAL_LOCALHDR_OFFS); + if ((lq < zf->data) || (lq > (zf->data + zf->length))) { + goto nextent; + } + nbcompr = zip_read_int(lq + ZIP_LOCAL_COMPLEN_OFFS); + if (!isdir && (nbcompr == 0) && + (zip_read_int(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0) && + (zip_read_int(lq + ZIP_LOCAL_CRC32_OFFS) == 0)) { + gq = q; + nbcompr = zip_read_int(gq + ZIP_CENTRAL_COMPLEN_OFFS); + } + offs = (lq - zf->data) + + ZIP_LOCAL_HEADER_LEN + + zip_read_short(lq + ZIP_LOCAL_PATHLEN_OFFS) + + zip_read_short(lq + ZIP_LOCAL_EXTRALEN_OFFS); + if ((offs + nbcompr) > zf->length) { + goto nextent; + } + if (!isdir && (mntpt[0] == '\0') && !CountSlashes(path)) { + goto nextent; + } + Tcl_DStringSetLength(&fpBuf, 0); + fullpath = CanonicalPath(mntpt, path, &fpBuf); + z = (ZipEntry *) Tcl_Alloc(sizeof (*z)); + z->name = NULL; + z->tnext = NULL; + z->depth = CountSlashes(fullpath); + z->zipfile = zf; + z->isdir = isdir; + z->isenc = (zip_read_short(lq + ZIP_LOCAL_FLAGS_OFFS) & 1) + && (nbcompr > 12); + z->offset = offs; + if (gq != NULL) { + z->crc32 = zip_read_int(gq + ZIP_CENTRAL_CRC32_OFFS); + dosDate = zip_read_short(gq + ZIP_CENTRAL_MDATE_OFFS); + dosTime = zip_read_short(gq + ZIP_CENTRAL_MTIME_OFFS); + z->timestamp = DosTimeDate(dosDate, dosTime); + z->nbyte = zip_read_int(gq + ZIP_CENTRAL_UNCOMPLEN_OFFS); + z->cmeth = zip_read_short(gq + ZIP_CENTRAL_COMPMETH_OFFS); + } else { + z->crc32 = zip_read_int(lq + ZIP_LOCAL_CRC32_OFFS); + dosDate = zip_read_short(lq + ZIP_LOCAL_MDATE_OFFS); + dosTime = zip_read_short(lq + ZIP_LOCAL_MTIME_OFFS); + z->timestamp = DosTimeDate(dosDate, dosTime); + z->nbyte = zip_read_int(lq + ZIP_LOCAL_UNCOMPLEN_OFFS); + z->cmeth = zip_read_short(lq + ZIP_LOCAL_COMPMETH_OFFS); + } + z->nbytecompr = nbcompr; + z->data = NULL; + hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, fullpath, &isNew); + if (!isNew) { + /* skip it */ + Tcl_Free((char *) z); + } else { + Tcl_SetHashValue(hPtr, (ClientData) z); + z->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + z->next = zf->entries; + zf->entries = z; + if (isdir && (mntpt[0] == '\0') && (z->depth == 1)) { + z->tnext = zf->topents; + zf->topents = z; + } + if (!z->isdir && (z->depth > 1)) { + char *dir, *end; + ZipEntry *zd; + + Tcl_DStringSetLength(&ds, strlen(z->name) + 8); + Tcl_DStringSetLength(&ds, 0); + Tcl_DStringAppend(&ds, z->name, -1); + dir = Tcl_DStringValue(&ds); + end = strrchr(dir, '/'); + while ((end != NULL) && (end != dir)) { + Tcl_DStringSetLength(&ds, end - dir); + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, dir); + if (hPtr != NULL) { + break; + } + zd = (ZipEntry *) Tcl_Alloc(sizeof (*zd)); + zd->name = NULL; + zd->tnext = NULL; + zd->depth = CountSlashes(dir); + zd->zipfile = zf; + zd->isdir = 1; + zd->isenc = 0; + zd->offset = z->offset; + zd->crc32 = 0; + zd->timestamp = z->timestamp; + zd->nbyte = zd->nbytecompr = 0; + zd->cmeth = ZIP_COMPMETH_STORED; + zd->data = NULL; + hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, dir, &isNew); + if (!isNew) { + /* should never happen but skip it */ + Tcl_Free((char *) zd); + } else { + Tcl_SetHashValue(hPtr, (ClientData) zd); + zd->name = Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + zd->next = zf->entries; + zf->entries = zd; + if ((mntpt[0] == '\0') && (zd->depth == 1)) { + zd->tnext = zf->topents; + zf->topents = zd; + } + } + end = strrchr(dir, '/'); + } + } + } +nextent: + q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; + } + Tcl_DStringFree(&fpBuf); + Tcl_DStringFree(&ds); + Unlock(); + Tcl_FSMountsChanged(NULL); + return TCL_OK; + +error: + Tcl_DStringFree(&ds); + Unlock(); + ZipFSCloseArchive(interp, zf); + Tcl_Free((char *) zf); + return TCL_ERROR; +} + +int +Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname) +{ + char *realname; + ZipFile *zf; + ZipEntry *z, *znext; + Tcl_HashEntry *hPtr; + Tcl_DString ds; + int ret = TCL_OK, unmounted = 0; + + Tcl_DStringInit(&ds); + realname = AbsolutePath(zipname, &ds); + WriteLock(); + if (!ZipFS.initialized) { + goto done; + } + hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, realname); + if (hPtr == NULL) { + /* does not report error */ + goto done; + } + zf = (ZipFile *) Tcl_GetHashValue(hPtr); + if (zf->nopen > 0) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("filesystem is busy", -1)); + } + ret = TCL_ERROR; + goto done; + } + Tcl_DeleteHashEntry(hPtr); + for (z = zf->entries; z; z = znext) { + znext = z->next; + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name); + if (hPtr) { + Tcl_DeleteHashEntry(hPtr); + } + if (z->data != NULL) { + Tcl_Free((char *) z->data); + } + Tcl_Free((char *) z); + } + ZipFSCloseArchive(interp, zf); + Tcl_Free((char *) zf); + unmounted = 1; +done: + Unlock(); + Tcl_DStringFree(&ds); + if (unmounted) { + Tcl_FSMountsChanged(NULL); + } + return ret; +} + +static int +ZipFSMountCmd(ClientData clientData, Tcl_Interp *interp, + int argc, CONST char **argv) +{ + if (argc > 4) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ?zipfile ?mountpoint? ?password???\"", 0); + return TCL_ERROR; + } + return Zipfs_Mount(interp, (argc > 1) ? argv[1] : NULL, + (argc > 2) ? argv[2] : NULL, + (argc > 3) ? argv[3] : NULL); +} + +static int +ZipFSUnmountCmd(ClientData clientData, Tcl_Interp *interp, + int argc, CONST char **argv) +{ + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " zipfile\"", (char *) NULL); + return TCL_ERROR; + } + return Zipfs_Unmount(interp, argv[1]); +} + +static int +ZipFSMkKeyCmd(ClientData clientData, Tcl_Interp *interp, + int argc, CONST char **argv) +{ + int len, i = 0; + char pwbuf[264]; + + if (argc != 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " password\"", (char *) NULL); + return TCL_ERROR; + } + len = strlen(argv[1]); + if (len == 0) { + return TCL_OK; + } + if ((len > 255) || (strchr(argv[1], 0xff) != NULL)) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("illegal password", -1)); + return TCL_ERROR; + } + while (len > 0) { + int ch = argv[1][len - 1]; + + pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; + i++; + len--; + } + pwbuf[i] = i; + ++i; + pwbuf[i++] = (char) ZIP_PASSWORD_END_SIG; + pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8); + pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16); + pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24); + pwbuf[i] = '\0'; + Tcl_AppendResult(interp, pwbuf, (char *) NULL); + return TCL_OK; +} + +static int +ZipAddFile(Tcl_Interp *interp, CONST char *path, Tcl_Channel out, + CONST char *passwd, char *buf, int bufsize, Tcl_HashTable *fileHash) +{ + Tcl_Channel in; + Tcl_HashEntry *hPtr; + ZipEntry *z; + z_stream stream; + CONST char *zpath; + int nbyte, nbytecompr, len, crc, flush, pos[3], zpathlen, olen; + int mtime = 0, isNew, align = 0, cmeth; + unsigned long keys[3], keys0[3]; + char obuf[4096]; + + zpath = path; + while (zpath != NULL && zpath[0] == '/') { + zpath++; + } + if ((zpath == NULL) || (zpath[0] == '\0')) { + return TCL_OK; + } + zpathlen = strlen(zpath); + if (zpathlen + ZIP_CENTRAL_HEADER_LEN > bufsize) { + Tcl_AppendResult(interp, "path too long for \"", path, "\"", + (char *) NULL); + return TCL_ERROR; + } + in = Tcl_OpenFileChannel(interp, path, "r", 0); + if ((in == NULL) || + (Tcl_SetChannelOption(interp, in, "-translation", "binary") + != TCL_OK) || + (Tcl_SetChannelOption(interp, in, "-encoding", "binary") + != TCL_OK)) { +#if defined(_WIN32) || defined(_WIN64) + /* hopefully a directory */ + if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) { + Tcl_Close(interp, in); + return TCL_OK; + } +#endif + Tcl_Close(interp, in); + return TCL_ERROR; + } else { + Tcl_Obj *pathObj = Tcl_NewStringObj(path, -1); + Tcl_StatBuf statBuf; + + Tcl_IncrRefCount(pathObj); + if (Tcl_FSStat(pathObj, &statBuf) != -1) { + mtime = statBuf.st_mtime; + } + Tcl_DecrRefCount(pathObj); + } + Tcl_ResetResult(interp); + crc = 0; + nbyte = nbytecompr = 0; + while ((len = Tcl_Read(in, buf, bufsize)) > 0) { + crc = crc32(crc, (unsigned char *) buf, len); + nbyte += len; + } + if (len == -1) { + if (nbyte == 0) { + if (strcmp("illegal operation on a directory", + Tcl_PosixError(interp)) == 0) { + Tcl_Close(interp, in); + return TCL_OK; + } + } + Tcl_AppendResult(interp, "read error on \"", path, "\"", + (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } + if (Tcl_Seek(in, 0, SEEK_SET) == -1) { + Tcl_AppendResult(interp, "seek error on \"", path, "\"", + (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } + pos[0] = Tcl_Tell(out); + memset(buf, '\0', ZIP_LOCAL_HEADER_LEN); + memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpath, zpathlen); + len = zpathlen + ZIP_LOCAL_HEADER_LEN; + if (Tcl_Write(out, buf, len) != len) { +wrerr: + Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } + if ((len + pos[0]) & 3) { + char abuf[8]; + + /* + * Align payload to next 4-byte boundary using a dummy extra + * entry similar to the zipalign tool from Android's SDK. + */ + align = 4 + ((len + pos[0]) & 3); + zip_write_short(abuf, 0xffff); + zip_write_short(abuf + 2, align - 4); + zip_write_int(abuf + 4, 0x03020100); + if (Tcl_Write(out, abuf, align) != align) { + goto wrerr; + } + } + if (passwd != NULL) { + int i, ch, tmp; + unsigned char kvbuf[24]; + Tcl_Obj *ret; + + init_keys(passwd, keys, crc32tab); + for (i = 0; i < 12 - 2; i++) { + if (Tcl_Eval(interp, "expr int(rand() * 256) % 256") != TCL_OK) { + Tcl_AppendResult(interp, "PRNG error", (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } + ret = Tcl_GetObjResult(interp); + if (Tcl_GetIntFromObj(interp, ret, &ch) != TCL_OK) { + Tcl_Close(interp, in); + return TCL_ERROR; + } + kvbuf[i + 12] = (unsigned char) zencode(keys, crc32tab, ch, tmp); + } + Tcl_ResetResult(interp); + init_keys(passwd, keys, crc32tab); + for (i = 0; i < 12 - 2; i++) { + kvbuf[i] = (unsigned char) zencode(keys, crc32tab, + kvbuf[i + 12], tmp); + } + kvbuf[i++] = (unsigned char) zencode(keys, crc32tab, crc >> 16, tmp); + kvbuf[i++] = (unsigned char) zencode(keys, crc32tab, crc >> 24, tmp); + len = Tcl_Write(out, (char *) kvbuf, 12); + memset(kvbuf, 0, 24); + if (len != 12) { + Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } + memcpy(keys0, keys, sizeof (keys0)); + nbytecompr += 12; + } + Tcl_Flush(out); + pos[2] = Tcl_Tell(out); + cmeth = ZIP_COMPMETH_DEFLATED; + memset(&stream, 0, sizeof (stream)); + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + if (deflateInit2(&stream, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) + != Z_OK) { + Tcl_AppendResult(interp, "compression init error on \"", path, "\"", + (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } + do { + len = Tcl_Read(in, buf, bufsize); + if (len == -1) { + Tcl_AppendResult(interp, "read error on \"", path, "\"", + (char *) NULL); + deflateEnd(&stream); + Tcl_Close(interp, in); + return TCL_ERROR; + } + stream.avail_in = len; + stream.next_in = (unsigned char *) buf; + flush = Tcl_Eof(in) ? Z_FINISH : Z_NO_FLUSH; + do { + stream.avail_out = sizeof (obuf); + stream.next_out = (unsigned char *) obuf; + len = deflate(&stream, flush); + if (len == Z_STREAM_ERROR) { + Tcl_AppendResult(interp, "deflate error on \"", path, "\"", + (char *) NULL); + deflateEnd(&stream); + Tcl_Close(interp, in); + return TCL_ERROR; + } + olen = sizeof (obuf) - stream.avail_out; + if (passwd != NULL) { + int i, tmp; + + for (i = 0; i < olen; i++) { + obuf[i] = (char) zencode(keys, crc32tab, obuf[i], tmp); + } + } + if (olen && (Tcl_Write(out, obuf, olen) != olen)) { + Tcl_AppendResult(interp, "write error", (char *) NULL); + deflateEnd(&stream); + Tcl_Close(interp, in); + return TCL_ERROR; + } + nbytecompr += olen; + } while (stream.avail_out == 0); + } while (flush != Z_FINISH); + deflateEnd(&stream); + Tcl_Flush(out); + pos[1] = Tcl_Tell(out); + if (nbyte - nbytecompr <= 0) { + /* + * Compressed file larger than input, + * write it again uncompressed. + */ + if ((int) Tcl_Seek(in, 0, SEEK_SET) != 0) { + goto seekErr; + } + if ((int) Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) { +seekErr: + Tcl_Close(interp, in); + Tcl_AppendResult(interp, "seek error", (char *) NULL); + return TCL_ERROR; + } + nbytecompr = (passwd != NULL) ? 12 : 0; + while (1) { + len = Tcl_Read(in, buf, bufsize); + if (len == -1) { + Tcl_AppendResult(interp, "read error on \"", path, "\"", + (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } else if (len == 0) { + break; + } + if (passwd != NULL) { + int i, tmp; + + for (i = 0; i < len; i++) { + buf[i] = (char) zencode(keys0, crc32tab, buf[i], tmp); + } + } + if (Tcl_Write(out, buf, len) != len) { + Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_Close(interp, in); + return TCL_ERROR; + } + nbytecompr += len; + } + cmeth = ZIP_COMPMETH_STORED; + Tcl_Flush(out); + pos[1] = Tcl_Tell(out); + Tcl_TruncateChannel(out, pos[1]); + } + Tcl_Close(interp, in); + + z = (ZipEntry *) Tcl_Alloc(sizeof (*z)); + z->name = NULL; + z->tnext = NULL; + z->depth = 0; + z->zipfile = NULL; + z->isdir = 0; + z->isenc = (passwd != NULL) ? 1 : 0; + z->offset = pos[0]; + z->crc32 = crc; + z->timestamp = mtime; + z->nbyte = nbyte; + z->nbytecompr = nbytecompr; + z->cmeth = cmeth; + z->data = NULL; + hPtr = Tcl_CreateHashEntry(fileHash, zpath, &isNew); + if (!isNew) { + Tcl_AppendResult(interp, "not unique path name \"", path, "\"", + (char *) NULL); + Tcl_Free((char *) z); + return TCL_ERROR; + } else { + Tcl_SetHashValue(hPtr, (ClientData) z); + z->name = Tcl_GetHashKey(fileHash, hPtr); + z->next = NULL; + } + + /* + * Write final local header information. + */ + zip_write_int(buf + ZIP_LOCAL_SIG_OFFS, ZIP_LOCAL_HEADER_SIG); + zip_write_short(buf + ZIP_LOCAL_VERSION_OFFS, ZIP_MIN_VERSION); + zip_write_short(buf + ZIP_LOCAL_FLAGS_OFFS, z->isenc); + zip_write_short(buf + ZIP_LOCAL_COMPMETH_OFFS, z->cmeth); + zip_write_short(buf + ZIP_LOCAL_MTIME_OFFS, ToDosTime(z->timestamp)); + zip_write_short(buf + ZIP_LOCAL_MDATE_OFFS, ToDosDate(z->timestamp)); + zip_write_int(buf + ZIP_LOCAL_CRC32_OFFS, z->crc32); + zip_write_int(buf + ZIP_LOCAL_COMPLEN_OFFS, z->nbytecompr); + zip_write_int(buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->nbyte); + zip_write_short(buf + ZIP_LOCAL_PATHLEN_OFFS, zpathlen); + zip_write_short(buf + ZIP_LOCAL_EXTRALEN_OFFS, align); + if ((int) Tcl_Seek(out, pos[0], SEEK_SET) != pos[0]) { + Tcl_DeleteHashEntry(hPtr); + Tcl_Free((char *) z); + Tcl_AppendResult(interp, "seek error", (char *) NULL); + return TCL_ERROR; + } + if (Tcl_Write(out, buf, ZIP_LOCAL_HEADER_LEN) != ZIP_LOCAL_HEADER_LEN) { + Tcl_DeleteHashEntry(hPtr); + Tcl_Free((char *) z); + Tcl_AppendResult(interp, "write error", (char *) NULL); + return TCL_ERROR; + } + Tcl_Flush(out); + if ((int) Tcl_Seek(out, pos[1], SEEK_SET) != pos[1]) { + Tcl_DeleteHashEntry(hPtr); + Tcl_Free((char *) z); + Tcl_AppendResult(interp, "seek error", (char *) NULL); + return TCL_ERROR; + } + return TCL_OK; +} + +static int +ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, + int isImg, int argc, CONST char **argv) +{ + Tcl_Channel out; + int len = 0, pwlen = 0, i, ret = TCL_ERROR, largc, pos[3]; + CONST char **largv; + Tcl_DString ds; + ZipEntry *z; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + Tcl_HashTable fileHash; + char pwbuf[264], buf[4096]; + + if ((argc < 3) || (argc > (isImg ? 5 : 4))) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " outfile indir ?password?", + isImg ? " ?infile?\"" : "\"", (char *) NULL); + return TCL_ERROR; + } + pwbuf[0] = 0; + if (argc > 3) { + pwlen = strlen(argv[3]); + if ((pwlen > 255) || (strchr(argv[1], 0xff) != NULL)) { + Tcl_AppendResult(interp, "illegal password", (char *) NULL); + return TCL_ERROR; + } + } + Tcl_DStringInit(&ds); + Tcl_DStringAppendElement(&ds, "::zipfs::find"); + Tcl_DStringAppendElement(&ds, argv[2]); + if (Tcl_Eval(interp, Tcl_DStringValue(&ds)) != TCL_OK) { + Tcl_DStringFree(&ds); + return TCL_ERROR; + } + Tcl_DStringFree(&ds); + if (Tcl_SplitList(interp, Tcl_GetStringResult(interp), &largc, &largv) + != TCL_OK) { + return TCL_ERROR; + } + Tcl_ResetResult(interp); + if (largc == 0) { + Tcl_Free((char *) largv); + Tcl_AppendResult(interp, "empty archive", (char *) NULL); + return TCL_ERROR; + } + out = Tcl_OpenFileChannel(interp, argv[1], "w", 0755); + if ((out == NULL) || + (Tcl_SetChannelOption(interp, out, "-translation", "binary") + != TCL_OK) || + (Tcl_SetChannelOption(interp, out, "-encoding", "binary") + != TCL_OK)) { + Tcl_Close(interp, out); + Tcl_Free((char *) largv); + return TCL_ERROR; + } + if (isImg) { + ZipFile zf0; + + if (ZipFSOpenArchive(interp, (argc > 4) ? argv[4] : + Tcl_GetNameOfExecutable(), 0, &zf0) != TCL_OK) { + Tcl_Close(interp, out); + Tcl_Free((char *) largv); + return TCL_ERROR; + } + if (pwlen && (argc > 3)) { + i = 0; + len = pwlen; + while (len > 0) { + int ch = argv[3][len - 1]; + + pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; + i++; + len--; + } + pwbuf[i] = i; + ++i; + pwbuf[i++] = (char) ZIP_PASSWORD_END_SIG; + pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8); + pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16); + pwbuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24); + pwbuf[i] = '\0'; + } + i = Tcl_Write(out, (char *) zf0.data, zf0.baseoffsp); + if (i != zf0.baseoffsp) { + Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_Close(interp, out); + Tcl_Free((char *) largv); + ZipFSCloseArchive(interp, &zf0); + return TCL_ERROR; + } + ZipFSCloseArchive(interp, &zf0); + len = strlen(pwbuf); + if (len > 0) { + i = Tcl_Write(out, pwbuf, len); + if (i != len) { + Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_Close(interp, out); + Tcl_Free((char *) largv); + return TCL_ERROR; + } + } + memset(pwbuf, 0, sizeof (pwbuf)); + Tcl_Flush(out); + } + Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS); + pos[0] = Tcl_Tell(out); + for (i = 0; i < largc; i++) { + if (ZipAddFile(interp, largv[i], out, (pwlen > 0) ? argv[3] : NULL, + buf, sizeof (buf), &fileHash) + != TCL_OK) { + goto done; + } + } + pos[1] = Tcl_Tell(out); + hPtr = Tcl_FirstHashEntry(&fileHash, &search); + i = 0; + while (hPtr != NULL) { + z = (ZipEntry *) Tcl_GetHashValue(hPtr); + len = strlen(z->name); + zip_write_int(buf + ZIP_CENTRAL_SIG_OFFS, ZIP_CENTRAL_HEADER_SIG); + zip_write_short(buf + ZIP_CENTRAL_VERSIONMADE_OFFS, ZIP_MIN_VERSION); + zip_write_short(buf + ZIP_CENTRAL_VERSION_OFFS, ZIP_MIN_VERSION); + zip_write_short(buf + ZIP_CENTRAL_FLAGS_OFFS, z->isenc ? 1 : 0); + zip_write_short(buf + ZIP_CENTRAL_COMPMETH_OFFS, z->cmeth); + zip_write_short(buf + ZIP_CENTRAL_MTIME_OFFS, ToDosTime(z->timestamp)); + zip_write_short(buf + ZIP_CENTRAL_MDATE_OFFS, ToDosDate(z->timestamp)); + zip_write_int(buf + ZIP_CENTRAL_CRC32_OFFS, z->crc32); + zip_write_int(buf + ZIP_CENTRAL_COMPLEN_OFFS, z->nbytecompr); + zip_write_int(buf + ZIP_CENTRAL_UNCOMPLEN_OFFS, z->nbyte); + zip_write_short(buf + ZIP_CENTRAL_PATHLEN_OFFS, len); + zip_write_short(buf + ZIP_CENTRAL_EXTRALEN_OFFS, 0); + zip_write_short(buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0); + zip_write_short(buf + ZIP_CENTRAL_DISKFILE_OFFS, 0); + zip_write_short(buf + ZIP_CENTRAL_IATTR_OFFS, 0); + zip_write_int(buf + ZIP_CENTRAL_EATTR_OFFS, 0); + zip_write_int(buf + ZIP_CENTRAL_LOCALHDR_OFFS, z->offset - pos[0]); + memcpy(buf + ZIP_CENTRAL_HEADER_LEN, z->name, len); + len += ZIP_CENTRAL_HEADER_LEN; + if (Tcl_Write(out, buf, len) != len) { + Tcl_AppendResult(interp, "write error", (char *) NULL); + goto done; + } + hPtr = Tcl_NextHashEntry(&search); + ++i; + } + Tcl_Flush(out); + pos[2] = Tcl_Tell(out); + zip_write_int(buf + ZIP_CENTRAL_END_SIG_OFFS, ZIP_CENTRAL_END_SIG); + zip_write_short(buf + ZIP_CENTRAL_DISKNO_OFFS, 0); + zip_write_short(buf + ZIP_CENTRAL_DISKDIR_OFFS, 0); + zip_write_short(buf + ZIP_CENTRAL_ENTS_OFFS, i); + zip_write_short(buf + ZIP_CENTRAL_TOTALENTS_OFFS, i); + zip_write_int(buf + ZIP_CENTRAL_DIRSIZE_OFFS, pos[2] - pos[1]); + zip_write_int(buf + ZIP_CENTRAL_DIRSTART_OFFS, pos[1] - pos[0]); + zip_write_short(buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0); + if (Tcl_Write(out, buf, ZIP_CENTRAL_END_LEN) != ZIP_CENTRAL_END_LEN) { + Tcl_AppendResult(interp, "write error", (char *) NULL); + goto done; + } + Tcl_Flush(out); + ret = TCL_OK; +done: + Tcl_Free((char *) largv); + Tcl_Close(interp, out); + hPtr = Tcl_FirstHashEntry(&fileHash, &search); + while (hPtr != NULL) { + z = (ZipEntry *) Tcl_GetHashValue(hPtr); + Tcl_Free((char *) z); + Tcl_DeleteHashEntry(hPtr); + hPtr = Tcl_FirstHashEntry(&fileHash, &search); + } + Tcl_DeleteHashTable(&fileHash); + return ret; +} + +static int +ZipFSMkZipCmd(ClientData clientData, Tcl_Interp *interp, + int argc, CONST char **argv) +{ + return ZipFSMkZipOrImgCmd(clientData, interp, 0, argc, argv); +} + +static int +ZipFSMkImgCmd(ClientData clientData, Tcl_Interp *interp, + int argc, CONST char **argv) +{ + return ZipFSMkZipOrImgCmd(clientData, interp, 1, argc, argv); +} + +static int +ZipFSExistsObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + char *filename; + int exists; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "filename"); + return TCL_ERROR; + } + filename = Tcl_GetStringFromObj(objv[1], 0); + ReadLock(); + exists = ZipFSLookup(filename) != NULL; + Unlock(); + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), exists); + return TCL_OK; +} + +static int +ZipFSInfoObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + char *filename; + ZipEntry *z; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "filename"); + return TCL_ERROR; + } + filename = Tcl_GetStringFromObj(objv[1], 0); + ReadLock(); + z = ZipFSLookup(filename); + if (z != NULL) { + Tcl_Obj *result = Tcl_GetObjResult(interp); + + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(z->zipfile->name, -1)); + Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(z->nbyte)); + Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(z->nbytecompr)); + Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(z->offset)); + } + Unlock(); + return TCL_OK; +} + +static int +ZipFSListObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + char *pattern = NULL; + Tcl_RegExp regexp = NULL; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + Tcl_Obj *result = Tcl_GetObjResult(interp); + + if (objc > 3) { + Tcl_WrongNumArgs(interp, 1, objv, "?(-glob|-regexp)? ?pattern?"); + return TCL_ERROR; + } + if (objc == 3) { + int n; + char *what = Tcl_GetStringFromObj(objv[1], &n); + + if ((n >= 2) && (strncmp(what, "-glob", n) == 0)) { + pattern = Tcl_GetString(objv[2]); + } else if ((n >= 2) && (strncmp(what, "-regexp", n) == 0)) { + regexp = Tcl_RegExpCompile(interp, Tcl_GetString(objv[2])); + if (regexp == NULL) { + return TCL_ERROR; + } + } else { + Tcl_AppendResult(interp, "unknown option: ", what, (char *) NULL); + return TCL_ERROR; + } + } else if (objc == 2) { + pattern = Tcl_GetStringFromObj(objv[1], 0); + } + ReadLock(); + if (pattern != NULL) { + for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); + + if (Tcl_StringMatch(z->name, pattern)) { + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(z->name, -1)); + } + } + } else if (regexp != NULL) { + for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); + + if (Tcl_RegExpExec(interp, regexp, z->name, z->name)) { + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(z->name, -1)); + } + } + } else { + for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); + + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(z->name, -1)); + } + } + Unlock(); + return TCL_OK; +} + +static int +ZipChannelClose(ClientData instanceData, Tcl_Interp *interp) +{ + ZipChannel *info = (ZipChannel *) instanceData; + + if (info->iscompr && (info->ubuf != NULL)) { + Tcl_Free((char *) info->ubuf); + info->ubuf = NULL; + } + if (info->isenc) { + info->isenc = 0; + memset(info->keys, 0, sizeof (info->keys)); + } + if (info->iswr) { + ZipEntry *z = info->zipentry; + unsigned char *newdata; + + newdata = + (unsigned char *) Tcl_Realloc((char *) info->ubuf, info->nread); + if (newdata != NULL) { + if (z->data != NULL) { + Tcl_Free((char *) z->data); + } + z->data = newdata; + z->nbyte = z->nbytecompr = info->nbyte; + z->cmeth = ZIP_COMPMETH_STORED; + z->timestamp = time(NULL); + z->isdir = 0; + z->isenc = 0; + z->offset = 0; + z->crc32 = 0; + } else { + Tcl_Free((char *) info->ubuf); + } + } + WriteLock(); + info->zipfile->nopen--; + Unlock(); + Tcl_Free((char *) info); + return TCL_OK; +} + +static int +ZipChannelRead(ClientData instanceData, char *buf, int toRead, int *errloc) +{ + ZipChannel *info = (ZipChannel *) instanceData; + unsigned long nextpos; + + if (info->isdir) { + *errloc = EISDIR; + return -1; + } + nextpos = info->nread + toRead; + if (nextpos > info->nbyte) { + toRead = info->nbyte - info->nread; + nextpos = info->nbyte; + } + if (toRead == 0) { + return 0; + } + if (info->isenc) { + int i, ch; + + for (i = 0; i < toRead; i++) { + ch = info->ubuf[i + info->nread]; + buf[i] = zdecode(info->keys, crc32tab, ch); + } + } else { + memcpy(buf, info->ubuf + info->nread, toRead); + } + info->nread = nextpos; + *errloc = 0; + return toRead; +} + +static int +ZipChannelWrite(ClientData instanceData, CONST char *buf, + int toWrite, int *errloc) +{ + ZipChannel *info = (ZipChannel *) instanceData; + unsigned long nextpos; + + if (!info->iswr) { + *errloc = EINVAL; + return -1; + } + nextpos = info->nread + toWrite; + if (nextpos > info->nmax) { + toWrite = info->nmax - info->nread; + nextpos = info->nmax; + } + if (toWrite == 0) { + return 0; + } + memcpy(info->ubuf + info->nread, buf, toWrite); + info->nread = nextpos; + if (info->nread > info->nbyte) { + info->nbyte = info->nread; + } + *errloc = 0; + return toWrite; +} + +static int +ZipChannelSeek(ClientData instanceData, long offset, int mode, int *errloc) +{ + ZipChannel *info = (ZipChannel *) instanceData; + + if (info->isdir) { + *errloc = EINVAL; + return -1; + } + switch (mode) { + case SEEK_CUR: + offset += info->nread; + break; + case SEEK_END: + offset += info->nbyte; + break; + case SEEK_SET: + break; + default: + *errloc = EINVAL; + return -1; + } + if (info->iswr) { + if (offset > info->nmax) { + *errloc = EINVAL; + return -1; + } + if (offset > info->nbyte) { + info->nbyte = offset; + } + } else if (offset > info->nbyte) { + *errloc = EINVAL; + return -1; + } + if (offset < 0) { + *errloc = EINVAL; + return -1; + } + info->nread = (unsigned long) offset; + return info->nread; +} + +static void +ZipChannelWatchChannel(ClientData instanceData, int mask) +{ + return; +} +static int +ZipChannelGetFile(ClientData instanceData, int direction, + ClientData *handlePtr) +{ + return TCL_ERROR; +} + +static Tcl_ChannelType ZipChannelType = { + "zip", /* Type name. */ +#ifdef TCL_CHANNEL_VERSION_4 + TCL_CHANNEL_VERSION_4, + ZipChannelClose, /* Close channel, clean instance data */ + ZipChannelRead, /* Handle read request */ + ZipChannelWrite, /* Handle write request */ + ZipChannelSeek, /* Move location of access point, NULL'able */ + NULL, /* Set options, NULL'able */ + NULL, /* Get options, NULL'able */ + ZipChannelWatchChannel, /* Initialize notifier */ + ZipChannelGetFile, /* Get OS handle from the channel */ + NULL, /* 2nd version of close channel, NULL'able */ + NULL, /* Set blocking mode for raw channel, NULL'able */ + NULL, /* Function to flush channel, NULL'able */ + NULL, /* Function to handle event, NULL'able */ + NULL, /* Wide seek function, NULL'able */ + NULL, /* Thread action function, NULL'able */ +#else + NULL, /* Set blocking/nonblocking behaviour, NULL'able */ + ZipChannelClose, /* Close channel, clean instance data */ + ZipChannelRead, /* Handle read request */ + ZipChannelWrite, /* Handle write request */ + ZipChannelSeek, /* Move location of access point, NULL'able */ + NULL, /* Set options, NULL'able */ + NULL, /* Get options, NULL'able */ + ZipChannelWatchChannel, /* Initialize notifier */ + ZipChannelGetFile, /* Get OS handle from the channel */ +#endif +}; + +static Tcl_Channel +ZipChannelOpen(Tcl_Interp *interp, char *filename, int mode, int permissions) +{ + ZipEntry *z; + ZipChannel *info; + static int count = 1; + int i, ch, trunc, wr, flags = 0; + char cname[128]; + + if ((mode & O_APPEND) || + ((ZipFS.wrmax <= 0) && (mode & (O_WRONLY | O_RDWR)))) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported open mode", -1)); + } + return NULL; + } + WriteLock(); + z = ZipFSLookup(filename); + if (z == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("file not found", -1)); + } + goto error; + } + trunc = (mode & O_TRUNC) != 0; + wr = (mode & (O_WRONLY | O_RDWR)) != 0; + if ((z->cmeth != ZIP_COMPMETH_STORED) && + (z->cmeth != ZIP_COMPMETH_DEFLATED)) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("unsupported compression method", -1)); + } + goto error; + } + if (wr && z->isdir) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("unsupported file type", -1)); + } + goto error; + } + if (!trunc) { + flags |= TCL_READABLE; + if (z->isenc && (z->zipfile->pwbuf[0] == 0)) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("decryption failed", -1)); + } + goto error; + } else if (wr && (z->data == NULL) && (z->nbyte > ZipFS.wrmax)) { + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("file too large", -1)); + } + goto error; + } + } else { + flags = TCL_WRITABLE; + } + info = (ZipChannel *) Tcl_Alloc (sizeof (*info)); + info->zipfile = z->zipfile; + info->zipentry = z; + info->nread = 0; + if (wr) { + flags |= TCL_WRITABLE; + info->iswr = 1; + info->isdir = 0; + info->nmax = ZipFS.wrmax; + info->iscompr = 0; + info->isenc = 0; + info->ubuf = (unsigned char *) Tcl_Alloc(info->nmax); + memset(info->ubuf, 0, info->nmax); + if (trunc) { + info->nbyte = 0; + } else { + if (z->data != NULL) { + i = z->nbyte; + if (i > info->nmax) { + i = info->nmax; + } + memcpy(info->ubuf, z->data, i); + info->nbyte = i; + } else { + unsigned char *zbuf = z->zipfile->data + z->offset; + + if (z->isenc) { + int len = z->zipfile->pwbuf[0]; + char pwbuf[260]; + + for (i = 0; i < len; i++) { + ch = z->zipfile->pwbuf[len - i]; + pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; + } + pwbuf[i] = '\0'; + init_keys(pwbuf, info->keys, crc32tab); + memset(pwbuf, 0, sizeof (pwbuf)); + for (i = 0; i < 12; i++) { + ch = info->ubuf[i]; + zdecode(info->keys, crc32tab, ch); + } + zbuf += i; + } + if (z->cmeth == ZIP_COMPMETH_DEFLATED) { + z_stream stream; + int err; + unsigned char *cbuf = NULL; + + memset(&stream, 0, sizeof (stream)); + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.avail_in = z->nbytecompr; + if (z->isenc) { + stream.avail_in -= 12; + cbuf = (unsigned char *) Tcl_Alloc(stream.avail_in); + for (i = 0; i < stream.avail_in; i++) { + ch = info->ubuf[i]; + cbuf[i] = zdecode(info->keys, crc32tab, ch); + } + stream.next_in = cbuf; + } else { + stream.next_in = zbuf; + } + stream.next_out = info->ubuf; + stream.avail_out = info->nmax; + if (inflateInit2(&stream, -15) != Z_OK) { + goto cerror0; + } + err = inflate(&stream, Z_SYNC_FLUSH); + inflateEnd(&stream); + if ((err == Z_STREAM_END) || + ((err == Z_OK) && (stream.avail_in == 0))) { + if (cbuf != NULL) { + memset(info->keys, 0, sizeof (info->keys)); + Tcl_Free((char *) cbuf); + } + goto wrapchan; + } +cerror0: + if (cbuf != NULL) { + memset(info->keys, 0, sizeof (info->keys)); + Tcl_Free((char *) cbuf); + } + if (info->ubuf != NULL) { + Tcl_Free((char *) info->ubuf); + } + Tcl_Free((char *) info); + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("decompression error", -1)); + } + goto error; + } else if (z->isenc) { + for (i = 0; i < z->nbyte - 12; i++) { + ch = zbuf[i]; + info->ubuf[i] = zdecode(info->keys, crc32tab, ch); + } + } else { + memcpy(info->ubuf, zbuf, z->nbyte); + } + memset(info->keys, 0, sizeof (info->keys)); + goto wrapchan; + } + } + } else if (z->data != NULL) { + flags |= TCL_READABLE; + info->iswr = 0; + info->iscompr = 0; + info->isdir = 0; + info->isenc = 0; + info->nbyte = z->nbyte; + info->nmax = 0; + info->ubuf = z->data; + } else { + flags |= TCL_READABLE; + info->iswr = 0; + info->iscompr = z->cmeth == ZIP_COMPMETH_DEFLATED; + info->ubuf = z->zipfile->data + z->offset; + info->isdir = z->isdir; + info->isenc = z->isenc; + info->nbyte = z->nbyte; + info->nmax = 0; + if (info->isenc) { + int len = z->zipfile->pwbuf[0]; + char pwbuf[260]; + + for (i = 0; i < len; i++) { + ch = z->zipfile->pwbuf[len - i]; + pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; + } + pwbuf[i] = '\0'; + init_keys(pwbuf, info->keys, crc32tab); + memset(pwbuf, 0, sizeof (pwbuf)); + for (i = 0; i < 12; i++) { + ch = info->ubuf[i]; + zdecode(info->keys, crc32tab, ch); + } + info->ubuf += i; + } + if (info->iscompr) { + z_stream stream; + int err; + unsigned char *ubuf = NULL; + + memset(&stream, 0, sizeof (stream)); + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.avail_in = z->nbytecompr; + if (info->isenc) { + stream.avail_in -= 12; + ubuf = (unsigned char *) Tcl_Alloc(stream.avail_in); + for (i = 0; i < stream.avail_in; i++) { + ch = info->ubuf[i]; + ubuf[i] = zdecode(info->keys, crc32tab, ch); + } + stream.next_in = ubuf; + } else { + stream.next_in = info->ubuf; + } + stream.next_out = info->ubuf = + (unsigned char *) Tcl_Alloc(info->nbyte); + stream.avail_out = info->nbyte; + if (inflateInit2(&stream, -15) != Z_OK) { + goto cerror; + } + err = inflate(&stream, Z_SYNC_FLUSH); + inflateEnd(&stream); + if ((err == Z_STREAM_END) || + ((err == Z_OK) && (stream.avail_in == 0))) { + if (ubuf != NULL) { + info->isenc = 0; + memset(info->keys, 0, sizeof (info->keys)); + Tcl_Free((char *) ubuf); + } + goto wrapchan; + } +cerror: + if (ubuf != NULL) { + info->isenc = 0; + memset(info->keys, 0, sizeof (info->keys)); + Tcl_Free((char *) ubuf); + } + if (info->ubuf != NULL) { + Tcl_Free((char *) info->ubuf); + } + Tcl_Free((char *) info); + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("decompression error", -1)); + } + goto error; + } + } +wrapchan: + sprintf(cname, "zipfs_%lx_%d", (unsigned long) z->offset, count++); + z->zipfile->nopen++; + Unlock(); + return Tcl_CreateChannel(&ZipChannelType, cname, (ClientData) info, flags); + +error: + Unlock(); + return NULL; +} + +static int +ZipEntryStat(char *path, Tcl_StatBuf *buf) +{ + ZipEntry *z; + int ret = -1; + + ReadLock(); + z = ZipFSLookup(path); + if (z == NULL) { + goto done; + } + memset(buf, 0, sizeof (Tcl_StatBuf)); + if (z->isdir) { + buf->st_mode = S_IFDIR | 0555; + } else { + buf->st_mode = S_IFREG | 0555; + } + buf->st_size = z->nbyte; + buf->st_mtime = z->timestamp; + buf->st_ctime = z->timestamp; + buf->st_atime = z->timestamp; + ret = 0; +done: + Unlock(); + return ret; +} + +static int +ZipEntryAccess(char *path, int mode) +{ + ZipEntry *z; + + if (mode & 3) { + return -1; + } + ReadLock(); + z = ZipFSLookup(path); + Unlock(); + return (z != NULL) ? 0 : -1; +} + +static Tcl_Channel +Zip_FSOpenFileChannelProc(Tcl_Interp *interp, Tcl_Obj *pathPtr, + int mode, int permissions) +{ + int len; + + return ZipChannelOpen(interp, Tcl_GetStringFromObj(pathPtr, &len), + mode, permissions); +} + +static int +Zip_FSStatProc(Tcl_Obj *pathPtr, Tcl_StatBuf *buf) +{ + int len; + + return ZipEntryStat(Tcl_GetStringFromObj(pathPtr, &len), buf); +} + +static int +Zip_FSAccessProc(Tcl_Obj *pathPtr, int mode) +{ + int len; + + return ZipEntryAccess(Tcl_GetStringFromObj(pathPtr, &len), mode); +} + +static Tcl_Obj * +Zip_FSFilesystemSeparatorProc(Tcl_Obj *pathPtr) +{ + return Tcl_NewStringObj("/", -1); +} + +static int +Zip_FSMatchInDirectoryProc(Tcl_Interp* interp, Tcl_Obj *result, + Tcl_Obj *pathPtr, CONST char *pattern, + Tcl_GlobTypeData *types) +{ + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + int scnt, len, l, dirOnly = -1, prefixLen, strip = 0; + char *pat, *prefix, *path; +#if defined(_WIN32) || defined(_WIN64) + char drivePrefix[3]; +#endif + Tcl_DString ds, dsPref; + +#if defined(_WIN32) || defined(_WIN64) + if ((pattern != NULL) && (pattern[0] != '\0') && + (strchr(alpha, pattern[0]) != NULL) && (pattern[1] == ':')) { + pattern += 2; + } +#endif + if (types != NULL) { + dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR; + } + Tcl_DStringInit(&ds); + Tcl_DStringInit(&dsPref); + prefix = Tcl_GetStringFromObj(pathPtr, &prefixLen); + Tcl_DStringAppend(&dsPref, prefix, prefixLen); + prefix = Tcl_DStringValue(&dsPref); + path = AbsolutePath(prefix, &ds); + len = Tcl_DStringLength(&ds); + if (strcmp(prefix, path) == 0) { + prefix = NULL; + } else { +#if defined(_WIN32) || defined(_WIN64) + if ((strchr(alpha, prefix[0]) != NULL) && (prefix[1] == ':')) { + if (strcmp(prefix + 2, path) == 0) { + strncpy(drivePrefix, prefix, 3); + drivePrefix[2] = '\0'; + prefix = drivePrefix; + } + } else { + strip = len + 1; + } +#else + strip = len + 1; +#endif + } + if (prefix != NULL) { +#if defined(_WIN32) || defined(_WIN64) + if (prefix == drivePrefix) { + Tcl_DStringSetLength(&dsPref, 0); + Tcl_DStringAppend(&dsPref, drivePrefix, -1); + prefixLen = Tcl_DStringLength(&dsPref); + } else { + Tcl_DStringAppend(&dsPref, "/", 1); + prefixLen++; + } + prefix = Tcl_DStringValue(&dsPref); +#else + Tcl_DStringAppend(&dsPref, "/", 1); + prefixLen++; + prefix = Tcl_DStringValue(&dsPref); +#endif + } + ReadLock(); + if ((types != NULL) && (types->type == TCL_GLOB_TYPE_MOUNT)) { + l = CountSlashes(path); + if (path[len - 1] == '/') { + len--; + } else { + l++; + } + if ((pattern == NULL) || (pattern[0] == '\0')) { + pattern = "*"; + } + hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); + while (hPtr != NULL) { + ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr); + + if (zf->mntptlen == 0) { + ZipEntry *z = zf->topents; + + while (z != NULL) { + int lenz = strlen(z->name); + + if ((lenz > len + 1) && + (strncmp(z->name, path, len) == 0) && + (z->name[len] == '/') && + (CountSlashes(z->name) == l) && + Tcl_StringCaseMatch(z->name + len + 1, pattern, 0)) { + if (prefix != NULL) { + Tcl_DStringAppend(&dsPref, z->name, lenz); + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(Tcl_DStringValue(&dsPref), + Tcl_DStringLength(&dsPref))); + Tcl_DStringSetLength(&dsPref, prefixLen); + } else { + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(z->name, lenz)); + } + } + z = z->tnext; + } + } else if ((zf->mntptlen > len + 1) && + (strncmp(zf->mntpt, path, len) == 0) && + (zf->mntpt[len] == '/') && + (CountSlashes(zf->mntpt) == l) && + Tcl_StringCaseMatch(zf->mntpt + len + 1, pattern, 0)) { + if (prefix != NULL) { + Tcl_DStringAppend(&dsPref, zf->mntpt, zf->mntptlen); + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(Tcl_DStringValue(&dsPref), + Tcl_DStringLength(&dsPref))); + Tcl_DStringSetLength(&dsPref, prefixLen); + } else { + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(zf->mntpt, zf->mntptlen)); + } + } + hPtr = Tcl_NextHashEntry(&search); + } + goto end; + } + if ((pattern == NULL) || (pattern[0] == '\0')) { + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path); + if (hPtr != NULL) { + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); + + if ((dirOnly < 0) || + (!dirOnly && !z->isdir) || + (dirOnly && z->isdir)) { + if (prefix != NULL) { + Tcl_DStringAppend(&dsPref, z->name, -1); + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(Tcl_DStringValue(&dsPref), + Tcl_DStringLength(&dsPref))); + Tcl_DStringSetLength(&dsPref, prefixLen); + } else { + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(z->name, -1)); + } + } + } + goto end; + } + l = strlen(pattern); + pat = Tcl_Alloc(len + l + 2); + memcpy(pat, path, len); + while ((len > 1) && (pat[len - 1] == '/')) { + --len; + } + if ((len > 1) || (pat[0] != '/')) { + pat[len] = '/'; + ++len; + } + memcpy(pat + len, pattern, l + 1); + scnt = CountSlashes(pat); + for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); + + if ((dirOnly >= 0) && + ((dirOnly && !z->isdir) || (!dirOnly && z->isdir))) { + continue; + } + if ((z->depth == scnt) && Tcl_StringCaseMatch(z->name, pat, 0)) { + if (prefix != NULL) { + Tcl_DStringAppend(&dsPref, z->name + strip, -1); + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(Tcl_DStringValue(&dsPref), + Tcl_DStringLength(&dsPref))); + Tcl_DStringSetLength(&dsPref, prefixLen); + } else { + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(z->name + strip, -1)); + } + } + } + Tcl_Free(pat); +end: + Unlock(); + Tcl_DStringFree(&dsPref); + Tcl_DStringFree(&ds); + return TCL_OK; +} + +static int +Zip_FSNormalizePathProc(Tcl_Interp *interp, Tcl_Obj *pathPtr, + int nextCheckpoint) +{ + char *path; + Tcl_DString ds; + int len; + + path = Tcl_GetStringFromObj(pathPtr, &len); + Tcl_DStringInit(&ds); + path = AbsolutePath(path, &ds); + nextCheckpoint = Tcl_DStringLength(&ds); + Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + return nextCheckpoint; +} + +static int +Zip_FSPathInFilesystemProc(Tcl_Obj *pathPtr, ClientData *clientDataPtr) +{ + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + ZipFile *zf; + int ret = -1, len; + char *path; + Tcl_DString ds; + + path = Tcl_GetStringFromObj(pathPtr, &len); + Tcl_DStringInit(&ds); + path = AbsolutePath(path, &ds); + len = Tcl_DStringLength(&ds); +#if defined(_WIN32) || defined(_WIN64) + if (len && (strchr(alpha, path[0]) != NULL) && (path[1] == ':')) { + path += 2; + len -= 2; + } +#endif + ReadLock(); + hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path); + if (hPtr != NULL) { + ret = TCL_OK; + goto endloop; + } + hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); + while (hPtr != NULL) { + zf = (ZipFile *) Tcl_GetHashValue(hPtr); + if (zf->mntptlen == 0) { + ZipEntry *z = zf->topents; + + while (z != NULL) { + int lenz = strlen(z->name); + + if ((len >= lenz) && + (strncmp(path, z->name, lenz) == 0)) { + ret = TCL_OK; + goto endloop; + } + z = z->tnext; + } + } else if ((len >= zf->mntptlen) && + (strncmp(path, zf->mntpt, zf->mntptlen) == 0)) { + ret = TCL_OK; + goto endloop; + } + hPtr = Tcl_NextHashEntry(&search); + } +endloop: + Unlock(); + Tcl_DStringFree(&ds); + return ret; +} + +static Tcl_Obj * +Zip_FSListVolumesProc(void) +{ + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + ZipFile *zf; + Tcl_Obj *vols = Tcl_NewObj(), *vol; + + ReadLock(); + hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); + while (hPtr != NULL) { + zf = (ZipFile *) Tcl_GetHashValue(hPtr); + vol = Tcl_NewStringObj(zf->mntpt, zf->mntptlen); + Tcl_ListObjAppendList(NULL, vols, vol); + Tcl_DecrRefCount(vol); + hPtr = Tcl_NextHashEntry(&search); + } + Unlock(); + return vols; +} + +static int +Zip_FSChdirProc(Tcl_Obj *pathPtr) +{ + int len; + char *path; + Tcl_DString ds; + ZipEntry *z; + int ret = TCL_OK; + + path = Tcl_GetStringFromObj(pathPtr, &len); + Tcl_DStringInit(&ds); + path = AbsolutePath(path, &ds); + ReadLock(); + z = ZipFSLookup(path); + if ((z == NULL) || !z->isdir) { + Tcl_SetErrno(ENOENT); + ret = -1; + } + Unlock(); + Tcl_DStringFree(&ds); + return ret; +} + +static CONST char *CONST86 * +Zip_FSFileAttrStringsProc(Tcl_Obj *pathPtr, Tcl_Obj** objPtrRef) +{ + static CONST char *attrs[] = { + "-uncompsize", + "-compsize", + "-offset", + "-mount", + "-archive", + "-permissions", + NULL, + }; + + return attrs; +} + +static int +Zip_FSFileAttrsGetProc(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, + Tcl_Obj **objPtrRef) +{ + int len, ret = TCL_OK; + char *path; + ZipEntry *z; + + path = Tcl_GetStringFromObj(pathPtr, &len); + ReadLock(); + z = ZipFSLookup(path); + if (z == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("file not found", -1)); + } + ret = TCL_ERROR; + goto done; + } + switch (index) { + case 0: + *objPtrRef = Tcl_NewIntObj(z->nbyte); + goto done; + case 1: + *objPtrRef= Tcl_NewIntObj(z->nbytecompr); + goto done; + case 2: + *objPtrRef= Tcl_NewLongObj(z->offset); + goto done; + case 3: + *objPtrRef= Tcl_NewStringObj(z->zipfile->mntpt, -1); + goto done; + case 4: + *objPtrRef= Tcl_NewStringObj(z->zipfile->name, -1); + goto done; + case 5: + *objPtrRef= Tcl_NewStringObj("0555", -1); + goto done; + } + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("unknown attribute", -1)); + } + ret = TCL_ERROR; +done: + Unlock(); + return ret; +} + +static int +Zip_FSFileAttrsSetProc(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, + Tcl_Obj *objPtr) +{ + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported operation", -1)); + } + return TCL_ERROR; +} + + +static Tcl_Obj * +Zip_FSFilesystemPathTypeProc(Tcl_Obj *pathPtr) +{ + return Tcl_NewStringObj("zip", -1); +} + +#ifndef ANDROID +static int +Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, + Tcl_FSUnloadFileProc **unloadProcPtr, int flags) +{ + Tcl_FSLoadFileProc2 *loadFileProc; + Tcl_Obj *altPath = NULL; + int ret = -1; + + if (Tcl_FSAccess(path, R_OK) == 0) { + /* + * EXDEV should trigger loading by copying to temp store. + */ + Tcl_SetErrno(EXDEV); + return ret; + } else { + Tcl_Obj *objs[2] = { NULL, NULL }; + + objs[1] = TclPathPart(interp, path, TCL_PATH_DIRNAME); + if ((objs[1] != NULL) && (Zip_FSAccessProc(objs[1], R_OK) == 0)) { + /* + * Shared object is not in ZIP but its path prefix is, + * thus try to load from directory where the executable + * came from. + */ + TclDecrRefCount(objs[1]); + objs[1] = TclPathPart(interp, path, TCL_PATH_TAIL); + objs[0] = TclPathPart(interp, TclGetObjNameOfExecutable(), + TCL_PATH_DIRNAME); + if (objs[0] != NULL) { + altPath = TclJoinPath(2, objs); + if (altPath != NULL) { + Tcl_IncrRefCount(altPath); + if (Tcl_FSAccess(altPath, R_OK) == 0) { + path = altPath; + } + } + } + } + if (objs[0] != NULL) { + Tcl_DecrRefCount(objs[0]); + } + if (objs[1] != NULL) { + Tcl_DecrRefCount(objs[1]); + } + } + loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc; + if (loadFileProc != NULL) { + ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); + } else { + Tcl_SetErrno(ENOENT); + } + if (altPath != NULL) { + Tcl_DecrRefCount(altPath); + } + return ret; +} +#endif + +Tcl_Filesystem zipfsFilesystem = { + "zipfs", + sizeof (Tcl_Filesystem), + TCL_FILESYSTEM_VERSION_2, + Zip_FSPathInFilesystemProc, + NULL, /* dupInternalRepProc */ + NULL, /* freeInternalRepProc */ + NULL, /* internalToNormalizedProc */ + NULL, /* createInternalRepProc */ + Zip_FSNormalizePathProc, + Zip_FSFilesystemPathTypeProc, + Zip_FSFilesystemSeparatorProc, + Zip_FSStatProc, + Zip_FSAccessProc, + Zip_FSOpenFileChannelProc, + Zip_FSMatchInDirectoryProc, + NULL, /* utimeProc */ + NULL, /* linkProc */ + Zip_FSListVolumesProc, + Zip_FSFileAttrStringsProc, + Zip_FSFileAttrsGetProc, + Zip_FSFileAttrsSetProc, + NULL, /* createDirectoryProc */ + NULL, /* removeDirectoryProc */ + NULL, /* deleteFileProc */ + NULL, /* copyFileProc */ + NULL, /* renameFileProc */ + NULL, /* copyDirectoryProc */ + NULL, /* lstatProc */ +#ifdef ANDROID + NULL, /* loadFileProc */ +#else + (Tcl_FSLoadFileProc *) Zip_FSLoadFile, +#endif + NULL, /* getCwdProc */ + Zip_FSChdirProc, +}; + +#endif /* HAVE_ZLIB */ + +static int +Zipfs_doInit(Tcl_Interp *interp, int safe) +{ +#ifdef HAVE_ZLIB + static CONST char findproc[] = + "proc ::zipfs::find d {\n" + " set ret {}\n" + " foreach f [glob -directory $d -tails -nocomplain * .*] {\n" + " if {$f eq \".\" || $f eq \"..\"} {\n" + " continue\n" + " }\n" + " set f [file join $d $f]\n" + " lappend ret $f\n" + " foreach f [::zipfs::find $f] {\n" + " lappend ret $f\n" + " }\n" + " }\n" + " return [lsort $ret]\n" + "}\n"; + +#ifdef USE_TCL_STUBS + if (Tcl_InitStubs(interp, "8.0", 0) == NULL) { + return TCL_ERROR; + } +#endif + /* one-time initialization */ + WriteLock(); + if (!ZipFS.initialized) { + static const Tcl_Time t = { 0, 0 }; + + /* inflate condition */ + Tcl_MutexLock(&ZipFSMutex); + Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, &t); + Tcl_MutexUnlock(&ZipFSMutex); +#ifdef ANDROID + /* force loadFileProc to native one */ + zipfsFilesystem.loadFileProc = tclNativeFilesystem.loadFileProc; +#endif + Tcl_FSRegister(NULL, &zipfsFilesystem); + Tcl_InitHashTable(&ZipFS.fileHash, TCL_STRING_KEYS); + Tcl_InitHashTable(&ZipFS.zipHash, TCL_STRING_KEYS); + ZipFS.initialized = 1; +#if defined(ZIPFS_IN_TCL) || defined(ZIPFS_IN_TK) + Tcl_StaticPackage(interp, "zipfs", Zipfs_Init, Zipfs_SafeInit); +#endif + } + Unlock(); +#if !defined(ZIPFS_IN_TCL) && !defined(ZIPFS_IN_TK) + Tcl_PkgProvide(interp, "zipfs", "1.0"); +#endif + if (!safe) { + Tcl_CreateCommand(interp, "::zipfs::mount", ZipFSMountCmd, 0, 0); + Tcl_CreateCommand(interp, "::zipfs::unmount", ZipFSUnmountCmd, 0, 0); + Tcl_CreateCommand(interp, "::zipfs::mkkey", ZipFSMkKeyCmd, 0, 0); + Tcl_CreateCommand(interp, "::zipfs::mkimg", ZipFSMkImgCmd, 0, 0); + Tcl_CreateCommand(interp, "::zipfs::mkzip", ZipFSMkZipCmd, 0, 0); + Tcl_GlobalEval(interp, findproc); + } + Tcl_CreateObjCommand(interp, "::zipfs::exists", ZipFSExistsObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::info", ZipFSInfoObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::list", ZipFSListObjCmd, 0, 0); + if (!safe) { + Tcl_LinkVar(interp, "::zipfs::wrmax", (char *) &ZipFS.wrmax, + TCL_LINK_INT); + } + return TCL_OK; +#else + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("no zlib available", -1)); + } + return TCL_ERROR; +#endif +} + +int +Zipfs_Init(Tcl_Interp *interp) +{ + return Zipfs_doInit(interp, 0); +} + +int +Zipfs_SafeInit(Tcl_Interp *interp) +{ + return Zipfs_doInit(interp, 1); +} + +#ifndef HAVE_ZLIB + +int +Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, + CONST char *passwd) +{ + return Zipfs_doInit(interp, 1); +} + +int +Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname) +{ + return Zipfs_doInit(interp, 1); +} + +#endif + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/zipfs.h b/generic/zipfs.h new file mode 100644 index 0000000..587fed8 --- /dev/null +++ b/generic/zipfs.h @@ -0,0 +1,43 @@ +#ifndef _ZIPFS_H +#define _ZIPFS_H + +#ifdef ZIPFS_IN_TK +#include "tkInt.h" +#define Zipfs_Mount Tkzipfs_Mount +#define Zipfs_Unmount Tkzipfs_Unmount +#define Zipfs_Init Tkzipfs_Init +#define Zipfs_SafeInit Tkzipfs_SafeInit +#endif + +#ifdef ZIPFS_IN_TCL +#include "tclPort.h" +#define Zipfs_Mount Tclzipfs_Mount +#define Zipfs_Unmount Tclzipfs_Unmount +#define Zipfs_Init Tclzipfs_Init +#define Zipfs_SafeInit Tclzipfs_SafeInit +#endif + +#ifndef EXTERN +#define EXTERN extern +#endif + +#ifdef BUILD_tcl +#undef EXTERN +#define EXTERN +#endif + +EXTERN int Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, + CONST char *mntpt, CONST char *passwd); +EXTERN int Zipfs_Unmount(Tcl_Interp *interp, CONST char *mountname); +EXTERN int Zipfs_Init(Tcl_Interp *interp); +EXTERN int Zipfs_SafeInit(Tcl_Interp *interp); + +#endif + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/pkgs/Android.mk b/pkgs/Android.mk new file mode 100644 index 0000000..5053e7d --- /dev/null +++ b/pkgs/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/tcl-config.mk b/tcl-config.mk new file mode 100644 index 0000000..ae14b6b --- /dev/null +++ b/tcl-config.mk @@ -0,0 +1,60 @@ +tcl_includes := $(tcl_path)/generic $(tcl_path)/unix + +tcl_cflags := \ + -DHAVE_SYS_SELECT_H=1 \ + -DHAVE_LIMITS_H=1 \ + -DHAVE_UNISTD_H=1 \ + -DHAVE_SYS_PARAM_H=1 \ + -D_LARGEFILE64_SOURCE=1 \ + -DTCL_WIDE_INT_TYPE="long long" \ + -DTCL_SHLIB_EXT="\".so\"" \ + -DHAVE_CAST_TO_UNION=1 \ + -DHAVE_GETCWD=1 \ + -DHAVE_OPENDIR=1 \ + -DHAVE_MKSTEMP=1 \ + -DHAVE_MKSTEMPS=1 \ + -DHAVE_STRSTR=1 \ + -DHAVE_STRTOL=1 \ + -DHAVE_STRTOLL=1 \ + -DHAVE_STRTOULL=1 \ + -DHAVE_TMPNAM=1 \ + -DHAVE_WAITPID=1 \ + -DHAVE_STRUCT_ADDRINFO=1 \ + -DHAVE_STRUCT_IN6_ADDR=1 \ + -DHAVE_STRUCT_SOCKADDR_IN6=1 \ + -DHAVE_STRUCT_SOCKADDR_STORAGE=1 \ + -DUSE_TERMIOS=1 \ + -DHAVE_MKTIME=1 \ + -DUSE_INTERP_ERRORLINE=1 \ + -DHAVE_SYS_TIME_H=1 \ + -DTIME_WITH_SYS_TIME=1 \ + -DHAVE_TM_ZONE=1 \ + -DHAVE_GMTIME_R=1 \ + -DHAVE_LOCALTIME_R=1 \ + -DHAVE_TM_GMTOFF=1 \ + -DHAVE_TIMEZONE_VAR=1 \ + -DHAVE_ST_BLKSIZE=1 \ + -DSTDC_HEADERS=1 \ + -DHAVE_INTPTR_T=1 \ + -DHAVE_UINTPTR_T=1 \ + -DHAVE_SIGNED_CHAR=1 \ + -DHAVE_SYS_IOCTL_H=1 \ + -DHAVE_MEMCPY=1 \ + -DHAVE_MEMMOVE=1 \ + -DVOID=void \ + -DNO_UNION_WAIT=1 \ + -DHAVE_ZLIB=1 \ + -DMP_PREC=4 \ + -DTCL_TOMMATH=1 \ + -D_REENTRANT=1 \ + -D_THREADSAFE=1 \ + -DTCL_THREADS=1 \ + -DTCL_PTHREAD_ATFORK=1 \ + -DUSE_THREAD_ALLOC=1 \ + -DTCL_CFGVAL_ENCODING="\"utf-8\"" \ + -DTCL_UNLOAD_DLLS=1 \ + -DTCL_CFG_OPTIMIZED=1 \ + -DZIPFS_IN_TCL=1 \ + -DTCL_PACKAGE_PATH="\"/assets\"" \ + -DTCL_LIBRARY="\"/assets/tcl8.6\"" + diff --git a/unix/Makefile.in b/unix/Makefile.in index 18c90fa..eb1ba3c 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -308,7 +308,7 @@ GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \ tclStrToD.o tclThread.o \ tclThreadAlloc.o tclThreadJoin.o tclThreadStorage.o tclStubInit.o \ tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o tclZlib.o \ - tclTomMathInterface.o + tclTomMathInterface.o zipfs.o OO_OBJS = tclOO.o tclOOBasic.o tclOOCall.o tclOODefineCmds.o tclOOInfo.o \ tclOOMethod.o tclOOStubInit.o @@ -382,7 +382,8 @@ GENERIC_HDRS = \ $(GENERIC_DIR)/tclPatch.h \ $(GENERIC_DIR)/tclPlatDecls.h \ $(GENERIC_DIR)/tclPort.h \ - $(GENERIC_DIR)/tclRegexp.h + $(GENERIC_DIR)/tclRegexp.h \ + $(GENERIC_DIR)/zipfs.h GENERIC_SRCS = \ $(GENERIC_DIR)/regcomp.c \ @@ -463,7 +464,8 @@ GENERIC_SRCS = \ $(GENERIC_DIR)/tclUtil.c \ $(GENERIC_DIR)/tclVar.c \ $(GENERIC_DIR)/tclAssembly.c \ - $(GENERIC_DIR)/tclZlib.c + $(GENERIC_DIR)/tclZlib.c \ + $(GENERIC_DIR)/zipfs.c OO_SRCS = \ $(GENERIC_DIR)/tclOO.c \ @@ -1321,6 +1323,9 @@ tclVar.o: $(GENERIC_DIR)/tclVar.c tclZlib.o: $(GENERIC_DIR)/tclZlib.c $(CC) -c $(CC_SWITCHES) $(ZLIB_INCLUDE) $(GENERIC_DIR)/tclZlib.c +zipfs.o: $(GENERIC_DIR)/zipfs.c + $(CC) -c $(CC_SWITCHES) $(ZLIB_INCLUDE) $(GENERIC_DIR)/zipfs.c + tclTest.o: $(GENERIC_DIR)/tclTest.c $(IOHDR) $(TCLREHDRS) $(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTest.c diff --git a/unix/tclLoadDl.c b/unix/tclLoadDl.c index dc711f8..3376d94 100644 --- a/unix/tclLoadDl.c +++ b/unix/tclLoadDl.c @@ -97,7 +97,11 @@ TclpDlopen( } else { dlopenflags |= RTLD_NOW; } - handle = dlopen(native, dlopenflags); + if (native == NULL) { + handle = NULL; + } else { + handle = dlopen(native, dlopenflags); + } if (handle == NULL) { /* * Let the OS loader examine the binary search path for whatever @@ -115,7 +119,41 @@ TclpDlopen( handle = dlopen(native, dlopenflags); Tcl_DStringFree(&ds); } +#ifdef ANDROID + /* + * If not an absolute or relative path, try to load + * from $INTERNAL_STORAGE/../lib (the place where the + * system has installed bundled .so files from the .APK) + */ + if (handle == NULL) { + native = Tcl_GetString(pathPtr); + if ((native != NULL) && (strchr(native, '/') == NULL)) { + char *storage = getenv("INTERNAL_STORAGE"); + Tcl_DString ds2; + if ((storage != NULL) && (storage[0] != '\0')) { + Tcl_DStringInit(&ds2); + Tcl_DStringAppend(&ds2, storage, -1); + Tcl_DStringAppend(&ds2, "/../lib/", -1); + Tcl_DStringAppend(&ds2, native, -1); + handle = dlopen(Tcl_DStringValue(&ds2), RTLD_NOW | RTLD_GLOBAL); + Tcl_DStringFree(&ds2); + } + if (handle == NULL) { + storage = getenv("TK_TCL_WISH_LD_LIBS"); + if ((storage != NULL) && (storage[0] != '\0')) { + Tcl_DStringInit(&ds2); + Tcl_DStringAppend(&ds2, storage, -1); + Tcl_DStringAppend(&ds2, "/", -1); + Tcl_DStringAppend(&ds2, native, -1); + handle = + dlopen(Tcl_DStringValue(&ds2), RTLD_NOW | RTLD_GLOBAL); + Tcl_DStringFree(&ds2); + } + } + } + } + #endif if (handle == NULL) { /* * Write the string to a variable first to work around a compiler bug diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 3b1b6ca..0193dae 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -465,6 +465,9 @@ DoCopyFile( /* Used to determine filetype. */ { Tcl_StatBuf dstStatBuf; +#ifdef ANDROID + int ret; +#endif if (S_ISDIR(statBufPtr->st_mode)) { errno = EISDIR; @@ -520,7 +523,15 @@ DoCopyFile( if (mkfifo(dst, statBufPtr->st_mode) < 0) { /* INTL: Native. */ return TCL_ERROR; } +#ifdef ANDROID + ret = CopyFileAtts(src, dst, statBufPtr); + if (ret != TCL_OK && errno == EPERM) { + ret = TCL_OK; + } + return ret; +#else return CopyFileAtts(src, dst, statBufPtr); +#endif default: return TclUnixCopyFile(src, dst, statBufPtr, 0); } @@ -629,6 +640,11 @@ TclUnixCopyFile( return TCL_ERROR; } if (!dontCopyAtts && CopyFileAtts(src, dst, statBufPtr) == TCL_ERROR) { +#ifdef ANDROID + if (errno == EPERM) { + return TCL_OK; + } +#endif /* * The copy succeeded, but setting the permissions failed, so be in a * consistent state, we remove the file that was created by the copy. @@ -1203,6 +1219,11 @@ TraversalCopy( Tcl_DStringValue(dstPtr), statBufPtr) == TCL_OK) { return TCL_OK; } +#ifdef ANDROID + if (errno == EPERM) { + return TCL_OK; + } +#endif break; } diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index 520c8e5..927b1a6 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -541,6 +541,11 @@ TclpInitLibraryPath( */ str = defaultLibraryDir; +#ifdef ZIPFS_IN_TCL + if (Tclzipfs_Mount(NULL, NULL, NULL, NULL) == TCL_OK) { + str = ""; + } +#endif } if (str[0] != '\0') { objPtr = Tcl_NewStringObj(str, -1); diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h index 123abec..6558332 100644 --- a/unix/tclUnixPort.h +++ b/unix/tclUnixPort.h @@ -447,9 +447,11 @@ extern int gettimeofday(struct timeval *tp, *--------------------------------------------------------------------------- */ +#ifndef ANDROID #ifndef L_tmpnam # define L_tmpnam 100 #endif +#endif /* *--------------------------------------------------------------------------- diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index 315bcf9..19cafe6 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -529,7 +529,10 @@ static void CleanupMemory( ClientData ignored) { - ckfree(lastTZ); + if (lastTZ != NULL) { + ckfree(lastTZ); + lastTZ = NULL; + } } /* diff --git a/win/Makefile.in b/win/Makefile.in index 168da2e..13a3e0c 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -296,7 +296,8 @@ GENERIC_OBJS = \ tclUtf.$(OBJEXT) \ tclUtil.$(OBJEXT) \ tclVar.$(OBJEXT) \ - tclZlib.$(OBJEXT) + tclZlib.$(OBJEXT) \ + zipfs.$(OBJEXT) TOMMATH_OBJS = \ bncore.${OBJEXT} \ @@ -741,7 +742,7 @@ clean: cleanhelp clean-packages distclean: distclean-packages clean $(RM) Makefile config.status config.cache config.log tclConfig.sh \ - tcl.hpj config.status.lineno + tcl.hpj config.status.lineno tclsh.exe.manifest # # Bundled package targets -- cgit v0.12 From d68207f7ca77f987f9c8d2c8400c089b2c976604 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 15 Jul 2015 09:31:11 +0000 Subject: Remove unused local variables. Now unix/tclUnixTime.c is idential in "androwish" compared to "novem". (Yes, those functions are planned to be removed in Tcl 9.0!) --- unix/tclUnixTime.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index 240bc91..470b122 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -17,25 +17,6 @@ #endif /* - * TclpGetDate is coded to return a pointer to a 'struct tm'. For thread - * safety, this structure must be in thread-specific data. The 'tmKey' - * variable is the key to this buffer. - */ - -static Tcl_ThreadDataKey tmKey; -typedef struct ThreadSpecificData { - struct tm gmtime_buf; - struct tm localtime_buf; -} ThreadSpecificData; - -/* - * If we fall back on the thread-unsafe versions of gmtime and localtime, use - * this mutex to try to protect them. - */ - -TCL_DECLARE_MUTEX(tmMutex) - -/* * Static functions declared in this file. */ -- cgit v0.12 From 6e0d4b67612beec4f87f531f87878314a26db669 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 24 Aug 2015 07:58:42 +0000 Subject: Remove unused internal stub entries as well. --- generic/tclInt.decls | 18 ++-- generic/tclIntPlatDecls.h | 32 +++---- win/tclWinTime.c | 222 ---------------------------------------------- 3 files changed, 23 insertions(+), 249 deletions(-) diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 27245f1..9f990f7 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -534,7 +534,7 @@ declare 132 { int TclpHasSockets(Tcl_Interp *interp) } # Removed in androwish -#declare 133 { +# declare 133 { # struct tm *TclpGetDate(const time_t *time, int useGMT) #} # Removed in 8.5 @@ -750,6 +750,8 @@ declare 179 { # const char *file, int line) #} +# TclpGmtime and TclpLocaltime promoted to the generic interface from unix + # Removed in androwish #declare 182 { # struct tm *TclpLocaltime(const time_t *clock) @@ -1218,12 +1220,14 @@ declare 10 unix { } # Slots 11 and 12 are forwarders for functions that were promoted to # generic Stubs -declare 11 unix { - struct tm *TclpLocaltime_unix(const time_t *clock) -} -declare 12 unix { - struct tm *TclpGmtime_unix(const time_t *clock) -} +# Removed in androwish +#declare 11 unix { +# struct tm *TclpLocaltime_unix(const time_t *clock) +#} +# Removed in androwish +#declare 12 unix { +# struct tm *TclpGmtime_unix(const time_t *clock) +#} declare 13 unix { char *TclpInetNtoa(struct in_addr addr) } diff --git a/generic/tclIntPlatDecls.h b/generic/tclIntPlatDecls.h index ac06787..b7a44d8 100644 --- a/generic/tclIntPlatDecls.h +++ b/generic/tclIntPlatDecls.h @@ -73,10 +73,8 @@ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout); EXTERN TclFile TclpCreateTempFile(const char *contents); /* 10 */ EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); -/* 11 */ -EXTERN struct tm * TclpLocaltime_unix(const time_t *clock); -/* 12 */ -EXTERN struct tm * TclpGmtime_unix(const time_t *clock); +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ /* 13 */ EXTERN char * TclpInetNtoa(struct in_addr addr); /* 14 */ @@ -207,10 +205,8 @@ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout); EXTERN TclFile TclpCreateTempFile(const char *contents); /* 10 */ EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); -/* 11 */ -EXTERN struct tm * TclpLocaltime_unix(const time_t *clock); -/* 12 */ -EXTERN struct tm * TclpGmtime_unix(const time_t *clock); +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ /* 13 */ EXTERN char * TclpInetNtoa(struct in_addr addr); /* 14 */ @@ -270,8 +266,8 @@ typedef struct TclIntPlatStubs { int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ - struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */ - struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */ + void (*reserved11)(void); + void (*reserved12)(void); char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ void (*reserved15)(void); @@ -336,8 +332,8 @@ typedef struct TclIntPlatStubs { int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ - struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */ - struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */ + void (*reserved11)(void); + void (*reserved12)(void); char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ int (*tclMacOSXGetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 15 */ @@ -393,10 +389,8 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr; (tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */ #define TclpReaddir \ (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ -#define TclpLocaltime_unix \ - (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */ -#define TclpGmtime_unix \ - (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */ +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ #define TclpInetNtoa \ (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */ #define TclUnixCopyFile \ @@ -504,10 +498,8 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr; (tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */ #define TclpReaddir \ (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ -#define TclpLocaltime_unix \ - (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */ -#define TclpGmtime_unix \ - (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */ +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ #define TclpInetNtoa \ (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */ #define TclUnixCopyFile \ diff --git a/win/tclWinTime.c b/win/tclWinTime.c index 7045c72..97e1f41 100644 --- a/win/tclWinTime.c +++ b/win/tclWinTime.c @@ -113,7 +113,6 @@ static TimeInfo timeInfo = { * Declarations for functions defined later in this file. */ -static struct tm * ComputeGMT(const time_t *tp); static void StopCalibration(ClientData clientData); static DWORD WINAPI CalibrationThread(LPVOID arg); static void UpdateTimeEachSecond(void); @@ -489,227 +488,6 @@ StopCalibration( /* *---------------------------------------------------------------------- * - * TclpGetDate -- - * - * This function converts between seconds and struct tm. If useGMT is - * true, then the returned date will be in Greenwich Mean Time (GMT). - * Otherwise, it will be in the local time zone. - * - * Results: - * Returns a static tm structure. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -struct tm * -TclpGetDate( - const time_t *t, - int useGMT) -{ - struct tm *tmPtr; - time_t time; - - if (!useGMT) { - tzset(); - - /* - * If we are in the valid range, let the C run-time library handle it. - * Otherwise we need to fake it. Note that this algorithm ignores - * daylight savings time before the epoch. - */ - - /* - * Hm, Borland's localtime manages to return NULL under certain - * circumstances (e.g. wintime.test, test 1.2). Nobody tests for this, - * since 'localtime' isn't supposed to do this, possibly leading to - * crashes. - * - * Patch: We only call this function if we are at least one day into - * the epoch, else we handle it ourselves (like we do for times < 0). - * H. Giese, June 2003 - */ - -#ifdef __BORLANDC__ -#define LOCALTIME_VALIDITY_BOUNDARY SECSPERDAY -#else -#define LOCALTIME_VALIDITY_BOUNDARY 0 -#endif - - if (*t >= LOCALTIME_VALIDITY_BOUNDARY) { - return TclpLocaltime(t); - } - - time = *t - timezone; - - /* - * If we aren't near to overflowing the long, just add the bias and - * use the normal calculation. Otherwise we will need to adjust the - * result at the end. - */ - - if (*t < (LONG_MAX - 2*SECSPERDAY) && *t > (LONG_MIN + 2*SECSPERDAY)) { - tmPtr = ComputeGMT(&time); - } else { - tmPtr = ComputeGMT(t); - - tzset(); - - /* - * Add the bias directly to the tm structure to avoid overflow. - * Propagate seconds overflow into minutes, hours and days. - */ - - time = tmPtr->tm_sec - timezone; - tmPtr->tm_sec = (int)(time % 60); - if (tmPtr->tm_sec < 0) { - tmPtr->tm_sec += 60; - time -= 60; - } - - time = tmPtr->tm_min + time/60; - tmPtr->tm_min = (int)(time % 60); - if (tmPtr->tm_min < 0) { - tmPtr->tm_min += 60; - time -= 60; - } - - time = tmPtr->tm_hour + time/60; - tmPtr->tm_hour = (int)(time % 24); - if (tmPtr->tm_hour < 0) { - tmPtr->tm_hour += 24; - time -= 24; - } - - time /= 24; - tmPtr->tm_mday += (int)time; - tmPtr->tm_yday += (int)time; - tmPtr->tm_wday = (tmPtr->tm_wday + (int)time) % 7; - } - } else { - tmPtr = ComputeGMT(t); - } - return tmPtr; -} - -/* - *---------------------------------------------------------------------- - * - * ComputeGMT -- - * - * This function computes GMT given the number of seconds since the epoch - * (midnight Jan 1 1970). - * - * Results: - * Returns a (per thread) statically allocated struct tm. - * - * Side effects: - * Updates the values of the static struct tm. - * - *---------------------------------------------------------------------- - */ - -static struct tm * -ComputeGMT( - const time_t *tp) -{ - struct tm *tmPtr; - long tmp, rem; - int isLeap; - const int *days; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - tmPtr = &tsdPtr->tm; - - /* - * Compute the 4 year span containing the specified time. - */ - - tmp = (long)(*tp / SECSPER4YEAR); - rem = (long)(*tp % SECSPER4YEAR); - - /* - * Correct for weird mod semantics so the remainder is always positive. - */ - - if (rem < 0) { - tmp--; - rem += SECSPER4YEAR; - } - - /* - * Compute the year after 1900 by taking the 4 year span and adjusting for - * the remainder. This works because 2000 is a leap year, and 1900/2100 - * are out of the range. - */ - - tmp = (tmp * 4) + 70; - isLeap = 0; - if (rem >= SECSPERYEAR) { /* 1971, etc. */ - tmp++; - rem -= SECSPERYEAR; - if (rem >= SECSPERYEAR) { /* 1972, etc. */ - tmp++; - rem -= SECSPERYEAR; - if (rem >= SECSPERYEAR + SECSPERDAY) { /* 1973, etc. */ - tmp++; - rem -= SECSPERYEAR + SECSPERDAY; - } else { - isLeap = 1; - } - } - } - tmPtr->tm_year = tmp; - - /* - * Compute the day of year and leave the seconds in the current day in the - * remainder. - */ - - tmPtr->tm_yday = rem / SECSPERDAY; - rem %= SECSPERDAY; - - /* - * Compute the time of day. - */ - - tmPtr->tm_hour = rem / 3600; - rem %= 3600; - tmPtr->tm_min = rem / 60; - tmPtr->tm_sec = rem % 60; - - /* - * Compute the month and day of month. - */ - - days = (isLeap) ? leapDays : normalDays; - for (tmp = 1; days[tmp] < tmPtr->tm_yday; tmp++) { - /* empty body */ - } - tmPtr->tm_mon = --tmp; - tmPtr->tm_mday = tmPtr->tm_yday - days[tmp]; - - /* - * Compute day of week. Epoch started on a Thursday. - */ - - tmPtr->tm_wday = (long)(*tp / SECSPERDAY) + 4; - if ((*tp % SECSPERDAY) < 0) { - tmPtr->tm_wday--; - } - tmPtr->tm_wday %= 7; - if (tmPtr->tm_wday < 0) { - tmPtr->tm_wday += 7; - } - - return tmPtr; -} - -/* - *---------------------------------------------------------------------- - * * CalibrationThread -- * * Thread that manages calibration of the hi-resolution time derived from -- cgit v0.12 From ecc90e3787b23274b9f03670ba869c8f7da8213a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 24 Aug 2015 08:01:23 +0000 Subject: one more.... --- generic/tclStubInit.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index edeb42a..8359fa6 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -294,10 +294,6 @@ static int formatInt(char *buffer, int n){ #define TclFormatInt (int(*)(char *, long))formatInt #endif - -#else /* UNIX and MAC */ -# define TclpLocaltime_unix TclpLocaltime -# define TclpGmtime_unix TclpGmtime #endif /* @@ -586,8 +582,8 @@ static const TclIntPlatStubs tclIntPlatStubs = { TclUnixWaitForFile, /* 8 */ TclpCreateTempFile, /* 9 */ TclpReaddir, /* 10 */ - TclpLocaltime_unix, /* 11 */ - TclpGmtime_unix, /* 12 */ + 0, /* 11 */ + 0, /* 12 */ TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ 0, /* 15 */ @@ -652,8 +648,8 @@ static const TclIntPlatStubs tclIntPlatStubs = { TclUnixWaitForFile, /* 8 */ TclpCreateTempFile, /* 9 */ TclpReaddir, /* 10 */ - TclpLocaltime_unix, /* 11 */ - TclpGmtime_unix, /* 12 */ + 0, /* 11 */ + 0, /* 12 */ TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ TclMacOSXGetFileAttribute, /* 15 */ -- cgit v0.12 From dbe627594edb4a5b12aa260f2c02d9c2b2b48c3f Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 31 Aug 2015 17:30:01 +0000 Subject: Dependancies from androwish upstream --- Android.mk | 2 ++ tcl-config.mk | 72 +++++++++++++++++++++++++++++---------------------------- win/Makefile.in | 5 ++-- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/Android.mk b/Android.mk index 9d8ce27..13e55d9 100644 --- a/Android.mk +++ b/Android.mk @@ -12,6 +12,8 @@ tcl_path := $(LOCAL_PATH) include $(tcl_path)/tcl-config.mk +LOCAL_ADDITIONAL_DEPENDENCIES += $(tcl_path)/tcl-config.mk + LOCAL_MODULE := tcl LOCAL_ARM_MODE := arm diff --git a/tcl-config.mk b/tcl-config.mk index ae14b6b..e072516 100644 --- a/tcl-config.mk +++ b/tcl-config.mk @@ -1,60 +1,62 @@ tcl_includes := $(tcl_path)/generic $(tcl_path)/unix tcl_cflags := \ - -DHAVE_SYS_SELECT_H=1 \ - -DHAVE_LIMITS_H=1 \ - -DHAVE_UNISTD_H=1 \ - -DHAVE_SYS_PARAM_H=1 \ - -D_LARGEFILE64_SOURCE=1 \ - -DTCL_WIDE_INT_TYPE="long long" \ - -DTCL_SHLIB_EXT="\".so\"" \ - -DHAVE_CAST_TO_UNION=1 \ - -DHAVE_GETCWD=1 \ - -DHAVE_OPENDIR=1 \ + -DHAVE_SYS_SELECT_H=1 \ + -DHAVE_LIMITS_H=1 \ + -DHAVE_UNISTD_H=1 \ + -DHAVE_SYS_PARAM_H=1 \ + -D_LARGEFILE64_SOURCE=1 \ + -DTCL_WIDE_INT_TYPE="long long" \ + -DTCL_SHLIB_EXT="\".so\"" \ + -DHAVE_CAST_TO_UNION=1 \ + -DHAVE_GETCWD=1 \ + -DHAVE_OPENDIR=1 \ -DHAVE_MKSTEMP=1 \ -DHAVE_MKSTEMPS=1 \ - -DHAVE_STRSTR=1 \ - -DHAVE_STRTOL=1 \ - -DHAVE_STRTOLL=1 \ - -DHAVE_STRTOULL=1 \ - -DHAVE_TMPNAM=1 \ - -DHAVE_WAITPID=1 \ + -DHAVE_STRSTR=1 \ + -DHAVE_STRTOL=1 \ + -DHAVE_STRTOLL=1 \ + -DHAVE_STRTOULL=1 \ + -DHAVE_TMPNAM=1 \ + -DHAVE_WAITPID=1 \ -DHAVE_STRUCT_ADDRINFO=1 \ -DHAVE_STRUCT_IN6_ADDR=1 \ -DHAVE_STRUCT_SOCKADDR_IN6=1 \ -DHAVE_STRUCT_SOCKADDR_STORAGE=1 \ - -DUSE_TERMIOS=1 \ - -DHAVE_MKTIME=1 \ - -DUSE_INTERP_ERRORLINE=1 \ - -DHAVE_SYS_TIME_H=1 \ - -DTIME_WITH_SYS_TIME=1 \ - -DHAVE_TM_ZONE=1 \ - -DHAVE_GMTIME_R=1 \ - -DHAVE_LOCALTIME_R=1 \ - -DHAVE_TM_GMTOFF=1 \ - -DHAVE_TIMEZONE_VAR=1 \ - -DHAVE_ST_BLKSIZE=1 \ - -DSTDC_HEADERS=1 \ + -DHAVE_GETHOSTBYNAME_R=1 \ + -DUSE_TERMIOS=1 \ + -DHAVE_MKTIME=1 \ + -DUSE_INTERP_ERRORLINE=1 \ + -DHAVE_SYS_TIME_H=1 \ + -DTIME_WITH_SYS_TIME=1 \ + -DHAVE_TM_ZONE=1 \ + -DHAVE_GMTIME_R=1 \ + -DHAVE_LOCALTIME_R=1 \ + -DHAVE_TM_GMTOFF=1 \ + -DHAVE_TIMEZONE_VAR=1 \ + -DHAVE_ST_BLKSIZE=1 \ + -DSTDC_HEADERS=1 \ -DHAVE_INTPTR_T=1 \ -DHAVE_UINTPTR_T=1 \ -DHAVE_SIGNED_CHAR=1 \ - -DHAVE_SYS_IOCTL_H=1 \ - -DHAVE_MEMCPY=1 \ - -DHAVE_MEMMOVE=1 \ - -DVOID=void \ - -DNO_UNION_WAIT=1 \ - -DHAVE_ZLIB=1 \ + -DHAVE_SYS_IOCTL_H=1 \ + -DHAVE_MEMCPY=1 \ + -DHAVE_MEMMOVE=1 \ + -DVOID=void \ + -DNO_UNION_WAIT=1 \ + -DHAVE_ZLIB=1 \ -DMP_PREC=4 \ -DTCL_TOMMATH=1 \ -D_REENTRANT=1 \ -D_THREADSAFE=1 \ + -DTCL_UTF_MAX=6 \ -DTCL_THREADS=1 \ -DTCL_PTHREAD_ATFORK=1 \ -DUSE_THREAD_ALLOC=1 \ -DTCL_CFGVAL_ENCODING="\"utf-8\"" \ -DTCL_UNLOAD_DLLS=1 \ -DTCL_CFG_OPTIMIZED=1 \ - -DZIPFS_IN_TCL=1 \ + -DZIPFS_IN_TCL=1 \ -DTCL_PACKAGE_PATH="\"/assets\"" \ -DTCL_LIBRARY="\"/assets/tcl8.6\"" diff --git a/win/Makefile.in b/win/Makefile.in index b92a062..b8a130c 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -296,7 +296,8 @@ GENERIC_OBJS = \ tclUtf.$(OBJEXT) \ tclUtil.$(OBJEXT) \ tclVar.$(OBJEXT) \ - tclZlib.$(OBJEXT) + tclZlib.$(OBJEXT) \ + zipfs.$(OBJEXT) TOMMATH_OBJS = \ bncore.${OBJEXT} \ @@ -741,7 +742,7 @@ clean: cleanhelp clean-packages distclean: distclean-packages clean $(RM) Makefile config.status config.cache config.log tclConfig.sh \ - tcl.hpj config.status.lineno + tcl.hpj config.status.lineno tclsh.exe.manifest # # Bundled package targets -- cgit v0.12 From 842b15b839b378f34b23291dda5ba279cffe1607 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 17 Sep 2015 11:47:04 +0000 Subject: fixed bug in zipfs error handling (backported from androwish) --- generic/zipfs.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/generic/zipfs.c b/generic/zipfs.c index ec58d9f..c150da0 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -819,10 +819,13 @@ Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, if (!isNew) { zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (interp != NULL) { - Tcl_AppendResult(interp, "already mounted at ", zf->mntpt, - (char *) NULL); + Tcl_AppendResult(interp, "already mounted on \"", zf->mntptlen ? + zf->mntpt : "/", "\"", (char *) NULL); } - goto error; + Unlock(); + Tcl_DStringFree(&ds); + ZipFSCloseArchive(interp, &zf0); + return TCL_ERROR; } if (strcmp(mntpt, "/") == 0) { mntpt = ""; @@ -915,6 +918,7 @@ Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, goto nextent; } if (!isdir && (mntpt[0] == '\0') && !CountSlashes(path)) { + /* regular files skipped when mounting on root */ goto nextent; } Tcl_DStringSetLength(&fpBuf, 0); @@ -947,7 +951,7 @@ Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, z->data = NULL; hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, fullpath, &isNew); if (!isNew) { - /* skip it */ + /* should not happen but skip it anyway */ Tcl_Free((char *) z); } else { Tcl_SetHashValue(hPtr, (ClientData) z); @@ -988,7 +992,7 @@ Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, zd->data = NULL; hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, dir, &isNew); if (!isNew) { - /* should never happen but skip it */ + /* should not happen but skip it anyway */ Tcl_Free((char *) zd); } else { Tcl_SetHashValue(hPtr, (ClientData) zd); @@ -1012,13 +1016,6 @@ nextent: Unlock(); Tcl_FSMountsChanged(NULL); return TCL_OK; - -error: - Tcl_DStringFree(&ds); - Unlock(); - ZipFSCloseArchive(interp, zf); - Tcl_Free((char *) zf); - return TCL_ERROR; } int @@ -1039,7 +1036,7 @@ Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname) } hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, realname); if (hPtr == NULL) { - /* does not report error */ + /* don't report error */ goto done; } zf = (ZipFile *) Tcl_GetHashValue(hPtr); @@ -1707,7 +1704,8 @@ ZipFSListObjCmd(ClientData clientData, Tcl_Interp *interp, return TCL_ERROR; } } else { - Tcl_AppendResult(interp, "unknown option: ", what, (char *) NULL); + Tcl_AppendResult(interp, "unknown option \"", what, + "\"", (char *) NULL); return TCL_ERROR; } } else if (objc == 2) { -- cgit v0.12 From 9dd94f739633837da43ddf3f0af5f99a36c2e803 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 28 Sep 2015 10:58:30 +0000 Subject: Don't use mutex retry mechanism on Android. (problems ???) --- unix/tclUnixThrd.c | 51 +++++---------------------------------------------- win/tclWinThrd.c | 37 +++++-------------------------------- 2 files changed, 10 insertions(+), 78 deletions(-) diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index ae81c5f..0e8070d 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -22,19 +22,6 @@ typedef struct ThreadSpecificData { static Tcl_ThreadDataKey dataKey; /* - * This is the number of milliseconds to wait between internal retries in - * the Tcl_MutexLock function. This value must be greater than zero and - * should be a suitable value for the given platform. - * - * TODO: This may need to be dynamically determined, based on the relative - * performance of the running process. - */ - -#ifndef TCL_MUTEX_LOCK_SLEEP_TIME -# define TCL_MUTEX_LOCK_SLEEP_TIME (25) -#endif - -/* * masterLock is used to serialize creation of mutexes, condition variables, * and thread local storage. This is the only place that can count on the * ability to statically initialize the mutex. @@ -58,13 +45,6 @@ static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t *allocLockPtr = &allocLock; /* - * The mutexLock serializes Tcl_MutexLock. This is necessary to prevent - * races when finalizing a mutex that some other thread may want to lock. - */ - -static pthread_mutex_t mutexLock = PTHREAD_MUTEX_INITIALIZER; - -/* * These are for the critical sections inside this file. */ @@ -380,7 +360,6 @@ TclpMasterUnlock(void) pthread_mutex_unlock(&masterLock); #endif } - /* *---------------------------------------------------------------------- @@ -457,32 +436,12 @@ retry: } MASTER_UNLOCK; } - while (1) { - pthread_mutex_lock(&mutexLock); - pmutexPtr = *((pthread_mutex_t **)mutexPtr); - if (pmutexPtr == NULL) { - pthread_mutex_unlock(&mutexLock); - goto retry; - } - if (pthread_mutex_trylock(pmutexPtr) == 0) { - pthread_mutex_unlock(&mutexLock); - return; - } - pthread_mutex_unlock(&mutexLock); - /* - * BUGBUG: All core and Thread package tests pass when usleep() - * is used; however, the Thread package tests hang at - * various places when Tcl_Sleep() is used, typically - * while running test "thread-17.8", "thread-17.9", or - * "thread-17.11a". Really, what we want here is just - * to yield to other threads for a while. - */ -#ifdef HAVE_USLEEP - usleep(TCL_MUTEX_LOCK_SLEEP_TIME * 1000); -#else - Tcl_Sleep(TCL_MUTEX_LOCK_SLEEP_TIME); -#endif + + pmutexPtr = *((pthread_mutex_t **)mutexPtr); + if (pmutexPtr == NULL) { + goto retry; } + pthread_mutex_lock(pmutexPtr); } /* diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index ae7ce80..927e115 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -24,16 +24,6 @@ _CRTIMP unsigned int __cdecl _controlfp (unsigned int unNew, unsigned int unMask #endif /* - * This is the number of milliseconds to wait between internal retries in - * the Tcl_MutexLock function. This value must be greater than or equal - * to zero and should be a suitable value for the given platform. - */ - -#ifndef TCL_MUTEX_LOCK_SLEEP_TIME -# define TCL_MUTEX_LOCK_SLEEP_TIME (0) -#endif - -/* * This is the master lock used to serialize access to other serialization * data structures. */ @@ -67,13 +57,6 @@ static int allocOnce = 0; #endif /* TCL_THREADS */ /* - * The mutexLock serializes Tcl_MutexLock. This is necessary to prevent - * races when finalizing a mutex that some other thread may want to lock. - */ - -static CRITICAL_SECTION mutexLock; - -/* * The joinLock serializes Create- and ExitThread. This is necessary to * prevent a race where a new joinable thread exits before the creating thread * had the time to create the necessary data structures in the emulation @@ -386,7 +369,6 @@ TclpInitLock(void) */ init = 1; - InitializeCriticalSection(&mutexLock); InitializeCriticalSection(&joinLock); InitializeCriticalSection(&initLock); InitializeCriticalSection(&masterLock); @@ -534,7 +516,6 @@ void TclFinalizeLock(void) { MASTER_LOCK; - DeleteCriticalSection(&mutexLock); DeleteCriticalSection(&joinLock); /* @@ -605,20 +586,12 @@ retry: } MASTER_UNLOCK; } - while (1) { - EnterCriticalSection(&mutexLock); - csPtr = *((CRITICAL_SECTION **)mutexPtr); - if (csPtr == NULL) { - LeaveCriticalSection(&mutexLock); - goto retry; - } - if (TryEnterCriticalSection(csPtr)) { - LeaveCriticalSection(&mutexLock); - return; - } - LeaveCriticalSection(&mutexLock); - Tcl_Sleep(TCL_MUTEX_LOCK_SLEEP_TIME); + + csPtr = *((CRITICAL_SECTION **)mutexPtr); + if (csPtr == NULL) { + goto retry; } + EnterCriticalSection(csPtr); } /* -- cgit v0.12 From f98d4ff8596454556cb3dd753ac4aceb60e7455b Mon Sep 17 00:00:00 2001 From: venkat Date: Tue, 27 Oct 2015 23:16:06 +0000 Subject: Update to tzdata2015g from ietf --- library/tzdata/America/Fort_Nelson | 151 +++++++++++++++++++++++++++++++++++++ library/tzdata/Europe/Istanbul | 3 +- library/tzdata/Pacific/Fiji | 72 +++++++++--------- library/tzdata/Pacific/Norfolk | 3 + 4 files changed, 192 insertions(+), 37 deletions(-) create mode 100644 library/tzdata/America/Fort_Nelson diff --git a/library/tzdata/America/Fort_Nelson b/library/tzdata/America/Fort_Nelson new file mode 100644 index 0000000..d819368 --- /dev/null +++ b/library/tzdata/America/Fort_Nelson @@ -0,0 +1,151 @@ +# created by tools/tclZIC.tcl - do not edit + +set TZData(:America/Fort_Nelson) { + {-9223372036854775808 -29447 0 LMT} + {-2713880953 -28800 0 PST} + {-1632060000 -25200 1 PDT} + {-1615129200 -28800 0 PST} + {-880207200 -25200 1 PWT} + {-769395600 -25200 1 PPT} + {-765385200 -28800 0 PST} + {-757353600 -28800 0 PST} + {-725817600 -28800 0 PST} + {-715788000 -25200 1 PDT} + {-702486000 -28800 0 PST} + {-684338400 -25200 1 PDT} + {-671036400 -28800 0 PST} + {-652888800 -25200 1 PDT} + {-639586800 -28800 0 PST} + {-620834400 -25200 1 PDT} + {-608137200 -28800 0 PST} + {-589384800 -25200 1 PDT} + {-576082800 -28800 0 PST} + {-557935200 -25200 1 PDT} + {-544633200 -28800 0 PST} + {-526485600 -25200 1 PDT} + {-513183600 -28800 0 PST} + {-495036000 -25200 1 PDT} + {-481734000 -28800 0 PST} + {-463586400 -25200 1 PDT} + {-450284400 -28800 0 PST} + {-431532000 -25200 1 PDT} + {-418230000 -28800 0 PST} + {-400082400 -25200 1 PDT} + {-386780400 -28800 0 PST} + {-368632800 -25200 1 PDT} + {-355330800 -28800 0 PST} + {-337183200 -25200 1 PDT} + {-323881200 -28800 0 PST} + {-305733600 -25200 1 PDT} + {-292431600 -28800 0 PST} + {-273679200 -25200 1 PDT} + {-260982000 -28800 0 PST} + {-242229600 -25200 1 PDT} + {-226508400 -28800 0 PST} + {-210780000 -25200 1 PDT} + {-195058800 -28800 0 PST} + {-179330400 -25200 1 PDT} + {-163609200 -28800 0 PST} + {-147880800 -25200 1 PDT} + {-131554800 -28800 0 PST} + {-116431200 -25200 1 PDT} + {-100105200 -28800 0 PST} + {-84376800 -25200 1 PDT} + {-68655600 -28800 0 PST} + {-52927200 -25200 1 PDT} + {-37206000 -28800 0 PST} + {-21477600 -25200 1 PDT} + {-5756400 -28800 0 PST} + {9972000 -25200 1 PDT} + {25693200 -28800 0 PST} + {41421600 -25200 1 PDT} + {57747600 -28800 0 PST} + {73476000 -25200 1 PDT} + {89197200 -28800 0 PST} + {104925600 -25200 1 PDT} + {120646800 -28800 0 PST} + {136375200 -25200 1 PDT} + {152096400 -28800 0 PST} + {167824800 -25200 1 PDT} + {183546000 -28800 0 PST} + {199274400 -25200 1 PDT} + {215600400 -28800 0 PST} + {230724000 -25200 1 PDT} + {247050000 -28800 0 PST} + {262778400 -25200 1 PDT} + {278499600 -28800 0 PST} + {294228000 -25200 1 PDT} + {309949200 -28800 0 PST} + {325677600 -25200 1 PDT} + {341398800 -28800 0 PST} + {357127200 -25200 1 PDT} + {372848400 -28800 0 PST} + {388576800 -25200 1 PDT} + {404902800 -28800 0 PST} + {420026400 -25200 1 PDT} + {436352400 -28800 0 PST} + {452080800 -25200 1 PDT} + {467802000 -28800 0 PST} + {483530400 -25200 1 PDT} + {499251600 -28800 0 PST} + {514980000 -25200 1 PDT} + {530701200 -28800 0 PST} + {536486400 -28800 0 PST} + {544615200 -25200 1 PDT} + {562150800 -28800 0 PST} + {576064800 -25200 1 PDT} + {594205200 -28800 0 PST} + {607514400 -25200 1 PDT} + {625654800 -28800 0 PST} + {638964000 -25200 1 PDT} + {657104400 -28800 0 PST} + {671018400 -25200 1 PDT} + {688554000 -28800 0 PST} + {702468000 -25200 1 PDT} + {720003600 -28800 0 PST} + {733917600 -25200 1 PDT} + {752058000 -28800 0 PST} + {765367200 -25200 1 PDT} + {783507600 -28800 0 PST} + {796816800 -25200 1 PDT} + {814957200 -28800 0 PST} + {828871200 -25200 1 PDT} + {846406800 -28800 0 PST} + {860320800 -25200 1 PDT} + {877856400 -28800 0 PST} + {891770400 -25200 1 PDT} + {909306000 -28800 0 PST} + {923220000 -25200 1 PDT} + {941360400 -28800 0 PST} + {954669600 -25200 1 PDT} + {972810000 -28800 0 PST} + {986119200 -25200 1 PDT} + {1004259600 -28800 0 PST} + {1018173600 -25200 1 PDT} + {1035709200 -28800 0 PST} + {1049623200 -25200 1 PDT} + {1067158800 -28800 0 PST} + {1081072800 -25200 1 PDT} + {1099213200 -28800 0 PST} + {1112522400 -25200 1 PDT} + {1130662800 -28800 0 PST} + {1143972000 -25200 1 PDT} + {1162112400 -28800 0 PST} + {1173607200 -25200 1 PDT} + {1194166800 -28800 0 PST} + {1205056800 -25200 1 PDT} + {1225616400 -28800 0 PST} + {1236506400 -25200 1 PDT} + {1257066000 -28800 0 PST} + {1268560800 -25200 1 PDT} + {1289120400 -28800 0 PST} + {1300010400 -25200 1 PDT} + {1320570000 -28800 0 PST} + {1331460000 -25200 1 PDT} + {1352019600 -28800 0 PST} + {1362909600 -25200 1 PDT} + {1383469200 -28800 0 PST} + {1394359200 -25200 1 PDT} + {1414918800 -28800 0 PST} + {1425808800 -25200 0 MST} +} diff --git a/library/tzdata/Europe/Istanbul b/library/tzdata/Europe/Istanbul index 7cb4820..8eadbc3 100644 --- a/library/tzdata/Europe/Istanbul +++ b/library/tzdata/Europe/Istanbul @@ -133,7 +133,8 @@ set TZData(:Europe/Istanbul) { {1396227600 10800 0 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} - {1445734800 7200 0 EET} + {1445734800 10800 1 EEST} + {1446944400 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} diff --git a/library/tzdata/Pacific/Fiji b/library/tzdata/Pacific/Fiji index 4aae330..8f8b12f 100644 --- a/library/tzdata/Pacific/Fiji +++ b/library/tzdata/Pacific/Fiji @@ -20,9 +20,9 @@ set TZData(:Pacific/Fiji) { {1414850400 46800 1 FJST} {1421503200 43200 0 FJT} {1446300000 46800 1 FJST} - {1453557600 43200 0 FJT} + {1452952800 43200 0 FJT} {1478354400 46800 1 FJST} - {1485007200 43200 0 FJT} + {1484402400 43200 0 FJT} {1509804000 46800 1 FJST} {1516456800 43200 0 FJT} {1541253600 46800 1 FJST} @@ -30,11 +30,11 @@ set TZData(:Pacific/Fiji) { {1572703200 46800 1 FJST} {1579356000 43200 0 FJT} {1604152800 46800 1 FJST} - {1611410400 43200 0 FJT} + {1610805600 43200 0 FJT} {1636207200 46800 1 FJST} - {1642860000 43200 0 FJT} + {1642255200 43200 0 FJT} {1667656800 46800 1 FJST} - {1674309600 43200 0 FJT} + {1673704800 43200 0 FJT} {1699106400 46800 1 FJST} {1705759200 43200 0 FJT} {1730556000 46800 1 FJST} @@ -42,9 +42,9 @@ set TZData(:Pacific/Fiji) { {1762005600 46800 1 FJST} {1768658400 43200 0 FJT} {1793455200 46800 1 FJST} - {1800712800 43200 0 FJT} + {1800108000 43200 0 FJT} {1825509600 46800 1 FJST} - {1832162400 43200 0 FJT} + {1831557600 43200 0 FJT} {1856959200 46800 1 FJST} {1863612000 43200 0 FJT} {1888408800 46800 1 FJST} @@ -54,9 +54,9 @@ set TZData(:Pacific/Fiji) { {1951308000 46800 1 FJST} {1957960800 43200 0 FJT} {1983362400 46800 1 FJST} - {1990015200 43200 0 FJT} + {1989410400 43200 0 FJT} {2014812000 46800 1 FJST} - {2021464800 43200 0 FJT} + {2020860000 43200 0 FJT} {2046261600 46800 1 FJST} {2052914400 43200 0 FJT} {2077711200 46800 1 FJST} @@ -64,11 +64,11 @@ set TZData(:Pacific/Fiji) { {2109160800 46800 1 FJST} {2115813600 43200 0 FJT} {2140610400 46800 1 FJST} - {2147868000 43200 0 FJT} + {2147263200 43200 0 FJT} {2172664800 46800 1 FJST} - {2179317600 43200 0 FJT} + {2178712800 43200 0 FJT} {2204114400 46800 1 FJST} - {2210767200 43200 0 FJT} + {2210162400 43200 0 FJT} {2235564000 46800 1 FJST} {2242216800 43200 0 FJT} {2267013600 46800 1 FJST} @@ -76,9 +76,9 @@ set TZData(:Pacific/Fiji) { {2298463200 46800 1 FJST} {2305116000 43200 0 FJT} {2329912800 46800 1 FJST} - {2337170400 43200 0 FJT} + {2336565600 43200 0 FJT} {2361967200 46800 1 FJST} - {2368620000 43200 0 FJT} + {2368015200 43200 0 FJT} {2393416800 46800 1 FJST} {2400069600 43200 0 FJT} {2424866400 46800 1 FJST} @@ -86,11 +86,11 @@ set TZData(:Pacific/Fiji) { {2456316000 46800 1 FJST} {2462968800 43200 0 FJT} {2487765600 46800 1 FJST} - {2495023200 43200 0 FJT} + {2494418400 43200 0 FJT} {2519820000 46800 1 FJST} - {2526472800 43200 0 FJT} + {2525868000 43200 0 FJT} {2551269600 46800 1 FJST} - {2557922400 43200 0 FJT} + {2557317600 43200 0 FJT} {2582719200 46800 1 FJST} {2589372000 43200 0 FJT} {2614168800 46800 1 FJST} @@ -98,9 +98,9 @@ set TZData(:Pacific/Fiji) { {2645618400 46800 1 FJST} {2652271200 43200 0 FJT} {2677068000 46800 1 FJST} - {2684325600 43200 0 FJT} + {2683720800 43200 0 FJT} {2709122400 46800 1 FJST} - {2715775200 43200 0 FJT} + {2715170400 43200 0 FJT} {2740572000 46800 1 FJST} {2747224800 43200 0 FJT} {2772021600 46800 1 FJST} @@ -110,9 +110,9 @@ set TZData(:Pacific/Fiji) { {2834920800 46800 1 FJST} {2841573600 43200 0 FJT} {2866975200 46800 1 FJST} - {2873628000 43200 0 FJT} + {2873023200 43200 0 FJT} {2898424800 46800 1 FJST} - {2905077600 43200 0 FJT} + {2904472800 43200 0 FJT} {2929874400 46800 1 FJST} {2936527200 43200 0 FJT} {2961324000 46800 1 FJST} @@ -120,11 +120,11 @@ set TZData(:Pacific/Fiji) { {2992773600 46800 1 FJST} {2999426400 43200 0 FJT} {3024223200 46800 1 FJST} - {3031480800 43200 0 FJT} + {3030876000 43200 0 FJT} {3056277600 46800 1 FJST} - {3062930400 43200 0 FJT} + {3062325600 43200 0 FJT} {3087727200 46800 1 FJST} - {3094380000 43200 0 FJT} + {3093775200 43200 0 FJT} {3119176800 46800 1 FJST} {3125829600 43200 0 FJT} {3150626400 46800 1 FJST} @@ -132,9 +132,9 @@ set TZData(:Pacific/Fiji) { {3182076000 46800 1 FJST} {3188728800 43200 0 FJT} {3213525600 46800 1 FJST} - {3220783200 43200 0 FJT} + {3220178400 43200 0 FJT} {3245580000 46800 1 FJST} - {3252232800 43200 0 FJT} + {3251628000 43200 0 FJT} {3277029600 46800 1 FJST} {3283682400 43200 0 FJT} {3308479200 46800 1 FJST} @@ -142,11 +142,11 @@ set TZData(:Pacific/Fiji) { {3339928800 46800 1 FJST} {3346581600 43200 0 FJT} {3371378400 46800 1 FJST} - {3378636000 43200 0 FJT} + {3378031200 43200 0 FJT} {3403432800 46800 1 FJST} - {3410085600 43200 0 FJT} + {3409480800 43200 0 FJT} {3434882400 46800 1 FJST} - {3441535200 43200 0 FJT} + {3440930400 43200 0 FJT} {3466332000 46800 1 FJST} {3472984800 43200 0 FJT} {3497781600 46800 1 FJST} @@ -154,9 +154,9 @@ set TZData(:Pacific/Fiji) { {3529231200 46800 1 FJST} {3535884000 43200 0 FJT} {3560680800 46800 1 FJST} - {3567938400 43200 0 FJT} + {3567333600 43200 0 FJT} {3592735200 46800 1 FJST} - {3599388000 43200 0 FJT} + {3598783200 43200 0 FJT} {3624184800 46800 1 FJST} {3630837600 43200 0 FJT} {3655634400 46800 1 FJST} @@ -166,9 +166,9 @@ set TZData(:Pacific/Fiji) { {3718533600 46800 1 FJST} {3725186400 43200 0 FJT} {3750588000 46800 1 FJST} - {3757240800 43200 0 FJT} + {3756636000 43200 0 FJT} {3782037600 46800 1 FJST} - {3788690400 43200 0 FJT} + {3788085600 43200 0 FJT} {3813487200 46800 1 FJST} {3820140000 43200 0 FJT} {3844936800 46800 1 FJST} @@ -176,11 +176,11 @@ set TZData(:Pacific/Fiji) { {3876386400 46800 1 FJST} {3883039200 43200 0 FJT} {3907836000 46800 1 FJST} - {3915093600 43200 0 FJT} + {3914488800 43200 0 FJT} {3939890400 46800 1 FJST} - {3946543200 43200 0 FJT} + {3945938400 43200 0 FJT} {3971340000 46800 1 FJST} - {3977992800 43200 0 FJT} + {3977388000 43200 0 FJT} {4002789600 46800 1 FJST} {4009442400 43200 0 FJT} {4034239200 46800 1 FJST} diff --git a/library/tzdata/Pacific/Norfolk b/library/tzdata/Pacific/Norfolk index a8fac15..b12ab8c 100644 --- a/library/tzdata/Pacific/Norfolk +++ b/library/tzdata/Pacific/Norfolk @@ -4,4 +4,7 @@ set TZData(:Pacific/Norfolk) { {-9223372036854775808 40312 0 LMT} {-2177493112 40320 0 NMT} {-599656320 41400 0 NFT} + {152029800 45000 1 NFST} + {162912600 41400 0 NFT} + {1443882600 39600 0 NFT} } -- cgit v0.12 From a2efc41118bae86e8df3f7dbb0c09aa1456399d7 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 28 Oct 2015 21:15:21 +0000 Subject: Expose some of the TclBN operations through the internal API, so clients of the bignum code don't need to use tclTomMath.h directly. --- generic/tclInt.h | 7 +------ generic/tclTomMath.decls | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index 356d250..f9d2edf 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4435,17 +4435,12 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, /* *---------------------------------------------------------------------- * - * Core procedures added to libtommath for bignum manipulation. + * Core procedure added to libtommath for bignum manipulation. * *---------------------------------------------------------------------- */ MODULE_SCOPE Tcl_PackageInitProc TclTommath_Init; -MODULE_SCOPE void TclBNInitBignumFromLong(mp_int *bignum, long initVal); -MODULE_SCOPE void TclBNInitBignumFromWideInt(mp_int *bignum, - Tcl_WideInt initVal); -MODULE_SCOPE void TclBNInitBignumFromWideUInt(mp_int *bignum, - Tcl_WideUInt initVal); /* *---------------------------------------------------------------------- diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index ea3abb1..8d9e05f 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -1,9 +1,8 @@ # tclTomMath.decls -- # -# This file contains the declarations for the functions in -# 'libtommath' that are contained within the Tcl library. -# This file is used to generate the 'tclTomMathDecls.h' and -# 'tclTomMathStub.c' files. +# This file contains the declarations for the functions in 'libtommath' +# that are contained within the Tcl library. This file is used to +# generate the 'tclTomMathDecls.h' and 'tclTomMathStub.c' files. # # If you edit this file, advance the revision number (and the epoch # if the new stubs are not backward compatible) in tclTomMathDecls.h @@ -221,3 +220,19 @@ declare 62 { declare 63 { int 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 { + void TclBNInitBignumFromLong(mp_int *bignum, long initVal) +} +declare 65 { + void TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal) +} +declare 66 { + void TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal) +} + +# Local Variables: +# mode: tcl +# End: -- cgit v0.12 From 04d1b415226ca00c8733a32dafe9f25fa4aee293 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 28 Oct 2015 21:15:52 +0000 Subject: make genstubs --- generic/tclStubInit.c | 3 +++ generic/tclTomMathDecls.h | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 7d44163..5b7a1cd 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -746,6 +746,9 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_mp_init_set_int, /* 61 */ TclBN_mp_set_int, /* 62 */ TclBN_mp_cnt_lsb, /* 63 */ + TclBNInitBignumFromLong, /* 64 */ + TclBNInitBignumFromWideInt, /* 65 */ + TclBNInitBignumFromWideUInt, /* 66 */ }; static const TclStubHooks tclStubHooks = { diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index 69b095c..2ce9d5a 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -279,6 +279,14 @@ EXTERN int TclBN_mp_init_set_int(mp_int *a, unsigned long i); EXTERN int TclBN_mp_set_int(mp_int *a, unsigned long i); /* 63 */ EXTERN int TclBN_mp_cnt_lsb(const mp_int *a); +/* 64 */ +EXTERN void TclBNInitBignumFromLong(mp_int *bignum, long initVal); +/* 65 */ +EXTERN void TclBNInitBignumFromWideInt(mp_int *bignum, + Tcl_WideInt initVal); +/* 66 */ +EXTERN void TclBNInitBignumFromWideUInt(mp_int *bignum, + Tcl_WideUInt initVal); typedef struct TclTomMathStubs { int magic; @@ -348,6 +356,9 @@ typedef struct TclTomMathStubs { 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 */ + void (*tclBNInitBignumFromLong) (mp_int *bignum, long initVal); /* 64 */ + void (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ + void (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ } TclTomMathStubs; extern const TclTomMathStubs *tclTomMathStubsPtr; @@ -490,6 +501,12 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_mp_set_int) /* 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 */ #endif /* defined(USE_TCL_STUBS) */ -- cgit v0.12 From 38d734ddcfc00e2885ad397ee93ac12e062be4ef Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 3 Nov 2015 13:13:14 +0000 Subject: better handle out-of-memory conditions in ZIP filesystem hard-wire initial encoding on Android to UTF-8 --- generic/zipfs.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++------- unix/tclUnixInit.c | 4 +++ 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/generic/zipfs.c b/generic/zipfs.c index 1722688..e3bb7db 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -830,7 +830,14 @@ ZipFSOpenArchive(Tcl_Interp *interp, CONST char *zipname, int needZip, goto error; } Tcl_Seek(zf->chan, 0, SEEK_SET); - zf->tofree = zf->data = (unsigned char *) Tcl_Alloc(zf->length); + zf->tofree = zf->data = (unsigned char *) Tcl_AttemptAlloc(zf->length); + if (zf->tofree == NULL) { + if (interp) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("out of memory", -1)); + } + goto error; + } i = Tcl_Read(zf->chan, (char *) zf->data, zf->length); if (i != zf->length) { if (interp) { @@ -1092,7 +1099,16 @@ Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, if (strcmp(mntpt, "/") == 0) { mntpt = ""; } - zf = (ZipFile *) Tcl_Alloc(sizeof (*zf) + strlen(mntpt) + 1); + zf = (ZipFile *) Tcl_AttemptAlloc(sizeof (*zf) + strlen(mntpt) + 1); + if (zf == NULL) { + if (interp != NULL) { + Tcl_AppendResult(interp, "out of memory", (char *) NULL); + } + Unlock(); + Tcl_DStringFree(&ds); + ZipFSCloseArchive(interp, &zf0); + return TCL_ERROR; + } *zf = zf0; zf->name = Tcl_GetHashKey(&ZipFS.zipHash, hPtr); strcpy(zf->mntpt, mntpt); @@ -2263,8 +2279,8 @@ ZipChannelClose(ClientData instanceData, Tcl_Interp *interp) ZipEntry *z = info->zipentry; unsigned char *newdata; - newdata = - (unsigned char *) Tcl_Realloc((char *) info->ubuf, info->nread); + newdata = (unsigned char *) + Tcl_AttemptRealloc((char *) info->ubuf, info->nread); if (newdata != NULL) { if (z->data != NULL) { Tcl_Free((char *) z->data); @@ -2595,7 +2611,13 @@ ZipChannelOpen(Tcl_Interp *interp, char *filename, int mode, int permissions) } else { flags = TCL_WRITABLE; } - info = (ZipChannel *) Tcl_Alloc (sizeof (*info)); + info = (ZipChannel *) Tcl_AttemptAlloc(sizeof (*info)); + if (info == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("out of memory", -1)); + } + goto error; + } info->zipfile = z->zipfile; info->zipentry = z; info->nread = 0; @@ -2606,7 +2628,19 @@ ZipChannelOpen(Tcl_Interp *interp, char *filename, int mode, int permissions) info->nmax = ZipFS.wrmax; info->iscompr = 0; info->isenc = 0; - info->ubuf = (unsigned char *) Tcl_Alloc(info->nmax); + info->ubuf = (unsigned char *) Tcl_AttemptAlloc(info->nmax); + if (info->ubuf == NULL) { +merror0: + if (info->ubuf != NULL) { + Tcl_Free((char *) info->ubuf); + } + Tcl_Free((char *) info); + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("out of memory", -1)); + } + goto error; + } memset(info->ubuf, 0, info->nmax); if (trunc) { info->nbyte = 0; @@ -2650,7 +2684,11 @@ ZipChannelOpen(Tcl_Interp *interp, char *filename, int mode, int permissions) stream.avail_in = z->nbytecompr; if (z->isenc) { stream.avail_in -= 12; - cbuf = (unsigned char *) Tcl_Alloc(stream.avail_in); + cbuf = (unsigned char *) + Tcl_AttemptAlloc(stream.avail_in); + if (cbuf == NULL) { + goto merror0; + } for (i = 0; i < stream.avail_in; i++) { ch = info->ubuf[i]; cbuf[i] = zdecode(info->keys, crc32tab, ch); @@ -2747,7 +2785,11 @@ cerror0: stream.avail_in = z->nbytecompr; if (info->isenc) { stream.avail_in -= 12; - ubuf = (unsigned char *) Tcl_Alloc(stream.avail_in); + ubuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in); + if (ubuf == NULL) { + info->ubuf = NULL; + goto merror; + } for (i = 0; i < stream.avail_in; i++) { ch = info->ubuf[i]; ubuf[i] = zdecode(info->keys, crc32tab, ch); @@ -2757,7 +2799,21 @@ cerror0: stream.next_in = info->ubuf; } stream.next_out = info->ubuf = - (unsigned char *) Tcl_Alloc(info->nbyte); + (unsigned char *) Tcl_AttemptAlloc(info->nbyte); + if (info->ubuf == NULL) { +merror: + if (ubuf != NULL) { + info->isenc = 0; + memset(info->keys, 0, sizeof (info->keys)); + Tcl_Free((char *) ubuf); + } + Tcl_Free((char *) info); + if (interp != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("out of memory", -1)); + } + goto error; + } stream.avail_out = info->nbyte; if (inflateInit2(&stream, -15) != Z_OK) { goto cerror; diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index c0fa94d..cb1f70e 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -588,10 +588,14 @@ TclpInitLibraryPath( void TclpSetInitialEncodings(void) { +#ifdef ANDROID + Tcl_SetSystemEncoding(NULL, "utf-8"); +#else Tcl_DString encodingName; Tcl_SetSystemEncoding(NULL, Tcl_GetEncodingNameFromEnvironment(&encodingName)); Tcl_DStringFree(&encodingName); +#endif } void -- cgit v0.12 From f3a2810d2049b0ffed472ae53c2e872ed36be307 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 10 Nov 2015 16:31:29 +0000 Subject: [261a8a79f0] Integer overflow leads to segfault. --- generic/tclIO.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclIO.c b/generic/tclIO.c index 9a4735f..7bc849e 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -5938,7 +5938,7 @@ TranslateInputEOL( break; default: /* In other modes, at most 2 src bytes become a dst byte. */ - if (srcLen > 2 * dstLen) { + if (srcLen/2 > dstLen) { srcLen = 2 * dstLen; } break; -- cgit v0.12 From 9965b67d8e8da955fdd9fe68550022af77ac6591 Mon Sep 17 00:00:00 2001 From: max Date: Wed, 11 Nov 2015 09:56:41 +0000 Subject: Remove unused calculation of the result set size from TclCreateSocketAddress() --- generic/tclIOSock.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/generic/tclIOSock.c b/generic/tclIOSock.c index d578d19..c5b7d28 100644 --- a/generic/tclIOSock.c +++ b/generic/tclIOSock.c @@ -171,7 +171,7 @@ TclCreateSocketAddress( char *native = NULL, portbuf[TCL_INTEGER_SPACE], *portstring; const char *family = NULL; Tcl_DString ds; - int result, i; + int result; if (host != NULL) { native = Tcl_UtfToExternalDString(NULL, host, -1, &ds); @@ -279,11 +279,6 @@ TclCreateSocketAddress( *addrlist = v4head; } } - i = 0; - for (p = *addrlist; p != NULL; p = p->ai_next) { - i++; - } - return 1; } -- cgit v0.12 From d85dd92c27562ffe41be0a59d06b4df81b832973 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 13 Nov 2015 08:40:54 +0000 Subject: Fix [https://www.sqlite.org/src/info/34eb6911afee09e7|34eb6911af], taken over from SQLite: Fix uses of ctype functions (ex: isspace()) on signed characters in test programs and in some obscure extensions. No changes to the core. --- win/nmakehlp.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/win/nmakehlp.c b/win/nmakehlp.c index d0edcf0..84cf75c 100644 --- a/win/nmakehlp.c +++ b/win/nmakehlp.c @@ -498,9 +498,10 @@ GetVersionFromFile( p = strstr(szBuffer, match); if (p != NULL) { /* - * Skip to first digit. + * Skip to first digit after the match. */ + p += strlen(match); while (*p && !isdigit(*p)) { ++p; } @@ -605,8 +606,8 @@ SubstituteFile( sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { - char *ks, *ke, *vs, *ve; - ks = szBuffer; + unsigned char *ks, *ke, *vs, *ve; + ks = (unsigned char*)szBuffer; while (ks && *ks && isspace(*ks)) ++ks; ke = ks; while (ke && *ke && !isspace(*ke)) ++ke; @@ -615,7 +616,7 @@ SubstituteFile( ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; - list_insert(&substPtr, ks, vs); + list_insert(&substPtr, (char*)ks, (char*)vs); } fclose(sp); } @@ -630,11 +631,11 @@ SubstituteFile( } } #endif - + /* * Run the substitutions over each line of the input */ - + while (fgets(szBuffer, cbBuffer, fp) != NULL) { list_item_t *p = NULL; for (p = substPtr; p != NULL; p = p->nextPtr) { @@ -654,7 +655,7 @@ SubstituteFile( } printf(szBuffer); } - + list_free(&substPtr); } fclose(fp); -- cgit v0.12 From 4e12f02a757c83c7f40ca1e29f44654b9627a757 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 16 Nov 2015 10:32:40 +0000 Subject: =?UTF-8?q?Fix=20--enable-symbols=20build=20on=20Cygwin.=20Reporte?= =?UTF-8?q?d=20by=20Fran=C3=A7ois=20Vogel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- unix/Makefile.in | 2 +- win/Makefile.in | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/unix/Makefile.in b/unix/Makefile.in index 1f2cd77..84d0391 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -560,7 +560,7 @@ ${LIB_FILE}: ${STUB_LIB_FILE} ${OBJS} ${STUB_LIB_FILE}: ${STUB_LIB_OBJS} @if test "x${LIB_FILE}" = "xlibtcl${MAJOR_VERSION}.${MINOR_VERSION}.dll"; then \ - (cd ${TOP_DIR}/win; ${MAKE} libtclstub${MAJOR_VERSION}${MINOR_VERSION}.a); \ + (cd ${TOP_DIR}/win; ${MAKE} winextensions); \ fi rm -f $@ @MAKE_STUB_LIB@ diff --git a/win/Makefile.in b/win/Makefile.in index e9a28c4..ada9448 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -400,6 +400,8 @@ winhelp: $(ROOT_DIR)/tools/man2help.tcl $(MAN2TCL) ./$(TCLSH) "$(ROOT_DIR_NATIVE)"/tools/man2help.tcl tcl "$(VER)" $(TCL_DOCS) hcw /c /e tcl.hpj +winextensions: ${DDE_DLL_FILE} ${REG_DLL_FILE} + $(MAN2TCL): $(ROOT_DIR)/tools/man2tcl.c $(CC) $(CFLAGS_OPTIMIZE) $(MAN2TCLFLAGS) -o $(MAN2TCL) "$(ROOT_DIR_NATIVE)"/tools/man2tcl.c -- cgit v0.12 From c3e6dcaa6708a3c30c57abc83697fea22ff77809 Mon Sep 17 00:00:00 2001 From: oehhar Date: Tue, 17 Nov 2015 17:01:58 +0000 Subject: Spanish translation of example corrected --- doc/msgcat.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/msgcat.n b/doc/msgcat.n index 7e46528..34e153d 100644 --- a/doc/msgcat.n +++ b/doc/msgcat.n @@ -384,7 +384,7 @@ the package. For example, a short \fBes.msg\fR might contain: .PP .CS namespace eval ::mypackage { - \fB::msgcat::mcflset\fR "Free Beer!" "Cerveza Gracias!" + \fB::msgcat::mcflset\fR "Free Beer" "Cerveza Gratis" } .CE .SH "RECOMMENDED MESSAGE SETUP FOR PACKAGES" -- cgit v0.12 From 81ee44ac3b9b322ec63118b417f1b7f2d19fc407 Mon Sep 17 00:00:00 2001 From: oehhar Date: Tue, 17 Nov 2015 17:07:33 +0000 Subject: Spanish translation of example corrected --- doc/msgcat.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/msgcat.n b/doc/msgcat.n index bae6dbe..b4f7140 100644 --- a/doc/msgcat.n +++ b/doc/msgcat.n @@ -321,7 +321,7 @@ the package. For example, a short \fBes.msg\fR might contain: .PP .CS namespace eval ::mypackage { - \fB::msgcat::mcflset\fR "Free Beer!" "Cerveza Gracias!" + \fB::msgcat::mcflset\fR "Free Beer" "Cerveza Gratis" } .CE .SH "RECOMMENDED MESSAGE SETUP FOR PACKAGES" -- cgit v0.12 From f4b65459ef36d86c50bf8b28aabd416c013b1022 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 20 Nov 2015 15:47:30 +0000 Subject: [40f628e8e3] Tcl_ListObjReplace() callers need to handle TCL_ERROR. --- generic/tclCmdIL.c | 10 ++++++++-- generic/tclUtil.c | 8 +++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index ea9c1e4..02e5812 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -2233,7 +2233,10 @@ Tcl_LinsertObjCmd( Tcl_ListObjAppendElement(NULL, listPtr, objv[3]); } else { - Tcl_ListObjReplace(NULL, listPtr, index, 0, (objc-3), &(objv[3])); + if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, index, 0, + (objc-3), &(objv[3]))) { + return TCL_ERROR; + } } /* @@ -2598,7 +2601,10 @@ Tcl_LreplaceObjCmd( * optimize this case away. */ - Tcl_ListObjReplace(NULL, listPtr, first, numToDelete, objc-4, &(objv[4])); + if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, first, numToDelete, + objc-4, &(objv[4]))) { + return TCL_ERROR; + } /* * Set the interpreter's object result. diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 69d0b17..bc1490e 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -1791,7 +1791,12 @@ Tcl_ConcatObj( TclListObjGetElements(NULL, objPtr, &listc, &listv); if (listc) { if (resPtr) { - Tcl_ListObjReplace(NULL, resPtr, INT_MAX, 0, listc, listv); + if (TCL_OK != Tcl_ListObjReplace(NULL, resPtr, + INT_MAX, 0, listc, listv)) { + /* Abandon ship! */ + Tcl_DecrRefCount(resPtr); + goto slow; + } } else { resPtr = TclListObjCopy(NULL, objPtr); } @@ -1808,6 +1813,7 @@ Tcl_ConcatObj( * the slow way, using the string representations. */ + slow: /* First try to pre-allocate the size required */ for (i = 0; i < objc; i++) { element = TclGetStringFromObj(objv[i], &elemLength); -- cgit v0.12 From 7e6cdc9cc44c2cbf916639ff537171bd10c175dd Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 20 Nov 2015 16:58:11 +0000 Subject: [3293874] Simplified fix (not backport). Also detect >LIST_MAX early. --- generic/tclListObj.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 289cf2d..c4b5cfc 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -854,8 +854,13 @@ Tcl_ListObjReplace( count = numElems - first; } + if (objc > LIST_MAX - (numElems - count)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "max length of a Tcl list (%d elements) exceeded", LIST_MAX)); + return TCL_ERROR; + } isShared = (listRepPtr->refCount > 1); - numRequired = numElems - count + objc; + numRequired = numElems - count + objc; /* Known <= LIST_MAX */ for (i = 0; i < objc; i++) { Tcl_IncrRefCount(objv[i]); @@ -906,6 +911,8 @@ Tcl_ListObjReplace( listRepPtr = AttemptNewList(interp, newMax, NULL); if (listRepPtr == NULL) { + listRepPtr = AttemptNewList(interp, numRequired, NULL); + if (listRepPtr == NULL) { for (i = 0; i < objc; i++) { /* See bug 3598580 */ #if TCL_MAJOR_VERSION > 8 @@ -916,6 +923,7 @@ Tcl_ListObjReplace( } return TCL_ERROR; } + } listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr; listRepPtr->refCount++; -- cgit v0.12 From e922cb1cd3d13490b9f58bc1ff9a09dae1c5f77c Mon Sep 17 00:00:00 2001 From: dkf Date: Sat, 21 Nov 2015 22:22:49 +0000 Subject: [3d96b7076e] Prevent crashes when destroying an object's class inside a method call. --- generic/tclOO.c | 20 +++++++++++++++---- generic/tclOODefineCmds.c | 15 ++++++++++---- generic/tclOOInfo.c | 12 +++++++++++ generic/tclOOInt.h | 3 +++ tests/oo.test | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 8 deletions(-) diff --git a/generic/tclOO.c b/generic/tclOO.c index 84bb85a..5fca220 100644 --- a/generic/tclOO.c +++ b/generic/tclOO.c @@ -951,6 +951,16 @@ ReleaseClassContents( } if (!IsRootClass(oPtr)) { FOREACH(instancePtr, clsPtr->instances) { + int j; + if (instancePtr->selfCls == clsPtr) { + instancePtr->flags |= CLASS_GONE; + } + for(j=0 ; jmixins.num ; j++) { + Class *mixin = instancePtr->mixins.list[j]; + if (mixin == clsPtr) { + instancePtr->mixins.list[j] = NULL; + } + } if (instancePtr != NULL && !IsRoot(instancePtr)) { AddRef(instancePtr); } @@ -1131,12 +1141,14 @@ ObjectNamespaceDeleted( * methods on the object. */ - if (!IsRootObject(oPtr)) { + if (!IsRootObject(oPtr) && !(oPtr->flags & CLASS_GONE)) { TclOORemoveFromInstances(oPtr, oPtr->selfCls); } FOREACH(mixinPtr, oPtr->mixins) { - TclOORemoveFromInstances(oPtr, mixinPtr); + if (mixinPtr) { + TclOORemoveFromInstances(oPtr, mixinPtr); + } } if (i) { ckfree(oPtr->mixins.list); @@ -1908,13 +1920,13 @@ Tcl_CopyObjectInstance( */ FOREACH(mixinPtr, o2Ptr->mixins) { - if (mixinPtr != o2Ptr->selfCls) { + if (mixinPtr && mixinPtr != o2Ptr->selfCls) { TclOORemoveFromInstances(o2Ptr, mixinPtr); } } DUPLICATE(o2Ptr->mixins, oPtr->mixins, Class *); FOREACH(mixinPtr, o2Ptr->mixins) { - if (mixinPtr != o2Ptr->selfCls) { + if (mixinPtr && mixinPtr != o2Ptr->selfCls) { TclOOAddToInstances(o2Ptr, mixinPtr); } } diff --git a/generic/tclOODefineCmds.c b/generic/tclOODefineCmds.c index 85f6c31..c880754 100644 --- a/generic/tclOODefineCmds.c +++ b/generic/tclOODefineCmds.c @@ -323,7 +323,9 @@ TclOOObjectSetMixins( if (numMixins == 0) { if (oPtr->mixins.num != 0) { FOREACH(mixinPtr, oPtr->mixins) { - TclOORemoveFromInstances(oPtr, mixinPtr); + if (mixinPtr) { + TclOORemoveFromInstances(oPtr, mixinPtr); + } } ckfree(oPtr->mixins.list); oPtr->mixins.num = 0; @@ -332,7 +334,7 @@ TclOOObjectSetMixins( } else { if (oPtr->mixins.num != 0) { FOREACH(mixinPtr, oPtr->mixins) { - if (mixinPtr != oPtr->selfCls) { + if (mixinPtr && mixinPtr != oPtr->selfCls) { TclOORemoveFromInstances(oPtr, mixinPtr); } } @@ -1213,6 +1215,9 @@ TclOODefineClassObjCmd( TclOORemoveFromInstances(oPtr, oPtr->selfCls); oPtr->selfCls = clsPtr; TclOOAddToInstances(oPtr, oPtr->selfCls); + if (!(clsPtr->thisPtr->flags & OBJECT_DELETED)) { + oPtr->flags &= ~CLASS_GONE; + } if (oPtr->classPtr != NULL) { BumpGlobalEpoch(interp, oPtr->classPtr); } else { @@ -2509,8 +2514,10 @@ ObjMixinGet( resultObj = Tcl_NewObj(); FOREACH(mixinPtr, oPtr->mixins) { - Tcl_ListObjAppendElement(NULL, resultObj, - TclOOObjectName(interp, mixinPtr->thisPtr)); + if (mixinPtr) { + Tcl_ListObjAppendElement(NULL, resultObj, + TclOOObjectName(interp, mixinPtr->thisPtr)); + } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; diff --git a/generic/tclOOInfo.c b/generic/tclOOInfo.c index 0c22bcf..76eaef5 100644 --- a/generic/tclOOInfo.c +++ b/generic/tclOOInfo.c @@ -196,6 +196,9 @@ InfoObjectClassCmd( } FOREACH(mixinPtr, oPtr->mixins) { + if (!mixinPtr) { + continue; + } if (TclOOIsReachable(o2clsPtr, mixinPtr)) { Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); return TCL_OK; @@ -467,6 +470,9 @@ InfoObjectIsACmd( Class *mixinPtr; FOREACH(mixinPtr, oPtr->mixins) { + if (!mixinPtr) { + continue; + } if (TclOOIsReachable(o2Ptr->classPtr, mixinPtr)) { result = 1; break; @@ -665,6 +671,9 @@ InfoObjectMixinsCmd( resultObj = Tcl_NewObj(); FOREACH(mixinPtr, oPtr->mixins) { + if (!mixinPtr) { + continue; + } Tcl_ListObjAppendElement(NULL, resultObj, TclOOObjectName(interp, mixinPtr->thisPtr)); } @@ -1281,6 +1290,9 @@ InfoClassMixinsCmd( resultObj = Tcl_NewObj(); FOREACH(mixinPtr, clsPtr->mixins) { + if (!mixinPtr) { + continue; + } Tcl_ListObjAppendElement(NULL, resultObj, TclOOObjectName(interp, mixinPtr->thisPtr)); } diff --git a/generic/tclOOInt.h b/generic/tclOOInt.h index 208e32c..b75ffdb 100644 --- a/generic/tclOOInt.h +++ b/generic/tclOOInt.h @@ -193,6 +193,9 @@ typedef struct Object { * destroyed. */ #define DESTRUCTOR_CALLED 2 /* Flag to say that the destructor has been * called. */ +#define CLASS_GONE 4 /* Indicates that the class of this object has + * been deleted, and so the object should not + * attempt to remove itself from its class. */ #define ROOT_OBJECT 0x1000 /* Flag to say that this object is the root of * the class hierarchy and should be treated * specially during teardown. */ diff --git a/tests/oo.test b/tests/oo.test index c83e015..2112f10 100644 --- a/tests/oo.test +++ b/tests/oo.test @@ -638,6 +638,57 @@ test oo-3.9 {Bug 2944404: deleting the object in the destructor} -setup { } -cleanup { cls destroy } -result {in destructor} +test oo-3.10 {Bug 3d96b7076e: killing the object's class in a method call} -setup { + oo::class create Super +} -body { + # Only reliably failed in a memdebug build + oo::class create Cls { + superclass Super + method mthd {} { + [self class] destroy + return ok + } + } + [Cls new] mthd +} -cleanup { + Super destroy +} -result ok +test oo-3.11 {Bug 3d96b7076e: killing the object's class in a method call} -setup { + oo::class create Super + oo::class create Sub { + superclass Super + } +} -body { + # Only reliably failed in a memdebug build + oo::class create Cls { + superclass Super + method mthd {} { + oo::objdefine [self] class Sub + Cls destroy + return ok + } + } + [Cls new] mthd +} -cleanup { + Super destroy +} -result ok +test oo-3.12 {Bug 3d96b7076e: killing the object's class in a method call} -setup { + oo::class create Super +} -body { + # Only reliably failed in a memdebug build + oo::class create Cls { + superclass Super + method mthd {} { + [self class] destroy + return ok + } + } + set o [Super new] + oo::objdefine $o mixin Cls + $o mthd +} -cleanup { + Super destroy +} -result ok test oo-4.1 {basic test of OO functionality: export} { set o [oo::object new] -- cgit v0.12 From 9782f13f464f639524e29a072323586a2b8ec22a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 22 Nov 2015 21:02:29 +0000 Subject: Cherrypick [812a81812ebf89d2416059d45fabd27e45603f5e|812a81812e]: Turn off NRE asserts by default. About a 5% speedup on [clock format]. --- generic/regc_nfa.c | 12 ++++++------ generic/tclBasic.c | 3 --- generic/tclExecute.c | 3 --- generic/tclInt.h | 4 +++- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/generic/regc_nfa.c b/generic/regc_nfa.c index 0e0343e..088c6c0 100644 --- a/generic/regc_nfa.c +++ b/generic/regc_nfa.c @@ -293,7 +293,7 @@ newarc( } } } - + /* no dup, so create the arc */ createarc(nfa, t, co, from, to); } @@ -657,7 +657,7 @@ sortins_cmp( } return 0; } - + /* * sortouts - sort the out arcs of a state by to/color/type */ @@ -2020,7 +2020,7 @@ fixempties( arcarray[arccount++] = a; } } - + /* Reset the tmp fields as we walk back */ nexts = s2->tmp; s2->tmp = NULL; @@ -2042,7 +2042,7 @@ fixempties( } inarcsorig[s->no] = a; } - + FREE(arcarray); FREE(inarcsorig); @@ -2193,7 +2193,7 @@ fixconstraintloops( dropstate(nfa, s); } } - + /* Nothing to do if no remaining constraint arcs */ if (NISERR() || !hasconstraints) { return; @@ -2909,7 +2909,7 @@ carc_cmp( { const struct carc *aa = (const struct carc *) a; const struct carc *bb = (const struct carc *) b; - + if (aa->co < bb->co) { return -1; } diff --git a/generic/tclBasic.c b/generic/tclBasic.c index a09bf10..5c5bc64 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -22,10 +22,7 @@ #include "tclCompile.h" #include "tommath.h" #include - -#if NRE_ENABLE_ASSERTS #include -#endif #define INTERP_STACK_INITIAL_SIZE 2000 #define CORO_STACK_INITIAL_SIZE 200 diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 7f65262..b10af65 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -20,10 +20,7 @@ #include "tclOOInt.h" #include "tommath.h" #include - -#if NRE_ENABLE_ASSERTS #include -#endif /* * Hack to determine whether we may expect IEEE floating point. The hack is diff --git a/generic/tclInt.h b/generic/tclInt.h index f9d2edf..082fab4 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4791,7 +4791,9 @@ void Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn)); */ #define NRE_USE_SMALL_ALLOC 1 /* Only turn off for debugging purposes. */ -#define NRE_ENABLE_ASSERTS 1 +#ifndef NRE_ENABLE_ASSERTS +#define NRE_ENABLE_ASSERTS 0 +#endif /* * This is the main data struct for representing NR commands. It is designed -- cgit v0.12 From 99ba912cebb5eee0ef3ab63cb2019ef586057563 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 24 Nov 2015 09:00:27 +0000 Subject: Make ::tcl::tm::roots work for alpha/beta Tcl releases. (backported from "novem", will be needed anyway for whatever future developments) --- library/tm.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/tm.tcl b/library/tm.tcl index 55efda6..66c56a1 100644 --- a/library/tm.tcl +++ b/library/tm.tcl @@ -354,7 +354,7 @@ proc ::tcl::tm::Defaults {} { # Calls 'path add' to paths to the list of module search paths. proc ::tcl::tm::roots {paths} { - lassign [split [package present Tcl] .] major minor + regexp {^(\d+)\.(\d+)} [package present Tcl] - major minor foreach pa $paths { set p [file join $pa tcl$major] for {set n $minor} {$n >= 0} {incr n -1} { -- cgit v0.12 From d06ef17019c017d0f2c7df3a6418ff5085991391 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 24 Nov 2015 15:05:15 +0000 Subject: Fix comments at the top of the *.decls files, which are not correct any more for a long long time. --- generic/tcl.decls | 4 ++-- generic/tclInt.decls | 5 ++--- generic/tclTomMath.decls | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/generic/tcl.decls b/generic/tcl.decls index 28cee54..92ccdcf 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -2,8 +2,8 @@ # # This file contains the declarations for all supported public # functions that are exported by the Tcl library via the stubs table. -# This file is used to generate the tclDecls.h, tclPlatDecls.h, -# tclStub.c, and tclPlatStub.c files. +# This file is used to generate the tclDecls.h, tclPlatDecls.h +# and tclStubInit.c files. # # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 102d04b..920116c 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -2,9 +2,8 @@ # # This file contains the declarations for all unsupported # functions that are exported by the Tcl library. This file -# is used to generate the tclIntDecls.h, tclIntPlatDecls.h, -# tclIntStub.c, tclPlatStub.c, tclCompileDecls.h and tclCompileStub.c -# files +# is used to generate the tclIntDecls.h, tclIntPlatDecls.h +# and tclStubInit.c files # # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index 1bfc443..ab39e83 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -3,7 +3,7 @@ # This file contains the declarations for the functions in # 'libtommath' that are contained within the Tcl library. # This file is used to generate the 'tclTomMathDecls.h' and -# 'tclTomMathStub.c' files. +# 'tclStubInit.c' files. # # If you edit this file, advance the revision number (and the epoch # if the new stubs are not backward compatible) in tclTomMathDecls.h -- cgit v0.12 From e6fa255ed5fcc2fef65ea5a748cdc10a58ee5394 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 26 Nov 2015 11:46:02 +0000 Subject: On cygwin, install libtcl8.5.dll.a in the {prefix}/lib directory. On win32, don't create empty {prefix}/lib/tcl8/8.2 and {prefix}/lib/tcl8/8.3 directories any more during installing. --- unix/configure | 2 +- unix/tcl.m4 | 2 +- win/makefile.vc | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/unix/configure b/unix/configure index 692b801..a90aff3 100755 --- a/unix/configure +++ b/unix/configure @@ -8880,7 +8880,7 @@ fi MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' if test "${SHLIB_SUFFIX}" = ".dll"; then - INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;' DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" else diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 7a0b677..a7faae5 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -2069,7 +2069,7 @@ dnl # preprocessing tests use only CPPFLAGS. LIB_SUFFIX=${SHARED_LIB_SUFFIX} MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [ - INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;' DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" ], [ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' diff --git a/win/makefile.vc b/win/makefile.vc index 267f53f..8c8ecdf 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -1012,10 +1012,6 @@ install-libraries: tclConfig install-msgs install-tzdata $(MKDIR) "$(SCRIPT_INSTALL_DIR)" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8$(NULL)" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8" - @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.2$(NULL)" \ - $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.2" - @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.3$(NULL)" \ - $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.3" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4$(NULL)" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform$(NULL)" \ -- cgit v0.12 From a2b2c6bfc43a14a9b8814db775f15721a0819676 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 30 Nov 2015 18:24:03 +0000 Subject: [32c5740a4d] Have Tcl_ListObjReplace() try to use realloc() for growing when it can do so. --- generic/tclListObj.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 0dfa845..14b8a14 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -857,7 +857,7 @@ Tcl_ListObjReplace( { List *listRepPtr; register Tcl_Obj **elemPtrs; - int numElems, numRequired, numAfterLast, start, i, j, isShared; + int needGrow, numElems, numRequired, numAfterLast, start, i, j, isShared; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace"); @@ -913,12 +913,39 @@ Tcl_ListObjReplace( } isShared = (listRepPtr->refCount > 1); numRequired = numElems - count + objc; /* Known <= LIST_MAX */ + needGrow = numRequired > listRepPtr->maxElemCount; for (i = 0; i < objc; i++) { Tcl_IncrRefCount(objv[i]); } - if ((numRequired <= listRepPtr->maxElemCount) && !isShared) { + if (needGrow && !isShared) { + /* Try to use realloc */ + List *newPtr = NULL; + int attempt = 2 * numRequired; + if (attempt <= LIST_MAX) { + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr == NULL) { + attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; + if (attempt > LIST_MAX) { + attempt = LIST_MAX; + } + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr == NULL) { + attempt = numRequired; + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr) { + listRepPtr = newPtr; + listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; + elemPtrs = &listRepPtr->elements; + listRepPtr->maxElemCount = attempt; + needGrow = numRequired > listRepPtr->maxElemCount; + } + } + if (!needGrow && !isShared) { int shift; /* @@ -955,7 +982,7 @@ Tcl_ListObjReplace( Tcl_Obj **oldPtrs = elemPtrs; int newMax; - if (numRequired > listRepPtr->maxElemCount){ + if (needGrow){ newMax = 2 * numRequired; } else { newMax = listRepPtr->maxElemCount; -- cgit v0.12 From 6c1d8b86caf3af77eb2b0c97134dc5f7584abc89 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 2 Dec 2015 11:02:34 +0000 Subject: Fix 64-bit MSVC build without SDK: If the MSVC version is recent enough, compiling without SDK works fine (provided that the build is configured using "--enable-64bit"). --- win/configure | 12 ++++-------- win/tcl.m4 | 7 ++----- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/win/configure b/win/configure index 63d6765..090feaa 100755 --- a/win/configure +++ b/win/configure @@ -3722,15 +3722,11 @@ echo "${ECHO_T}using shared flags" >&6 ;; esac if test ! -d "${PATH64}" ; then - { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5 -echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;} - { echo "$as_me:$LINENO: WARNING: Ensure latest Platform SDK is installed" >&5 -echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;} - do64bit="no" - else - echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 -echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 + { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK" >&5 +echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK" >&2;} fi + echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 +echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 fi LIBS="user32.lib advapi32.lib ws2_32.lib" diff --git a/win/tcl.m4 b/win/tcl.m4 index 2795086..006778c 100644 --- a/win/tcl.m4 +++ b/win/tcl.m4 @@ -815,12 +815,9 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ ;; esac if test ! -d "${PATH64}" ; then - AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode]) - AC_MSG_WARN([Ensure latest Platform SDK is installed]) - do64bit="no" - else - AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) + AC_MSG_WARN([Could not find 64-bit $MACHINE SDK]) fi + AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) fi LIBS="user32.lib advapi32.lib ws2_32.lib" -- cgit v0.12 From 2e57446fb4328d096e1c2174b206489a11676cee Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 11 Dec 2015 10:13:33 +0000 Subject: Fix [c9eb6b0ac01bb8ef96a616c71426a3db4a279bec|c9eb6b0ac0]: ConvertLocalToUTCUsingC fails the first time if TZ is not set --- generic/tclClock.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 3ec94fb..32ba145 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -1994,22 +1994,23 @@ ClockSecondsObjCmd( static void TzsetIfNecessary(void) { - static char* tzWas = NULL; /* Previous value of TZ, protected by + static char* tzWas = INT2PTR(-1); /* Previous value of TZ, protected by * clockMutex. */ const char* tzIsNow; /* Current value of TZ */ Tcl_MutexLock(&clockMutex); tzIsNow = getenv("TZ"); - if (tzIsNow != NULL && (tzWas == NULL || strcmp(tzIsNow, tzWas) != 0)) { + if (tzIsNow != NULL && (tzWas == NULL || tzWas == INT2PTR(-1) + || strcmp(tzIsNow, tzWas) != 0)) { tzset(); - if (tzWas != NULL) { + if (tzWas != NULL && tzWas != INT2PTR(-1)) { ckfree(tzWas); } tzWas = ckalloc(strlen(tzIsNow) + 1); strcpy(tzWas, tzIsNow); } else if (tzIsNow == NULL && tzWas != NULL) { tzset(); - ckfree(tzWas); + if (tzWas != INT2PTR(-1)) ckfree(tzWas); tzWas = NULL; } Tcl_MutexUnlock(&clockMutex); -- cgit v0.12 From 0b00017862d0b4b3df83350a1d6e399026f13343 Mon Sep 17 00:00:00 2001 From: dkf Date: Sat, 12 Dec 2015 11:54:33 +0000 Subject: Issue the correct auxType when compiling [array set]. --- generic/tclCompCmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 18da741..8d0e2f6 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -365,7 +365,7 @@ TclCompileArraySetCmd( infoPtr->varLists[0]->numVars = 2; infoPtr->varLists[0]->varIndexes[0] = keyVar; infoPtr->varLists[0]->varIndexes[1] = valVar; - infoIndex = TclCreateAuxData(infoPtr, &tclForeachInfoType, envPtr); + infoIndex = TclCreateAuxData(infoPtr, &tclNewForeachInfoType, envPtr); /* * Start issuing instructions to write to the array. -- cgit v0.12 From 72dd32a3ca487853828c6a87d2e34d16cf7a2b36 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 15 Dec 2015 10:33:09 +0000 Subject: Eliminate AuxDataType table: since this table only contains 4 constant entries, it is overkill to use a hash table for that. --- generic/tclCompile.c | 156 ++++----------------------------------------------- generic/tclCompile.h | 2 - generic/tclExecute.c | 2 - 3 files changed, 10 insertions(+), 150 deletions(-) diff --git a/generic/tclCompile.c b/generic/tclCompile.c index f62ec14..6c4734d 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -17,15 +17,6 @@ #include /* - * Table of all AuxData types. - */ - -static Tcl_HashTable auxDataTypeTable; -static int auxDataTypeTableInitialized; /* 0 means not yet initialized. */ - -TCL_DECLARE_MUTEX(tableMutex) - -/* * Variable that controls whether compilation tracing is enabled and, if so, * what level of tracing is desired: * 0: no compilation tracing @@ -4221,59 +4212,6 @@ TclGetInstructionTable(void) } /* - *-------------------------------------------------------------- - * - * RegisterAuxDataType -- - * - * This procedure is called to register a new AuxData type in the table - * of all AuxData types supported by Tcl. - * - * Results: - * None. - * - * Side effects: - * The type is registered in the AuxData type table. If there was already - * a type with the same name as in typePtr, it is replaced with the new - * type. - * - *-------------------------------------------------------------- - */ - -static void -RegisterAuxDataType( - const AuxDataType *typePtr) /* Information about object type; storage must - * be statically allocated (must live forever; - * will not be deallocated). */ -{ - register Tcl_HashEntry *hPtr; - int isNew; - - Tcl_MutexLock(&tableMutex); - if (!auxDataTypeTableInitialized) { - TclInitAuxDataTypeTable(); - } - - /* - * If there's already a type with the given name, remove it. - */ - - hPtr = Tcl_FindHashEntry(&auxDataTypeTable, typePtr->name); - if (hPtr != NULL) { - Tcl_DeleteHashEntry(hPtr); - } - - /* - * Now insert the new object type. - */ - - hPtr = Tcl_CreateHashEntry(&auxDataTypeTable, typePtr->name, &isNew); - if (isNew) { - Tcl_SetHashValue(hPtr, typePtr); - } - Tcl_MutexUnlock(&tableMutex); -} - -/* *---------------------------------------------------------------------- * * TclGetAuxDataType -- @@ -4294,90 +4232,16 @@ const AuxDataType * TclGetAuxDataType( const char *typeName) /* Name of AuxData type to look up. */ { - register Tcl_HashEntry *hPtr; - const AuxDataType *typePtr = NULL; - - Tcl_MutexLock(&tableMutex); - if (!auxDataTypeTableInitialized) { - TclInitAuxDataTypeTable(); - } - - hPtr = Tcl_FindHashEntry(&auxDataTypeTable, typeName); - if (hPtr != NULL) { - typePtr = Tcl_GetHashValue(hPtr); - } - Tcl_MutexUnlock(&tableMutex); - - return typePtr; -} - -/* - *-------------------------------------------------------------- - * - * TclInitAuxDataTypeTable -- - * - * This procedure is invoked to perform once-only initialization of the - * AuxData type table. It also registers the AuxData types defined in - * this file. - * - * Results: - * None. - * - * Side effects: - * Initializes the table of defined AuxData types "auxDataTypeTable" with - * builtin AuxData types defined in this file. - * - *-------------------------------------------------------------- - */ - -void -TclInitAuxDataTypeTable(void) -{ - /* - * The table mutex must already be held before this routine is invoked. - */ - - auxDataTypeTableInitialized = 1; - Tcl_InitHashTable(&auxDataTypeTable, TCL_STRING_KEYS); - - /* - * There are only four AuxData types at this time, so register them here. - */ - - RegisterAuxDataType(&tclForeachInfoType); - RegisterAuxDataType(&tclNewForeachInfoType); - RegisterAuxDataType(&tclJumptableInfoType); - RegisterAuxDataType(&tclDictUpdateInfoType); -} - -/* - *---------------------------------------------------------------------- - * - * TclFinalizeAuxDataTypeTable -- - * - * This procedure is called by Tcl_Finalize after all exit handlers have - * been run to free up storage associated with the table of AuxData - * types. This procedure is called by TclFinalizeExecution() which is - * called by Tcl_Finalize(). - * - * Results: - * None. - * - * Side effects: - * Deletes all entries in the hash table of AuxData types. - * - *---------------------------------------------------------------------- - */ - -void -TclFinalizeAuxDataTypeTable(void) -{ - Tcl_MutexLock(&tableMutex); - if (auxDataTypeTableInitialized) { - Tcl_DeleteHashTable(&auxDataTypeTable); - auxDataTypeTableInitialized = 0; - } - Tcl_MutexUnlock(&tableMutex); + if (!strcmp(typeName, tclForeachInfoType.name)) { + return &tclForeachInfoType; + } else if (!strcmp(typeName, tclNewForeachInfoType.name)) { + return &tclNewForeachInfoType; + } else if (!strcmp(typeName, tclDictUpdateInfoType.name)) { + return &tclDictUpdateInfoType; + } else if (!strcmp(typeName, tclJumptableInfoType.name)) { + return &tclJumptableInfoType; + } + return NULL; } /* diff --git a/generic/tclCompile.h b/generic/tclCompile.h index b89346d..8811187 100644 --- a/generic/tclCompile.h +++ b/generic/tclCompile.h @@ -1123,7 +1123,6 @@ MODULE_SCOPE void TclExpandJumpFixupArray(JumpFixupArray *fixupArrayPtr); MODULE_SCOPE int TclNRExecuteByteCode(Tcl_Interp *interp, ByteCode *codePtr); MODULE_SCOPE Tcl_Obj * TclFetchLiteral(CompileEnv *envPtr, unsigned int index); -MODULE_SCOPE void TclFinalizeAuxDataTypeTable(void); MODULE_SCOPE int TclFindCompiledLocal(const char *name, int nameChars, int create, CompileEnv *envPtr); MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr, @@ -1131,7 +1130,6 @@ MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr, int distThreshold); MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr); MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr); -MODULE_SCOPE void TclInitAuxDataTypeTable(void); MODULE_SCOPE void TclInitByteCodeObj(Tcl_Obj *objPtr, CompileEnv *envPtr); MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp, diff --git a/generic/tclExecute.c b/generic/tclExecute.c index b10af65..dacc9e2 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -927,7 +927,6 @@ TclCreateExecEnv( Tcl_MutexLock(&execMutex); if (!execInitialized) { - TclInitAuxDataTypeTable(); InitByteCodeExecution(interp); execInitialized = 1; } @@ -1026,7 +1025,6 @@ TclFinalizeExecution(void) Tcl_MutexLock(&execMutex); execInitialized = 0; Tcl_MutexUnlock(&execMutex); - TclFinalizeAuxDataTypeTable(); } /* -- cgit v0.12 From 6df8a636f8a85c229a44ad096cd549f1fcb3dca0 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 15 Dec 2015 11:13:32 +0000 Subject: make some MODULE_SCOPE symbols static --- generic/tclCompCmds.c | 45 +++++++++++++++++++++++++++++++++++++++------ generic/tclCompile.c | 33 --------------------------------- generic/tclCompile.h | 11 ----------- 3 files changed, 39 insertions(+), 50 deletions(-) diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 8d0e2f6..3ab03cc 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -54,7 +54,7 @@ static int CompileDictEachCmd(Tcl_Interp *interp, * The structures below define the AuxData types defined in this file. */ -const AuxDataType tclForeachInfoType = { +static const AuxDataType foreachInfoType = { "ForeachInfo", /* name */ DupForeachInfo, /* dupProc */ FreeForeachInfo, /* freeProc */ @@ -62,7 +62,7 @@ const AuxDataType tclForeachInfoType = { DisassembleForeachInfo /* disassembleProc */ }; -const AuxDataType tclNewForeachInfoType = { +static const AuxDataType newForeachInfoType = { "NewForeachInfo", /* name */ DupForeachInfo, /* dupProc */ FreeForeachInfo, /* freeProc */ @@ -70,7 +70,7 @@ const AuxDataType tclNewForeachInfoType = { DisassembleNewForeachInfo /* disassembleProc */ }; -const AuxDataType tclDictUpdateInfoType = { +static const AuxDataType dictUpdateInfoType = { "DictUpdateInfo", /* name */ DupDictUpdateInfo, /* dupProc */ FreeDictUpdateInfo, /* freeProc */ @@ -81,6 +81,39 @@ const AuxDataType tclDictUpdateInfoType = { /* *---------------------------------------------------------------------- * + * TclGetAuxDataType -- + * + * This procedure looks up an Auxdata type by name. + * + * Results: + * If an AuxData type with name matching "typeName" is found, a pointer + * to its AuxDataType structure is returned; otherwise, NULL is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +const AuxDataType * +TclGetAuxDataType( + const char *typeName) /* Name of AuxData type to look up. */ +{ + if (!strcmp(typeName, foreachInfoType.name)) { + return &foreachInfoType; + } else if (!strcmp(typeName, newForeachInfoType.name)) { + return &newForeachInfoType; + } else if (!strcmp(typeName, dictUpdateInfoType.name)) { + return &dictUpdateInfoType; + } else if (!strcmp(typeName, tclJumptableInfoType.name)) { + return &tclJumptableInfoType; + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * * TclCompileAppendCmd -- * * Procedure called to compile the "append" command. @@ -365,7 +398,7 @@ TclCompileArraySetCmd( infoPtr->varLists[0]->numVars = 2; infoPtr->varLists[0]->varIndexes[0] = keyVar; infoPtr->varLists[0]->varIndexes[1] = valVar; - infoIndex = TclCreateAuxData(infoPtr, &tclNewForeachInfoType, envPtr); + infoIndex = TclCreateAuxData(infoPtr, &newForeachInfoType, envPtr); /* * Start issuing instructions to write to the array. @@ -1669,7 +1702,7 @@ TclCompileDictUpdateCmd( * can't be snagged by literal sharing and forced to shimmer dangerously. */ - infoIndex = TclCreateAuxData(duiPtr, &tclDictUpdateInfoType, envPtr); + infoIndex = TclCreateAuxData(duiPtr, &dictUpdateInfoType, envPtr); for (i=0 ; iauxDataArrayPtr[TclGetUInt4AtPtr(index)].clientData)) - /* * Structure used to hold information about a switch command that is needed * during program execution. These structures are stored in CompileEnv and @@ -1033,11 +1027,6 @@ typedef struct { * STRUCTURE. */ } DictUpdateInfo; -MODULE_SCOPE const AuxDataType tclDictUpdateInfoType; - -#define DICTUPDATEINFO(envPtr, index) \ - ((DictUpdateInfo*)((envPtr)->auxDataArrayPtr[TclGetUInt4AtPtr(index)].clientData)) - /* * ClientData type used by the math operator commands. */ -- cgit v0.12 From 605aff99c96f767c31e232ec4281beabdd6fcabf Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 15 Dec 2015 13:19:43 +0000 Subject: Remove unused static function definition --- generic/tclCompile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/generic/tclCompile.c b/generic/tclCompile.c index 6598829..4c259ab 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -679,7 +679,6 @@ static int IsCompactibleCompileEnv(Tcl_Interp *interp, #ifdef TCL_COMPILE_STATS static void RecordByteCodeStats(ByteCode *codePtr); #endif /* TCL_COMPILE_STATS */ -static void RegisterAuxDataType(const AuxDataType *typePtr); static int SetByteCodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void StartExpanding(CompileEnv *envPtr); -- cgit v0.12 From 19627fed479882d04fb4d3e738e4f959ff60b34d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 16 Dec 2015 13:26:54 +0000 Subject: Remove zipfs symbols from stub table. Those symbols should be exported as-is, without using the stub mechanism. --- generic/tclInt.decls | 12 ------------ generic/tclIntDecls.h | 18 ------------------ generic/tclStubInit.c | 3 --- generic/zipfs.h | 19 +++++-------------- 4 files changed, 5 insertions(+), 47 deletions(-) diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 5aadbf2..53d5ad0 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -1014,18 +1014,6 @@ declare 251 { int TclRegisterLiteral(void *envPtr, char *bytes, int length, int flags) } - -declare 252 { - int Tclzipfs_Init(Tcl_Interp *interp) -} -declare 253 { - int Tclzipfs_Mount(Tcl_Interp *interp, const char *zipname, - const char *mntpt, const char *passwd) -} -declare 254 { - int Tclzipfs_Unmount(Tcl_Interp *interp, const char *zipname) -} - ############################################################################## diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h index 5962b60..bbd1aae 100644 --- a/generic/tclIntDecls.h +++ b/generic/tclIntDecls.h @@ -614,15 +614,6 @@ EXTERN void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags, /* 251 */ EXTERN int TclRegisterLiteral(void *envPtr, char *bytes, int length, int flags); -/* 252 */ -EXTERN int Tclzipfs_Init(Tcl_Interp *interp); -/* 253 */ -EXTERN int Tclzipfs_Mount(Tcl_Interp *interp, - const char *zipname, const char *mntpt, - const char *passwd); -/* 254 */ -EXTERN int Tclzipfs_Unmount(Tcl_Interp *interp, - const char *zipname); typedef struct TclIntStubs { int magic; @@ -880,9 +871,6 @@ typedef struct TclIntStubs { char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */ void (*tclSetSlaveCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */ int (*tclRegisterLiteral) (void *envPtr, char *bytes, int length, int flags); /* 251 */ - int (*tclzipfs_Init) (Tcl_Interp *interp); /* 252 */ - int (*tclzipfs_Mount) (Tcl_Interp *interp, const char *zipname, const char *mntpt, const char *passwd); /* 253 */ - int (*tclzipfs_Unmount) (Tcl_Interp *interp, const char *zipname); /* 254 */ } TclIntStubs; extern const TclIntStubs *tclIntStubsPtr; @@ -1311,12 +1299,6 @@ extern const TclIntStubs *tclIntStubsPtr; (tclIntStubsPtr->tclSetSlaveCancelFlags) /* 250 */ #define TclRegisterLiteral \ (tclIntStubsPtr->tclRegisterLiteral) /* 251 */ -#define Tclzipfs_Init \ - (tclIntStubsPtr->tclzipfs_Init) /* 252 */ -#define Tclzipfs_Mount \ - (tclIntStubsPtr->tclzipfs_Mount) /* 253 */ -#define Tclzipfs_Unmount \ - (tclIntStubsPtr->tclzipfs_Unmount) /* 254 */ #endif /* defined(USE_TCL_STUBS) */ diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 214b0c4..95e46ca 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -562,9 +562,6 @@ static const TclIntStubs tclIntStubs = { TclDoubleDigits, /* 249 */ TclSetSlaveCancelFlags, /* 250 */ TclRegisterLiteral, /* 251 */ - Tclzipfs_Init, /* 252 */ - Tclzipfs_Mount, /* 253 */ - Tclzipfs_Unmount, /* 254 */ }; static const TclIntPlatStubs tclIntPlatStubs = { diff --git a/generic/zipfs.h b/generic/zipfs.h index a6bd45c..acc709b 100644 --- a/generic/zipfs.h +++ b/generic/zipfs.h @@ -33,20 +33,11 @@ extern "C" { #define Zipfs_SafeInit Tclzipfs_SafeInit #endif -#ifndef EXTERN -#define EXTERN extern -#endif - -#ifdef BUILD_tcl -#undef EXTERN -#define EXTERN -#endif - -EXTERN int Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, - CONST char *mntpt, CONST char *passwd); -EXTERN int Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname); -EXTERN int Zipfs_Init(Tcl_Interp *interp); -EXTERN int Zipfs_SafeInit(Tcl_Interp *interp); +DLLEXPORT int Zipfs_Mount(Tcl_Interp *interp, const char *zipname, + const char *mntpt, const char *passwd); +DLLEXPORT int Zipfs_Unmount(Tcl_Interp *interp, const char *zipname); +DLLEXPORT int Zipfs_Init(Tcl_Interp *interp); +DLLEXPORT int Zipfs_SafeInit(Tcl_Interp *interp); #ifdef __cplusplus } -- cgit v0.12 From 8f6089f225a01b69fadeb69105db95887d3ba9a5 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 16 Dec 2015 13:37:20 +0000 Subject: No need for more than tcl.h in zipfs.h --- generic/zipfs.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/generic/zipfs.h b/generic/zipfs.h index acc709b..a19e214 100644 --- a/generic/zipfs.h +++ b/generic/zipfs.h @@ -13,12 +13,13 @@ #ifndef _ZIPFS_H #define _ZIPFS_H +#include "tcl.h" + #ifdef __cplusplus extern "C" { #endif #ifdef ZIPFS_IN_TK -#include "tkInt.h" #define Zipfs_Mount Tkzipfs_Mount #define Zipfs_Unmount Tkzipfs_Unmount #define Zipfs_Init Tkzipfs_Init @@ -26,16 +27,15 @@ extern "C" { #endif #ifdef ZIPFS_IN_TCL -#include "tclPort.h" #define Zipfs_Mount Tclzipfs_Mount #define Zipfs_Unmount Tclzipfs_Unmount #define Zipfs_Init Tclzipfs_Init #define Zipfs_SafeInit Tclzipfs_SafeInit #endif -DLLEXPORT int Zipfs_Mount(Tcl_Interp *interp, const char *zipname, - const char *mntpt, const char *passwd); -DLLEXPORT int Zipfs_Unmount(Tcl_Interp *interp, const char *zipname); +DLLEXPORT int Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, + CONST char *mntpt, CONST char *passwd); +DLLEXPORT int Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname); DLLEXPORT int Zipfs_Init(Tcl_Interp *interp); DLLEXPORT int Zipfs_SafeInit(Tcl_Interp *interp); -- cgit v0.12 From 58ace2b1dc62afca0a94b701a8c7857f2b620313 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 16 Dec 2015 15:18:59 +0000 Subject: remove unnecessary Tclzipfs defines in tclStubInit.c --- generic/tclStubInit.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 95e46ca..9131c45 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -48,12 +48,6 @@ #undef TclWinGetSockOpt #undef TclWinSetSockOpt -#ifndef ZIPFS_IN_TCL -# define Tclzipfs_Init 0 -# define Tclzipfs_Mount 0 -# define Tclzipfs_Unmount 0 -#endif - /* See bug 510001: TclSockMinimumBuffers needs plat imp */ #ifdef _WIN64 # define TclSockMinimumBuffersOld 0 -- cgit v0.12 From d6fdfa46244d1d14d8c2dce5378e3a23ab51aac2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 17 Dec 2015 12:04:22 +0000 Subject: minor tweaks for MSVC --- generic/zipfs.h | 20 ++++++++++++++++---- unix/tclUnixInit.c | 3 +++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/generic/zipfs.h b/generic/zipfs.h index a19e214..15ca37c 100644 --- a/generic/zipfs.h +++ b/generic/zipfs.h @@ -19,11 +19,19 @@ extern "C" { #endif +#ifndef ZIPFSAPI +# define ZIPFSAPI extern +#endif + #ifdef ZIPFS_IN_TK #define Zipfs_Mount Tkzipfs_Mount #define Zipfs_Unmount Tkzipfs_Unmount #define Zipfs_Init Tkzipfs_Init #define Zipfs_SafeInit Tkzipfs_SafeInit +#ifdef BUILD_tk +# undef ZIPFSAPI +# define ZIPFSAPI DLLEXPORT +#endif #endif #ifdef ZIPFS_IN_TCL @@ -31,13 +39,17 @@ extern "C" { #define Zipfs_Unmount Tclzipfs_Unmount #define Zipfs_Init Tclzipfs_Init #define Zipfs_SafeInit Tclzipfs_SafeInit +#ifdef BUILD_tcl +# undef ZIPFSAPI +# define ZIPFSAPI DLLEXPORT +#endif #endif -DLLEXPORT int Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, +ZIPFSAPI int Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, CONST char *passwd); -DLLEXPORT int Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname); -DLLEXPORT int Zipfs_Init(Tcl_Interp *interp); -DLLEXPORT int Zipfs_SafeInit(Tcl_Interp *interp); +ZIPFSAPI int Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname); +ZIPFSAPI int Zipfs_Init(Tcl_Interp *interp); +ZIPFSAPI int Zipfs_SafeInit(Tcl_Interp *interp); #ifdef __cplusplus } diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index cb1f70e..e8ccc76 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -9,6 +9,9 @@ */ #include "tclInt.h" +#ifdef ZIPFS_IN_TCL +#include "zipfs.h" +#endif #include #include #ifdef HAVE_LANGINFO -- cgit v0.12 From ecd9567624afb68333af5c0439bf195145312858 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 17 Dec 2015 15:23:27 +0000 Subject: Minor tweaks on ZIPFS_IN_TCL --- generic/tclMain.c | 12 +++++++----- unix/configure | 18 ++++++++++++++++++ unix/configure.in | 8 ++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/generic/tclMain.c b/generic/tclMain.c index a52d62d..6acd15d 100644 --- a/generic/tclMain.c +++ b/generic/tclMain.c @@ -321,14 +321,14 @@ Tcl_MainEx( { Tcl_Obj *path, *resultPtr, *argvPtr, *appName; const char *encodingName = NULL; - int code, length, exitCode = 0; + int code, exitCode = 0; Tcl_MainLoopProc *mainLoopProc; Tcl_Channel chan; InteractiveState is; +#ifdef ZIPFS_IN_TCL const char *zipFile = NULL; Tcl_Obj *zipval = NULL; int autoRun = 1; -#ifdef ZIPFS_IN_TCL int zipOk = TCL_ERROR; #ifndef ANDROID const char *exeName; @@ -337,7 +337,7 @@ Tcl_MainEx( TclpSetInitialEncodings(); TclpFindExecutable((const char *)argv[0]); -#ifndef ANDROID +#if defined(ZIPFS_IN_TCL) && !defined(ANDROID) exeName = Tcl_GetNameOfExecutable(); #endif @@ -369,8 +369,9 @@ Tcl_MainEx( Tcl_DecrRefCount(value); argc -= 3; argv += 3; +#ifdef ZIPFS_IN_TCL } else if (argc > 2) { - length = strlen((char *) argv[1]); + int length = strlen((char *) argv[1]); if ((length >= 2) && (0 == _tcsncmp(TEXT("-zip"), argv[1], length))) { argc--; @@ -387,6 +388,7 @@ Tcl_MainEx( argc--; argv++; } +#endif } else if ((argc > 1) && ('-' != argv[1][0])) { Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL); argc--; @@ -475,11 +477,11 @@ Tcl_MainEx( Tcl_DStringFree(&dsLib); #endif } -#endif if (zipval != NULL) { Tcl_DecrRefCount(zipval); zipval = NULL; } +#endif /* * Invoke application-specific initialization. diff --git a/unix/configure b/unix/configure index c19a77a..3e72a0d 100755 --- a/unix/configure +++ b/unix/configure @@ -869,6 +869,7 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-encoding encoding for configuration values (default: iso8859-1) + --with-zipfs include ZIP filesystem --with-tzdata install timezone data (default: autodetect) Some influential environment variables: @@ -6211,6 +6212,23 @@ cat >>confdefs.h <<\_ACEOF _ACEOF +# Check whether --with-zipfs or --without-zipfs was given. +if test "${with_zipfs+set}" = set; then + withval="$with_zipfs" + tcl_ok=$withval +else + tcl_ok=no +fi; +echo "$as_me:$LINENO: result: $tcl_ok" >&5 +echo "${ECHO_T}$tcl_ok" >&6 +if test $tcl_ok = yes; then + +cat >>confdefs.h <<\_ACEOF +#define ZIPFS_IN_TCL 1 +_ACEOF + +fi + #-------------------------------------------------------------------- # The statements below define a collection of compile flags. This # macro depends on the value of SHARED_BUILD, and should be called diff --git a/unix/configure.in b/unix/configure.in index c7b0edc..7eeff3b 100644 --- a/unix/configure.in +++ b/unix/configure.in @@ -171,6 +171,14 @@ AS_IF([test $zlib_ok = no], [ AC_SUBST(ZLIB_INCLUDE,[-I\${ZLIB_DIR}]) ]) AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?]) +AC_ARG_WITH(zipfs, + AC_HELP_STRING([--with-zipfs], + [include ZIP filesystem]), + [tcl_ok=$withval], [tcl_ok=no]) +AC_MSG_RESULT([$tcl_ok]) +if test $tcl_ok = yes; then + AC_DEFINE(ZIPFS_IN_TCL, 1, [Include ZIP filesystem?]) +fi #-------------------------------------------------------------------- # The statements below define a collection of compile flags. This -- cgit v0.12 From c795f44ea527a23d9d9cba2f4c811053ac7af6ff Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 18 Dec 2015 12:39:24 +0000 Subject: upstream androwish change --- debian/rules | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/debian/rules b/debian/rules index 7a0214c..a4b3bd4 100755 --- a/debian/rules +++ b/debian/rules @@ -18,8 +18,6 @@ else CFLAGS=-g -O2 -fno-unit-at-a-time endif -CFLAGS+=-DZIPFS_IN_TCL=1 - unpatch: dh_testdir quilt pop -a || test $$? = 2 @@ -49,7 +47,8 @@ build-stamp: patch-stamp --enable-man-symlinks \ --enable-man-compression=gzip \ --enable-threads \ - --without-tzdata && \ + --without-tzdata \ + --with-zipfs && \ touch ../generic/tclStubInit.c && \ $(MAKE) # Build the static library. -- cgit v0.12 From 4d946107e7d14769b306d8bf05ff4f661b7883ff Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 09:16:38 +0000 Subject: Put back the stub entries for TclpGetDate/TclpLocaltime/TclpGmtime. Although those functions are dead (they will be removed in Tcl 9, already done in the "novem" branch), removing those functions is a good idea, this cannot be done in any 8.x release. It hinders the acceptance of a "zipfs" TIP, therefore this change should not be part of the "androwish" change-set. --- generic/tclInt.decls | 35 +++--- generic/tclIntDecls.h | 24 ++-- generic/tclIntPlatDecls.h | 32 +++-- generic/tclStubInit.c | 18 +-- unix/tclUnixTime.c | 197 +++++++++++++++++++++++++++++ win/tclWinTime.c | 308 +++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 565 insertions(+), 49 deletions(-) diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 53d5ad0..4e7e422 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -532,10 +532,9 @@ declare 131 { declare 132 { int TclpHasSockets(Tcl_Interp *interp) } -# Removed in androwish -# declare 133 { -# struct tm *TclpGetDate(const time_t *time, int useGMT) -#} +declare 133 { + struct tm *TclpGetDate(const time_t *time, int useGMT) +} # Removed in 8.5 #declare 134 { # size_t TclpStrftime(char *s, size_t maxsize, const char *format, @@ -751,14 +750,12 @@ declare 179 { # TclpGmtime and TclpLocaltime promoted to the generic interface from unix -# Removed in androwish -#declare 182 { -# struct tm *TclpLocaltime(const time_t *clock) -#} -# Removed in androwish -#declare 183 { -# struct tm *TclpGmtime(const time_t *clock) -#} +declare 182 { + struct tm *TclpLocaltime(const time_t *clock) +} +declare 183 { + struct tm *TclpGmtime(const time_t *clock) +} # For the new "Thread Storage" subsystem. @@ -1207,14 +1204,12 @@ declare 10 unix { } # Slots 11 and 12 are forwarders for functions that were promoted to # generic Stubs -# Removed in androwish -#declare 11 unix { -# struct tm *TclpLocaltime_unix(const time_t *clock) -#} -# Removed in androwish -#declare 12 unix { -# struct tm *TclpGmtime_unix(const time_t *clock) -#} +declare 11 unix { + struct tm *TclpLocaltime_unix(const time_t *clock) +} +declare 12 unix { + struct tm *TclpGmtime_unix(const time_t *clock) +} declare 13 unix { char *TclpInetNtoa(struct in_addr addr) } diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h index bbd1aae..f95f999 100644 --- a/generic/tclIntDecls.h +++ b/generic/tclIntDecls.h @@ -349,7 +349,8 @@ EXTERN void Tcl_SetNamespaceResolvers( Tcl_ResolveCompiledVarProc *compiledVarProc); /* 132 */ EXTERN int TclpHasSockets(Tcl_Interp *interp); -/* Slot 133 is reserved */ +/* 133 */ +EXTERN struct tm * TclpGetDate(const time_t *time, int useGMT); /* Slot 134 is reserved */ /* Slot 135 is reserved */ /* Slot 136 is reserved */ @@ -462,8 +463,10 @@ EXTERN void Tcl_SetStartupScript(Tcl_Obj *pathPtr, EXTERN Tcl_Obj * Tcl_GetStartupScript(const char **encodingNamePtr); /* Slot 180 is reserved */ /* Slot 181 is reserved */ -/* Slot 182 is reserved */ -/* Slot 183 is reserved */ +/* 182 */ +EXTERN struct tm * TclpLocaltime(const time_t *clock); +/* 183 */ +EXTERN struct tm * TclpGmtime(const time_t *clock); /* Slot 184 is reserved */ /* Slot 185 is reserved */ /* Slot 186 is reserved */ @@ -752,7 +755,7 @@ typedef struct TclIntStubs { int (*tcl_RemoveInterpResolvers) (Tcl_Interp *interp, const char *name); /* 130 */ void (*tcl_SetNamespaceResolvers) (Tcl_Namespace *namespacePtr, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 131 */ int (*tclpHasSockets) (Tcl_Interp *interp); /* 132 */ - void (*reserved133)(void); + struct tm * (*tclpGetDate) (const time_t *time, int useGMT); /* 133 */ void (*reserved134)(void); void (*reserved135)(void); void (*reserved136)(void); @@ -801,8 +804,8 @@ typedef struct TclIntStubs { Tcl_Obj * (*tcl_GetStartupScript) (const char **encodingNamePtr); /* 179 */ void (*reserved180)(void); void (*reserved181)(void); - void (*reserved182)(void); - void (*reserved183)(void); + struct tm * (*tclpLocaltime) (const time_t *clock); /* 182 */ + struct tm * (*tclpGmtime) (const time_t *clock); /* 183 */ void (*reserved184)(void); void (*reserved185)(void); void (*reserved186)(void); @@ -1100,7 +1103,8 @@ extern const TclIntStubs *tclIntStubsPtr; (tclIntStubsPtr->tcl_SetNamespaceResolvers) /* 131 */ #define TclpHasSockets \ (tclIntStubsPtr->tclpHasSockets) /* 132 */ -/* Slot 133 is reserved */ +#define TclpGetDate \ + (tclIntStubsPtr->tclpGetDate) /* 133 */ /* Slot 134 is reserved */ /* Slot 135 is reserved */ /* Slot 136 is reserved */ @@ -1185,8 +1189,10 @@ extern const TclIntStubs *tclIntStubsPtr; (tclIntStubsPtr->tcl_GetStartupScript) /* 179 */ /* Slot 180 is reserved */ /* Slot 181 is reserved */ -/* Slot 182 is reserved */ -/* Slot 183 is reserved */ +#define TclpLocaltime \ + (tclIntStubsPtr->tclpLocaltime) /* 182 */ +#define TclpGmtime \ + (tclIntStubsPtr->tclpGmtime) /* 183 */ /* Slot 184 is reserved */ /* Slot 185 is reserved */ /* Slot 186 is reserved */ diff --git a/generic/tclIntPlatDecls.h b/generic/tclIntPlatDecls.h index b7a44d8..ac06787 100644 --- a/generic/tclIntPlatDecls.h +++ b/generic/tclIntPlatDecls.h @@ -73,8 +73,10 @@ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout); EXTERN TclFile TclpCreateTempFile(const char *contents); /* 10 */ EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); -/* Slot 11 is reserved */ -/* Slot 12 is reserved */ +/* 11 */ +EXTERN struct tm * TclpLocaltime_unix(const time_t *clock); +/* 12 */ +EXTERN struct tm * TclpGmtime_unix(const time_t *clock); /* 13 */ EXTERN char * TclpInetNtoa(struct in_addr addr); /* 14 */ @@ -205,8 +207,10 @@ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout); EXTERN TclFile TclpCreateTempFile(const char *contents); /* 10 */ EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); -/* Slot 11 is reserved */ -/* Slot 12 is reserved */ +/* 11 */ +EXTERN struct tm * TclpLocaltime_unix(const time_t *clock); +/* 12 */ +EXTERN struct tm * TclpGmtime_unix(const time_t *clock); /* 13 */ EXTERN char * TclpInetNtoa(struct in_addr addr); /* 14 */ @@ -266,8 +270,8 @@ typedef struct TclIntPlatStubs { int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ - void (*reserved11)(void); - void (*reserved12)(void); + struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */ + struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ void (*reserved15)(void); @@ -332,8 +336,8 @@ typedef struct TclIntPlatStubs { int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ - void (*reserved11)(void); - void (*reserved12)(void); + struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */ + struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ int (*tclMacOSXGetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 15 */ @@ -389,8 +393,10 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr; (tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */ #define TclpReaddir \ (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ -/* Slot 11 is reserved */ -/* Slot 12 is reserved */ +#define TclpLocaltime_unix \ + (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */ +#define TclpGmtime_unix \ + (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */ #define TclpInetNtoa \ (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */ #define TclUnixCopyFile \ @@ -498,8 +504,10 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr; (tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */ #define TclpReaddir \ (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ -/* Slot 11 is reserved */ -/* Slot 12 is reserved */ +#define TclpLocaltime_unix \ + (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */ +#define TclpGmtime_unix \ + (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */ #define TclpInetNtoa \ (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */ #define TclUnixCopyFile \ diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 9131c45..5b7a1cd 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -288,6 +288,10 @@ static int formatInt(char *buffer, int n){ #define TclFormatInt (int(*)(char *, long))formatInt #endif + +#else /* UNIX and MAC */ +# define TclpLocaltime_unix TclpLocaltime +# define TclpGmtime_unix TclpGmtime #endif /* @@ -437,7 +441,7 @@ static const TclIntStubs tclIntStubs = { Tcl_RemoveInterpResolvers, /* 130 */ Tcl_SetNamespaceResolvers, /* 131 */ TclpHasSockets, /* 132 */ - 0, /* 133 */ + TclpGetDate, /* 133 */ 0, /* 134 */ 0, /* 135 */ 0, /* 136 */ @@ -486,8 +490,8 @@ static const TclIntStubs tclIntStubs = { Tcl_GetStartupScript, /* 179 */ 0, /* 180 */ 0, /* 181 */ - 0, /* 182 */ - 0, /* 183 */ + TclpLocaltime, /* 182 */ + TclpGmtime, /* 183 */ 0, /* 184 */ 0, /* 185 */ 0, /* 186 */ @@ -573,8 +577,8 @@ static const TclIntPlatStubs tclIntPlatStubs = { TclUnixWaitForFile, /* 8 */ TclpCreateTempFile, /* 9 */ TclpReaddir, /* 10 */ - 0, /* 11 */ - 0, /* 12 */ + TclpLocaltime_unix, /* 11 */ + TclpGmtime_unix, /* 12 */ TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ 0, /* 15 */ @@ -639,8 +643,8 @@ static const TclIntPlatStubs tclIntPlatStubs = { TclUnixWaitForFile, /* 8 */ TclpCreateTempFile, /* 9 */ TclpReaddir, /* 10 */ - 0, /* 11 */ - 0, /* 12 */ + TclpLocaltime_unix, /* 11 */ + TclpGmtime_unix, /* 12 */ TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ TclMacOSXGetFileAttribute, /* 15 */ diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index 470b122..315bcf9 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -17,9 +17,34 @@ #endif /* + * TclpGetDate is coded to return a pointer to a 'struct tm'. For thread + * safety, this structure must be in thread-specific data. The 'tmKey' + * variable is the key to this buffer. + */ + +static Tcl_ThreadDataKey tmKey; +typedef struct ThreadSpecificData { + struct tm gmtime_buf; + struct tm localtime_buf; +} ThreadSpecificData; + +/* + * If we fall back on the thread-unsafe versions of gmtime and localtime, use + * this mutex to try to protect them. + */ + +TCL_DECLARE_MUTEX(tmMutex) + +static char *lastTZ = NULL; /* Holds the last setting of the TZ + * environment variable, or an empty string if + * the variable was not set. */ + +/* * Static functions declared in this file. */ +static void SetTZIfNecessary(void); +static void CleanupMemory(ClientData clientData); static void NativeScaleTime(Tcl_Time *timebuf, ClientData clientData); static void NativeGetTime(Tcl_Time *timebuf, @@ -223,6 +248,114 @@ Tcl_GetTime( /* *---------------------------------------------------------------------- * + * TclpGetDate -- + * + * This function converts between seconds and struct tm. If useGMT is + * true, then the returned date will be in Greenwich Mean Time (GMT). + * Otherwise, it will be in the local time zone. + * + * Results: + * Returns a static tm structure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpGetDate( + const time_t *time, + int useGMT) +{ + if (useGMT) { + return TclpGmtime(time); + } else { + return TclpLocaltime(time); + } +} + +/* + *---------------------------------------------------------------------- + * + * TclpGmtime -- + * + * Wrapper around the 'gmtime' library function to make it thread safe. + * + * Results: + * Returns a pointer to a 'struct tm' in thread-specific data. + * + * Side effects: + * Invokes gmtime or gmtime_r as appropriate. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpGmtime( + const time_t *timePtr) /* Pointer to the number of seconds since the + * local system's epoch */ +{ + /* + * Get a thread-local buffer to hold the returned time. + */ + + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tmKey); + +#ifdef HAVE_GMTIME_R + gmtime_r(timePtr, &tsdPtr->gmtime_buf); +#else + Tcl_MutexLock(&tmMutex); + memcpy(&tsdPtr->gmtime_buf, gmtime(timePtr), sizeof(struct tm)); + Tcl_MutexUnlock(&tmMutex); +#endif + + return &tsdPtr->gmtime_buf; +} + +/* + *---------------------------------------------------------------------- + * + * TclpLocaltime -- + * + * Wrapper around the 'localtime' library function to make it thread + * safe. + * + * Results: + * Returns a pointer to a 'struct tm' in thread-specific data. + * + * Side effects: + * Invokes localtime or localtime_r as appropriate. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpLocaltime( + const time_t *timePtr) /* Pointer to the number of seconds since the + * local system's epoch */ +{ + /* + * Get a thread-local buffer to hold the returned time. + */ + + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tmKey); + + SetTZIfNecessary(); +#ifdef HAVE_LOCALTIME_R + localtime_r(timePtr, &tsdPtr->localtime_buf); +#else + Tcl_MutexLock(&tmMutex); + memcpy(&tsdPtr->localtime_buf, localtime(timePtr), sizeof(struct tm)); + Tcl_MutexUnlock(&tmMutex); +#endif + + return &tsdPtr->localtime_buf; +} + +/* + *---------------------------------------------------------------------- + * * Tcl_SetTimeProc -- * * TIP #233 (Virtualized Time): Registers two handlers for the @@ -334,6 +467,70 @@ NativeGetTime( timePtr->sec = tv.tv_sec; timePtr->usec = tv.tv_usec; } +/* + *---------------------------------------------------------------------- + * + * SetTZIfNecessary -- + * + * Determines whether a call to 'tzset' is needed prior to the next call + * to 'localtime' or examination of the 'timezone' variable. + * + * Results: + * None. + * + * Side effects: + * If 'tzset' has never been called in the current process, or if the + * value of the environment variable TZ has changed since the last call + * to 'tzset', then 'tzset' is called again. + * + *---------------------------------------------------------------------- + */ + +static void +SetTZIfNecessary(void) +{ + const char *newTZ = getenv("TZ"); + + Tcl_MutexLock(&tmMutex); + if (newTZ == NULL) { + newTZ = ""; + } + if (lastTZ == NULL || strcmp(lastTZ, newTZ)) { + tzset(); + if (lastTZ == NULL) { + Tcl_CreateExitHandler(CleanupMemory, NULL); + } else { + ckfree(lastTZ); + } + lastTZ = ckalloc(strlen(newTZ) + 1); + strcpy(lastTZ, newTZ); + } + Tcl_MutexUnlock(&tmMutex); +} + +/* + *---------------------------------------------------------------------- + * + * CleanupMemory -- + * + * Releases the private copy of the TZ environment variable upon exit + * from Tcl. + * + * Results: + * None. + * + * Side effects: + * Frees allocated memory. + * + *---------------------------------------------------------------------- + */ + +static void +CleanupMemory( + ClientData ignored) +{ + ckfree(lastTZ); +} /* * Local Variables: diff --git a/win/tclWinTime.c b/win/tclWinTime.c index 0762362..7045c72 100644 --- a/win/tclWinTime.c +++ b/win/tclWinTime.c @@ -12,6 +12,10 @@ #include "tclInt.h" +#define SECSPERDAY (60L * 60L * 24L) +#define SECSPERYEAR (SECSPERDAY * 365L) +#define SECSPER4YEAR (SECSPERYEAR * 4L + SECSPERDAY) + /* * Number of samples over which to estimate the performance counter. */ @@ -19,10 +23,29 @@ #define SAMPLES 64 /* + * The following arrays contain the day of year for the last day of each + * month, where index 1 is January. + */ + +static const int normalDays[] = { + -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 +}; + +static const int leapDays[] = { + -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 +}; + +typedef struct ThreadSpecificData { + char tzName[64]; /* Time zone name */ + struct tm tm; /* time information */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* * Data for managing high-resolution timers. */ -typedef struct { +typedef struct TimeInfo { CRITICAL_SECTION cs; /* Mutex guarding this structure. */ int initialized; /* Flag == 1 if this structure is * initialized. */ @@ -90,6 +113,7 @@ static TimeInfo timeInfo = { * Declarations for functions defined later in this file. */ +static struct tm * ComputeGMT(const time_t *tp); static void StopCalibration(ClientData clientData); static DWORD WINAPI CalibrationThread(LPVOID arg); static void UpdateTimeEachSecond(void); @@ -465,6 +489,227 @@ StopCalibration( /* *---------------------------------------------------------------------- * + * TclpGetDate -- + * + * This function converts between seconds and struct tm. If useGMT is + * true, then the returned date will be in Greenwich Mean Time (GMT). + * Otherwise, it will be in the local time zone. + * + * Results: + * Returns a static tm structure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpGetDate( + const time_t *t, + int useGMT) +{ + struct tm *tmPtr; + time_t time; + + if (!useGMT) { + tzset(); + + /* + * If we are in the valid range, let the C run-time library handle it. + * Otherwise we need to fake it. Note that this algorithm ignores + * daylight savings time before the epoch. + */ + + /* + * Hm, Borland's localtime manages to return NULL under certain + * circumstances (e.g. wintime.test, test 1.2). Nobody tests for this, + * since 'localtime' isn't supposed to do this, possibly leading to + * crashes. + * + * Patch: We only call this function if we are at least one day into + * the epoch, else we handle it ourselves (like we do for times < 0). + * H. Giese, June 2003 + */ + +#ifdef __BORLANDC__ +#define LOCALTIME_VALIDITY_BOUNDARY SECSPERDAY +#else +#define LOCALTIME_VALIDITY_BOUNDARY 0 +#endif + + if (*t >= LOCALTIME_VALIDITY_BOUNDARY) { + return TclpLocaltime(t); + } + + time = *t - timezone; + + /* + * If we aren't near to overflowing the long, just add the bias and + * use the normal calculation. Otherwise we will need to adjust the + * result at the end. + */ + + if (*t < (LONG_MAX - 2*SECSPERDAY) && *t > (LONG_MIN + 2*SECSPERDAY)) { + tmPtr = ComputeGMT(&time); + } else { + tmPtr = ComputeGMT(t); + + tzset(); + + /* + * Add the bias directly to the tm structure to avoid overflow. + * Propagate seconds overflow into minutes, hours and days. + */ + + time = tmPtr->tm_sec - timezone; + tmPtr->tm_sec = (int)(time % 60); + if (tmPtr->tm_sec < 0) { + tmPtr->tm_sec += 60; + time -= 60; + } + + time = tmPtr->tm_min + time/60; + tmPtr->tm_min = (int)(time % 60); + if (tmPtr->tm_min < 0) { + tmPtr->tm_min += 60; + time -= 60; + } + + time = tmPtr->tm_hour + time/60; + tmPtr->tm_hour = (int)(time % 24); + if (tmPtr->tm_hour < 0) { + tmPtr->tm_hour += 24; + time -= 24; + } + + time /= 24; + tmPtr->tm_mday += (int)time; + tmPtr->tm_yday += (int)time; + tmPtr->tm_wday = (tmPtr->tm_wday + (int)time) % 7; + } + } else { + tmPtr = ComputeGMT(t); + } + return tmPtr; +} + +/* + *---------------------------------------------------------------------- + * + * ComputeGMT -- + * + * This function computes GMT given the number of seconds since the epoch + * (midnight Jan 1 1970). + * + * Results: + * Returns a (per thread) statically allocated struct tm. + * + * Side effects: + * Updates the values of the static struct tm. + * + *---------------------------------------------------------------------- + */ + +static struct tm * +ComputeGMT( + const time_t *tp) +{ + struct tm *tmPtr; + long tmp, rem; + int isLeap; + const int *days; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + tmPtr = &tsdPtr->tm; + + /* + * Compute the 4 year span containing the specified time. + */ + + tmp = (long)(*tp / SECSPER4YEAR); + rem = (long)(*tp % SECSPER4YEAR); + + /* + * Correct for weird mod semantics so the remainder is always positive. + */ + + if (rem < 0) { + tmp--; + rem += SECSPER4YEAR; + } + + /* + * Compute the year after 1900 by taking the 4 year span and adjusting for + * the remainder. This works because 2000 is a leap year, and 1900/2100 + * are out of the range. + */ + + tmp = (tmp * 4) + 70; + isLeap = 0; + if (rem >= SECSPERYEAR) { /* 1971, etc. */ + tmp++; + rem -= SECSPERYEAR; + if (rem >= SECSPERYEAR) { /* 1972, etc. */ + tmp++; + rem -= SECSPERYEAR; + if (rem >= SECSPERYEAR + SECSPERDAY) { /* 1973, etc. */ + tmp++; + rem -= SECSPERYEAR + SECSPERDAY; + } else { + isLeap = 1; + } + } + } + tmPtr->tm_year = tmp; + + /* + * Compute the day of year and leave the seconds in the current day in the + * remainder. + */ + + tmPtr->tm_yday = rem / SECSPERDAY; + rem %= SECSPERDAY; + + /* + * Compute the time of day. + */ + + tmPtr->tm_hour = rem / 3600; + rem %= 3600; + tmPtr->tm_min = rem / 60; + tmPtr->tm_sec = rem % 60; + + /* + * Compute the month and day of month. + */ + + days = (isLeap) ? leapDays : normalDays; + for (tmp = 1; days[tmp] < tmPtr->tm_yday; tmp++) { + /* empty body */ + } + tmPtr->tm_mon = --tmp; + tmPtr->tm_mday = tmPtr->tm_yday - days[tmp]; + + /* + * Compute day of week. Epoch started on a Thursday. + */ + + tmPtr->tm_wday = (long)(*tp / SECSPERDAY) + 4; + if ((*tp % SECSPERDAY) < 0) { + tmPtr->tm_wday--; + } + tmPtr->tm_wday %= 7; + if (tmPtr->tm_wday < 0) { + tmPtr->tm_wday += 7; + } + + return tmPtr; +} + +/* + *---------------------------------------------------------------------- + * * CalibrationThread -- * * Thread that manages calibration of the hi-resolution time derived from @@ -792,6 +1037,67 @@ AccumulateSample( /* *---------------------------------------------------------------------- * + * TclpGmtime -- + * + * Wrapper around the 'gmtime' library function to make it thread safe. + * + * Results: + * Returns a pointer to a 'struct tm' in thread-specific data. + * + * Side effects: + * Invokes gmtime or gmtime_r as appropriate. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpGmtime( + const time_t *timePtr) /* Pointer to the number of seconds since the + * local system's epoch */ +{ + /* + * The MS implementation of gmtime is thread safe because it returns the + * time in a block of thread-local storage, and Windows does not provide a + * Posix gmtime_r function. + */ + + return gmtime(timePtr); +} + +/* + *---------------------------------------------------------------------- + * + * TclpLocaltime -- + * + * Wrapper around the 'localtime' library function to make it thread + * safe. + * + * Results: + * Returns a pointer to a 'struct tm' in thread-specific data. + * + * Side effects: + * Invokes localtime or localtime_r as appropriate. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpLocaltime( + const time_t *timePtr) /* Pointer to the number of seconds since the + * local system's epoch */ +{ + /* + * The MS implementation of localtime is thread safe because it returns + * the time in a block of thread-local storage, and Windows does not + * provide a Posix localtime_r function. + */ + + return localtime(timePtr); +} + +/* + *---------------------------------------------------------------------- + * * Tcl_SetTimeProc -- * * TIP #233 (Virtualized Time): Registers two handlers for the -- cgit v0.12 From cb73551e8dda297b93eecea5b526196ef7589c86 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 09:31:36 +0000 Subject: Start of "zipfs" branch, meant for keeping track of the proposed changes for a new TIP. Remove some android-specific build/configure files. --- Android.mk | 204 --------------------------------------------- debian/changelog | 23 ----- debian/compat | 1 - debian/control | 37 -------- debian/copyright | 141 ------------------------------- debian/rules | 130 ----------------------------- debian/sdltcl8.6-dev.dirs | 2 - debian/sdltcl8.6-dev.files | 2 - debian/sdltcl8.6-doc.files | 2 - debian/sdltcl8.6.files | 18 ---- debian/shlibs.local | 1 - pkgs/Android.mk | 1 - tcl-config.mk | 62 -------------- 13 files changed, 624 deletions(-) delete mode 100644 Android.mk delete mode 100644 debian/changelog delete mode 100644 debian/compat delete mode 100644 debian/control delete mode 100644 debian/copyright delete mode 100755 debian/rules delete mode 100644 debian/sdltcl8.6-dev.dirs delete mode 100644 debian/sdltcl8.6-dev.files delete mode 100644 debian/sdltcl8.6-doc.files delete mode 100644 debian/sdltcl8.6.files delete mode 100644 debian/shlibs.local delete mode 100644 pkgs/Android.mk delete mode 100644 tcl-config.mk diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 13e55d9..0000000 --- a/Android.mk +++ /dev/null @@ -1,204 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -########################### -# -# Tcl shared library -# -########################### - -include $(CLEAR_VARS) - -tcl_path := $(LOCAL_PATH) - -include $(tcl_path)/tcl-config.mk - -LOCAL_ADDITIONAL_DEPENDENCIES += $(tcl_path)/tcl-config.mk - -LOCAL_MODULE := tcl - -LOCAL_ARM_MODE := arm - -LOCAL_C_INCLUDES := $(tcl_includes) $(LOCAL_PATH)/libtommath - -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) - -LOCAL_SRC_FILES := \ - libtommath/bncore.c \ - libtommath/bn_reverse.c \ - libtommath/bn_fast_s_mp_mul_digs.c \ - libtommath/bn_fast_s_mp_sqr.c \ - libtommath/bn_mp_add.c \ - libtommath/bn_mp_add_d.c \ - libtommath/bn_mp_and.c \ - libtommath/bn_mp_clamp.c \ - libtommath/bn_mp_clear.c \ - libtommath/bn_mp_clear_multi.c \ - libtommath/bn_mp_cmp.c \ - libtommath/bn_mp_cmp_d.c \ - libtommath/bn_mp_cmp_mag.c \ - libtommath/bn_mp_copy.c \ - libtommath/bn_mp_cnt_lsb.c \ - libtommath/bn_mp_count_bits.c \ - libtommath/bn_mp_div.c \ - libtommath/bn_mp_div_d.c \ - libtommath/bn_mp_div_2.c \ - libtommath/bn_mp_div_2d.c \ - libtommath/bn_mp_div_3.c \ - libtommath/bn_mp_exch.c \ - libtommath/bn_mp_expt_d.c \ - libtommath/bn_mp_grow.c \ - libtommath/bn_mp_init.c \ - libtommath/bn_mp_init_copy.c \ - libtommath/bn_mp_init_multi.c \ - libtommath/bn_mp_init_set.c \ - libtommath/bn_mp_init_set_int.c \ - libtommath/bn_mp_init_size.c \ - libtommath/bn_mp_karatsuba_mul.c \ - libtommath/bn_mp_karatsuba_sqr.c \ - libtommath/bn_mp_lshd.c \ - libtommath/bn_mp_mod.c \ - libtommath/bn_mp_mod_2d.c \ - libtommath/bn_mp_mul.c \ - libtommath/bn_mp_mul_2.c \ - libtommath/bn_mp_mul_2d.c \ - libtommath/bn_mp_mul_d.c \ - libtommath/bn_mp_neg.c \ - libtommath/bn_mp_or.c \ - libtommath/bn_mp_radix_size.c \ - libtommath/bn_mp_radix_smap.c \ - libtommath/bn_mp_read_radix.c \ - libtommath/bn_mp_rshd.c \ - libtommath/bn_mp_set.c \ - libtommath/bn_mp_set_int.c \ - libtommath/bn_mp_shrink.c \ - libtommath/bn_mp_sqr.c \ - libtommath/bn_mp_sqrt.c \ - libtommath/bn_mp_sub.c \ - libtommath/bn_mp_sub_d.c \ - libtommath/bn_mp_to_unsigned_bin.c \ - libtommath/bn_mp_to_unsigned_bin_n.c \ - libtommath/bn_mp_toom_mul.c \ - libtommath/bn_mp_toom_sqr.c \ - libtommath/bn_mp_toradix_n.c \ - libtommath/bn_mp_unsigned_bin_size.c \ - libtommath/bn_mp_xor.c \ - libtommath/bn_mp_zero.c \ - libtommath/bn_s_mp_add.c \ - libtommath/bn_s_mp_mul_digs.c \ - libtommath/bn_s_mp_sqr.c \ - libtommath/bn_s_mp_sub.c \ - generic/regcomp.c \ - generic/regexec.c \ - generic/regfree.c \ - generic/regerror.c \ - generic/tclAlloc.c \ - generic/tclAssembly.c \ - generic/tclAsync.c \ - generic/tclBasic.c \ - generic/tclBinary.c \ - generic/tclCkalloc.c \ - generic/tclClock.c \ - generic/tclCmdAH.c \ - generic/tclCmdIL.c \ - generic/tclCmdMZ.c \ - generic/tclCompCmds.c \ - generic/tclCompCmdsGR.c \ - generic/tclCompCmdsSZ.c \ - generic/tclCompExpr.c \ - generic/tclCompile.c \ - generic/tclConfig.c \ - generic/tclDate.c \ - generic/tclDictObj.c \ - generic/tclDisassemble.c \ - generic/tclEncoding.c \ - generic/tclEnsemble.c \ - generic/tclEnv.c \ - generic/tclEvent.c \ - generic/tclExecute.c \ - generic/tclFCmd.c \ - generic/tclFileName.c \ - generic/tclGet.c \ - generic/tclHash.c \ - generic/tclHistory.c \ - generic/tclIndexObj.c \ - generic/tclInterp.c \ - generic/tclIO.c \ - generic/tclIOCmd.c \ - generic/tclIOGT.c \ - generic/tclIOSock.c \ - generic/tclIOUtil.c \ - generic/tclIORChan.c \ - generic/tclIORTrans.c \ - generic/tclLink.c \ - generic/tclListObj.c \ - generic/tclLiteral.c \ - generic/tclLoad.c \ - generic/tclMain.c \ - generic/tclNamesp.c \ - generic/tclNotify.c \ - generic/tclObj.c \ - generic/tclOptimize.c \ - generic/tclPanic.c \ - generic/tclParse.c \ - generic/tclPathObj.c \ - generic/tclPipe.c \ - generic/tclPkg.c \ - generic/tclPkgConfig.c \ - generic/tclPosixStr.c \ - generic/tclPreserve.c \ - generic/tclProc.c \ - generic/tclRegexp.c \ - generic/tclResolve.c \ - generic/tclResult.c \ - generic/tclScan.c \ - generic/tclStubInit.c \ - generic/tclStringObj.c \ - generic/tclStrToD.c \ - generic/tclThread.c \ - generic/tclThreadAlloc.c \ - generic/tclThreadJoin.c \ - generic/tclThreadStorage.c \ - generic/tclTimer.c \ - generic/tclTomMathInterface.c \ - generic/tclTrace.c \ - generic/tclUtil.c \ - generic/tclUtf.c \ - generic/tclVar.c \ - generic/tclZlib.c \ - generic/tclOO.c \ - generic/tclOOBasic.c \ - generic/tclOOCall.c \ - generic/tclOODefineCmds.c \ - generic/tclOOInfo.c \ - generic/tclOOMethod.c \ - generic/tclOOStubInit.c \ - generic/tclStubLib.c \ - generic/tclTomMathStubLib.c \ - generic/tclOOStubLib.c \ - generic/zipfs.c \ - unix/tclAppInit.c \ - unix/tclLoadDl.c \ - unix/tclUnixChan.c \ - unix/tclUnixCompat.c \ - unix/tclUnixEvent.c \ - unix/tclUnixFCmd.c \ - unix/tclUnixFile.c \ - unix/tclUnixInit.c \ - unix/tclUnixNotfy.c \ - unix/tclUnixPipe.c \ - unix/tclUnixSock.c \ - unix/tclUnixTest.c \ - unix/tclUnixThrd.c \ - unix/tclUnixTime.c - -LOCAL_CFLAGS := $(tcl_cflags) \ - -DPACKAGE_NAME="\"tcl\"" \ - -DPACKAGE_VERSION="\"8.6\"" \ - -DBUILD_tcl=1 \ - -Dmain=tclsh \ - -O2 - -LOCAL_LDLIBS := -ldl -lz -llog - -include $(BUILD_SHARED_LIBRARY) - diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index caad3ba..0000000 --- a/debian/changelog +++ /dev/null @@ -1,23 +0,0 @@ -sdltcl8.6 (8.6.4-1) unstable; urgency=low - - * Update to 8.6.4 - - -- Christian Werner Thu, 12 Mar 2015 22:00:00 +0100 - -sdltcl8.6 (8.6.3-1) unstable; urgency=low - - * Update to 8.6.3 - - -- Christian Werner Wed, 12 Nov 2014 20:00:00 +0100 - -sdltcl8.6 (8.6.2-1) unstable; urgency=low - - * Update to 8.6.2 - - -- Christian Werner Thu, 28 Aug 2014 07:10:10 +0200 - -sdltcl8.6 (8.6.1-1) unstable; urgency=low - - * Initial packaging - - -- Christian Werner Sat, 05 Apr 2014 14:44:48 +0200 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7ed6ff8..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/debian/control b/debian/control deleted file mode 100644 index 3434297..0000000 --- a/debian/control +++ /dev/null @@ -1,37 +0,0 @@ -Source: sdltcl8.6 -Section: libs -Priority: optional -Maintainer: -Build-Depends: debhelper (>= 5.0.0), quilt -Standards-Version: 3.8.3 -Homepage: http://www.tcl.tk/ - -Package: sdltcl8.6 -Section: interpreters -Priority: optional -Architecture: any -Depends: ${shlibs:Depends} -Description: Tcl (the Tool Command Language) v8.6 - run-time files - Tcl is a powerful, easy to use, embeddable, cross-platform interpreted - scripting language. This package contains everything you need to run - Tcl scripts and Tcl-enabled apps. This version includes thread support. - -Package: sdltcl8.6-doc -Section: doc -Priority: optional -Architecture: all -Suggests: sdltcl8.6 -Description: Tcl (the Tool Command Language) v8.6 - manual pages - Tcl is a powerful, easy-to-use, embeddable, cross-platform interpreted - scripting language. This package contains the man pages for Tcl commands. - -Package: sdltcl8.6-dev -Section: devel -Priority: optional -Architecture: any -Depends: sdltcl8.6 (= ${binary:Version}) -Suggests: sdltcl8.6-doc -Description: Tcl (the Tool Command Language) v8.6 - development files - Tcl is a powerful, easy-to-use, embeddable, cross-platform interpreted - scripting language. This package contains the headers and libraries - needed to embed or extend Tcl. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 075c312..0000000 --- a/debian/copyright +++ /dev/null @@ -1,141 +0,0 @@ -This package was originally debianized by David Engel -from sources obtained at http://prdownloads.sourceforge.net/tcl - -List of copyright holders mentioned in individual files: - -Copyright 1983, 1988-1994 The Regents of the University of California -Copyright 1991-1999 Karl Lehenbauer and Mark Diekhans -Copyright 1992-1996 Free Software Foundation, Inc. -Copyright 1993-1994 Lockheed Missle & Space Company, AI Center -Copyright 1993-1997 Bell Labs Innovations for Lucent Technologies -Copyright 1993-1997 Lucent Technologies -Copyright 1994-1998 Sun Microsystems, Inc. -Copyright 1995 General Electric Company -Copyright 1995 Dave Nebinger -Copyright 1995-1997 Roger E. Critchlow Jr -Copyright 1996 Lucent Technologies and Jim Ingham -Copyright 1997-2000 Ajuba Solutions -Copyright 1998-2000 Scriptics Corporation -Copyright 1998-1999 Henry Spencer -Copyright 1998 Paul Duffin -Copyright 1998 Mark Harrison -Copyright 1999 America Online, Inc. -Copyright 1999-2000 Andreas Kupries -Copyright 2000-2001 ActiveState Corporation, et al -Copyright 2001 ActiveState Tool Corp. -Copyright 2001-2002 Apple Computer, Inc. -Copyright 2001-2002 ActiveState Corporation -Copyright 2001-2002 Vincent Darley -Copyright 2001-2002 Donal K. Fellows -Copyright 2001-2003 Kevin B. Kenny -Copyright 2001-2002 David Gravereaux -Contributions from Don Porter, NIST, 2002-2003. (not subject to US copyright) -Copyright 2005 Tcl Core Team -Copyright 2005 Daniel A. Steffen - -Copyright: - -This software is copyrighted by the Regents of the University of -California, Sun Microsystems, Inc., Scriptics Corporation, -and other parties. The following terms apply to all files associated -with the software unless explicitly disclaimed in individual files. - -The authors hereby grant permission to use, copy, modify, distribute, -and license this software and its documentation for any purpose, provided -that existing copyright notices are retained in all copies and that this -notice is included verbatim in any distributions. No written agreement, -license, or royalty fee is required for any of the authorized uses. -Modifications to this software may be copyrighted by their authors -and need not follow the licensing terms described here, provided that -the new terms are clearly indicated on the first page of each file where -they apply. - -IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY -FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY -DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE -IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE -NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -MODIFICATIONS. - -GOVERNMENT USE: If you are acquiring this software on behalf of the -U.S. government, the Government shall have only "Restricted Rights" -in the software and related documentation as defined in the Federal -Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you -are acquiring the software on behalf of the Department of Defense, the -software shall be classified as "Commercial Computer Software" and the -Government shall have only "Restricted Rights" as defined in Clause -252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the -authors grant the U.S. Government and others acting in its behalf -permission to use and distribute the software in accordance with the -terms specified in this license. - -Several files are distributed under other conditions: - -compat/strftime.c: -/* - * strftime.c -- - * - * This file contains a modified version of the BSD 4.4 strftime - * function. - * - * This file is a modified version of the strftime.c file from the BSD 4.4 - * source. See the copyright notice below for details on redistribution - * restrictions. The "license.terms" file does not apply to this file. - * - * Changes 2002 Copyright (c) 2002 ActiveState Corporation. - * - * RCS: @(#) $Id: strftime.c,v 1.10.2.3 2005/11/04 18:18:04 kennykb Exp $ - */ - -/* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -compat/dlfcn.h and unix/tclLoadAix.c: - * This file is subject to the following copyright notice, which is - * different from the notice used elsewhere in Tcl but rougly - * equivalent in meaning. - * - * Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH - * Not derived from licensed software. - * - * Permission is granted to freely use, copy, modify, and redistribute - * this software, provided that the author is not construed to be liable - * for any results of using the software, alterations are clearly marked - * as such, and this notice is not modified. - diff --git a/debian/rules b/debian/rules deleted file mode 100755 index a4b3bd4..0000000 --- a/debian/rules +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/make -f -# debian/rules that uses debhelper. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) -DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) - -export QUILT_PATCHES := debian/patches - -v = 8.6 - -ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) -CFLAGS=-g -O0 -else -# See bug #446335 -CFLAGS=-g -O2 -fno-unit-at-a-time -endif - -unpatch: - dh_testdir - quilt pop -a || test $$? = 2 - rm -rf patch-stamp .pc - -patch: patch-stamp -patch-stamp: - dh_testdir - quilt push -a || test $$? = 2 - touch patch-stamp - -build: build-stamp -build-stamp: patch-stamp - dh_testdir -# So so ugly but it works... - touch generic/tclStubInit.c - cd unix && \ - CFLAGS="$(CFLAGS)" \ - ac_cv_func_strtod=yes \ - tcl_cv_strtod_buggy=1 \ - ./configure --host=$(DEB_HOST_GNU_TYPE) \ - --build=$(DEB_BUILD_GNU_TYPE) \ - --prefix=/opt/sdltk86 \ - --includedir=/opt/sdltk86/include \ - --enable-shared \ - --mandir=/opt/sdltk86/man \ - --enable-man-symlinks \ - --enable-man-compression=gzip \ - --enable-threads \ - --without-tzdata \ - --with-zipfs && \ - touch ../generic/tclStubInit.c && \ - $(MAKE) -# Build the static library. - cd unix && \ - ar cr libtcl$(v).a *.o && \ - ar d libtcl$(v).a tclAppInit.o && \ - ranlib libtcl$(v).a - touch build-stamp - -clean: clean-patched unpatch - dh_testdir - dh_testroot - dh_clean - -clean-patched: - dh_testdir - dh_testroot - rm -f build-stamp install-stamp - cd unix && [ ! -f Makefile ] || $(MAKE) distclean -# Remove forgotten files - rm -f tests/pkg/pkga.so unix/config.log unix/Tcltest.so - -install: install-stamp -install-stamp: build-stamp - dh_testdir - dh_testroot - dh_clean -k - dh_installdirs - cd unix && \ - GZIP=-9 \ - $(MAKE) INSTALL_ROOT=`pwd`/../debian/tmp \ - MAN_INSTALL_DIR=`pwd`/../debian/tmp/opt/sdltk86/man \ - install install-private-headers install-packages -# Fix up the libraries. - cp unix/libtcl$(v).a debian/tmp/opt/sdltk86/lib - touch install-stamp - -# Build architecture-independent files here. -binary-indep: build install - dh_testdir -i - dh_testroot -i - dh_movefiles -i - dh_installdocs -i - dh_installchangelogs -i ChangeLog - dh_compress -i - dh_fixperms -i - dh_installdeb -i - dh_gencontrol -i - dh_md5sums -i - dh_builddeb -i - -# Build architecture-dependent files here. -binary-arch: build install - dh_testdir -a - dh_testroot -a - dh_movefiles -a -# now, fix up file locations for .sh - mv debian/sdltcl$(v)/opt/sdltk86/lib/tclConfig.sh \ - debian/sdltcl$(v)-dev/opt/sdltk86/lib - dh_installdocs -a - dh_installmenu -a - dh_installchangelogs -a ChangeLog - dh_fixperms -a - dh_strip -a - dh_compress -a - dh_makeshlibs -a -V 'sdltcl$(v) (>= 8.6.2)' -XTcltest - dh_installdeb -a - dh_shlibdeps -a -ldebian/sdltcl$(v)/opt/sdltk86/lib - dh_gencontrol -a - dh_md5sums -a - dh_builddeb -a - -source diff: - @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false - -binary: binary-indep binary-arch - -.PHONY: patch unpatch clean-patched build clean binary-indep binary-arch binary install - diff --git a/debian/sdltcl8.6-dev.dirs b/debian/sdltcl8.6-dev.dirs deleted file mode 100644 index 4de4819..0000000 --- a/debian/sdltcl8.6-dev.dirs +++ /dev/null @@ -1,2 +0,0 @@ -opt/sdltk86/lib -opt/sdltk86/include diff --git a/debian/sdltcl8.6-dev.files b/debian/sdltcl8.6-dev.files deleted file mode 100644 index 5cd0878..0000000 --- a/debian/sdltcl8.6-dev.files +++ /dev/null @@ -1,2 +0,0 @@ -opt/sdltk86/include -opt/sdltk86/lib/*.a diff --git a/debian/sdltcl8.6-doc.files b/debian/sdltcl8.6-doc.files deleted file mode 100644 index 56ca7e7..0000000 --- a/debian/sdltcl8.6-doc.files +++ /dev/null @@ -1,2 +0,0 @@ -opt/sdltk86/man/man3 -opt/sdltk86/man/mann diff --git a/debian/sdltcl8.6.files b/debian/sdltcl8.6.files deleted file mode 100644 index 501d10a..0000000 --- a/debian/sdltcl8.6.files +++ /dev/null @@ -1,18 +0,0 @@ -opt/sdltk86/bin -opt/sdltk86/lib/tcl8 -opt/sdltk86/lib/tcl8/* -opt/sdltk86/lib/tcl8.6 -opt/sdltk86/lib/tcl8.6/* -opt/sdltk86/lib/*.so -opt/sdltk86/lib/*.sh -opt/sdltk86/lib/itcl* -opt/sdltk86/lib/itcl*/* -opt/sdltk86/lib/pkgconfig -opt/sdltk86/lib/pkgconfig/* -opt/sdltk86/lib/sqlite* -opt/sdltk86/lib/sqlite*/* -opt/sdltk86/lib/tdbc* -opt/sdltk86/lib/tdbc*/* -opt/sdltk86/lib/thread* -opt/sdltk86/lib/thread*/* -opt/sdltk86/man/man1 diff --git a/debian/shlibs.local b/debian/shlibs.local deleted file mode 100644 index 7da5dd4..0000000 --- a/debian/shlibs.local +++ /dev/null @@ -1 +0,0 @@ -libtcl8.6 1 diff --git a/pkgs/Android.mk b/pkgs/Android.mk deleted file mode 100644 index 5053e7d..0000000 --- a/pkgs/Android.mk +++ /dev/null @@ -1 +0,0 @@ -include $(call all-subdir-makefiles) diff --git a/tcl-config.mk b/tcl-config.mk deleted file mode 100644 index e072516..0000000 --- a/tcl-config.mk +++ /dev/null @@ -1,62 +0,0 @@ -tcl_includes := $(tcl_path)/generic $(tcl_path)/unix - -tcl_cflags := \ - -DHAVE_SYS_SELECT_H=1 \ - -DHAVE_LIMITS_H=1 \ - -DHAVE_UNISTD_H=1 \ - -DHAVE_SYS_PARAM_H=1 \ - -D_LARGEFILE64_SOURCE=1 \ - -DTCL_WIDE_INT_TYPE="long long" \ - -DTCL_SHLIB_EXT="\".so\"" \ - -DHAVE_CAST_TO_UNION=1 \ - -DHAVE_GETCWD=1 \ - -DHAVE_OPENDIR=1 \ - -DHAVE_MKSTEMP=1 \ - -DHAVE_MKSTEMPS=1 \ - -DHAVE_STRSTR=1 \ - -DHAVE_STRTOL=1 \ - -DHAVE_STRTOLL=1 \ - -DHAVE_STRTOULL=1 \ - -DHAVE_TMPNAM=1 \ - -DHAVE_WAITPID=1 \ - -DHAVE_STRUCT_ADDRINFO=1 \ - -DHAVE_STRUCT_IN6_ADDR=1 \ - -DHAVE_STRUCT_SOCKADDR_IN6=1 \ - -DHAVE_STRUCT_SOCKADDR_STORAGE=1 \ - -DHAVE_GETHOSTBYNAME_R=1 \ - -DUSE_TERMIOS=1 \ - -DHAVE_MKTIME=1 \ - -DUSE_INTERP_ERRORLINE=1 \ - -DHAVE_SYS_TIME_H=1 \ - -DTIME_WITH_SYS_TIME=1 \ - -DHAVE_TM_ZONE=1 \ - -DHAVE_GMTIME_R=1 \ - -DHAVE_LOCALTIME_R=1 \ - -DHAVE_TM_GMTOFF=1 \ - -DHAVE_TIMEZONE_VAR=1 \ - -DHAVE_ST_BLKSIZE=1 \ - -DSTDC_HEADERS=1 \ - -DHAVE_INTPTR_T=1 \ - -DHAVE_UINTPTR_T=1 \ - -DHAVE_SIGNED_CHAR=1 \ - -DHAVE_SYS_IOCTL_H=1 \ - -DHAVE_MEMCPY=1 \ - -DHAVE_MEMMOVE=1 \ - -DVOID=void \ - -DNO_UNION_WAIT=1 \ - -DHAVE_ZLIB=1 \ - -DMP_PREC=4 \ - -DTCL_TOMMATH=1 \ - -D_REENTRANT=1 \ - -D_THREADSAFE=1 \ - -DTCL_UTF_MAX=6 \ - -DTCL_THREADS=1 \ - -DTCL_PTHREAD_ATFORK=1 \ - -DUSE_THREAD_ALLOC=1 \ - -DTCL_CFGVAL_ENCODING="\"utf-8\"" \ - -DTCL_UNLOAD_DLLS=1 \ - -DTCL_CFG_OPTIMIZED=1 \ - -DZIPFS_IN_TCL=1 \ - -DTCL_PACKAGE_PATH="\"/assets\"" \ - -DTCL_LIBRARY="\"/assets/tcl8.6\"" - -- cgit v0.12 From b0a98f480d3a16432d023ddb8cb4ba8e22edd973 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 10:03:06 +0000 Subject: Undo more Android-specific changes, which don't form part of Zipfs, as further preparation for Zipfs TIP. Rename zipfs.h to tclZipfs.h, so it can be installed together with tcl.h --- generic/tclIOUtil.c | 2 +- generic/tclMain.c | 197 ---------------------------------------------------- generic/tclZipfs.h | 65 +++++++++++++++++ generic/zipfs.c | 6 +- generic/zipfs.h | 66 ------------------ unix/Makefile.in | 4 +- unix/configure | 18 ----- unix/configure.in | 8 --- unix/tclUnixInit.c | 8 --- win/Makefile.in | 1 + win/configure | 19 ----- win/configure.in | 8 --- win/makefile.vc | 1 + 13 files changed, 75 insertions(+), 328 deletions(-) create mode 100644 generic/tclZipfs.h delete mode 100644 generic/zipfs.h diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 9bc868b..0ef6d3b 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -192,7 +192,7 @@ const Tcl_Filesystem tclNativeFilesystem = { }; #ifdef ZIPFS_IN_TCL -extern Tcl_Filesystem zipfsFilesystem; +MODULE_SCOPE Tcl_Filesystem zipfsFilesystem; #endif /* diff --git a/generic/tclMain.c b/generic/tclMain.c index 6acd15d..927de7e 100644 --- a/generic/tclMain.c +++ b/generic/tclMain.c @@ -34,15 +34,6 @@ #include "tclInt.h" -#ifdef ZIPFS_IN_TCL -#include "zipfs.h" -#endif - -#ifdef ANDROID -#undef ZIPFS_BOOTDIR -#define ZIPFS_BOOTDIR "/assets" -#endif - /* * The default prompt used when the user has not overridden it. */ @@ -60,7 +51,6 @@ # define TCHAR char # define TEXT(arg) arg # define _tcscmp strcmp -# define _tcsncmp strncmp #endif /* @@ -325,21 +315,9 @@ Tcl_MainEx( Tcl_MainLoopProc *mainLoopProc; Tcl_Channel chan; InteractiveState is; -#ifdef ZIPFS_IN_TCL - const char *zipFile = NULL; - Tcl_Obj *zipval = NULL; - int autoRun = 1; - int zipOk = TCL_ERROR; -#ifndef ANDROID - const char *exeName; -#endif -#endif TclpSetInitialEncodings(); TclpFindExecutable((const char *)argv[0]); -#if defined(ZIPFS_IN_TCL) && !defined(ANDROID) - exeName = Tcl_GetNameOfExecutable(); -#endif Tcl_InitMemory(interp); @@ -369,26 +347,6 @@ Tcl_MainEx( Tcl_DecrRefCount(value); argc -= 3; argv += 3; -#ifdef ZIPFS_IN_TCL - } else if (argc > 2) { - int length = strlen((char *) argv[1]); - if ((length >= 2) && - (0 == _tcsncmp(TEXT("-zip"), argv[1], length))) { - argc--; - argv++; - if ((argc > 1) && (argv[1][0] != (TCHAR) '-')) { - zipval = NewNativeObj(argv[1], -1); - zipFile = Tcl_GetString(zipval); - autoRun = 0; - argc--; - argv++; - } - } else if ('-' != argv[1][0]) { - Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL); - argc--; - argv++; - } -#endif } else if ((argc > 1) && ('-' != argv[1][0])) { Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL); argc--; @@ -422,67 +380,6 @@ Tcl_MainEx( Tcl_SetVar2Ex(interp, "tcl_interactive", NULL, Tcl_NewIntObj(!path && is.tty), TCL_GLOBAL_ONLY); -#ifdef ZIPFS_IN_TCL - zipOk = Tclzipfs_Init(interp); - if (zipOk == TCL_OK) { - int relax = 0; - - if (zipFile == NULL) { - relax = 1; -#ifdef ANDROID - zipFile = getenv("PACKAGE_CODE_PATH"); - if (zipFile == NULL) { - zipFile = Tcl_GetNameOfExecutable(); - } -#else - zipFile = exeName; -#endif - } - if (zipFile != NULL) { -#ifdef ANDROID - zipOk = Tclzipfs_Mount(interp, zipFile, "", NULL); -#else - zipOk = Tclzipfs_Mount(interp, zipFile, exeName, NULL); -#endif - if (!relax && (zipOk != TCL_OK)) { - exitCode = 1; - goto done; - } - } else { - zipOk = TCL_ERROR; - } - Tcl_ResetResult(interp); - } - if (zipOk == TCL_OK) { -#ifdef ZIPFS_BOOTDIR - char *tcl_lib = ZIPFS_BOOTDIR "/tcl" TCL_VERSION; - char *tcl_pkg = ZIPFS_BOOTDIR; -#else - char *tcl_lib; - char *tcl_pkg = (char *) exeName; - Tcl_DString dsLib; - - Tcl_DStringInit(&dsLib); - Tcl_DStringAppend(&dsLib, exeName, -1); - Tcl_DStringAppend(&dsLib, "/tcl" TCL_VERSION, -1); - tcl_lib = Tcl_DStringValue(&dsLib); -#endif - Tcl_SetVar2(interp, "env", "TCL_LIBRARY", tcl_lib, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tcl_libPath", tcl_lib, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tcl_library", tcl_lib, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tcl_pkgPath", tcl_pkg, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "auto_path", tcl_lib, - TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT); -#ifndef ZIPFS_BOOTDIR - Tcl_DStringFree(&dsLib); -#endif - } - if (zipval != NULL) { - Tcl_DecrRefCount(zipval); - zipval = NULL; - } -#endif - /* * Invoke application-specific initialization. */ @@ -512,100 +409,6 @@ Tcl_MainEx( Tcl_CreateExitHandler(FreeMainInterp, interp); } -#ifdef ZIPFS_IN_TCL - /* - * Setup auto loading info to point to mounted ZIP file. - */ - - if (zipOk == TCL_OK) { -#ifdef ZIPFS_BOOTDIR - char *tcl_lib = ZIPFS_BOOTDIR "/tcl" TCL_VERSION; - char *tcl_pkg = ZIPFS_BOOTDIR; -#else - char *tcl_lib; - char *tcl_pkg = (char *) exeName; - Tcl_DString dsLib; - - Tcl_DStringInit(&dsLib); - Tcl_DStringAppend(&dsLib, exeName, -1); - Tcl_DStringAppend(&dsLib, "/tcl" TCL_VERSION, -1); - tcl_lib = Tcl_DStringValue(&dsLib); -#endif - Tcl_SetVar(interp, "tcl_libPath", tcl_lib, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tcl_library", tcl_lib, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tcl_pkgPath", tcl_pkg, TCL_GLOBAL_ONLY); -#ifndef ZIPFS_BOOTDIR - Tcl_DStringFree(&dsLib); -#endif - - /* - * We need to re-init encoding (after initializing Tcl), - * otherwise "encoding system" will return "identity" - */ - - TclpSetInitialEncodings(); - } - - /* - * Set embedded application startup file, if any. - */ - - if ((zipOk == TCL_OK) && autoRun) { - char *filename; - Tcl_Channel chan; -#ifdef ZIPFS_BOOTDIR - filename = ZIPFS_BOOTDIR "/app/main.tcl"; -#else - Tcl_DString dsFile; - - Tcl_DStringInit(&dsFile); - Tcl_DStringAppend(&dsFile, exeName, -1); - Tcl_DStringAppend(&dsFile, "/app/main.tcl", -1); - filename = Tcl_DStringValue(&dsFile); -#endif - chan = Tcl_OpenFileChannel(NULL, filename, "r", 0); - if (chan != (Tcl_Channel) NULL) { - Tcl_Obj *arg; - - Tcl_Close(NULL, chan); - - /* - * Push back script file to argv, if any. - */ - if ((arg = Tcl_GetStartupScript(NULL)) != NULL) { - Tcl_Obj *v, *no; - - no = Tcl_NewStringObj("argv", 4); - v = Tcl_ObjGetVar2(interp, no, NULL, TCL_GLOBAL_ONLY); - if (v != NULL) { - Tcl_Obj **objv, *nv; - int objc, i; - - objc = 0; - Tcl_ListObjGetElements(NULL, v, &objc, &objv); - nv = Tcl_NewListObj(1, &arg); - for (i = 0; i < objc; i++) { - Tcl_ListObjAppendElement(NULL, nv, objv[i]); - } - Tcl_IncrRefCount(nv); - if (Tcl_ObjSetVar2(interp, no, NULL, nv, TCL_GLOBAL_ONLY) - != NULL) { - Tcl_GlobalEval(interp, "incr argc"); - } - Tcl_DecrRefCount(nv); - } - Tcl_DecrRefCount(no); - } - Tcl_SetStartupScript(Tcl_NewStringObj(filename, -1), NULL); - Tcl_SetVar(interp, "argv0", filename, TCL_GLOBAL_ONLY); - Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY); - } -#ifndef ANDROID - Tcl_DStringFree(&dsFile); -#endif - } -#endif - /* * Invoke the script specified on the command line, if any. Must fetch it * again, as the appInitProc might have reset it. diff --git a/generic/tclZipfs.h b/generic/tclZipfs.h new file mode 100644 index 0000000..bf3a3cb --- /dev/null +++ b/generic/tclZipfs.h @@ -0,0 +1,65 @@ +/* + * tclZipfs.h -- + * + * This header file describes the interface of the ZIPFS filesystem + * + * Copyright (c) 2013-2015 Christian Werner + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifndef _ZIPFS_H +#define _ZIPFS_H + +#include "tcl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ZIPFSAPI +# define ZIPFSAPI extern +#endif + +#ifdef ZIPFS_IN_TK +#define Zipfs_Mount Tkzipfs_Mount +#define Zipfs_Unmount Tkzipfs_Unmount +#define Zipfs_Init Tkzipfs_Init +#define Zipfs_SafeInit Tkzipfs_SafeInit +#ifdef BUILD_tk +# undef ZIPFSAPI +# define ZIPFSAPI DLLEXPORT +#endif +#endif + +#ifdef ZIPFS_IN_TCL +#define Zipfs_Mount Tclzipfs_Mount +#define Zipfs_Unmount Tclzipfs_Unmount +#define Zipfs_Init Tclzipfs_Init +#define Zipfs_SafeInit Tclzipfs_SafeInit +#ifdef BUILD_tcl +# undef ZIPFSAPI +# define ZIPFSAPI DLLEXPORT +#endif +#endif + +ZIPFSAPI int Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, + CONST char *mntpt, CONST char *passwd); +ZIPFSAPI int Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname); +ZIPFSAPI int Zipfs_Init(Tcl_Interp *interp); +ZIPFSAPI int Zipfs_SafeInit(Tcl_Interp *interp); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZIPFS_H */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/zipfs.c b/generic/zipfs.c index 0683c32..6d49f4f 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -24,7 +24,7 @@ #endif #include "tclInt.h" #include "tclFileSystem.h" -#include "zipfs.h" +#include "tclZipfs.h" #ifdef HAVE_ZLIB @@ -3821,7 +3821,9 @@ Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, * Define the ZIP filesystem dispatch table. */ -Tcl_Filesystem zipfsFilesystem = { +MODULE_SCOPE const Tcl_Filesystem zipfsFilesystem; + +const Tcl_Filesystem zipfsFilesystem = { "zipfs", sizeof (Tcl_Filesystem), TCL_FILESYSTEM_VERSION_2, diff --git a/generic/zipfs.h b/generic/zipfs.h deleted file mode 100644 index 15ca37c..0000000 --- a/generic/zipfs.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * zipfs.h -- - * - * This header file describes the interface of the ZIPFS filesystem - * used in AndroWish. - * - * Copyright (c) 2013-2015 Christian Werner - * - * See the file "license.terms" for information on usage and redistribution of - * this file, and for a DISCLAIMER OF ALL WARRANTIES. - */ - -#ifndef _ZIPFS_H -#define _ZIPFS_H - -#include "tcl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ZIPFSAPI -# define ZIPFSAPI extern -#endif - -#ifdef ZIPFS_IN_TK -#define Zipfs_Mount Tkzipfs_Mount -#define Zipfs_Unmount Tkzipfs_Unmount -#define Zipfs_Init Tkzipfs_Init -#define Zipfs_SafeInit Tkzipfs_SafeInit -#ifdef BUILD_tk -# undef ZIPFSAPI -# define ZIPFSAPI DLLEXPORT -#endif -#endif - -#ifdef ZIPFS_IN_TCL -#define Zipfs_Mount Tclzipfs_Mount -#define Zipfs_Unmount Tclzipfs_Unmount -#define Zipfs_Init Tclzipfs_Init -#define Zipfs_SafeInit Tclzipfs_SafeInit -#ifdef BUILD_tcl -# undef ZIPFSAPI -# define ZIPFSAPI DLLEXPORT -#endif -#endif - -ZIPFSAPI int Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, - CONST char *mntpt, CONST char *passwd); -ZIPFSAPI int Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname); -ZIPFSAPI int Zipfs_Init(Tcl_Interp *interp); -ZIPFSAPI int Zipfs_SafeInit(Tcl_Interp *interp); - -#ifdef __cplusplus -} -#endif - -#endif /* _ZIPFS_H */ - -/* - * Local Variables: - * mode: c - * c-basic-offset: 4 - * fill-column: 78 - * End: - */ diff --git a/unix/Makefile.in b/unix/Makefile.in index ebbd61c..c09fb35 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -373,6 +373,7 @@ GENERIC_HDRS = \ $(GENERIC_DIR)/tclInt.h \ $(GENERIC_DIR)/tclIntDecls.h \ $(GENERIC_DIR)/tclIntPlatDecls.h \ + $(GENERIC_DIR)/tclZipfs.h \ $(GENERIC_DIR)/tclTomMath.h \ $(GENERIC_DIR)/tclTomMathDecls.h \ $(GENERIC_DIR)/tclOO.h \ @@ -383,7 +384,7 @@ GENERIC_HDRS = \ $(GENERIC_DIR)/tclPlatDecls.h \ $(GENERIC_DIR)/tclPort.h \ $(GENERIC_DIR)/tclRegexp.h \ - $(GENERIC_DIR)/zipfs.h + $(GENERIC_DIR)/tclZipfs.h GENERIC_SRCS = \ $(GENERIC_DIR)/regcomp.c \ @@ -954,6 +955,7 @@ install-headers: @for i in $(GENERIC_DIR)/tcl.h $(GENERIC_DIR)/tclDecls.h \ $(GENERIC_DIR)/tclOO.h $(GENERIC_DIR)/tclOODecls.h \ $(GENERIC_DIR)/tclPlatDecls.h \ + $(GENERIC_DIR)/tclZipfs.h \ $(GENERIC_DIR)/tclTomMath.h \ $(GENERIC_DIR)/tclTomMathDecls.h ; \ do \ diff --git a/unix/configure b/unix/configure index 3e72a0d..c19a77a 100755 --- a/unix/configure +++ b/unix/configure @@ -869,7 +869,6 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-encoding encoding for configuration values (default: iso8859-1) - --with-zipfs include ZIP filesystem --with-tzdata install timezone data (default: autodetect) Some influential environment variables: @@ -6212,23 +6211,6 @@ cat >>confdefs.h <<\_ACEOF _ACEOF -# Check whether --with-zipfs or --without-zipfs was given. -if test "${with_zipfs+set}" = set; then - withval="$with_zipfs" - tcl_ok=$withval -else - tcl_ok=no -fi; -echo "$as_me:$LINENO: result: $tcl_ok" >&5 -echo "${ECHO_T}$tcl_ok" >&6 -if test $tcl_ok = yes; then - -cat >>confdefs.h <<\_ACEOF -#define ZIPFS_IN_TCL 1 -_ACEOF - -fi - #-------------------------------------------------------------------- # The statements below define a collection of compile flags. This # macro depends on the value of SHARED_BUILD, and should be called diff --git a/unix/configure.in b/unix/configure.in index 7eeff3b..c7b0edc 100644 --- a/unix/configure.in +++ b/unix/configure.in @@ -171,14 +171,6 @@ AS_IF([test $zlib_ok = no], [ AC_SUBST(ZLIB_INCLUDE,[-I\${ZLIB_DIR}]) ]) AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?]) -AC_ARG_WITH(zipfs, - AC_HELP_STRING([--with-zipfs], - [include ZIP filesystem]), - [tcl_ok=$withval], [tcl_ok=no]) -AC_MSG_RESULT([$tcl_ok]) -if test $tcl_ok = yes; then - AC_DEFINE(ZIPFS_IN_TCL, 1, [Include ZIP filesystem?]) -fi #-------------------------------------------------------------------- # The statements below define a collection of compile flags. This diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index e8ccc76..5e4ef0a 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -9,9 +9,6 @@ */ #include "tclInt.h" -#ifdef ZIPFS_IN_TCL -#include "zipfs.h" -#endif #include #include #ifdef HAVE_LANGINFO @@ -544,11 +541,6 @@ TclpInitLibraryPath( */ str = defaultLibraryDir; -#ifdef ZIPFS_IN_TCL - if (Tclzipfs_Mount(NULL, NULL, NULL, NULL) == TCL_OK) { - str = ""; - } -#endif } if (str[0] != '\0') { objPtr = Tcl_NewStringObj(str, -1); diff --git a/win/Makefile.in b/win/Makefile.in index 00f5c99..f6d006b 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -636,6 +636,7 @@ install-libraries: libraries install-tzdata install-msgs @echo "Installing header files"; @for i in "$(GENERIC_DIR)/tcl.h" "$(GENERIC_DIR)/tclDecls.h" \ "$(GENERIC_DIR)/tclOO.h" "$(GENERIC_DIR)/tclOODecls.h" \ + "$(GENERIC_DIR)/tclZipfs.h" \ "$(GENERIC_DIR)/tclPlatDecls.h" \ "$(GENERIC_DIR)/tclTomMath.h" \ "$(GENERIC_DIR)/tclTomMathDecls.h"; \ diff --git a/win/configure b/win/configure index 27f2c10..3ebc697 100755 --- a/win/configure +++ b/win/configure @@ -853,7 +853,6 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-encoding encoding for configuration values --with-celib=DIR use Windows/CE support library from DIR - --with-zipfs include ZIP filesystem Some influential environment variables: CC C compiler command @@ -4409,24 +4408,6 @@ cat >>confdefs.h <<\_ACEOF _ACEOF -# Check whether --with-zipfs or --without-zipfs was given. -if test "${with_zipfs+set}" = set; then - withval="$with_zipfs" - tcl_ok=$withval -else - tcl_ok=no -fi; -echo "$as_me:$LINENO: result: $tcl_ok" >&5 -echo "${ECHO_T}$tcl_ok" >&6 -if test $tcl_ok = yes; then - -cat >>confdefs.h <<\_ACEOF -#define ZIPFS_IN_TCL 1 -_ACEOF - -fi - - echo "$as_me:$LINENO: checking for intptr_t" >&5 echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6 if test "${ac_cv_type_intptr_t+set}" = set; then diff --git a/win/configure.in b/win/configure.in index c8ab2e3..9e9df90 100644 --- a/win/configure.in +++ b/win/configure.in @@ -141,14 +141,6 @@ AS_IF([test "$tcl_ok" = "yes"], [ AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}]) ]) AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?]) -AC_ARG_WITH(zipfs, - AC_HELP_STRING([--with-zipfs], - [include ZIP filesystem]), - [tcl_ok=$withval], [tcl_ok=no]) -AC_MSG_RESULT([$tcl_ok]) -if test $tcl_ok = yes; then - AC_DEFINE(ZIPFS_IN_TCL, 1, [Include ZIP filesystem?]) -fi AC_CHECK_TYPE([intptr_t], [ AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [ diff --git a/win/makefile.vc b/win/makefile.vc index ecfcecf..82dd655 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -1115,6 +1115,7 @@ install-libraries: tclConfig install-msgs install-tzdata @$(CPY) "$(GENERICDIR)\tclDecls.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclOO.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclOODecls.h" "$(INCLUDE_INSTALL_DIR)\" + @$(CPY) "$(GENERICDIR)\tclZipfs.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclPlatDecls.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclTomMath.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclTomMathDecls.h" "$(INCLUDE_INSTALL_DIR)\" -- cgit v0.12 From e39b986e81e3813d59d6eb18cf095c1f8ceac086 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 10:27:19 +0000 Subject: Code-cleanup: CONST -> const, don't use macro's like __REG_CONST and types like re_void any more. No change in functionality. --- generic/regcustom.h | 8 ------- generic/regex.h | 60 ++++++++++++++--------------------------------------- unix/Makefile.in | 2 +- win/tclWinChan.c | 2 +- 4 files changed, 18 insertions(+), 54 deletions(-) diff --git a/generic/regcustom.h b/generic/regcustom.h index 1c970ea..681b97d 100644 --- a/generic/regcustom.h +++ b/generic/regcustom.h @@ -60,12 +60,6 @@ #ifdef __REG_REGOFF_T #undef __REG_REGOFF_T #endif -#ifdef __REG_VOID_T -#undef __REG_VOID_T -#endif -#ifdef __REG_CONST -#undef __REG_CONST -#endif #ifdef __REG_NOFRONT #undef __REG_NOFRONT #endif @@ -75,8 +69,6 @@ /* Interface types */ #define __REG_WIDE_T Tcl_UniChar #define __REG_REGOFF_T long /* Not really right, but good enough... */ -#define __REG_VOID_T void -#define __REG_CONST const /* Names and declarations */ #define __REG_WIDE_COMPILE TclReComp #define __REG_WIDE_EXEC TclReExec diff --git a/generic/regex.h b/generic/regex.h index 53450e5..8845f72 100644 --- a/generic/regex.h +++ b/generic/regex.h @@ -92,12 +92,6 @@ extern "C" { #ifdef __REG_REGOFF_T #undef __REG_REGOFF_T #endif -#ifdef __REG_VOID_T -#undef __REG_VOID_T -#endif -#ifdef __REG_CONST -#undef __REG_CONST -#endif #ifdef __REG_NOFRONT #undef __REG_NOFRONT #endif @@ -107,8 +101,6 @@ extern "C" { /* interface types */ #define __REG_WIDE_T Tcl_UniChar #define __REG_REGOFF_T long /* not really right, but good enough... */ -#define __REG_VOID_T void -#define __REG_CONST const /* names and declarations */ #define __REG_WIDE_COMPILE TclReComp #define __REG_WIDE_EXEC TclReExec @@ -134,26 +126,6 @@ typedef long regoff_t; #endif /* - * For benefit of old compilers, we offer the option of - * overriding the `void' type used to declare nonexistent return types. - */ -#ifdef __REG_VOID_T -typedef __REG_VOID_T re_void; -#else -typedef void re_void; -#endif - -/* - * Also for benefit of old compilers, can supply a macro which - * expands to a substitute for `const'. - */ -#ifndef __REG_CONST -#define __REG_CONST const -#endif - - - -/* * other interface types */ @@ -197,13 +169,13 @@ typedef struct { /* * compilation ^ #ifndef __REG_NOCHAR - ^ int re_comp(regex_t *, __REG_CONST char *, size_t, int); + ^ int re_comp(regex_t *, const char *, size_t, int); ^ #endif ^ #ifndef __REG_NOFRONT - ^ int regcomp(regex_t *, __REG_CONST char *, int); + ^ int regcomp(regex_t *, const char *, int); ^ #endif ^ #ifdef __REG_WIDE_T - ^ int __REG_WIDE_COMPILE(regex_t *, __REG_CONST __REG_WIDE_T *, size_t, int); + ^ int __REG_WIDE_COMPILE(regex_t *, const __REG_WIDE_T *, size_t, int); ^ #endif */ #define REG_BASIC 000000 /* BREs (convenience) */ @@ -228,14 +200,14 @@ typedef struct { /* * execution ^ #ifndef __REG_NOCHAR - ^ int re_exec(regex_t *, __REG_CONST char *, size_t, + ^ int re_exec(regex_t *, const char *, size_t, ^ rm_detail_t *, size_t, regmatch_t [], int); ^ #endif ^ #ifndef __REG_NOFRONT - ^ int regexec(regex_t *, __REG_CONST char *, size_t, regmatch_t [], int); + ^ int regexec(regex_t *, const char *, size_t, regmatch_t [], int); ^ #endif ^ #ifdef __REG_WIDE_T - ^ int __REG_WIDE_EXEC(regex_t *, __REG_CONST __REG_WIDE_T *, size_t, + ^ int __REG_WIDE_EXEC(regex_t *, const __REG_WIDE_T *, size_t, ^ rm_detail_t *, size_t, regmatch_t [], int); ^ #endif */ @@ -248,7 +220,7 @@ typedef struct { /* * misc generics (may be more functions here eventually) - ^ re_void regfree(regex_t *); + ^ void regfree(regex_t *); */ /* @@ -260,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, __REG_CONST regex_t *, char *, size_t); + ^ extern size_t regerror(int, const regex_t *, char *, size_t); */ #define REG_OKAY 0 /* no errors detected */ #define REG_NOMATCH 1 /* failed to match */ @@ -293,25 +265,25 @@ typedef struct { /* automatically gathered by fwd; do not hand-edit */ /* === regproto.h === */ #ifndef __REG_NOCHAR -int re_comp(regex_t *, __REG_CONST char *, size_t, int); +int re_comp(regex_t *, const char *, size_t, int); #endif #ifndef __REG_NOFRONT -int regcomp(regex_t *, __REG_CONST char *, int); +int regcomp(regex_t *, const char *, int); #endif #ifdef __REG_WIDE_T -MODULE_SCOPE int __REG_WIDE_COMPILE(regex_t *, __REG_CONST __REG_WIDE_T *, size_t, int); +MODULE_SCOPE int __REG_WIDE_COMPILE(regex_t *, const __REG_WIDE_T *, size_t, int); #endif #ifndef __REG_NOCHAR -int re_exec(regex_t *, __REG_CONST char *, size_t, rm_detail_t *, size_t, regmatch_t [], int); +int re_exec(regex_t *, const char *, size_t, rm_detail_t *, size_t, regmatch_t [], int); #endif #ifndef __REG_NOFRONT -int regexec(regex_t *, __REG_CONST char *, size_t, regmatch_t [], int); +int regexec(regex_t *, const char *, size_t, regmatch_t [], int); #endif #ifdef __REG_WIDE_T -MODULE_SCOPE int __REG_WIDE_EXEC(regex_t *, __REG_CONST __REG_WIDE_T *, size_t, rm_detail_t *, 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 re_void regfree(regex_t *); -MODULE_SCOPE size_t regerror(int, __REG_CONST regex_t *, char *, size_t); +MODULE_SCOPE void regfree(regex_t *); +MODULE_SCOPE size_t regerror(int, const regex_t *, char *, size_t); /* automatically gathered by fwd; do not hand-edit */ /* =====^!^===== end forwards =====^!^===== */ diff --git a/unix/Makefile.in b/unix/Makefile.in index da43c5d..bc73118 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -1828,7 +1828,7 @@ gendate: # -e 's?SCCSID?RCS: @(#) ?' \ # -e '/#ifdef __STDC__/,/#endif/d' -e '/TclDateerrlab:/d' \ # -e '/TclDatenewstate:/d' -e '/#pragma/d' \ -# -e '/#include /d' -e 's/const /CONST /g' \ +# -e '/#include /d' \ # -e '/#define YYNEW/s/malloc/TclDateAlloc/g' \ # -e '/#define YYENLARGE/,/realloc/s/realloc/TclDateRealloc/g' \ # $(GENERIC_DIR)/tclDate.c diff --git a/win/tclWinChan.c b/win/tclWinChan.c index cca0dab..78b510b 100644 --- a/win/tclWinChan.c +++ b/win/tclWinChan.c @@ -95,7 +95,7 @@ static void FileThreadActionProc(ClientData instanceData, static int FileTruncateProc(ClientData instanceData, Tcl_WideInt length); static DWORD FileGetType(HANDLE handle); -static int NativeIsComPort(CONST TCHAR *nativeName); +static int NativeIsComPort(const TCHAR *nativeName); /* * This structure describes the channel type structure for file based IO. */ -- cgit v0.12 From 4d007159025e0fc8ea75aae346bc7e6588e391c2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 10:49:36 +0000 Subject: CONST -> const --- generic/tclZipfs.h | 6 ++--- generic/zipfs.c | 68 +++++++++++++++++++++++++++--------------------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/generic/tclZipfs.h b/generic/tclZipfs.h index bf3a3cb..75dcb13 100644 --- a/generic/tclZipfs.h +++ b/generic/tclZipfs.h @@ -44,9 +44,9 @@ extern "C" { #endif #endif -ZIPFSAPI int Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, - CONST char *mntpt, CONST char *passwd); -ZIPFSAPI int Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname); +ZIPFSAPI int Zipfs_Mount(Tcl_Interp *interp, const char *zipname, + const char *mntpt, const char *passwd); +ZIPFSAPI int Zipfs_Unmount(Tcl_Interp *interp, const char *zipname); ZIPFSAPI int Zipfs_Init(Tcl_Interp *interp); ZIPFSAPI int Zipfs_SafeInit(Tcl_Interp *interp); diff --git a/generic/zipfs.c b/generic/zipfs.c index 6d49f4f..a9f0a39 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -109,7 +109,7 @@ #if defined(_WIN32) || defined(_WIN64) #define HAS_DRIVES 1 -static CONST char drvletters[] = +static const char drvletters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; #else #define HAS_DRIVES 0 @@ -223,7 +223,7 @@ static struct { * For password rotation. */ -static CONST char pwrot[16] = { +static const char pwrot[16] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 }; @@ -232,7 +232,7 @@ static CONST char pwrot[16] = { * Table to compute CRC32. */ -static CONST unsigned int crc32tab[256] = { +static const unsigned int crc32tab[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, @@ -458,10 +458,10 @@ ToDosDate(time_t when) */ static int -CountSlashes(CONST char *string) +CountSlashes(const char *string) { int count = 0; - CONST char *p = string; + const char *p = string; while (*p != '\0') { if (*p == '/') { @@ -491,7 +491,7 @@ CountSlashes(CONST char *string) */ static char * -CanonicalPath(CONST char *root, CONST char *tail, Tcl_DString *dsPtr) +CanonicalPath(const char *root, const char *tail, Tcl_DString *dsPtr) { char *path; int i, j, c, isunc = 0; @@ -598,7 +598,7 @@ CanonicalPath(CONST char *root, CONST char *tail, Tcl_DString *dsPtr) */ static char * -AbsolutePath(CONST char *path, +AbsolutePath(const char *path, #if HAS_DRIVES int *drvPtr, #endif @@ -832,7 +832,7 @@ ZipFSCloseArchive(Tcl_Interp *interp, ZipFile *zf) */ static int -ZipFSOpenArchive(Tcl_Interp *interp, CONST char *zipname, int needZip, +ZipFSOpenArchive(Tcl_Interp *interp, const char *zipname, int needZip, ZipFile *zf) { int i; @@ -1049,8 +1049,8 @@ error: */ int -Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, - CONST char *passwd) +Zipfs_Mount(Tcl_Interp *interp, const char *zipname, const char *mntpt, + const char *passwd) { char *realname, *p; int i, pwlen, isNew; @@ -1420,7 +1420,7 @@ nextent: */ int -Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname) +Zipfs_Unmount(Tcl_Interp *interp, const char *zipname) { char *realname; ZipFile *zf; @@ -1504,7 +1504,7 @@ done: static int ZipFSMountCmd(ClientData clientData, Tcl_Interp *interp, - int argc, CONST char **argv) + int argc, const char **argv) { if (argc > 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], @@ -1534,7 +1534,7 @@ ZipFSMountCmd(ClientData clientData, Tcl_Interp *interp, static int ZipFSUnmountCmd(ClientData clientData, Tcl_Interp *interp, - int argc, CONST char **argv) + int argc, const char **argv) { if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], @@ -1563,7 +1563,7 @@ ZipFSUnmountCmd(ClientData clientData, Tcl_Interp *interp, static int ZipFSMkKeyCmd(ClientData clientData, Tcl_Interp *interp, - int argc, CONST char **argv) + int argc, const char **argv) { int len, i = 0; char pwbuf[264]; @@ -1621,15 +1621,15 @@ ZipFSMkKeyCmd(ClientData clientData, Tcl_Interp *interp, */ static int -ZipAddFile(Tcl_Interp *interp, CONST char *path, CONST char *name, - Tcl_Channel out, CONST char *passwd, +ZipAddFile(Tcl_Interp *interp, const char *path, const char *name, + Tcl_Channel out, const char *passwd, char *buf, int bufsize, Tcl_HashTable *fileHash) { Tcl_Channel in; Tcl_HashEntry *hPtr; ZipEntry *z; z_stream stream; - CONST char *zpath; + const char *zpath; int nbyte, nbytecompr, len, crc, flush, pos[3], zpathlen, olen; int mtime = 0, isNew, align = 0, cmeth; unsigned long keys[3], keys0[3]; @@ -1947,11 +1947,11 @@ seekErr: static int ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, - int isImg, int argc, CONST char **argv) + int isImg, int argc, const char **argv) { Tcl_Channel out; int len = 0, pwlen = 0, slen = 0, i, count, ret = TCL_ERROR, largc, pos[3]; - CONST char **largv; + const char **largv; Tcl_DString ds; ZipEntry *z; Tcl_HashEntry *hPtr; @@ -2056,7 +2056,7 @@ ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, slen = strlen(argv[3]); } for (i = 0; i < largc; i++) { - CONST char *name = largv[i]; + const char *name = largv[i]; if (slen > 0) { len = strlen(name); @@ -2080,7 +2080,7 @@ ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, pos[1] = Tcl_Tell(out); count = 0; for (i = 0; i < largc; i++) { - CONST char *name = largv[i]; + const char *name = largv[i]; if (slen > 0) { len = strlen(name); @@ -2175,7 +2175,7 @@ done: static int ZipFSMkZipCmd(ClientData clientData, Tcl_Interp *interp, - int argc, CONST char **argv) + int argc, const char **argv) { return ZipFSMkZipOrImgCmd(clientData, interp, 0, argc, argv); } @@ -2199,7 +2199,7 @@ ZipFSMkZipCmd(ClientData clientData, Tcl_Interp *interp, static int ZipFSMkImgCmd(ClientData clientData, Tcl_Interp *interp, - int argc, CONST char **argv) + int argc, const char **argv) { return ZipFSMkZipOrImgCmd(clientData, interp, 1, argc, argv); } @@ -2224,7 +2224,7 @@ ZipFSMkImgCmd(ClientData clientData, Tcl_Interp *interp, static int ZipFSExistsObjCmd(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) + int objc, Tcl_Obj *const objv[]) { char *filename; int exists; @@ -2262,7 +2262,7 @@ ZipFSExistsObjCmd(ClientData clientData, Tcl_Interp *interp, static int ZipFSInfoObjCmd(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) + int objc, Tcl_Obj *const objv[]) { char *filename; ZipEntry *z; @@ -2307,7 +2307,7 @@ ZipFSInfoObjCmd(ClientData clientData, Tcl_Interp *interp, static int ZipFSListObjCmd(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) + int objc, Tcl_Obj *const objv[]) { char *pattern = NULL; Tcl_RegExp regexp = NULL; @@ -2496,7 +2496,7 @@ ZipChannelRead(ClientData instanceData, char *buf, int toRead, int *errloc) */ static int -ZipChannelWrite(ClientData instanceData, CONST char *buf, +ZipChannelWrite(ClientData instanceData, const char *buf, int toWrite, int *errloc) { ZipChannel *info = (ZipChannel *) instanceData; @@ -3176,7 +3176,7 @@ Zip_FSFilesystemSeparatorProc(Tcl_Obj *pathPtr) static int Zip_FSMatchInDirectoryProc(Tcl_Interp* interp, Tcl_Obj *result, - Tcl_Obj *pathPtr, CONST char *pattern, + Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types) { Tcl_HashEntry *hPtr; @@ -3606,10 +3606,10 @@ Zip_FSChdirProc(Tcl_Obj *pathPtr) *------------------------------------------------------------------------- */ -static CONST char *CONST86 * +static const char *const * Zip_FSFileAttrStringsProc(Tcl_Obj *pathPtr, Tcl_Obj** objPtrRef) { - static CONST char *attrs[] = { + static const char *const attrs[] = { "-uncompsize", "-compsize", "-offset", @@ -3885,7 +3885,7 @@ static int Zipfs_doInit(Tcl_Interp *interp, int safe) { #ifdef HAVE_ZLIB - static CONST char findproc[] = + static const char findproc[] = "proc ::zipfs::find dir {\n" " set result {}\n" " if {[catch {glob -directory $dir -tails -nocomplain * .*} list]} {\n" @@ -4009,14 +4009,14 @@ Zipfs_SafeInit(Tcl_Interp *interp) */ int -Zipfs_Mount(Tcl_Interp *interp, CONST char *zipname, CONST char *mntpt, - CONST char *passwd) +Zipfs_Mount(Tcl_Interp *interp, const char *zipname, const char *mntpt, + const char *passwd) { return Zipfs_doInit(interp, 1); } int -Zipfs_Unmount(Tcl_Interp *interp, CONST char *zipname) +Zipfs_Unmount(Tcl_Interp *interp, const char *zipname) { return Zipfs_doInit(interp, 1); } -- cgit v0.12 From 8ecd6aeb5b622ad2cc8c4690880e066c60abec54 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 11:29:38 +0000 Subject: Make it compile warning-free with MSVC compiler (VS2013, at least). Other tweaks. --- generic/tclPkgConfig.c | 20 -------------------- generic/zipfs.c | 31 ++++++++++++++++--------------- unix/Makefile.in | 3 +-- unix/tclLoadDl.c | 40 +--------------------------------------- unix/tclUnixFCmd.c | 21 --------------------- unix/tclUnixInit.c | 4 ---- win/makefile.vc | 6 +++++- 7 files changed, 23 insertions(+), 102 deletions(-) diff --git a/generic/tclPkgConfig.c b/generic/tclPkgConfig.c index 3f8178e..466d535 100644 --- a/generic/tclPkgConfig.c +++ b/generic/tclPkgConfig.c @@ -100,35 +100,19 @@ static Tcl_Config const cfg[] = { /* Runtime paths to various stuff */ -#ifdef ANDROID - {"libdir,runtime", ""}, - {"bindir,runtime", ""}, - {"scriptdir,runtime", ""}, - {"includedir,runtime", ""}, - {"docdir,runtime", ""}, -#else {"libdir,runtime", CFG_RUNTIME_LIBDIR}, {"bindir,runtime", CFG_RUNTIME_BINDIR}, {"scriptdir,runtime", CFG_RUNTIME_SCRDIR}, {"includedir,runtime", CFG_RUNTIME_INCDIR}, {"docdir,runtime", CFG_RUNTIME_DOCDIR}, -#endif /* Installation paths to various stuff */ -#ifdef ANDROID - {"libdir,install", ""}, - {"bindir,install", ""}, - {"scriptdir,install", ""}, - {"includedir,install", ""}, - {"docdir,install", ""}, -#else {"libdir,install", CFG_INSTALL_LIBDIR}, {"bindir,install", CFG_INSTALL_BINDIR}, {"scriptdir,install", CFG_INSTALL_SCRDIR}, {"includedir,install", CFG_INSTALL_INCDIR}, {"docdir,install", CFG_INSTALL_DOCDIR}, -#endif /* Last entry, closes the array */ {NULL, NULL} @@ -139,10 +123,6 @@ TclInitEmbeddedConfigurationInformation( Tcl_Interp *interp) /* Interpreter the configuration command is * registered in. */ { -#if defined(ANDROID) && !defined(TCL_CFGVAL_ENCODING) -#define TCL_CFGVAL_ENCODING "utf-8" -#endif - Tcl_RegisterConfig(interp, "tcl", cfg, TCL_CFGVAL_ENCODING); } diff --git a/generic/zipfs.c b/generic/zipfs.c index a9f0a39..67390a6 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -2561,19 +2561,19 @@ ZipChannelSeek(ClientData instanceData, long offset, int mode, int *errloc) *errloc = EINVAL; return -1; } + if (offset < 0) { + *errloc = EINVAL; + return -1; + } if (info->iswr) { - if (offset > info->nmax) { + if ((unsigned long) offset > info->nmax) { *errloc = EINVAL; return -1; } - if (offset > info->nbyte) { + if ((unsigned long) offset > info->nbyte) { info->nbyte = offset; } - } else if (offset > info->nbyte) { - *errloc = EINVAL; - return -1; - } - if (offset < 0) { + } else if ((unsigned long) offset > info->nbyte) { *errloc = EINVAL; return -1; } @@ -2772,12 +2772,12 @@ merror0: info->nbyte = 0; } else { if (z->data != NULL) { - i = z->nbyte; - if (i > info->nmax) { - i = info->nmax; + unsigned int j = z->nbyte; + if (j > info->nmax) { + j = info->nmax; } - memcpy(info->ubuf, z->data, i); - info->nbyte = i; + memcpy(info->ubuf, z->data, j); + info->nbyte = j; } else { unsigned char *zbuf = z->zipfile->data + z->offset; @@ -2809,15 +2809,16 @@ merror0: stream.opaque = Z_NULL; stream.avail_in = z->nbytecompr; if (z->isenc) { + unsigned int j; stream.avail_in -= 12; cbuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in); if (cbuf == NULL) { goto merror0; } - for (i = 0; i < stream.avail_in; i++) { - ch = info->ubuf[i]; - cbuf[i] = zdecode(info->keys, crc32tab, ch); + for (j = 0; j < stream.avail_in; j++) { + ch = info->ubuf[j]; + cbuf[j] = zdecode(info->keys, crc32tab, ch); } stream.next_in = cbuf; } else { diff --git a/unix/Makefile.in b/unix/Makefile.in index 3e4cfc7..d65dceb 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -383,8 +383,7 @@ GENERIC_HDRS = \ $(GENERIC_DIR)/tclPatch.h \ $(GENERIC_DIR)/tclPlatDecls.h \ $(GENERIC_DIR)/tclPort.h \ - $(GENERIC_DIR)/tclRegexp.h \ - $(GENERIC_DIR)/tclZipfs.h + $(GENERIC_DIR)/tclRegexp.h GENERIC_SRCS = \ $(GENERIC_DIR)/regcomp.c \ diff --git a/unix/tclLoadDl.c b/unix/tclLoadDl.c index bb2361c..aec071c 100644 --- a/unix/tclLoadDl.c +++ b/unix/tclLoadDl.c @@ -97,11 +97,7 @@ TclpDlopen( } else { dlopenflags |= RTLD_NOW; } - if (native == NULL) { - handle = NULL; - } else { - handle = dlopen(native, dlopenflags); - } + handle = dlopen(native, dlopenflags); if (handle == NULL) { /* * Let the OS loader examine the binary search path for whatever @@ -119,41 +115,7 @@ TclpDlopen( handle = dlopen(native, dlopenflags); Tcl_DStringFree(&ds); } -#ifdef ANDROID - /* - * If not an absolute or relative path, try to load - * from $INTERNAL_STORAGE/../lib (the place where the - * system has installed bundled .so files from the .APK) - */ - if (handle == NULL) { - native = Tcl_GetString(pathPtr); - if ((native != NULL) && (strchr(native, '/') == NULL)) { - char *storage = getenv("INTERNAL_STORAGE"); - Tcl_DString ds2; - if ((storage != NULL) && (storage[0] != '\0')) { - Tcl_DStringInit(&ds2); - Tcl_DStringAppend(&ds2, storage, -1); - Tcl_DStringAppend(&ds2, "/../lib/", -1); - Tcl_DStringAppend(&ds2, native, -1); - handle = dlopen(Tcl_DStringValue(&ds2), RTLD_NOW | RTLD_GLOBAL); - Tcl_DStringFree(&ds2); - } - if (handle == NULL) { - storage = getenv("TK_TCL_WISH_LD_LIBS"); - if ((storage != NULL) && (storage[0] != '\0')) { - Tcl_DStringInit(&ds2); - Tcl_DStringAppend(&ds2, storage, -1); - Tcl_DStringAppend(&ds2, "/", -1); - Tcl_DStringAppend(&ds2, native, -1); - handle = - dlopen(Tcl_DStringValue(&ds2), RTLD_NOW | RTLD_GLOBAL); - Tcl_DStringFree(&ds2); - } - } - } - } - #endif if (handle == NULL) { /* * Write the string to a variable first to work around a compiler bug diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 0193dae..3b1b6ca 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -465,9 +465,6 @@ DoCopyFile( /* Used to determine filetype. */ { Tcl_StatBuf dstStatBuf; -#ifdef ANDROID - int ret; -#endif if (S_ISDIR(statBufPtr->st_mode)) { errno = EISDIR; @@ -523,15 +520,7 @@ DoCopyFile( if (mkfifo(dst, statBufPtr->st_mode) < 0) { /* INTL: Native. */ return TCL_ERROR; } -#ifdef ANDROID - ret = CopyFileAtts(src, dst, statBufPtr); - if (ret != TCL_OK && errno == EPERM) { - ret = TCL_OK; - } - return ret; -#else return CopyFileAtts(src, dst, statBufPtr); -#endif default: return TclUnixCopyFile(src, dst, statBufPtr, 0); } @@ -640,11 +629,6 @@ TclUnixCopyFile( return TCL_ERROR; } if (!dontCopyAtts && CopyFileAtts(src, dst, statBufPtr) == TCL_ERROR) { -#ifdef ANDROID - if (errno == EPERM) { - return TCL_OK; - } -#endif /* * The copy succeeded, but setting the permissions failed, so be in a * consistent state, we remove the file that was created by the copy. @@ -1219,11 +1203,6 @@ TraversalCopy( Tcl_DStringValue(dstPtr), statBufPtr) == TCL_OK) { return TCL_OK; } -#ifdef ANDROID - if (errno == EPERM) { - return TCL_OK; - } -#endif break; } diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index 5e4ef0a..5fc0035 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -583,14 +583,10 @@ TclpInitLibraryPath( void TclpSetInitialEncodings(void) { -#ifdef ANDROID - Tcl_SetSystemEncoding(NULL, "utf-8"); -#else Tcl_DString encodingName; Tcl_SetSystemEncoding(NULL, Tcl_GetEncodingNameFromEnvironment(&encodingName)); Tcl_DStringFree(&encodingName); -#endif } void diff --git a/win/makefile.vc b/win/makefile.vc index 82dd655..2e04f15 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -344,7 +344,8 @@ COREOBJS = \ $(TMP_DIR)\tclUtf.obj \ $(TMP_DIR)\tclUtil.obj \ $(TMP_DIR)\tclVar.obj \ - $(TMP_DIR)\tclZlib.obj + $(TMP_DIR)\tclZlib.obj \ + $(TMP_DIR)\zipfs.obj ZLIBOBJS = \ $(TMP_DIR)\adler32.obj \ @@ -942,6 +943,9 @@ $(TMP_DIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c $(TMP_DIR)\tclZlib.obj: $(GENERICDIR)\tclZlib.c $(cc32) $(TCL_CFLAGS) -I$(COMPATDIR)\zlib -DBUILD_tcl -Fo$@ $? +$(TMP_DIR)\zipfs.obj: $(GENERICDIR)\zipfs.c + $(cc32) $(TCL_CFLAGS) -I$(COMPATDIR)\zlib -DBUILD_tcl -Fo$@ $? + $(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c $(cc32) -DBUILD_tcl $(TCL_CFLAGS) \ -DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \ -- cgit v0.12 From 1c3288f038d8b2f9883e3b9f63f37f42e6811969 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 11:59:08 +0000 Subject: Finally, make it compile warning-free using Visual Studio, if ZIPFS_IN_TCL is defined --- generic/zipfs.c | 17 ++++++++--------- win/makefile.vc | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/generic/zipfs.c b/generic/zipfs.c index 67390a6..6179542 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -9,6 +9,9 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tclInt.h" +#include "tclFileSystem.h" +#include "tclZipfs.h" #if !defined(_WIN32) && !defined(_WIN64) #include #endif @@ -18,15 +21,10 @@ #include #include #include + #ifdef HAVE_ZLIB #include "zlib.h" #include "zcrypt.h" -#endif -#include "tclInt.h" -#include "tclFileSystem.h" -#include "tclZipfs.h" - -#ifdef HAVE_ZLIB /* * Various constants and offsets found in ZIP archive files. @@ -2904,6 +2902,7 @@ cerror0: z_stream stream; int err; unsigned char *ubuf = NULL; + unsigned int j; memset(&stream, 0, sizeof (stream)); stream.zalloc = Z_NULL; @@ -2917,9 +2916,9 @@ cerror0: info->ubuf = NULL; goto merror; } - for (i = 0; i < stream.avail_in; i++) { - ch = info->ubuf[i]; - ubuf[i] = zdecode(info->keys, crc32tab, ch); + for (j = 0; j < stream.avail_in; j++) { + ch = info->ubuf[j]; + ubuf[j] = zdecode(info->keys, crc32tab, ch); } stream.next_in = ubuf; } else { diff --git a/win/makefile.vc b/win/makefile.vc index 2e04f15..80682b9 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -504,7 +504,7 @@ crt = -MT !endif TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" -I"$(TOMMATHDIR)" -TCL_DEFINES = -DTCL_TOMMATH -DMP_PREC=4 -Dinline=__inline -DHAVE_ZLIB=1 +TCL_DEFINES = -DTCL_TOMMATH -DMP_PREC=4 -Dinline=__inline -DHAVE_ZLIB=1 -DZIPFS_IN_TCL BASE_CFLAGS = $(cflags) $(cdebug) $(crt) $(TCL_INCLUDES) $(TCL_DEFINES) CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE TCL_CFLAGS = $(BASE_CFLAGS) $(OPTDEFINES) -- cgit v0.12 From 63b07461da87c89858482b065e62b2d31d765c40 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 12:43:54 +0000 Subject: Fix android compilation (zipfsFilesystem.loadFileProc is a constant, so it cannot be written) --- generic/zipfs.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/generic/zipfs.c b/generic/zipfs.c index 6179542..b54d5a2 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -2807,7 +2807,7 @@ merror0: stream.opaque = Z_NULL; stream.avail_in = z->nbytecompr; if (z->isenc) { - unsigned int j; + unsigned int j; stream.avail_in -= 12; cbuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in); @@ -3734,7 +3734,6 @@ Zip_FSFilesystemPathTypeProc(Tcl_Obj *pathPtr) return Tcl_NewStringObj("zip", -1); } -#ifndef ANDROID /* *------------------------------------------------------------------------- @@ -3762,6 +3761,14 @@ static int Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, Tcl_FSUnloadFileProc **unloadProcPtr, int flags) { +#ifdef ANDROID + /* + * Force loadFileProc to native implementation since the + * package manger already extracted the shared libraries + * from the APK at install time. + */ + return tclNativeFilesystem.loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); +#else Tcl_FSLoadFileProc2 *loadFileProc; Tcl_Obj *altPath = NULL; int ret = -1; @@ -3813,8 +3820,8 @@ Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, Tcl_DecrRefCount(altPath); } return ret; -} #endif +} /* @@ -3852,11 +3859,7 @@ const Tcl_Filesystem zipfsFilesystem = { NULL, /* renameFileProc */ NULL, /* copyDirectoryProc */ NULL, /* lstatProc */ -#ifdef ANDROID - NULL, /* loadFileProc */ -#else (Tcl_FSLoadFileProc *) Zip_FSLoadFile, -#endif NULL, /* getCwdProc */ Zip_FSChdirProc, }; @@ -3922,14 +3925,6 @@ Zipfs_doInit(Tcl_Interp *interp, int safe) Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, &t); Tcl_MutexUnlock(&ZipFSMutex); #endif -#ifdef ANDROID - /* - * Force loadFileProc to native implementation since the - * package manger already extracted the shared libraries - * from the APK at install time. - */ - zipfsFilesystem.loadFileProc = tclNativeFilesystem.loadFileProc; -#endif Tcl_FSRegister(NULL, &zipfsFilesystem); Tcl_InitHashTable(&ZipFS.fileHash, TCL_STRING_KEYS); Tcl_InitHashTable(&ZipFS.zipHash, TCL_STRING_KEYS); -- cgit v0.12 From 56c5833c4ab4b228c29eb2ade13ba727e1e45da5 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 14:01:57 +0000 Subject: Eliminate all use of ZIPFS_IN_TCL --- generic/tclIOUtil.c | 6 ------ generic/tclZipfs.h | 25 ++++--------------------- generic/zipfs.c | 42 +++++++++++++++++++----------------------- win/makefile.vc | 2 +- 4 files changed, 24 insertions(+), 51 deletions(-) diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 0ef6d3b..79ec894 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -191,9 +191,7 @@ const Tcl_Filesystem tclNativeFilesystem = { TclpObjChdir }; -#ifdef ZIPFS_IN_TCL MODULE_SCOPE Tcl_Filesystem zipfsFilesystem; -#endif /* * Define the tail of the linked list. Note that for unconventional uses of @@ -1415,7 +1413,6 @@ TclFSNormalizeToUniquePath( Claim(); for (fsRecPtr=firstFsRecPtr; fsRecPtr!=NULL; fsRecPtr=fsRecPtr->nextPtr) { -#ifdef ZIPFS_IN_TCL if (fsRecPtr->fsPtr == &zipfsFilesystem) { ClientData clientData = NULL; /* @@ -1432,7 +1429,6 @@ TclFSNormalizeToUniquePath( } continue; } -#endif if (fsRecPtr->fsPtr != &tclNativeFilesystem) { continue; } @@ -1457,11 +1453,9 @@ TclFSNormalizeToUniquePath( if (fsRecPtr->fsPtr == &tclNativeFilesystem) { continue; } -#ifdef ZIPFS_IN_TCL if (fsRecPtr->fsPtr == &zipfsFilesystem) { continue; } -#endif if (fsRecPtr->fsPtr->normalizePathProc != NULL) { startAt = fsRecPtr->fsPtr->normalizePathProc(interp, pathPtr, diff --git a/generic/tclZipfs.h b/generic/tclZipfs.h index 75dcb13..bcf6cef 100644 --- a/generic/tclZipfs.h +++ b/generic/tclZipfs.h @@ -22,33 +22,16 @@ extern "C" { # define ZIPFSAPI extern #endif -#ifdef ZIPFS_IN_TK -#define Zipfs_Mount Tkzipfs_Mount -#define Zipfs_Unmount Tkzipfs_Unmount -#define Zipfs_Init Tkzipfs_Init -#define Zipfs_SafeInit Tkzipfs_SafeInit -#ifdef BUILD_tk -# undef ZIPFSAPI -# define ZIPFSAPI DLLEXPORT -#endif -#endif - -#ifdef ZIPFS_IN_TCL -#define Zipfs_Mount Tclzipfs_Mount -#define Zipfs_Unmount Tclzipfs_Unmount -#define Zipfs_Init Tclzipfs_Init -#define Zipfs_SafeInit Tclzipfs_SafeInit #ifdef BUILD_tcl # undef ZIPFSAPI # define ZIPFSAPI DLLEXPORT #endif -#endif -ZIPFSAPI int Zipfs_Mount(Tcl_Interp *interp, const char *zipname, +ZIPFSAPI int Tclzipfs_Mount(Tcl_Interp *interp, const char *zipname, const char *mntpt, const char *passwd); -ZIPFSAPI int Zipfs_Unmount(Tcl_Interp *interp, const char *zipname); -ZIPFSAPI int Zipfs_Init(Tcl_Interp *interp); -ZIPFSAPI int Zipfs_SafeInit(Tcl_Interp *interp); +ZIPFSAPI int Tclzipfs_Unmount(Tcl_Interp *interp, const char *zipname); +ZIPFSAPI int Tclzipfs_Init(Tcl_Interp *interp); +ZIPFSAPI int Tclzipfs_SafeInit(Tcl_Interp *interp); #ifdef __cplusplus } diff --git a/generic/zipfs.c b/generic/zipfs.c index b54d5a2..144be30 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -1031,7 +1031,7 @@ error: /* *------------------------------------------------------------------------- * - * Zipfs_Mount -- + * Tclzipfs_Mount -- * * This procedure is invoked to mount a given ZIP archive file on * a given mountpoint with optional ZIP password. @@ -1047,7 +1047,7 @@ error: */ int -Zipfs_Mount(Tcl_Interp *interp, const char *zipname, const char *mntpt, +Tclzipfs_Mount(Tcl_Interp *interp, const char *zipname, const char *mntpt, const char *passwd) { char *realname, *p; @@ -1404,7 +1404,7 @@ nextent: /* *------------------------------------------------------------------------- * - * Zipfs_Unmount -- + * Tclzipfs_Unmount -- * * This procedure is invoked to unmount a given ZIP archive. * @@ -1418,7 +1418,7 @@ nextent: */ int -Zipfs_Unmount(Tcl_Interp *interp, const char *zipname) +Tclzipfs_Unmount(Tcl_Interp *interp, const char *zipname) { char *realname; ZipFile *zf; @@ -1509,7 +1509,7 @@ ZipFSMountCmd(ClientData clientData, Tcl_Interp *interp, " ?zipfile ?mountpoint? ?password???\"", 0); return TCL_ERROR; } - return Zipfs_Mount(interp, (argc > 1) ? argv[1] : NULL, + return Tclzipfs_Mount(interp, (argc > 1) ? argv[1] : NULL, (argc > 2) ? argv[2] : NULL, (argc > 3) ? argv[3] : NULL); } @@ -1539,7 +1539,7 @@ ZipFSUnmountCmd(ClientData clientData, Tcl_Interp *interp, " zipfile\"", (char *) NULL); return TCL_ERROR; } - return Zipfs_Unmount(interp, argv[1]); + return Tclzipfs_Unmount(interp, argv[1]); } /* @@ -3870,7 +3870,7 @@ const Tcl_Filesystem zipfsFilesystem = { /* *------------------------------------------------------------------------- * - * Zipfs_doInit -- + * doInit -- * * Perform per interpreter initialization of this module. * @@ -3885,7 +3885,7 @@ const Tcl_Filesystem zipfsFilesystem = { */ static int -Zipfs_doInit(Tcl_Interp *interp, int safe) +doInit(Tcl_Interp *interp, int safe) { #ifdef HAVE_ZLIB static const char findproc[] = @@ -3929,14 +3929,10 @@ Zipfs_doInit(Tcl_Interp *interp, int safe) Tcl_InitHashTable(&ZipFS.fileHash, TCL_STRING_KEYS); Tcl_InitHashTable(&ZipFS.zipHash, TCL_STRING_KEYS); ZipFS.initialized = ZipFS.idCount = 1; -#if defined(ZIPFS_IN_TCL) || defined(ZIPFS_IN_TK) - Tcl_StaticPackage(interp, "zipfs", Zipfs_Init, Zipfs_SafeInit); -#endif + Tcl_StaticPackage(interp, "zipfs", Tclzipfs_Init, Tclzipfs_SafeInit); } Unlock(); -#if !defined(ZIPFS_IN_TCL) && !defined(ZIPFS_IN_TK) Tcl_PkgProvide(interp, "zipfs", "1.0"); -#endif if (!safe) { Tcl_CreateCommand(interp, "::zipfs::mount", ZipFSMountCmd, 0, 0); Tcl_CreateCommand(interp, "::zipfs::unmount", ZipFSUnmountCmd, 0, 0); @@ -3964,7 +3960,7 @@ Zipfs_doInit(Tcl_Interp *interp, int safe) /* *------------------------------------------------------------------------- * - * Zipfs_Init, Zipfs_SafeInit -- + * Tclzipfs_Init, Tclzipfs_SafeInit -- * * These functions are invoked to perform per interpreter initialization * of this module. @@ -3980,15 +3976,15 @@ Zipfs_doInit(Tcl_Interp *interp, int safe) */ int -Zipfs_Init(Tcl_Interp *interp) +Tclzipfs_Init(Tcl_Interp *interp) { - return Zipfs_doInit(interp, 0); + return doInit(interp, 0); } int -Zipfs_SafeInit(Tcl_Interp *interp) +Tclzipfs_SafeInit(Tcl_Interp *interp) { - return Zipfs_doInit(interp, 1); + return doInit(interp, 1); } #ifndef HAVE_ZLIB @@ -3996,7 +3992,7 @@ Zipfs_SafeInit(Tcl_Interp *interp) /* *------------------------------------------------------------------------- * - * Zipfs_Mount, Zipfs_Unmount -- + * Tclzipfs_Mount, Tclzipfs_Unmount -- * * Dummy version when no ZLIB support available. * @@ -4004,16 +4000,16 @@ Zipfs_SafeInit(Tcl_Interp *interp) */ int -Zipfs_Mount(Tcl_Interp *interp, const char *zipname, const char *mntpt, +Tclzipfs_Mount(Tcl_Interp *interp, const char *zipname, const char *mntpt, const char *passwd) { - return Zipfs_doInit(interp, 1); + return doInit(interp, 1); } int -Zipfs_Unmount(Tcl_Interp *interp, const char *zipname) +Tclzipfs_Unmount(Tcl_Interp *interp, const char *zipname) { - return Zipfs_doInit(interp, 1); + return doInit(interp, 1); } #endif diff --git a/win/makefile.vc b/win/makefile.vc index 80682b9..2e04f15 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -504,7 +504,7 @@ crt = -MT !endif TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" -I"$(TOMMATHDIR)" -TCL_DEFINES = -DTCL_TOMMATH -DMP_PREC=4 -Dinline=__inline -DHAVE_ZLIB=1 -DZIPFS_IN_TCL +TCL_DEFINES = -DTCL_TOMMATH -DMP_PREC=4 -Dinline=__inline -DHAVE_ZLIB=1 BASE_CFLAGS = $(cflags) $(cdebug) $(crt) $(TCL_INCLUDES) $(TCL_DEFINES) CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE TCL_CFLAGS = $(BASE_CFLAGS) $(OPTDEFINES) -- cgit v0.12 From 3c03a492f903c82b544cd54fb5b8f2e2e374a150 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 15:21:21 +0000 Subject: Start with a few simple basic test-cases --- generic/zipfs.c | 13 +++-------- tests/zipfs.test | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ unix/tclAppInit.c | 5 +++++ win/tclAppInit.c | 5 +++++ 4 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 tests/zipfs.test diff --git a/generic/zipfs.c b/generic/zipfs.c index 144be30..3c330b2 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -3761,15 +3761,15 @@ static int Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, Tcl_FSUnloadFileProc **unloadProcPtr, int flags) { + Tcl_FSLoadFileProc2 *loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc; #ifdef ANDROID /* * Force loadFileProc to native implementation since the * package manger already extracted the shared libraries * from the APK at install time. */ - return tclNativeFilesystem.loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); + return loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); #else - Tcl_FSLoadFileProc2 *loadFileProc; Tcl_Obj *altPath = NULL; int ret = -1; @@ -3810,7 +3810,6 @@ Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, Tcl_DecrRefCount(objs[1]); } } - loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc; if (loadFileProc != NULL) { ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); } else { @@ -3885,8 +3884,7 @@ const Tcl_Filesystem zipfsFilesystem = { */ static int -doInit(Tcl_Interp *interp, int safe) -{ +doInit(Tcl_Interp *interp, int safe) { #ifdef HAVE_ZLIB static const char findproc[] = "proc ::zipfs::find dir {\n" @@ -3907,11 +3905,6 @@ doInit(Tcl_Interp *interp, int safe) " return [lsort $result]\n" "}\n"; -#ifdef USE_TCL_STUBS - if (Tcl_InitStubs(interp, "8.0", 0) == NULL) { - return TCL_ERROR; - } -#endif /* one-time initialization */ WriteLock(); if (!ZipFS.initialized) { diff --git a/tests/zipfs.test b/tests/zipfs.test new file mode 100644 index 0000000..e8112f5 --- /dev/null +++ b/tests/zipfs.test @@ -0,0 +1,67 @@ +# The file tests the tclZlib.c file. +# +# This file contains a collection of tests for one or more of the Tcl built-in +# commands. Sourcing this file into Tcl runs the tests and generates output +# for errors. No output means no errors were found. +# +# Copyright (c) 1996-1998 by Sun Microsystems, Inc. +# Copyright (c) 1998-1999 by Scriptics Corporation. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. + +if {"::tcltest" ni [namespace children]} { + package require tcltest 2.1 + namespace import -force ::tcltest::* +} + +testConstraint zlib [llength [info commands zlib]] + +test zipfs-1.1 {zipfs basics} -constraints zlib -body { + load {} zipfs + package require zipfs +} -result {1.0} + +test zipfs-1.2 {zipfs basics} -constraints zlib -returnCodes error -body { + ::zipfs::mount a b c d e f +} -result {wrong # args: should be "::zipfs::mount ?zipfile ?mountpoint? ?password???"} + +test zipfs-1.3 {zipfs basics} -constraints zlib -returnCodes error -body { + ::zipfs::unmount a b c d e f +} -result {wrong # args: should be "::zipfs::unmount zipfile"} + +test zipfs-1.4 {zipfs basics} -constraints zlib -returnCodes error -body { + ::zipfs::mkkey a b c d e f +} -result {wrong # args: should be "::zipfs::mkkey password"} + +test zipfs-1.5 {zipfs basics} -constraints zlib -returnCodes error -body { + ::zipfs::mkimg a b c d e f +} -result {wrong # args: should be "::zipfs::mkimg outfile indir ?strip? ?password? ?infile?"} + +test zipfs-1.6 {zipfs basics} -constraints zlib -returnCodes error -body { + ::zipfs::mkzip a b c d e f +} -result {wrong # args: should be "::zipfs::mkzip outfile indir ?strip? ?password?"} + +test zipfs-1.7 {zipfs basics} -constraints zlib -returnCodes error -body { + ::zipfs::exists a b c d e f +} -result {wrong # args: should be "::zipfs::exists filename"} + +test zipfs-1.8 {zipfs basics} -constraints zlib -returnCodes error -body { + ::zipfs::info a b c d e f +} -result {wrong # args: should be "::zipfs::info filename"} + +test zipfs-1.9 {zipfs basics} -constraints zlib -returnCodes error -body { + ::zipfs::list a b c d e f +} -result {wrong # args: should be "::zipfs::list ?(-glob|-regexp)? ?pattern?"} + + + + + + +::tcltest::cleanupTests +return + +# Local Variables: +# mode: tcl +# End: diff --git a/unix/tclAppInit.c b/unix/tclAppInit.c index 9bbc88b..40b10f3 100644 --- a/unix/tclAppInit.c +++ b/unix/tclAppInit.c @@ -17,6 +17,7 @@ #include "tcl.h" #ifdef TCL_TEST +#include "tclZipfs.h" extern Tcl_PackageInitProc Tcltest_Init; extern Tcl_PackageInitProc Tcltest_SafeInit; #endif /* TCL_TEST */ @@ -123,6 +124,10 @@ Tcl_AppInit( return TCL_ERROR; } Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit); + if (Tclzipfs_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "zipfs", Tclzipfs_Init, Tclzipfs_SafeInit); #endif /* TCL_TEST */ /* diff --git a/win/tclAppInit.c b/win/tclAppInit.c index e06eaf5..b821ca7 100644 --- a/win/tclAppInit.c +++ b/win/tclAppInit.c @@ -25,6 +25,7 @@ #include #ifdef TCL_TEST +#include "tclZipfs.h" extern Tcl_PackageInitProc Tcltest_Init; extern Tcl_PackageInitProc Tcltest_SafeInit; #endif /* TCL_TEST */ @@ -174,6 +175,10 @@ Tcl_AppInit( return TCL_ERROR; } Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit); + if (Tclzipfs_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "zipfs", Tclzipfs_Init, Tclzipfs_SafeInit); #endif /* TCL_TEST */ /* -- cgit v0.12 From a03e74efc1bbec20a5c2488448a8de28d9fb28fb Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 Dec 2015 21:25:40 +0000 Subject: USE_TCL_STUBS is not defined anyway --- generic/zipfs.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/generic/zipfs.c b/generic/zipfs.c index 3c330b2..1f126ce 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -12,6 +12,7 @@ #include "tclInt.h" #include "tclFileSystem.h" #include "tclZipfs.h" + #if !defined(_WIN32) && !defined(_WIN64) #include #endif @@ -2771,6 +2772,7 @@ merror0: } else { if (z->data != NULL) { unsigned int j = z->nbyte; + if (j > info->nmax) { j = info->nmax; } @@ -2808,6 +2810,7 @@ merror0: stream.avail_in = z->nbytecompr; if (z->isenc) { unsigned int j; + stream.avail_in -= 12; cbuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in); @@ -3761,14 +3764,20 @@ static int Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, Tcl_FSUnloadFileProc **unloadProcPtr, int flags) { - Tcl_FSLoadFileProc2 *loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc; + Tcl_FSLoadFileProc2 *loadFileProc; #ifdef ANDROID - /* - * Force loadFileProc to native implementation since the - * package manger already extracted the shared libraries - * from the APK at install time. - */ - return loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); + /* + * Force loadFileProc to native implementation since the + * package manger already extracted the shared libraries + * from the APK at install time. + */ + + loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc; + if (loadFileProc != NULL) { + return loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); + } + Tcl_SetErrno(ENOENT); + return -1; #else Tcl_Obj *altPath = NULL; int ret = -1; @@ -3810,6 +3819,7 @@ Zip_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, Tcl_DecrRefCount(objs[1]); } } + loadFileProc = (Tcl_FSLoadFileProc2 *) tclNativeFilesystem.loadFileProc; if (loadFileProc != NULL) { ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); } else { @@ -3869,7 +3879,7 @@ const Tcl_Filesystem zipfsFilesystem = { /* *------------------------------------------------------------------------- * - * doInit -- + * Zipfs_doInit -- * * Perform per interpreter initialization of this module. * @@ -3884,7 +3894,8 @@ const Tcl_Filesystem zipfsFilesystem = { */ static int -doInit(Tcl_Interp *interp, int safe) { +Zipfs_doInit(Tcl_Interp *interp, int safe) +{ #ifdef HAVE_ZLIB static const char findproc[] = "proc ::zipfs::find dir {\n" @@ -3971,13 +3982,13 @@ doInit(Tcl_Interp *interp, int safe) { int Tclzipfs_Init(Tcl_Interp *interp) { - return doInit(interp, 0); + return Zipfs_doInit(interp, 0); } int Tclzipfs_SafeInit(Tcl_Interp *interp) { - return doInit(interp, 1); + return Zipfs_doInit(interp, 1); } #ifndef HAVE_ZLIB @@ -3996,13 +4007,13 @@ int Tclzipfs_Mount(Tcl_Interp *interp, const char *zipname, const char *mntpt, const char *passwd) { - return doInit(interp, 1); + return Zipfs_doInit(interp, 1); } int Tclzipfs_Unmount(Tcl_Interp *interp, const char *zipname) { - return doInit(interp, 1); + return Zipfs_doInit(interp, 1); } #endif -- cgit v0.12 From 299924e512e6809f22f5fa3e4410fcc706ceec82 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 22 Dec 2015 09:11:57 +0000 Subject: Remove TIP #414 fragment, not strictly needed for the zipfs TIP. Add more zipfs test-cases --- generic/tcl.h | 7 ----- generic/tclEncoding.c | 23 +++------------- tests/zipfs.test | 73 ++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 64 insertions(+), 39 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index fed6b78..a08edde 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2424,13 +2424,6 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, * TODO - tommath stubs export goes here! */ -/* Tcl_InitSubsystems, see TIP #414 */ - -#ifndef USE_TCL_STUBS -EXTERN const char * Tcl_InitSubsystems(TCL_NORETURN1 - Tcl_PanicProc *panicProc); -#endif - /* * Public functions that are not accessible via the stubs table. * Tcl_GetMemoryInfo is needed for AOLserver. [Bug 1868171] diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 4020445..4edebcf 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1440,10 +1440,10 @@ Tcl_UtfToExternal( /* *--------------------------------------------------------------------------- * - * Tcl_InitSubsystems/Tcl_FindExecutable -- + * Tcl_FindExecutable -- * - * This function initializes everything needed for the Tcl library - * to be able to operate. + * This function computes the absolute path name of the current + * application, given its argv[0] value. * * Results: * None. @@ -1454,23 +1454,6 @@ Tcl_UtfToExternal( * *--------------------------------------------------------------------------- */ -MODULE_SCOPE const TclStubs tclStubs; - -static const struct { - const TclStubs *stubs; - const char version[16]; -} stubInfo = { - &tclStubs, TCL_PATCH_LEVEL -}; - -const char * -Tcl_InitSubsystems(TCL_NORETURN1 Tcl_PanicProc *panicProc) -{ - Tcl_SetPanicProc(panicProc); - TclInitSubsystems(); - return stubInfo.version; -} - #undef Tcl_FindExecutable void Tcl_FindExecutable( diff --git a/tests/zipfs.test b/tests/zipfs.test index e8112f5..3f53cf8 100644 --- a/tests/zipfs.test +++ b/tests/zipfs.test @@ -15,49 +15,98 @@ if {"::tcltest" ni [namespace children]} { namespace import -force ::tcltest::* } -testConstraint zlib [llength [info commands zlib]] +testConstraint zipfs [expr {[llength [info commands zlib]] && [regexp tcltest [info nameofexecutable]]}] -test zipfs-1.1 {zipfs basics} -constraints zlib -body { +test zipfs-1.1 {zipfs basics} -constraints zipfs -body { load {} zipfs +} -result {} + +test zipfs-1.2 {zipfs basics} -constraints zipfs -body { package require zipfs } -result {1.0} -test zipfs-1.2 {zipfs basics} -constraints zlib -returnCodes error -body { +test zipfs-1.3 {zipfs basics} -constraints zipfs -returnCodes error -body { ::zipfs::mount a b c d e f } -result {wrong # args: should be "::zipfs::mount ?zipfile ?mountpoint? ?password???"} -test zipfs-1.3 {zipfs basics} -constraints zlib -returnCodes error -body { +test zipfs-1.4 {zipfs basics} -constraints zipfs -returnCodes error -body { ::zipfs::unmount a b c d e f } -result {wrong # args: should be "::zipfs::unmount zipfile"} -test zipfs-1.4 {zipfs basics} -constraints zlib -returnCodes error -body { +test zipfs-1.5 {zipfs basics} -constraints zipfs -returnCodes error -body { ::zipfs::mkkey a b c d e f } -result {wrong # args: should be "::zipfs::mkkey password"} -test zipfs-1.5 {zipfs basics} -constraints zlib -returnCodes error -body { +test zipfs-1.6 {zipfs basics} -constraints zipfs -returnCodes error -body { ::zipfs::mkimg a b c d e f } -result {wrong # args: should be "::zipfs::mkimg outfile indir ?strip? ?password? ?infile?"} -test zipfs-1.6 {zipfs basics} -constraints zlib -returnCodes error -body { +test zipfs-1.7 {zipfs basics} -constraints zipfs -returnCodes error -body { ::zipfs::mkzip a b c d e f } -result {wrong # args: should be "::zipfs::mkzip outfile indir ?strip? ?password?"} -test zipfs-1.7 {zipfs basics} -constraints zlib -returnCodes error -body { +test zipfs-1.8 {zipfs basics} -constraints zipfs -returnCodes error -body { ::zipfs::exists a b c d e f } -result {wrong # args: should be "::zipfs::exists filename"} -test zipfs-1.8 {zipfs basics} -constraints zlib -returnCodes error -body { +test zipfs-1.9 {zipfs basics} -constraints zipfs -returnCodes error -body { ::zipfs::info a b c d e f } -result {wrong # args: should be "::zipfs::info filename"} -test zipfs-1.9 {zipfs basics} -constraints zlib -returnCodes error -body { +test zipfs-1.10 {zipfs basics} -constraints zipfs -returnCodes error -body { ::zipfs::list a b c d e f } -result {wrong # args: should be "::zipfs::list ?(-glob|-regexp)? ?pattern?"} +test zipfs-2.1 {zipfs mkzip empty archive} -constraints zipfs -returnCodes error -body { + ::zipfs::mkzip abc.zip $tcl_library/xxxx +} -result {empty archive} + +test zipfs-2.2 {zipfs mkzip} -constraints zipfs -body { + set pwd [pwd] + cd $tcl_library/encoding + ::zipfs::mkzip abc.zip . + ::zipfs::mount abc.zip /abc + ::zipfs::list -glob /abc/cp850.* +} -cleanup { + cd $pwd +} -result {/abc/cp850.enc} + +test zipfs-2.3 {zipfs unmount} -constraints zipfs -body { + ::zipfs::info /abc/cp850.enc +} -result [list $tcl_library/encoding/abc.zip 1090 527 39434] + +test zipfs-2.4 {zipfs unmount} -constraints zipfs -body { + set f [open /abc/cp850.enc] + read $f +} -result {# Encoding file: cp850, single-byte +S +003F 0 1 +00 +0000000100020003000400050006000700080009000A000B000C000D000E000F +0010001100120013001400150016001700180019001A001B001C001D001E001F +0020002100220023002400250026002700280029002A002B002C002D002E002F +0030003100320033003400350036003700380039003A003B003C003D003E003F +0040004100420043004400450046004700480049004A004B004C004D004E004F +0050005100520053005400550056005700580059005A005B005C005D005E005F +0060006100620063006400650066006700680069006A006B006C006D006E006F +0070007100720073007400750076007700780079007A007B007C007D007E007F +00C700FC00E900E200E400E000E500E700EA00EB00E800EF00EE00EC00C400C5 +00C900E600C600F400F600F200FB00F900FF00D600DC00F800A300D800D70192 +00E100ED00F300FA00F100D100AA00BA00BF00AE00AC00BD00BC00A100AB00BB +2591259225932502252400C100C200C000A9256325512557255D00A200A52510 +25142534252C251C2500253C00E300C3255A25542569256625602550256C00A4 +00F000D000CA00CB00C8013100CD00CE00CF2518250C2588258400A600CC2580 +00D300DF00D400D200F500D500B500FE00DE00DA00DB00D900FD00DD00AF00B4 +00AD00B1201700BE00B600A700F700B800B000A800B700B900B300B225A000A0 +} - - +test zipfs-2.5 {zipfs exists} -constraints zipfs -body { + ::zipfs::unmount abc.zip + ::zipfs::exists /abc/cp850.enc +} -cleanup { + file delete abc.zip +} -result 1 ::tcltest::cleanupTests return -- cgit v0.12 From e9795fb40711ccc9e08e1a60232a31797bf8356a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 22 Dec 2015 11:39:28 +0000 Subject: first shot at documentation --- doc/zipfs.3 | 45 +++++++++++++++++++++++++++++++ doc/zipfs.n | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 doc/zipfs.3 create mode 100644 doc/zipfs.n diff --git a/doc/zipfs.3 b/doc/zipfs.3 new file mode 100644 index 0000000..9e031bc --- /dev/null +++ b/doc/zipfs.3 @@ -0,0 +1,45 @@ +'\" +'\" Copyright (c) 2015 Jan Nijtmans +'\" Copyright (c) 2015 Christian Werner +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +.TH Tclzipfs 3 8.7 Tcl "Tcl Library Procedures" +.so man.macros +.BS +.SH NAME +Tclzipfs_Init, Tclzipfs_SafeInit, Tclzipfs_Mount, Tclzipfs_Unmount \- handle ZIP files as VFS +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +int +\fBTclzipfs_Init\fR(\fIinterp\fR) +.sp +int +\fBTclzipfs_SafeInit\fR(\fIinterp\fR) +.sp +int +\fBTclzipfs_Mount\fR(\fIinterp, zipname, mntpt, passwd\fR) +.sp +int +\fBTclzipfs_Unmount\fR(\fIinterp, zipname\fR) +.SH ARGUMENTS +.AS Tcl_Interp **termPtr +.AP Tcl_Interp *interp in +Interpreter in which the zip file system is mounted. The interpreter's result is +modified to hold the result or error message from the script. +.AP "const char" *zipname in +Name of a zipfile. +.AP "const char" *mntpt in +Name of a mount point. +.AP "const char" *passwd in +An (optional) password. +.BE +.SH DESCRIPTION +.PP +TODO +.PP +.SH KEYWORDS +compress, filesystem, zip diff --git a/doc/zipfs.n b/doc/zipfs.n new file mode 100644 index 0000000..16b25e5 --- /dev/null +++ b/doc/zipfs.n @@ -0,0 +1,88 @@ +'\" +'\" Copyright (c) 2015 Jan Nijtmans +'\" Copyright (c) 2015 Christian Werner +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +.TH zipfs n 1.0 Zipfs "zipfs Commands" +.so man.macros +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +zipfs \- Mount and work with ZIP files within Tcl +.SH SYNOPSIS +.nf +\fBpackage require zipfs \fR?\fB1.0\fR? +.sp +\fB::zipfs::exists\fR \fIfilename\fR +\fB::zipfs::find\fR \fIdir\fR +\fB::zipfs::info\fR \fIfilename\fR +\fB::zipfs::list\fR \fB?(-glob|-regexp)?\fR \fI?pattern?\fR +\fB::zipfs::mkimg\fR \fIoutfile\fR \fIindir\fR \fI?strip?\fR \fI?password?\fR \fI?infile?\fR +\fB::zipfs::mkkey\fR \fIpassword\fR +\fB::zipfs::mkzip\fR \fIoutfile\fR \fIindir\fR \fI?strip?\fR \fI?password?\fR +\fB::zipfs::mount\fR \fI?zipfile\fR \fI?mountpoint?\fR \fI?password?\fR +\fB::zipfs::unmount\fR \fIzipfile\fR +.fi +.BE +.SH DESCRIPTION +.PP +The \fBzipfs\fR package provides tcl with the ability to mount +the contents of a zip file as a virtual file system. +.TP +\fB::zipfs::mount ?\fIzipfile\fR? ?\fImountpoint\fR? +. +The \fB::zipfs::mount\fR procedure mounts a zipfile as a VFS. +After this command executes, files contained in \fIzipfile\fR +will appear to Tcl to be regular files at the mount point. +.RS +.PP +With no \fImountpoint\fR, returns the mount point for \fIzipfile\fR. With no \fIzipfile\fR, +return all zipfile/mount pairs. If \fImountpoint\fR is specified as an empty +string, mount on file path. +.RE +.TP +\fB::zipfs::unmount \fIzipfile\fR +. +Unmounts a previously mounted zip, \fIzipfile\fR. +.TP +\fB::zipfs::exists\fR \fIfilename\fR +. +Return 1 if the given filename exists in the mounted zipfs and 0 if it does not. +.TP +\fB::zipfs::info\fR \fIfile\fR +. +Return information about the given file in the mounted zipfs. The information +consists of (1) the name of the ZIP zipfile that contains the file, (2) the +size of the file after decompressions, (3) the compressed size of the file, +and (4) the offset of the compressed data in the zipfile. +.RS +.PP +Note: querying the mount point gives the start of zip data offset in (4), +which can be used to truncate the zip info off an executable. +.RE +.TP +\fB::zipfs::list\fR \fB?(-glob|-regexp)?\fR \fI?pattern?\fR +. +Return a list of all files in the mounted zipfs. The order of the names +in the list is arbitrary. +.TP +\fB::zipfs::mkimg\fR \fIoutfile\fR \fIindir\fR \fI?strip?\fR \fI?password?\fR \fI?infile?\fR +. +TODO +.TP +\fB::zipfs::mkkey\fR \fIpassword\fR +. +TODO +.TP +\fB::zipfs::mkzip\fR \fIoutfile\fR \fIindir\fR \fI?strip?\fR \fI?password?\fR +. +TODO +.SH "SEE ALSO" +tclsh(1), file(n), zlib(n) +.SH "KEYWORDS" +compress, filesystem, zip +'\" Local Variables: +'\" mode: nroff +'\" End: -- cgit v0.12 From a1740d976679e2a4928898a1eddd1dad22f4fd16 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 1 Jan 2016 16:50:52 +0000 Subject: Make al zipfs command Tcl_Obj-based --- generic/tclZipfs.h | 2 +- generic/zipfs.c | 284 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 176 insertions(+), 110 deletions(-) diff --git a/generic/tclZipfs.h b/generic/tclZipfs.h index bcf6cef..01c9e96 100644 --- a/generic/tclZipfs.h +++ b/generic/tclZipfs.h @@ -28,7 +28,7 @@ extern "C" { #endif ZIPFSAPI int Tclzipfs_Mount(Tcl_Interp *interp, const char *zipname, - const char *mntpt, const char *passwd); + const char *mntpt, const char *passwd); ZIPFSAPI int Tclzipfs_Unmount(Tcl_Interp *interp, const char *zipname); ZIPFSAPI int Tclzipfs_Init(Tcl_Interp *interp); ZIPFSAPI int Tclzipfs_SafeInit(Tcl_Interp *interp); diff --git a/generic/zipfs.c b/generic/zipfs.c index 1f126ce..55c6d2c 100644 --- a/generic/zipfs.c +++ b/generic/zipfs.c @@ -91,15 +91,15 @@ * Macros to read and write 16 and 32 bit integers from/to ZIP archives. */ -#define zip_read_int(p) \ +#define zip_read_int(p) \ ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24)) -#define zip_read_short(p) \ +#define zip_read_short(p) \ ((p)[0] | ((p)[1] << 8)) -#define zip_write_int(p, v) \ - (p)[0] = (v) & 0xff; (p)[1] = ((v) >> 8) & 0xff; \ +#define zip_write_int(p, v) \ + (p)[0] = (v) & 0xff; (p)[1] = ((v) >> 8) & 0xff; \ (p)[2] = ((v) >> 16) & 0xff; (p)[3] = ((v) >> 24) & 0xff; -#define zip_write_short(p, v) \ +#define zip_write_short(p, v) \ (p)[0] = (v) & 0xff; (p)[1] = ((v) >> 8) & 0xff; /* @@ -1488,7 +1488,7 @@ done: /* *------------------------------------------------------------------------- * - * ZipFSMountCmd -- + * ZipFSMountObjCmd -- * * This procedure is invoked to process the "zipfs::mount" command. * @@ -1502,23 +1502,23 @@ done: */ static int -ZipFSMountCmd(ClientData clientData, Tcl_Interp *interp, - int argc, const char **argv) +ZipFSMountObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]) { - if (argc > 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ?zipfile ?mountpoint? ?password???\"", 0); + if (objc > 4) { + Tcl_WrongNumArgs(interp, 1, objv, + "?zipfile mountpoint password?"); return TCL_ERROR; } - return Tclzipfs_Mount(interp, (argc > 1) ? argv[1] : NULL, - (argc > 2) ? argv[2] : NULL, - (argc > 3) ? argv[3] : NULL); + return Tclzipfs_Mount(interp, (objc > 1) ? Tcl_GetString(objv[1]) : NULL, + (objc > 2) ? Tcl_GetString(objv[2]) : NULL, + (objc > 3) ? Tcl_GetString(objv[3]) : NULL); } /* *------------------------------------------------------------------------- * - * ZipFSUnmountCmd -- + * ZipFSUnmountObjCmd -- * * This procedure is invoked to process the "zipfs::unmount" command. * @@ -1532,21 +1532,20 @@ ZipFSMountCmd(ClientData clientData, Tcl_Interp *interp, */ static int -ZipFSUnmountCmd(ClientData clientData, Tcl_Interp *interp, - int argc, const char **argv) +ZipFSUnmountObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]) { - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " zipfile\"", (char *) NULL); + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "zipfile"); return TCL_ERROR; } - return Tclzipfs_Unmount(interp, argv[1]); + return Tclzipfs_Unmount(interp, Tcl_GetString(objv[1])); } /* *------------------------------------------------------------------------- * - * ZipFSMountCmd -- + * ZipFSMkKeyObjCmd -- * * This procedure is invoked to process the "zipfs::mkkey" command. * It produces a rotated password to be embedded into an image file. @@ -1561,28 +1560,28 @@ ZipFSUnmountCmd(ClientData clientData, Tcl_Interp *interp, */ static int -ZipFSMkKeyCmd(ClientData clientData, Tcl_Interp *interp, - int argc, const char **argv) +ZipFSMkKeyObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]) { int len, i = 0; - char pwbuf[264]; + char *pw, pwbuf[264]; - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " password\"", (char *) NULL); + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "password"); return TCL_ERROR; } - len = strlen(argv[1]); + pw = Tcl_GetString(objv[1]); + len = strlen(pw); if (len == 0) { return TCL_OK; } - if ((len > 255) || (strchr(argv[1], 0xff) != NULL)) { + if ((len > 255) || (strchr(pw, 0xff) != NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("illegal password", -1)); return TCL_ERROR; } while (len > 0) { - int ch = argv[1][len - 1]; + int ch = pw[len - 1]; pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; i++; @@ -1928,7 +1927,7 @@ seekErr: /* *------------------------------------------------------------------------- * - * ZipFSMkZipOrImgCmd -- + * ZipFSMkZipOrImgObjCmd -- * * This procedure is creates a new ZIP archive file or image file * given output filename, input directory of files to be archived, @@ -1945,75 +1944,107 @@ seekErr: */ static int -ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, - int isImg, int argc, const char **argv) +ZipFSMkZipOrImgObjCmd(ClientData clientData, Tcl_Interp *interp, + int isImg, int isList, int objc, Tcl_Obj *const objv[]) { Tcl_Channel out; - int len = 0, pwlen = 0, slen = 0, i, count, ret = TCL_ERROR, largc, pos[3]; - const char **largv; - Tcl_DString ds; + int len = 0, pwlen = 0, slen = 0, i, count, ret = TCL_ERROR, lobjc, pos[3]; + Tcl_Obj **lobjv, *list = NULL; ZipEntry *z; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_HashTable fileHash; - char pwbuf[264], buf[4096]; + char *strip = NULL, *pw = NULL, pwbuf[264], buf[4096]; - if ((argc < 3) || (argc > (isImg ? 6 : 5))) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " outfile indir ?strip? ?password?", - isImg ? " ?infile?\"" : "\"", (char *) NULL); - return TCL_ERROR; + if (isList) { + if ((objc < 3) || (objc > (isImg ? 5 : 4))) { + Tcl_WrongNumArgs(interp, 1, objv, isImg ? + "outfile inlist ?password infile?" : + "outfile inlist ?password?"); + return TCL_ERROR; + } + } else { + if ((objc < 3) || (objc > (isImg ? 6 : 5))) { + Tcl_WrongNumArgs(interp, 1, objv, isImg ? + "outfile indir ?strip password infile?" : + "outfile indir ?strip password?"); + return TCL_ERROR; + } } pwbuf[0] = 0; - if (argc > 4) { - pwlen = strlen(argv[4]); - if ((pwlen > 255) || (strchr(argv[4], 0xff) != NULL)) { - Tcl_AppendResult(interp, "illegal password", (char *) NULL); + if (objc > (isList ? 3 : 4)) { + pw = Tcl_GetString(objv[isList ? 3 : 4]); + pwlen = strlen(pw); + if ((pwlen > 255) || (strchr(pw, 0xff) != NULL)) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("illegal password", -1)); return TCL_ERROR; } } - Tcl_DStringInit(&ds); - Tcl_DStringAppendElement(&ds, "::zipfs::find"); - Tcl_DStringAppendElement(&ds, argv[2]); - if (Tcl_Eval(interp, Tcl_DStringValue(&ds)) != TCL_OK) { - Tcl_DStringFree(&ds); + if (isList) { + list = objv[2]; + Tcl_IncrRefCount(list); + } else { + Tcl_Obj *cmd[3]; + + cmd[1] = Tcl_NewStringObj("::zipfs::find", -1); + cmd[2] = objv[2]; + cmd[0] = Tcl_NewListObj(2, cmd + 1); + Tcl_IncrRefCount(cmd[0]); + if (Tcl_EvalObjEx(interp, cmd[0], TCL_EVAL_DIRECT) != TCL_OK) { + Tcl_DecrRefCount(cmd[0]); + return TCL_ERROR; + } + Tcl_DecrRefCount(cmd[0]); + list = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(list); + } + if (Tcl_ListObjGetElements(interp, list, &lobjc, &lobjv) != TCL_OK) { + Tcl_DecrRefCount(list); return TCL_ERROR; } - Tcl_DStringFree(&ds); - if (Tcl_SplitList(interp, Tcl_GetStringResult(interp), &largc, &largv) - != TCL_OK) { + if (isList && (lobjc % 2)) { + Tcl_DecrRefCount(list); + Tcl_SetObjResult(interp, + Tcl_NewStringObj("need even number of elements", -1)); return TCL_ERROR; } - Tcl_ResetResult(interp); - if (largc == 0) { - Tcl_Free((char *) largv); - Tcl_AppendResult(interp, "empty archive", (char *) NULL); + if (lobjc == 0) { + Tcl_DecrRefCount(list); + Tcl_SetObjResult(interp, Tcl_NewStringObj("empty archive", -1)); return TCL_ERROR; } - out = Tcl_OpenFileChannel(interp, argv[1], "w", 0755); + out = Tcl_OpenFileChannel(interp, Tcl_GetString(objv[1]), "w", 0755); if ((out == NULL) || (Tcl_SetChannelOption(interp, out, "-translation", "binary") != TCL_OK) || (Tcl_SetChannelOption(interp, out, "-encoding", "binary") != TCL_OK)) { + Tcl_DecrRefCount(list); Tcl_Close(interp, out); - Tcl_Free((char *) largv); return TCL_ERROR; } if (isImg) { ZipFile zf0; + const char *imgName; - if (ZipFSOpenArchive(interp, (argc > 5) ? argv[5] : - Tcl_GetNameOfExecutable(), 0, &zf0) != TCL_OK) { + if (isList) { + imgName = (objc > 4) ? Tcl_GetString(objv[4]) : + Tcl_GetNameOfExecutable(); + } else { + imgName = (objc > 5) ? Tcl_GetString(objv[5]) : + Tcl_GetNameOfExecutable(); + } + if (ZipFSOpenArchive(interp, imgName, 0, &zf0) != TCL_OK) { + Tcl_DecrRefCount(list); Tcl_Close(interp, out); - Tcl_Free((char *) largv); return TCL_ERROR; } - if (pwlen && (argc > 4)) { + if ((pw != NULL) && pwlen) { i = 0; len = pwlen; while (len > 0) { - int ch = argv[4][len - 1]; + int ch = pw[len - 1]; pwbuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; i++; @@ -2029,9 +2060,9 @@ ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, } i = Tcl_Write(out, (char *) zf0.data, zf0.baseoffsp); if (i != zf0.baseoffsp) { - Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_DecrRefCount(list); + Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); Tcl_Close(interp, out); - Tcl_Free((char *) largv); ZipFSCloseArchive(interp, &zf0); return TCL_ERROR; } @@ -2040,9 +2071,9 @@ ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, if (len > 0) { i = Tcl_Write(out, pwbuf, len); if (i != len) { - Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_DecrRefCount(list); + Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); Tcl_Close(interp, out); - Tcl_Free((char *) largv); return TCL_ERROR; } } @@ -2051,18 +2082,25 @@ ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, } Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS); pos[0] = Tcl_Tell(out); - if (argc > 3) { - slen = strlen(argv[3]); + if (!isList && (objc > 3)) { + strip = Tcl_GetString(objv[3]); + slen = strlen(strip); } - for (i = 0; i < largc; i++) { - const char *name = largv[i]; + for (i = 0; i < lobjc; i += (isList ? 2 : 1)) { + const char *path, *name; - if (slen > 0) { - len = strlen(name); - if ((len <= slen) || (strncmp(argv[3], name, slen) != 0)) { - continue; + path = Tcl_GetString(lobjv[i]); + if (isList) { + name = Tcl_GetString(lobjv[i + 1]); + } else { + name = path; + if (slen > 0) { + len = strlen(name); + if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { + continue; + } + name += slen; } - name += slen; } while (name[0] == '/') { ++name; @@ -2070,23 +2108,28 @@ ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, if (name[0] == '\0') { continue; } - if (ZipAddFile(interp, largv[i], name, out, - (pwlen > 0) ? argv[4] : NULL, buf, sizeof (buf), &fileHash) - != TCL_OK) { + if (ZipAddFile(interp, path, name, out, pw, buf, sizeof (buf), + &fileHash) != TCL_OK) { goto done; } } pos[1] = Tcl_Tell(out); count = 0; - for (i = 0; i < largc; i++) { - const char *name = largv[i]; + for (i = 0; i < lobjc; i += (isList ? 2 : 1)) { + const char *path, *name; - if (slen > 0) { - len = strlen(name); - if ((len <= slen) || (strncmp(argv[3], name, slen) != 0)) { - continue; + path = Tcl_GetString(lobjv[i]); + if (isList) { + name = Tcl_GetString(lobjv[i + 1]); + } else { + name = path; + if (slen > 0) { + len = strlen(name); + if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { + continue; + } + name += slen; } - name += slen; } while (name[0] == '/') { ++name; @@ -2117,10 +2160,10 @@ ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, zip_write_short(buf + ZIP_CENTRAL_IATTR_OFFS, 0); zip_write_int(buf + ZIP_CENTRAL_EATTR_OFFS, 0); zip_write_int(buf + ZIP_CENTRAL_LOCALHDR_OFFS, z->offset - pos[0]); - memcpy(buf + ZIP_CENTRAL_HEADER_LEN, z->name, len); - len += ZIP_CENTRAL_HEADER_LEN; - if (Tcl_Write(out, buf, len) != len) { - Tcl_AppendResult(interp, "write error", (char *) NULL); + if ((Tcl_Write(out, buf, ZIP_CENTRAL_HEADER_LEN) != + ZIP_CENTRAL_HEADER_LEN) || + (Tcl_Write(out, z->name, len) != len)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); goto done; } count++; @@ -2136,14 +2179,18 @@ ZipFSMkZipOrImgCmd(ClientData clientData, Tcl_Interp *interp, zip_write_int(buf + ZIP_CENTRAL_DIRSTART_OFFS, pos[1] - pos[0]); zip_write_short(buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0); if (Tcl_Write(out, buf, ZIP_CENTRAL_END_LEN) != ZIP_CENTRAL_END_LEN) { - Tcl_AppendResult(interp, "write error", (char *) NULL); + Tcl_SetObjResult(interp, Tcl_NewStringObj("write error", -1)); goto done; } Tcl_Flush(out); ret = TCL_OK; done: - Tcl_Free((char *) largv); - Tcl_Close(interp, out); + if (ret == TCL_OK) { + ret = Tcl_Close(interp, out); + } else { + Tcl_Close(interp, out); + } + Tcl_DecrRefCount(list); hPtr = Tcl_FirstHashEntry(&fileHash, &search); while (hPtr != NULL) { z = (ZipEntry *) Tcl_GetHashValue(hPtr); @@ -2158,7 +2205,7 @@ done: /* *------------------------------------------------------------------------- * - * ZipFSMkZipCmd -- + * ZipFSMkZipObjCmd -- * * This procedure is invoked to process the "zipfs::mkzip" command. * See description of ZipFSMkZipOrImgCmd(). @@ -2173,16 +2220,23 @@ done: */ static int -ZipFSMkZipCmd(ClientData clientData, Tcl_Interp *interp, - int argc, const char **argv) +ZipFSMkZipObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]) +{ + return ZipFSMkZipOrImgObjCmd(clientData, interp, 0, 0, objc, objv); +} + +static int +ZipFSLMkZipObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]) { - return ZipFSMkZipOrImgCmd(clientData, interp, 0, argc, argv); + return ZipFSMkZipOrImgObjCmd(clientData, interp, 0, 1, objc, objv); } /* *------------------------------------------------------------------------- * - * ZipFSMkImgCmd -- + * ZipFSMkImgObjCmd -- * * This procedure is invoked to process the "zipfs::mkimg" command. * See description of ZipFSMkZipOrImgCmd(). @@ -2197,10 +2251,17 @@ ZipFSMkZipCmd(ClientData clientData, Tcl_Interp *interp, */ static int -ZipFSMkImgCmd(ClientData clientData, Tcl_Interp *interp, - int argc, const char **argv) +ZipFSMkImgObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]) +{ + return ZipFSMkZipOrImgObjCmd(clientData, interp, 1, 0, objc, objv); +} + +static int +ZipFSLMkImgObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]) { - return ZipFSMkZipOrImgCmd(clientData, interp, 1, argc, argv); + return ZipFSMkZipOrImgObjCmd(clientData, interp, 1, 1, objc, objv); } /* @@ -3938,11 +3999,16 @@ Zipfs_doInit(Tcl_Interp *interp, int safe) Unlock(); Tcl_PkgProvide(interp, "zipfs", "1.0"); if (!safe) { - Tcl_CreateCommand(interp, "::zipfs::mount", ZipFSMountCmd, 0, 0); - Tcl_CreateCommand(interp, "::zipfs::unmount", ZipFSUnmountCmd, 0, 0); - Tcl_CreateCommand(interp, "::zipfs::mkkey", ZipFSMkKeyCmd, 0, 0); - Tcl_CreateCommand(interp, "::zipfs::mkimg", ZipFSMkImgCmd, 0, 0); - Tcl_CreateCommand(interp, "::zipfs::mkzip", ZipFSMkZipCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::mount", ZipFSMountObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::unmount", + ZipFSUnmountObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::mkkey", ZipFSMkKeyObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::mkimg", ZipFSMkImgObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::mkzip", ZipFSMkZipObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::lmkimg", + ZipFSLMkImgObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::zipfs::lmkzip", + ZipFSLMkZipObjCmd, 0, 0); Tcl_GlobalEval(interp, findproc); } Tcl_CreateObjCommand(interp, "::zipfs::exists", ZipFSExistsObjCmd, 0, 0); -- cgit v0.12 From 3c9ec7f76f99b7590f73d31e96b2316771696e71 Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 1 Jan 2016 17:46:45 +0000 Subject: Document the Tcl_CancelEval function correctly. It was missing its second argument, making using it correctly impossible, especially from C++. --- doc/Cancel.3 | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/doc/Cancel.3 b/doc/Cancel.3 index 5d258b7..f6b1636 100644 --- a/doc/Cancel.3 +++ b/doc/Cancel.3 @@ -13,20 +13,25 @@ Tcl_CancelEval, Tcl_Canceled \- cancel Tcl scripts .nf \fB#include \fR int -\fBTcl_CancelEval\fR(\fIinterp, clientData, flags\fR) +\fBTcl_CancelEval\fR(\fIinterp, resultObjPtr, clientData, flags\fR) .sp int \fBTcl_Canceled\fR(\fIinterp, flags\fR) .SH ARGUMENTS +.AS Tcl_Interp *interp .AP Tcl_Interp *interp in Interpreter in which to cancel the script. +.AP Tcl_Obj *resultObjPtr in +Error message to use in the cancellation, or NULL to use a default message. If +not NULL, this object will have its reference count decremented before +\fBTcl_CancelEval\fR returns. .AP int flags in ORed combination of flag bits that specify additional options. For \fBTcl_CancelEval\fR, only \fBTCL_CANCEL_UNWIND\fR is currently supported. For \fBTcl_Canceled\fR, only \fBTCL_LEAVE_ERR_MSG\fR and \fBTCL_CANCEL_UNWIND\fR are currently supported. .AP ClientData clientData in -Currently, reserved for future use. +Currently reserved for future use. It should be set to NULL. .BE .SH DESCRIPTION @@ -41,19 +46,21 @@ returns \fBTCL_ERROR\fR if it has. Otherwise, \fBTCL_OK\fR is returned. Extensions can use this function to check to see if they should abort a long running command. This function is thread sensitive and may only be called from the thread the interpreter was created in. -.SH "FLAG BITS" +.SS "FLAG BITS" Any ORed combination of the following values may be used for the \fIflags\fR argument to procedures such as \fBTcl_CancelEval\fR: -.TP 23 +.TP 20 \fBTCL_CANCEL_UNWIND\fR +. This flag is used by \fBTcl_CancelEval\fR and \fBTcl_Canceled\fR. For \fBTcl_CancelEval\fR, if this flag is set, the script in progress is canceled and the evaluation stack for the interpreter is unwound. For \fBTcl_Canceled\fR, if this flag is set, the script in progress is considered to be canceled only if the evaluation stack for the interpreter is being unwound. -.TP 23 +.TP 20 \fBTCL_LEAVE_ERR_MSG\fR +. This flag is only used by \fBTcl_Canceled\fR; it is ignored by other procedures. If an error is returned and this bit is set in \fIflags\fR, then an error message will be left in the interpreter's @@ -61,6 +68,7 @@ result, where it can be retrieved with \fBTcl_GetObjResult\fR or \fBTcl_GetStringResult\fR. If this flag bit is not set then no error message is left and the interpreter's result will not be modified. .SH "SEE ALSO" +interp(n), Tcl_Eval(3), TIP 285 .SH KEYWORDS cancel, unwind -- cgit v0.12 From 972aafc741825e93779b70c181d6108497d91f46 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 6 Jan 2016 11:15:20 +0000 Subject: Fix win32 mingw 32-bit build, bug was introduced by [c397433be321e6d9] (wrong zlib1.dll was copied) --- win/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/Makefile.in b/win/Makefile.in index 7e6486c..2d27a41 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -468,7 +468,7 @@ ${TEST_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${TCLTEST_OBJS} # use pre-built zlib1.dll ${ZLIB_DLL_FILE}: ${TCL_STUB_LIB_FILE} - @if test "@ZLIB_LIBS@set" != "${ZLIB_DIR}/win32/zdll.libset" ; then \ + @if test "@ZLIB_LIBS@set" != "${ZLIB_DIR_NATIVE}/win32/zdll.libset" ; then \ $(COPY) $(ZLIB_DIR)/win64/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \ else \ $(COPY) $(ZLIB_DIR)/win32/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \ -- cgit v0.12 From d533bb6a266000442f8dab719bd1250586c35a70 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 7 Jan 2016 11:33:02 +0000 Subject: Fix [f01d74dc8c]: DEFAULT_COPY_BLOCK_SIZE has incorrect value --- unix/tclUnixFCmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 3b1b6ca..a1a409e 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -564,7 +564,7 @@ TclUnixCopyFile( #define BINMODE #endif /* DJGPP */ -#define DEFAULT_COPY_BLOCK_SIZE 4069 +#define DEFAULT_COPY_BLOCK_SIZE 4096 if ((srcFd = TclOSopen(src, O_RDONLY BINMODE, 0)) < 0) { /* INTL: Native */ return TCL_ERROR; -- cgit v0.12