Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | merge novem |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | dgp-refactor |
Files: | files | file ages | folders |
SHA1: |
491c1074c5168e1d0a19a2320186c226 |
User & Date: | dgp 2017-04-27 13:28:51 |
Context
2017-05-08
| ||
16:34 | merge novem check-in: 4b307fb502 user: dgp tags: dgp-refactor | |
2017-04-27
| ||
13:28 | merge novem check-in: 491c1074c5 user: dgp tags: dgp-refactor | |
12:54 | merge trunk check-in: a7adf2c06d user: dgp tags: novem | |
2017-04-21
| ||
12:45 | merge novem check-in: d0afdcd2a7 user: dgp tags: dgp-refactor | |
Changes
Changes to generic/tclDisassemble.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 | static Tcl_Obj * DisassembleByteCodeAsDicts(Tcl_Interp *interp, Tcl_Obj *objPtr); static Tcl_Obj * DisassembleByteCodeObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static int FormatInstruction(ByteCode *codePtr, const unsigned char *pc, Tcl_Obj *bufferObj); | | | < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | static Tcl_Obj * DisassembleByteCodeAsDicts(Tcl_Interp *interp, Tcl_Obj *objPtr); static Tcl_Obj * DisassembleByteCodeObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static int FormatInstruction(ByteCode *codePtr, const unsigned char *pc, Tcl_Obj *bufferObj); static void GetLocationInformation(Proc *procPtr, Tcl_Obj **fileObjPtr, int *linePtr); static void PrintSourceToObj(Tcl_Obj *appendObj, const char *stringPtr, int maxChars); static void UpdateStringOfInstName(Tcl_Obj *objPtr); /* * The structure below defines an instruction name Tcl object to allow * reporting of inner contexts in errorstack without string allocation. |
︙ | ︙ | |||
69 70 71 72 73 74 75 | * None. * *---------------------------------------------------------------------- */ static void GetLocationInformation( | < < < < | | > > | > > > | | | | < < | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | * None. * *---------------------------------------------------------------------- */ static void GetLocationInformation( Proc *procPtr, /* What to look up the information for. */ Tcl_Obj **fileObjPtr, /* Where to write the information about what * file the code came from. Will be written * to, either with the object (assume shared!) * that describes what the file was, or with * NULL if the information is not * available. */ int *linePtr) /* Where to write the information about what * line number represented the start of the * code in question. Will be written to, * either with the line number or with -1 if * the information is not available. */ { CmdFrame *cfPtr = TclGetCmdFrameForProcedure(procPtr); *fileObjPtr = NULL; *linePtr = -1; if (cfPtr == NULL) { return; } /* * Get the source location data out of the CmdFrame. */ *linePtr = cfPtr->line[0]; if (cfPtr->type == TCL_LOCATION_SOURCE) { *fileObjPtr = cfPtr->data.eval.path; } } #ifdef TCL_COMPILE_DEBUG /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
271 272 273 274 275 276 277 | Tcl_AppendPrintfToObj(bufferObj, "ByteCode %p, refCt %" TCL_LL_MODIFIER "u, epoch %" TCL_LL_MODIFIER "u, interp %p (epoch %" TCL_LL_MODIFIER "u)\n", codePtr, (Tcl_WideInt)codePtr->refCount, (Tcl_WideInt)codePtr->compileEpoch, iPtr, (Tcl_WideInt)iPtr->compileEpoch); Tcl_AppendToObj(bufferObj, " Source ", -1); PrintSourceToObj(bufferObj, codePtr->source, TclMin(codePtr->numSrcBytes, 55)); | | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | Tcl_AppendPrintfToObj(bufferObj, "ByteCode %p, refCt %" TCL_LL_MODIFIER "u, epoch %" TCL_LL_MODIFIER "u, interp %p (epoch %" TCL_LL_MODIFIER "u)\n", codePtr, (Tcl_WideInt)codePtr->refCount, (Tcl_WideInt)codePtr->compileEpoch, iPtr, (Tcl_WideInt)iPtr->compileEpoch); Tcl_AppendToObj(bufferObj, " Source ", -1); PrintSourceToObj(bufferObj, codePtr->source, TclMin(codePtr->numSrcBytes, 55)); GetLocationInformation(codePtr->procPtr, &fileObj, &line); if (line > -1 && fileObj != NULL) { Tcl_AppendPrintfToObj(bufferObj, "\n File \"%s\" Line %d", Tcl_GetString(fileObj), line); } Tcl_AppendPrintfToObj(bufferObj, "\n Cmds %d, src %d, inst %d, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n", numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes, |
︙ | ︙ | |||
1219 1220 1221 1222 1223 1224 1225 | #undef Decode /* * Get the source file and line number information from the CmdFrame * system if it is available. */ | | | 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 | #undef Decode /* * Get the source file and line number information from the CmdFrame * system if it is available. */ GetLocationInformation(codePtr->procPtr, &file, &line); /* * Build the overall result. */ description = Tcl_NewObj(); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("literals", -1), |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
2987 2988 2989 2990 2991 2992 2993 | const char *encodingName); MODULE_SCOPE void TclFSUnloadTempFile(Tcl_LoadHandle loadHandle); MODULE_SCOPE int * TclGetAsyncReadyPtr(void); MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp); MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Channel *chanPtr, int *modePtr, int flags); | > | | 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 | const char *encodingName); MODULE_SCOPE void TclFSUnloadTempFile(Tcl_LoadHandle loadHandle); MODULE_SCOPE int * TclGetAsyncReadyPtr(void); MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp); MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Channel *chanPtr, int *modePtr, int flags); MODULE_SCOPE CmdFrame * TclGetCmdFrameForProcedure(Proc *procPtr); MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp, Tcl_Obj *value, int *code); MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, ClientData *clientDataPtr, int *typePtr); MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp, const char *modeString, int *seekFlagPtr, int *binaryPtr); |
︙ | ︙ | |||
3994 3995 3996 3997 3998 3999 4000 | struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); /* | | | 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 | struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); /* * Functions defined in generic/tclVar.c and currently exported only for use * by the bytecode compiler and engine. Some of these could later be placed in * the public interface. */ MODULE_SCOPE Var * TclObjLookupVarEx(Tcl_Interp * interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags, const char *msg, const int createPart1, |
︙ | ︙ |
Changes to generic/tclProc.c.
︙ | ︙ | |||
2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 | overflow = (nameLen > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (lambda term \"%.*s%s\" line %d)", (overflow ? limit : nameLen), procName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 | overflow = (nameLen > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (lambda term \"%.*s%s\" line %d)", (overflow ? limit : nameLen), procName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* *---------------------------------------------------------------------- * * TclGetCmdFrameForProcedure -- * * How to get the CmdFrame information for a procedure. * * Results: * A pointer to the CmdFrame (only guaranteed to be valid until the next * Tcl command is processed or the interpreter's state is otherwise * modified) or a NULL if the information is not available. * * Side effects: * none. * *---------------------------------------------------------------------- */ CmdFrame * TclGetCmdFrameForProcedure( Proc *procPtr) /* The procedure whose cmd-frame is to be * looked up. */ { Tcl_HashEntry *hePtr; if (procPtr == NULL || procPtr->iPtr == NULL) { return NULL; } hePtr = Tcl_FindHashEntry(procPtr->iPtr->linePBodyPtr, procPtr); if (hePtr == NULL) { return NULL; } return (CmdFrame *) Tcl_GetHashValue(hePtr); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: |
︙ | ︙ |
Changes to generic/tclZlib.c.
︙ | ︙ | |||
3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 | int e, produced; Tcl_Obj *errObj; if (cd->mode == TCL_ZLIB_STREAM_INFLATE) { return outProc(Tcl_GetChannelInstanceData(cd->parent), buf, toWrite, errorCodePtr); } cd->outStream.next_in = (Bytef *) buf; cd->outStream.avail_in = toWrite; | > > > > > > > > | | < < < < < | < | < < < | | | | | | < | 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 | int e, produced; Tcl_Obj *errObj; if (cd->mode == TCL_ZLIB_STREAM_INFLATE) { return outProc(Tcl_GetChannelInstanceData(cd->parent), buf, toWrite, errorCodePtr); } /* * No zero-length writes. Flushes must be explicit. */ if (toWrite == 0) { return 0; } cd->outStream.next_in = (Bytef *) buf; cd->outStream.avail_in = toWrite; while (cd->outStream.avail_in > 0) { e = Deflate(&cd->outStream, cd->outBuffer, cd->outAllocated, Z_NO_FLUSH, &produced); if (e != Z_OK || produced == 0) { break; } if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) < 0) { *errorCodePtr = Tcl_GetErrno(); return -1; } } if (e == Z_OK) { return toWrite - cd->outStream.avail_in; } errObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj("-errorcode",-1)); |
︙ | ︙ |
Changes to tests/zlib.test.
︙ | ︙ | |||
1000 1001 1002 1003 1004 1005 1006 | close $fin close $fout } file size $filedst } -cleanup { removeFile $filesrc removeFile $filedst | | | 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 | close $fin close $fout } file size $filedst } -cleanup { removeFile $filesrc removeFile $filedst } -result 56 ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: |
Changes to unix/tclUnixChan.c.
︙ | ︙ | |||
601 602 603 604 605 606 607 | * system calls results should be checked there. - dl */ TtySetAttributes(fsPtr->fd, &tty); return TCL_OK; } | < | 601 602 603 604 605 606 607 608 609 610 611 612 613 614 | * system calls results should be checked there. - dl */ TtySetAttributes(fsPtr->fd, &tty); return TCL_OK; } /* * Option -handshake none|xonxoff|rtscts|dtrdsr */ if ((len > 1) && (strncmp(optionName, "-handshake", len) == 0)) { /* * Reset all handshake options. DTR and RTS are ON by default. |
︙ | ︙ | |||
702 703 704 705 706 707 708 709 710 711 712 713 714 715 | tcsetattr(fsPtr->fd, TCSADRAIN, &iostate); return TCL_OK; } /* * Option -ttycontrol {DTR 1 RTS 0 BREAK 0} */ if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) { #if defined(TIOCMGET) && defined(TIOCMSET) int i, control, flag; if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } | > | 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | tcsetattr(fsPtr->fd, TCSADRAIN, &iostate); return TCL_OK; } /* * Option -ttycontrol {DTR 1 RTS 0 BREAK 0} */ if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) { #if defined(TIOCMGET) && defined(TIOCMSET) int i, control, flag; if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } |
︙ | ︙ | |||
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 | #if defined(TIOCMGET) /* * Get option -ttystatus * Option is readonly and returned by [fconfigure chan -ttystatus] but not * returned by unnamed [fconfigure chan]. */ if ((len > 4) && (strncmp(optionName, "-ttystatus", len) == 0)) { int status; valid = 1; ioctl(fsPtr->fd, TIOCMGET, &status); TtyModemStatusStr(status, dsPtr); } #endif /* TIOCMGET */ if (valid) { return TCL_OK; } | > | | < < | 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 | #if defined(TIOCMGET) /* * Get option -ttystatus * Option is readonly and returned by [fconfigure chan -ttystatus] but not * returned by unnamed [fconfigure chan]. */ if ((len > 4) && (strncmp(optionName, "-ttystatus", len) == 0)) { int status; valid = 1; ioctl(fsPtr->fd, TIOCMGET, &status); TtyModemStatusStr(status, dsPtr); } #endif /* TIOCMGET */ if (valid) { return TCL_OK; } return Tcl_BadChannelOption(interp, optionName, "mode queue ttystatus xchar"); } static const struct {int baud; speed_t speed;} speeds[] = { #ifdef B0 {0, B0}, #endif #ifdef B50 {50, B50}, #endif |
︙ | ︙ | |||
1019 1020 1021 1022 1023 1024 1025 | {3500000,B3500000}, #endif #ifdef B4000000 {4000000,B4000000}, #endif {-1, 0} }; | | | 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 | {3500000,B3500000}, #endif #ifdef B4000000 {4000000,B4000000}, #endif {-1, 0} }; /* *--------------------------------------------------------------------------- * * TtyGetSpeed -- * * Given an integer baud rate, get the speed_t value that should be * used to select that baud rate. |
︙ | ︙ | |||
1311 1312 1313 1314 1315 1316 1317 | * All other modes can be simulated on top of this in Tcl. * *--------------------------------------------------------------------------- */ static void TtyInit( | | > | < | 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 | * All other modes can be simulated on top of this in Tcl. * *--------------------------------------------------------------------------- */ static void TtyInit( int fd) /* Open file descriptor for serial port to be * initialized. */ { struct termios iostate; tcgetattr(fd, &iostate); if (iostate.c_iflag != IGNBRK || iostate.c_oflag != 0 || iostate.c_lflag != 0 || iostate.c_cflag & CREAD || iostate.c_cc[VMIN] != 1 || iostate.c_cc[VTIME] != 0) { iostate.c_iflag = IGNBRK; iostate.c_oflag = 0; iostate.c_lflag = 0; iostate.c_cflag |= CREAD; iostate.c_cc[VMIN] = 1; iostate.c_cc[VTIME] = 0; |
︙ | ︙ |
Changes to unix/tclUnixInit.c.
︙ | ︙ | |||
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 | * Side effects: * Sets "tclDefaultLibrary", "tcl_pkgPath", and "tcl_platform" Tcl * variables. * *---------------------------------------------------------------------- */ void TclpSetVariables( Tcl_Interp *interp) { #ifdef __CYGWIN__ SYSTEM_INFO sysInfo; static OSVERSIONINFOW osInfo; static int osInfoInitialized = 0; char buffer[TCL_INTEGER_SPACE * 2]; #elif !defined(NO_UNAME) struct utsname name; #endif int unameOK; Tcl_DString ds; #ifdef HAVE_COREFOUNDATION char tclLibPath[MAXPATHLEN + 1]; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | < < | < < < < < < < < < < < < < | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 | * Side effects: * Sets "tclDefaultLibrary", "tcl_pkgPath", and "tcl_platform" Tcl * variables. * *---------------------------------------------------------------------- */ #if defined(HAVE_COREFOUNDATION) && MAC_OS_X_VERSION_MAX_ALLOWED > 1020 /* * Helper because whether CFLocaleCopyCurrent and CFLocaleGetIdentifier are * strongly or weakly bound varies by version of OSX, triggering warnings. */ static inline void InitMacLocaleInfoVar( CFLocaleRef (*localeCopyCurrent)(void), CFStringRef (*localeGetIdentifier)(CFLocaleRef), Tcl_Interp *interp) { CFLocaleRef localeRef; CFStringRef locale; char loc[256]; if (localeCopyCurrent == NULL || localeGetIdentifier == NULL) { return; } localeRef = localeCopyCurrent(); if (!localeRef) { return; } locale = localeGetIdentifier(localeRef); if (locale && CFStringGetCString(locale, loc, 256, kCFStringEncodingUTF8)) { if (!Tcl_CreateNamespace(interp, "::tcl::mac", NULL, NULL)) { Tcl_ResetResult(interp); } Tcl_SetVar2(interp, "::tcl::mac::locale", NULL, loc, TCL_GLOBAL_ONLY); } CFRelease(localeRef); } #endif /*defined(HAVE_COREFOUNDATION) && MAC_OS_X_VERSION_MAX_ALLOWED > 1020*/ void TclpSetVariables( Tcl_Interp *interp) { #ifdef __CYGWIN__ SYSTEM_INFO sysInfo; static OSVERSIONINFOW osInfo; static int osInfoInitialized = 0; char buffer[TCL_INTEGER_SPACE * 2]; #elif !defined(NO_UNAME) struct utsname name; #endif int unameOK; Tcl_DString ds; #ifdef HAVE_COREFOUNDATION char tclLibPath[MAXPATHLEN + 1]; /* * Set msgcat fallback locale to current CFLocale identifier. */ #if MAC_OS_X_VERSION_MAX_ALLOWED > 1020 InitMacLocaleInfoVar(CFLocaleCopyCurrent, CFLocaleGetIdentifier, interp); #endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1020 */ if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) { const char *str; CFBundleRef bundleRef; Tcl_SetVar2(interp, "tclDefaultLibrary", NULL, tclLibPath, TCL_GLOBAL_ONLY); |
︙ | ︙ |
Changes to unix/tclUnixSock.c.
︙ | ︙ | |||
724 725 726 727 728 729 730 731 732 733 734 735 736 737 | * None. * * Side effects: * Adds three elements do dsPtr * *---------------------------------------------------------------------- */ static void TcpHostPortList( Tcl_Interp *interp, Tcl_DString *dsPtr, address addr, socklen_t salen) { | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | * None. * * Side effects: * Adds three elements do dsPtr * *---------------------------------------------------------------------- */ #ifndef NEED_FAKE_RFC2553 static inline int IPv6AddressNeedsNumericRendering( struct in6_addr addr) { if (IN6_ARE_ADDR_EQUAL(&addr, &in6addr_any)) { return 1; } /* * The IN6_IS_ADDR_V4MAPPED macro has a problem with aliasing warnings on * at least some versions of OSX. */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" if (!IN6_IS_ADDR_V4MAPPED(&addr)) { #pragma GCC diagnostic pop return 0; } return (addr.s6_addr[12] == 0 && addr.s6_addr[13] == 0 && addr.s6_addr[14] == 0 && addr.s6_addr[15] == 0); } #endif /* NEED_FAKE_RFC2553 */ static void TcpHostPortList( Tcl_Interp *interp, Tcl_DString *dsPtr, address addr, socklen_t salen) { |
︙ | ︙ | |||
750 751 752 753 754 755 756 | if (addr.sa.sa_family == AF_INET) { if (addr.sa4.sin_addr.s_addr == INADDR_ANY) { flags |= NI_NUMERICHOST; } #ifndef NEED_FAKE_RFC2553 } else if (addr.sa.sa_family == AF_INET6) { | < < | < < < | 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 | if (addr.sa.sa_family == AF_INET) { if (addr.sa4.sin_addr.s_addr == INADDR_ANY) { flags |= NI_NUMERICHOST; } #ifndef NEED_FAKE_RFC2553 } else if (addr.sa.sa_family == AF_INET6) { if (IPv6AddressNeedsNumericRendering(addr.sa6.sin6_addr)) { flags |= NI_NUMERICHOST; } #endif /* NEED_FAKE_RFC2553 */ } /* * Check if reverse DNS has been switched off globally. |
︙ | ︙ |
Changes to win/tclWinChan.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | #define FILE_ASYNC (1<<1) /* Channel is non-blocking. */ #define FILE_APPEND (1<<2) /* File is in append mode. */ #define FILE_TYPE_SERIAL (FILE_TYPE_PIPE+1) #define FILE_TYPE_CONSOLE (FILE_TYPE_PIPE+2) /* | | > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #define FILE_ASYNC (1<<1) /* Channel is non-blocking. */ #define FILE_APPEND (1<<2) /* File is in append mode. */ #define FILE_TYPE_SERIAL (FILE_TYPE_PIPE+1) #define FILE_TYPE_CONSOLE (FILE_TYPE_PIPE+2) /* * The following structure contains per-instance data for a file based * channel. */ typedef struct FileInfo { Tcl_Channel channel; /* Pointer to channel structure. */ int validMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which operations are valid on the file. */ |
︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | static void FileWatchProc(ClientData instanceData, int mask); static void FileThreadActionProc(ClientData instanceData, int action); static int FileTruncateProc(ClientData instanceData, Tcl_WideInt length); static DWORD FileGetType(HANDLE handle); static int NativeIsComPort(const TCHAR *nativeName); /* * This structure describes the channel type structure for file based IO. */ static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ | > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | static void FileWatchProc(ClientData instanceData, int mask); static void FileThreadActionProc(ClientData instanceData, int action); static int FileTruncateProc(ClientData instanceData, Tcl_WideInt length); static DWORD FileGetType(HANDLE handle); static int NativeIsComPort(const TCHAR *nativeName); /* * This structure describes the channel type structure for file based IO. */ static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ |
︙ | ︙ | |||
115 116 117 118 119 120 121 122 123 124 125 126 127 128 | FileBlockProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ FileWideSeekProc, /* Wide seek proc. */ FileThreadActionProc, /* Thread action proc. */ FileTruncateProc /* Truncate proc. */ }; /* *---------------------------------------------------------------------- * * FileInit -- * * This function creates the window used to simulate file events. | > > > > > > > > | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | FileBlockProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ FileWideSeekProc, /* Wide seek proc. */ FileThreadActionProc, /* Thread action proc. */ FileTruncateProc /* Truncate proc. */ }; /* * General useful clarification macros. */ #define SET_FLAG(var, flag) ((var) |= (flag)) #define CLEAR_FLAG(var, flag) ((var) &= ~(flag)) #define TEST_FLAG(value, flag) ((value) & (flag) != 0) /* *---------------------------------------------------------------------- * * FileInit -- * * This function creates the window used to simulate file events. |
︙ | ︙ | |||
136 137 138 139 140 141 142 | *---------------------------------------------------------------------- */ static ThreadSpecificData * FileInit(void) { ThreadSpecificData *tsdPtr = | | | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | *---------------------------------------------------------------------- */ static ThreadSpecificData * FileInit(void) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); if (tsdPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->firstFilePtr = NULL; Tcl_CreateEventSource(FileSetupProc, FileCheckProc, NULL); Tcl_CreateThreadExitHandler(FileChannelExitHandler, NULL); } |
︙ | ︙ | |||
197 198 199 200 201 202 203 | ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { FileInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); | | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { FileInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!TEST_FLAG(flags, TCL_FILE_EVENTS)) { return; } /* * Check to see if there is a ready file. If so, poll. */ |
︙ | ︙ | |||
240 241 242 243 244 245 246 | ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { FileEvent *evPtr; FileInfo *infoPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); | | | | | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { FileEvent *evPtr; FileInfo *infoPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!TEST_FLAG(flags, TCL_FILE_EVENTS)) { return; } /* * Queue events for any ready files that don't already have events queued * (caused by persistent states that won't generate WinSock events). */ for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask && !TEST_FLAG(infoPtr->flags, FILE_PENDING)) { SET_FLAG(infoPtr->flags, FILE_PENDING); evPtr = ckalloc(sizeof(FileEvent)); evPtr->header.proc = FileEventProc; evPtr->infoPtr = infoPtr; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); } } } |
︙ | ︙ | |||
292 293 294 295 296 297 298 | int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { FileEvent *fileEvPtr = (FileEvent *)evPtr; FileInfo *infoPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); | | | | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { FileEvent *fileEvPtr = (FileEvent *)evPtr; FileInfo *infoPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!TEST_FLAG(flags, TCL_FILE_EVENTS)) { return 0; } /* * Search through the list of watched files for the one whose handle * matches the event. We do this rather than simply dereferencing the * handle in the event so that files can be deleted while the event is in * the queue. */ for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (fileEvPtr->infoPtr == infoPtr) { CLEAR_FLAG(infoPtr->flags, FILE_PENDING); Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask); break; } } return 1; } |
︙ | ︙ | |||
346 347 348 349 350 351 352 | * Files on Windows can not be switched between blocking and nonblocking, * hence we have to emulate the behavior. This is done in the input * function by checking against a bit in the state. We set or unset the * bit here to cause the input function to emulate the correct behavior. */ if (mode == TCL_MODE_NONBLOCKING) { | | | | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | * Files on Windows can not be switched between blocking and nonblocking, * hence we have to emulate the behavior. This is done in the input * function by checking against a bit in the state. We set or unset the * bit here to cause the input function to emulate the correct behavior. */ if (mode == TCL_MODE_NONBLOCKING) { SET_FLAG(infoPtr->flags, FILE_ASYNC); } else { CLEAR_FLAG(infoPtr->flags, FILE_ASYNC); } return 0; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
468 469 470 471 472 473 474 | /* * Save our current place in case we need to roll-back the seek. */ oldPosHigh = 0; oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT); | | | | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | /* * Save our current place in case we need to roll-back the seek. */ oldPosHigh = 0; oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT); if (oldPos == (LONG) INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); *errorCodePtr = errno; return -1; } } newPosHigh = (offset < 0 ? -1 : 0); newPos = SetFilePointer(infoPtr->handle, offset, &newPosHigh, moveMethod); if (newPos == (LONG) INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); *errorCodePtr = errno; return -1; } |
︙ | ︙ | |||
543 544 545 546 547 548 549 | } else { moveMethod = FILE_END; } newPosHigh = Tcl_WideAsLong(offset >> 32); newPos = SetFilePointer(infoPtr->handle, Tcl_WideAsLong(offset), &newPosHigh, moveMethod); | | | > | 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 | } else { moveMethod = FILE_END; } newPosHigh = Tcl_WideAsLong(offset >> 32); newPos = SetFilePointer(infoPtr->handle, Tcl_WideAsLong(offset), &newPosHigh, moveMethod); if (newPos == (LONG) INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); *errorCodePtr = errno; return -1; } } return (((Tcl_WideInt)((unsigned)newPos)) | (Tcl_LongAsWide(newPosHigh) << 32)); } /* *---------------------------------------------------------------------- * * FileTruncateProc -- * |
︙ | ︙ | |||
585 586 587 588 589 590 591 | /* * Save where we were... */ oldPosHigh = 0; oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT); | | > | > | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 | /* * Save where we were... */ oldPosHigh = 0; oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT); if (oldPos == (LONG) INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); return errno; } } /* * Move to where we want to truncate */ newPosHigh = Tcl_WideAsLong(length >> 32); newPos = SetFilePointer(infoPtr->handle, Tcl_WideAsLong(length), &newPosHigh, FILE_BEGIN); if (newPos == (LONG) INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); return errno; } } /* |
︙ | ︙ | |||
658 659 660 661 662 663 664 | { FileInfo *infoPtr = instanceData; DWORD bytesRead; *errorCode = 0; /* | | | | | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | { FileInfo *infoPtr = instanceData; DWORD bytesRead; *errorCode = 0; /* * TODO: This comment appears to be out of date. We *do* have a console * driver, over in tclWinConsole.c. After some Windows developer confirms, * this comment should be revised. * * Note that we will block on reads from a console buffer until a full * line has been entered. The only way I know of to get around this is to * write a console driver. We should probably do this at some point, but * for now, we just block. The same problem exists for files being read * over the network. */ |
︙ | ︙ | |||
717 718 719 720 721 722 723 | *errorCode = 0; /* * If we are writing to a file that was opened with O_APPEND, we need to * seek to the end of the file before writing the current buffer. */ | | | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 | *errorCode = 0; /* * If we are writing to a file that was opened with O_APPEND, we need to * seek to the end of the file before writing the current buffer. */ if (TEST_FLAG(infoPtr->flags, FILE_APPEND)) { SetFilePointer(infoPtr->handle, 0, NULL, FILE_END); } if (WriteFile(infoPtr->handle, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) { TclWinConvertError(GetLastError()); *errorCode = errno; |
︙ | ︙ | |||
794 795 796 797 798 799 800 | FileGetHandleProc( ClientData instanceData, /* The file state. */ int direction, /* TCL_READABLE or TCL_WRITABLE */ ClientData *handlePtr) /* Where to store the handle. */ { FileInfo *infoPtr = instanceData; | | < < < > > > | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 | FileGetHandleProc( ClientData instanceData, /* The file state. */ int direction, /* TCL_READABLE or TCL_WRITABLE */ ClientData *handlePtr) /* Where to store the handle. */ { FileInfo *infoPtr = instanceData; if (!TEST_FLAG(direction, infoPtr->validMask)) { return TCL_ERROR; } *handlePtr = (ClientData) infoPtr->handle; return TCL_OK; } /* *---------------------------------------------------------------------- * * TclpOpenFileChannel -- * |
︙ | ︙ | |||
839 840 841 842 843 844 845 | const TCHAR *nativeName; HANDLE handle; char channelName[16 + TCL_INTEGER_SPACE]; TclFile readFile = NULL, writeFile = NULL; nativeName = Tcl_FSGetNativePath(pathPtr); if (nativeName == NULL) { | | | | | | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 | const TCHAR *nativeName; HANDLE handle; char channelName[16 + TCL_INTEGER_SPACE]; TclFile readFile = NULL, writeFile = NULL; nativeName = Tcl_FSGetNativePath(pathPtr); if (nativeName == NULL) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open \"%s\": filename is invalid on this platform", TclGetString(pathPtr))); } return NULL; } switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: accessMode = GENERIC_READ; |
︙ | ︙ | |||
890 891 892 893 894 895 896 | break; default: createMode = OPEN_EXISTING; break; } /* | | | | | < | > | | < | | > > | | | 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 | break; default: createMode = OPEN_EXISTING; break; } /* * [2413550] Avoid double-open of serial ports on Windows. Special * handling for Windows serial ports by a "name-hint" to directly open it * with the OVERLAPPED flag set. */ if (NativeIsComPort(nativeName)) { handle = TclWinSerialOpen(INVALID_HANDLE_VALUE, nativeName, accessMode); if (handle == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open serial \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); } return NULL; } /* * For natively named Windows serial ports we are done. */ channel = TclWinOpenSerialChannel(handle, channelName, channelPermissions); return channel; } /* * If the file is being created, get the file attributes from the * permissions argument, else use the existing file attributes. */ if (TEST_FLAG(mode, O_CREAT)) { if (TEST_FLAG(permissions, S_IWRITE)) { flags = FILE_ATTRIBUTE_NORMAL; } else { flags = FILE_ATTRIBUTE_READONLY; } } else { flags = GetFileAttributes(nativeName); if (flags == 0xFFFFFFFF) { |
︙ | ︙ | |||
951 952 953 954 955 956 957 | handle = CreateFile(nativeName, accessMode, shareMode, NULL, createMode, flags, (HANDLE) NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); if ((err & 0xffffL) == ERROR_OPEN_FAILED) { | > | | | | | | | | | > | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 | handle = CreateFile(nativeName, accessMode, shareMode, NULL, createMode, flags, (HANDLE) NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); if ((err & 0xffffL) == ERROR_OPEN_FAILED) { err = TEST_FLAG(mode, O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND; } TclWinConvertError(err); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); } return NULL; } channel = NULL; switch (FileGetType(handle)) { case FILE_TYPE_SERIAL: /* * Natively named serial ports "com1-9", "\\\\.\\comXX" are already * done with the code above. Here we handle all other serial port * names. * * Reopen channel for OVERLAPPED operation. Normally this shouldn't * fail, because the channel exists. */ handle = TclWinSerialOpen(handle, nativeName, accessMode); if (handle == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't reopen serial \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); } return NULL; } channel = TclWinOpenSerialChannel(handle, channelName, channelPermissions); break; case FILE_TYPE_CONSOLE: channel = TclWinOpenConsoleChannel(handle, channelName, channelPermissions); break; case FILE_TYPE_PIPE: if (TEST_FLAG(channelPermissions, TCL_READABLE)) { readFile = TclWinMakeFile(handle); } if (TEST_FLAG(channelPermissions, TCL_WRITABLE)) { writeFile = TclWinMakeFile(handle); } channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL); break; case FILE_TYPE_CHAR: case FILE_TYPE_DISK: case FILE_TYPE_UNKNOWN: channel = TclWinOpenFileChannel(handle, channelName, channelPermissions, TEST_FLAG(mode, O_APPEND) ? FILE_APPEND : 0); break; default: /* * The handle is of an unknown type, probably /dev/nul equivalent or * possibly a closed handle. */ |
︙ | ︙ | |||
1070 1071 1072 1073 1074 1075 1076 | case FILE_TYPE_SERIAL: channel = TclWinOpenSerialChannel(handle, channelName, mode); break; case FILE_TYPE_CONSOLE: channel = TclWinOpenConsoleChannel(handle, channelName, mode); break; case FILE_TYPE_PIPE: | | | | 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | case FILE_TYPE_SERIAL: channel = TclWinOpenSerialChannel(handle, channelName, mode); break; case FILE_TYPE_CONSOLE: channel = TclWinOpenConsoleChannel(handle, channelName, mode); break; case FILE_TYPE_PIPE: if (TEST_FLAG(mode, TCL_READABLE)) { readFile = TclWinMakeFile(handle); } if (TEST_FLAG(mode, TCL_WRITABLE)) { writeFile = TclWinMakeFile(handle); } channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL); break; case FILE_TYPE_DISK: case FILE_TYPE_CHAR: |
︙ | ︙ | |||
1520 1521 1522 1523 1524 1525 1526 | } /* *---------------------------------------------------------------------- * * NativeIsComPort -- * | | | | | > | 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 | } /* *---------------------------------------------------------------------- * * NativeIsComPort -- * * Determines if a path refers to a Windows serial port. A simple and * efficient solution is to use a "name hint" to detect COM ports by * their filename instead of resorting to a syscall to detect serialness * after the fact. * * The following patterns cover common serial port names: * COM[1-9] * \\.\COM[0-9]+ * * Results: * 1 = serial port, 0 = not. * |
︙ | ︙ | |||
1545 1546 1547 1548 1549 1550 1551 | const WCHAR *p = (const WCHAR *) nativePath; int i, len = wcslen(p); /* * 1. Look for com[1-9]:? */ | | | | | | | | | | 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 | const WCHAR *p = (const WCHAR *) nativePath; int i, len = wcslen(p); /* * 1. Look for com[1-9]:? */ if ((len == 4) && (_wcsnicmp(p, L"com", 3) == 0)) { /* * The 4th character must be a digit 1..9 */ if ((p[3] < L'1') || (p[3] > L'9')) { return 0; } return 1; } /* * 2. Look for \\.\com[0-9]+ */ if ((len >= 8) && (_wcsnicmp(p, L"\\\\.\\com", 7) == 0)) { /* * Charaters 8..end must be a digits 0..9 */ for (i=7; i<len; i++) { if ((p[i] < '0') || (p[i] > '9')) { return 0; } } return 1; } return 0; } |
︙ | ︙ |