@@ -1127,105 +1127,119 @@ function _fd(x::Union{LibuvStream, LibuvServer})
1127
1127
return fd[]
1128
1128
end
1129
1129
1130
- for (x, writable, unix_fd, c_symbol) in
1131
- ((:stdin , false , 0 , :jl_uv_stdin ),
1132
- (:stdout , true , 1 , :jl_uv_stdout ),
1133
- (:stderr , true , 2 , :jl_uv_stderr ))
1134
- f = Symbol (" redirect_" , lowercase (string (x)))
1135
- _f = Symbol (" _" , f)
1136
- @eval begin
1137
- function ($ _f)(stream)
1138
- global $ x
1139
- posix_fd = _fd (stream)
1140
- @static if Sys. iswindows ()
1141
- ccall (:SetStdHandle , stdcall, Int32, (Int32, OS_HANDLE),
1142
- $ (- 10 - unix_fd), Libc. _get_osfhandle (posix_fd))
1143
- end
1144
- dup (posix_fd, RawFD ($ unix_fd))
1145
- $ x = stream
1146
- nothing
1147
- end
1148
- function ($ f)(handle:: Union{LibuvStream, IOStream} )
1149
- $ (_f)(handle)
1150
- unsafe_store! (cglobal ($ (Expr (:quote , c_symbol)), Ptr{Cvoid}),
1151
- handle. handle)
1152
- return handle
1153
- end
1154
- function ($ f)()
1155
- p = link_pipe! (Pipe ())
1156
- read, write = p. out, p. in
1157
- ($ f)($ (writable ? :write : :read ))
1158
- return (read, write)
1159
- end
1160
- function ($ f)(:: DevNull )
1161
- global $ x
1162
- nulldev = @static Sys. iswindows () ? " NUL" : " /dev/null"
1163
- handle = open (nulldev, write= $ writable)
1164
- $ (_f)(handle)
1165
- close (handle) # handle has been dup'ed in $(_f)
1166
- $ x = devnull
1167
- return devnull
1168
- end
1169
- function ($ f)(io:: IOContext )
1170
- io2, _dict = unwrapcontext (io)
1171
- ($ f)(io2)
1172
- global $ x = io
1173
- return io
1130
+ struct redirect_stdio <: Function
1131
+ unix_fd:: Int
1132
+ writable:: Bool
1133
+ end
1134
+ for (f, writable, unix_fd) in
1135
+ ((:redirect_stdin , false , 0 ),
1136
+ (:redirect_stdout , true , 1 ),
1137
+ (:redirect_stderr , true , 2 ))
1138
+ @eval const ($ f) = redirect_stdio ($ unix_fd, $ writable)
1139
+ end
1140
+ function _redirect_io_libc (stream, unix_fd:: Int )
1141
+ posix_fd = _fd (stream)
1142
+ @static if Sys. iswindows ()
1143
+ if 0 <= unix_fd <= 2
1144
+ ccall (:SetStdHandle , stdcall, Int32, (Int32, OS_HANDLE),
1145
+ - 10 - unix_fd, Libc. _get_osfhandle (posix_fd))
1174
1146
end
1175
1147
end
1148
+ dup (posix_fd, RawFD (unix_fd))
1149
+ nothing
1150
+ end
1151
+ function _redirect_io_global (io, unix_fd:: Int )
1152
+ unix_fd == 0 && (global stdin = io)
1153
+ unix_fd == 1 && (global stdout = io)
1154
+ unix_fd == 2 && (global stderr = io)
1155
+ nothing
1156
+ end
1157
+ function (f:: redirect_stdio )(handle:: Union{LibuvStream, IOStream} )
1158
+ _redirect_io_libc (handle, f. unix_fd)
1159
+ c_sym = f. unix_fd == 0 ? cglobal (:jl_uv_stdin , Ptr{Cvoid}) :
1160
+ f. unix_fd == 1 ? cglobal (:jl_uv_stdout , Ptr{Cvoid}) :
1161
+ f. unix_fd == 2 ? cglobal (:jl_uv_stderr , Ptr{Cvoid}) :
1162
+ C_NULL
1163
+ c_sym == C_NULL || unsafe_store! (c_sym, handle. handle)
1164
+ _redirect_io_global (handle, f. unix_fd)
1165
+ return handle
1166
+ end
1167
+ function (f:: redirect_stdio )(:: DevNull )
1168
+ nulldev = @static Sys. iswindows () ? " NUL" : " /dev/null"
1169
+ handle = open (nulldev, write= f. writable)
1170
+ _redirect_io_libc (handle, f. unix_fd)
1171
+ close (handle) # handle has been dup'ed in _redirect_io_libc
1172
+ _redirect_io_global (devnull , f. unix_fd)
1173
+ return devnull
1174
+ end
1175
+ function (f:: redirect_stdio )(io:: AbstractPipe )
1176
+ io2 = (f. writable ? pipe_writer : pipe_reader)(io)
1177
+ f (io2)
1178
+ _redirect_io_global (io, f. unix_fd)
1179
+ return io
1180
+ end
1181
+ function (f:: redirect_stdio )(p:: Pipe )
1182
+ if p. in. status == StatusInit && p. out. status == StatusInit
1183
+ link_pipe! (p)
1184
+ end
1185
+ io2 = getfield (p, f. writable ? :in : :out )
1186
+ f (io2)
1187
+ return p
1176
1188
end
1189
+ (f:: redirect_stdio )() = f (Pipe ())
1190
+
1191
+ # Deprecate these in v2 (redirect_stdio support)
1192
+ iterate (p:: Pipe ) = (p. out, 1 )
1193
+ iterate (p:: Pipe , i:: Int ) = i == 1 ? (p. in, 2 ) : nothing
1194
+ getindex (p:: Pipe , key:: Int ) = key == 1 ? p. out : key == 2 ? p. in : throw (KeyError (key))
1177
1195
1178
1196
"""
1179
- redirect_stdout([stream]) -> (rd, wr)
1197
+ redirect_stdout([stream]) -> stream
1180
1198
1181
1199
Create a pipe to which all C and Julia level [`stdout`](@ref) output
1182
- will be redirected.
1183
- Returns a tuple `(rd, wr)` representing the pipe ends.
1200
+ will be redirected. Return a stream representing the pipe ends.
1184
1201
Data written to [`stdout`](@ref) may now be read from the `rd` end of
1185
- the pipe. The `wr` end is given for convenience in case the old
1186
- [`stdout`](@ref) object was cached by the user and needs to be replaced
1187
- elsewhere.
1188
-
1189
- If called with the optional `stream` argument, then returns `stream` itself.
1202
+ the pipe.
1190
1203
1191
1204
!!! note
1192
- `stream` must be an `IOStream`, a `TTY`, a `Pipe`, a socket, or `devnull`.
1205
+ `stream` must be a compatible objects, such as an `IOStream`, `TTY`,
1206
+ `Pipe`, socket, or `devnull`.
1193
1207
"""
1194
1208
redirect_stdout
1195
1209
1196
1210
"""
1197
- redirect_stderr([stream]) -> (rd, wr)
1211
+ redirect_stderr([stream]) -> stream
1198
1212
1199
1213
Like [`redirect_stdout`](@ref), but for [`stderr`](@ref).
1200
1214
1201
1215
!!! note
1202
- `stream` must be an `IOStream`, a `TTY`, a `Pipe`, a socket, or `devnull`.
1216
+ `stream` must be a compatible objects, such as an `IOStream`, `TTY`,
1217
+ `Pipe`, socket, or `devnull`.
1203
1218
"""
1204
1219
redirect_stderr
1205
1220
1206
1221
"""
1207
- redirect_stdin([stream]) -> (rd, wr)
1222
+ redirect_stdin([stream]) -> stream
1208
1223
1209
1224
Like [`redirect_stdout`](@ref), but for [`stdin`](@ref).
1210
- Note that the order of the return tuple is still `(rd, wr)`,
1211
- i.e. data to be read from [`stdin`](@ref) may be written to `wr`.
1225
+ Note that the direction of the stream is reversed.
1212
1226
1213
1227
!!! note
1214
- `stream` must be an `IOStream`, a `TTY`, a `Pipe`, a socket, or `devnull`.
1228
+ `stream` must be a compatible objects, such as an `IOStream`, `TTY`,
1229
+ `Pipe`, socket, or `devnull`.
1215
1230
"""
1216
1231
redirect_stdin
1217
1232
1218
- for (F,S) in ((:redirect_stdin , :stdin ), (:redirect_stdout , :stdout ), (:redirect_stderr , :stderr ))
1219
- @eval function $F (f:: Function , stream)
1220
- STDOLD = $ S
1221
- local ret
1222
- $ F (stream)
1223
- try
1224
- ret = f ()
1225
- finally
1226
- $ F (STDOLD)
1227
- end
1228
- ret
1233
+ function (f:: redirect_stdio )(thunk:: Function , stream)
1234
+ stdold = f. unix_fd == 0 ? stdin :
1235
+ f. unix_fd == 1 ? stdout :
1236
+ f. unix_fd == 2 ? stderr :
1237
+ throw (ArgumentError (" Not implemented to get old handle of fd except for stdio" ))
1238
+ f (stream)
1239
+ try
1240
+ return thunk ()
1241
+ finally
1242
+ f (stdold)
1229
1243
end
1230
1244
end
1231
1245
@@ -1234,9 +1248,6 @@ end
1234
1248
1235
1249
Run the function `f` while redirecting [`stdout`](@ref) to `stream`.
1236
1250
Upon completion, [`stdout`](@ref) is restored to its prior setting.
1237
-
1238
- !!! note
1239
- `stream` must be a `TTY`, a `Pipe`, or a socket.
1240
1251
"""
1241
1252
redirect_stdout (f:: Function , stream)
1242
1253
@@ -1245,9 +1256,6 @@ redirect_stdout(f::Function, stream)
1245
1256
1246
1257
Run the function `f` while redirecting [`stderr`](@ref) to `stream`.
1247
1258
Upon completion, [`stderr`](@ref) is restored to its prior setting.
1248
-
1249
- !!! note
1250
- `stream` must be a `TTY`, a `Pipe`, or a socket.
1251
1259
"""
1252
1260
redirect_stderr (f:: Function , stream)
1253
1261
@@ -1256,9 +1264,6 @@ redirect_stderr(f::Function, stream)
1256
1264
1257
1265
Run the function `f` while redirecting [`stdin`](@ref) to `stream`.
1258
1266
Upon completion, [`stdin`](@ref) is restored to its prior setting.
1259
-
1260
- !!! note
1261
- `stream` must be a `TTY`, a `Pipe`, or a socket.
1262
1267
"""
1263
1268
redirect_stdin (f:: Function , stream)
1264
1269
0 commit comments