printf() and stdio in the Julia runtime

    … and corresponding output functions:

    1. int jl_printf(uv_stream_t *s, const char *format, ...);
    2. int jl_vprintf(uv_stream_t *s, const char *format, va_list args);

    These printf functions are used by the .c files in the src/ and ui/ directories wherever stdio is needed to ensure that output buffering is handled in a unified way.

    In special cases, like signal handlers, where the full libuv infrastructure is too heavy, jl_safe_printf() can be used to directly to STDERR_FILENO:

    Base.stdin, and Base.stderr are bound to the JL_STD* libuv streams defined in the runtime.

    reinit_stdio() uses to retrieve pointers to JL_STD* and calls jl_uv_handle_type() to inspect the type of each stream. It then creates a Julia , Base.TTY or Base.PipeEndpoint object to represent each stream, e.g.:

    1. Tuple{Base.TTY,Base.TTY,Base.TTY}
    2. $ julia -e 'println(typeof((stdin, stdout, stderr)))' < /dev/null 2>/dev/null
    3. Tuple{IOStream,Base.TTY,IOStream}
    4. $ echo hello | julia -e 'println(typeof((stdin, stdout, stderr)))' | cat

    The Base.read and methods for these streams use ccall to call libuv wrappers in src/jl_uv.c, e.g.:

    The libuv streams relied upon by jl_printf() etc., are not available until midway through initialization of the runtime (see init.c, init_stdio()). Error messages or warnings that need to be printed before this are routed to the standard C library fwrite() function by the following mechanism:

    In sys.c, the JL_STD* stream pointers are statically initialized to integer constants: STD*_FILENO (0, 1 and 2). In jl_uv.c the jl_uv_puts() function checks its uv_stream_t* stream argument and calls fwrite() if stream is set to or STDERR_FILENO.

    The src/support/ios.c library is inherited from . It provides cross-platform buffered file IO and in-memory temporary buffers.

    ios.c is still used by:

    • src/flisp/*.c
    • src/dump.c – for serialization file IO and for memory buffers.
    • src/staticdata.c – for serialization file IO and for memory buffers.
    • base/iostream.jl – for file IO (see base/fs.jl for libuv equivalent).

    Use of ios.c in these modules is mostly self-contained and separated from the libuv I/O system. However, there is one place where femtolisp calls through to jl_printf() with a legacy ios_t stream.

    There is a hack in ios.h that makes the ios_t.bm field line up with the uv_stream_t.type and ensures that the values used for ios_t.bm to not overlap with valid UV_HANDLE_TYPE values. This allows uv_stream_t pointers to point to ios_t streams.

    1. if (stream->type > UV_HANDLE_TYPE_MAX) {