1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: ziodevsc.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* %stdxxx IODevice implementation using callouts for PostScript interpreter */
22
#include "gxiodev.h" /* must come after stream.h */
23
/* and before files.h */
29
/* Define the special devices. */
30
const char iodev_dtype_stdio[] = "Special";
31
#define iodev_special(dname, init, open) {\
32
dname, iodev_dtype_stdio,\
33
{ init, open, iodev_no_open_file, iodev_no_fopen, iodev_no_fclose,\
34
iodev_no_delete_file, iodev_no_rename_file, iodev_no_file_status,\
35
iodev_no_enumerate_files, NULL, NULL,\
36
iodev_no_get_params, iodev_no_put_params\
41
* We need the current context pointer for accessing / opening the %std
42
* IODevices. However, this is not available to the open routine.
43
* Therefore, we use the hack of storing this pointer in the IODevice state
44
* pointer just before calling the open routines. We clear the pointer
45
* immediately afterwards so as not to wind up with dangling references.
48
#define STDIN_BUF_SIZE 1024
49
static iodev_proc_init(stdin_init);
50
static iodev_proc_open_device(stdin_open);
51
const gx_io_device gs_iodev_stdin =
52
iodev_special("%stdin%", stdin_init, stdin_open);
54
#define STDOUT_BUF_SIZE 128
55
static iodev_proc_open_device(stdout_open);
56
const gx_io_device gs_iodev_stdout =
57
iodev_special("%stdout%", iodev_no_init, stdout_open);
59
#define STDERR_BUF_SIZE 128
60
static iodev_proc_open_device(stderr_open);
61
const gx_io_device gs_iodev_stderr =
62
iodev_special("%stderr%", iodev_no_init, stderr_open);
64
/* ------- %stdin, %stdout, and %stderr ------ */
67
* According to Adobe, it is legal to close the %std... files and then
68
* re-open them later. However, the re-opened file object is not 'eq' to
69
* the original file object (in our implementation, it has a different
70
* read_id or write_id). This is performed in 'file_close_file' by the
71
* call to file_close_disable.
75
s_stdin_read_process(stream_state *, stream_cursor_read *,
76
stream_cursor_write *, bool);
79
stdin_init(gx_io_device * iodev, gs_memory_t * mem)
81
mem->gs_lib_ctx->stdin_is_interactive = true;
85
/* Read from stdin into the buffer. */
86
/* If interactive, only read one character. */
88
s_stdin_read_process(stream_state * st, stream_cursor_read * ignore_pr,
89
stream_cursor_write * pw, bool last)
91
int wcount = (int)(pw->limit - pw->ptr);
93
gs_memory_t *mem = st->memory;
99
if (mem->gs_lib_ctx->stdin_fn)
100
count = (*mem->gs_lib_ctx->stdin_fn)
101
(mem->gs_lib_ctx->caller_handle, (char *)pw->ptr + 1,
102
mem->gs_lib_ctx->stdin_is_interactive ? 1 : wcount);
104
count = gp_stdin_read((char *)pw->ptr + 1, wcount,
105
mem->gs_lib_ctx->stdin_is_interactive,
106
mem->gs_lib_ctx->fstdin);
108
pw->ptr += (count < 0) ? 0 : count;
109
return ((count < 0) ? ERRC : (count == 0) ? EOFC : count);
113
stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
116
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
119
if (!streq1(access, 'r'))
120
return_error(e_invalidfileaccess);
121
if (file_is_invalid(s, &ref_stdin)) {
122
/****** stdin SHOULD NOT LINE-BUFFER ******/
123
gs_memory_t *mem = imemory_system;
125
static const stream_procs p = {
126
s_std_noavailable, s_std_noseek, s_std_read_reset,
127
s_std_read_flush, file_close_file, s_stdin_read_process
130
s = file_alloc_stream(mem, "stdin_open(stream)");
132
/* We want stdin to read only one character at a time, */
133
/* but it must have a substantial buffer, in case it is used */
134
/* by a stream that requires more than one input byte */
135
/* to make progress. */
136
buf = gs_alloc_bytes(mem, STDIN_BUF_SIZE, "stdin_open(buffer)");
137
if (s == 0 || buf == 0)
138
return_error(e_VMerror);
140
s_std_init(s, buf, STDIN_BUF_SIZE, &p, s_mode_read);
142
s->file_modes = s->modes;
144
s->file_limit = max_long;
145
s->save_close = s_std_null;
146
make_file(&ref_stdin, a_readonly | avm_system, s->read_id, s);
153
/* This is the public routine for getting the stdin stream. */
155
zget_stdin(i_ctx_t *i_ctx_p, stream ** ps)
161
if (file_is_valid(s, &ref_stdin)) {
165
iodev = gs_findiodevice((const byte *)"%stdin", 6);
166
iodev->state = i_ctx_p;
167
code = (*iodev->procs.open_device)(iodev, "r", ps, imemory_system);
172
/* Test whether a stream is stdin. */
174
zis_stdin(const stream *s)
176
return (s_is_valid(s) && s->procs.process == s_stdin_read_process);
179
/* Write a buffer to stdout, potentially writing to callback */
181
s_stdout_write_process(stream_state * st, stream_cursor_read *pr,
182
stream_cursor_write *ignore_pw, bool last)
184
uint count = pr->limit - pr->ptr;
189
written = outwrite(st->memory, (const char *)pr->ptr + 1, count);
197
stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
200
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
203
if (!streq1(access, 'w'))
204
return_error(e_invalidfileaccess);
205
if (file_is_invalid(s, &ref_stdout)) {
206
gs_memory_t *mem = imemory_system;
208
static const stream_procs p = {
209
s_std_noavailable, s_std_noseek, s_std_write_reset,
210
s_std_write_flush, file_close_file, s_stdout_write_process
213
s = file_alloc_stream(mem, "stdout_open(stream)");
214
buf = gs_alloc_bytes(mem, STDOUT_BUF_SIZE, "stdout_open(buffer)");
215
if (s == 0 || buf == 0)
216
return_error(e_VMerror);
217
s_std_init(s, buf, STDOUT_BUF_SIZE, &p, s_mode_write);
219
s->file_modes = s->modes;
220
s->file_offset = 0; /* in case we switch to reading later */
221
s->file_limit = max_long; /* ibid. */
222
s->save_close = s->procs.flush;
223
make_file(&ref_stdout, a_write | avm_system, s->write_id, s);
231
/* This is the public routine for getting the stdout stream. */
233
zget_stdout(i_ctx_t *i_ctx_p, stream ** ps)
239
if (file_is_valid(s, &ref_stdout)) {
243
iodev = gs_findiodevice((const byte *)"%stdout", 7);
244
iodev->state = i_ctx_p;
245
code = (*iodev->procs.open_device)(iodev, "w", ps, imemory_system);
250
/* Write a buffer to stderr, potentially writing to callback */
252
s_stderr_write_process(stream_state * st, stream_cursor_read *pr,
253
stream_cursor_write *ignore_pw, bool last)
255
uint count = pr->limit - pr->ptr;
260
written = errwrite((const char *)(pr->ptr + 1), count);
268
stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
271
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
274
if (!streq1(access, 'w'))
275
return_error(e_invalidfileaccess);
276
if (file_is_invalid(s, &ref_stderr)) {
277
gs_memory_t *mem = imemory_system;
279
static const stream_procs p = {
280
s_std_noavailable, s_std_noseek, s_std_write_reset,
281
s_std_write_flush, file_close_file, s_stderr_write_process
284
s = file_alloc_stream(mem, "stderr_open(stream)");
285
buf = gs_alloc_bytes(mem, STDERR_BUF_SIZE, "stderr_open(buffer)");
286
if (s == 0 || buf == 0)
287
return_error(e_VMerror);
288
s_std_init(s, buf, STDERR_BUF_SIZE, &p, s_mode_write);
290
s->file_modes = s->modes;
291
s->file_offset = 0; /* in case we switch to reading later */
292
s->file_limit = max_long; /* ibid. */
293
s->save_close = s->procs.flush;
294
make_file(&ref_stderr, a_write | avm_system, s->write_id, s);
302
/* This is the public routine for getting the stderr stream. */
304
zget_stderr(i_ctx_t *i_ctx_p, stream ** ps)
310
if (file_is_valid(s, &ref_stderr)) {
314
iodev = gs_findiodevice((const byte *)"%stderr", 7);
315
iodev->state = i_ctx_p;
316
code = (*iodev->procs.open_device)(iodev, "w", ps, imemory_system);