Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 2001 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: ziodevsc.c,v 1.7 2004/08/04 19:36:13 stefan Exp $ */
18
/* %stdxxx IODevice implementation using callouts for PostScript interpreter */
19
#include "stdio_.h"
20
#include "ghost.h"
21
#include "gpcheck.h"
22
#include "oper.h"
23
#include "stream.h"
24
#include "gxiodev.h"		/* must come after stream.h */
25
				/* and before files.h */
26
#include "istream.h"
27
#include "files.h"
28
#include "ifilter.h"
29
#include "store.h"
30
 
31
/* Define the special devices. */
32
const char iodev_dtype_stdio[] = "Special";
33
#define iodev_special(dname, init, open) {\
34
    dname, iodev_dtype_stdio,\
35
	{ init, open, iodev_no_open_file, iodev_no_fopen, iodev_no_fclose,\
36
	  iodev_no_delete_file, iodev_no_rename_file, iodev_no_file_status,\
37
	  iodev_no_enumerate_files, NULL, NULL,\
38
	  iodev_no_get_params, iodev_no_put_params\
39
	}\
40
}
41
 
42
/*
43
 * We need the current context pointer for accessing / opening the %std
44
 * IODevices.  However, this is not available to the open routine.
45
 * Therefore, we use the hack of storing this pointer in the IODevice state
46
 * pointer just before calling the open routines.  We clear the pointer
47
 * immediately afterwards so as not to wind up with dangling references.
48
 */
49
 
50
#define STDIN_BUF_SIZE 128
51
private iodev_proc_init(stdin_init);
52
private iodev_proc_open_device(stdin_open);
53
const gx_io_device gs_iodev_stdin =
54
    iodev_special("%stdin%", stdin_init, stdin_open);
55
 
56
#define STDOUT_BUF_SIZE 128
57
private iodev_proc_open_device(stdout_open);
58
const gx_io_device gs_iodev_stdout =
59
    iodev_special("%stdout%", iodev_no_init, stdout_open);
60
 
61
#define STDERR_BUF_SIZE 128
62
private iodev_proc_open_device(stderr_open);
63
const gx_io_device gs_iodev_stderr =
64
    iodev_special("%stderr%", iodev_no_init, stderr_open);
65
 
66
/* ------- %stdin, %stdout, and %stderr ------ */
67
 
68
/*
69
 * According to Adobe, it is legal to close the %std... files and then
70
 * re-open them later.  However, the re-opened file object is not 'eq' to
71
 * the original file object (in our implementation, it has a different
72
 * read_id or write_id).
73
 */
74
 
75
private int
76
stdio_close(stream *s)
77
{
78
    int code = (*s->save_close)(s);
79
    if (code)
80
	return code;
81
    /* Increment the IDs to prevent further access. */
82
    s->read_id = s->write_id = (s->read_id | s->write_id) + 1;
83
    return 0;
84
}
85
 
86
private int
87
stdin_init(gx_io_device * iodev, gs_memory_t * mem)
88
{
89
    mem->gs_lib_ctx->stdin_is_interactive = true;
90
    return 0;
91
}
92
 
93
/* stdin stream implemented as procedure */
94
private int
95
stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
96
	    gs_memory_t * mem)
97
{
98
    i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state;	/* see above */
99
    stream *s;
100
    int code;
101
 
102
    if (!streq1(access, 'r'))
103
	return_error(e_invalidfileaccess);
104
    if (file_is_invalid(s, &ref_stdin)) {
105
	/* procedure source */
106
	gs_ref_memory_t *imem = (gs_ref_memory_t *)imemory_system;
107
	ref rint;
108
 
109
	/* The procedure isn't used. */
110
	/* Set it to literal 0 to recognised stdin. */
111
	make_int(&rint, 0);
112
 
113
	/* implement stdin as a procedure */
114
	code = sread_proc(&rint, &s, imem);
115
	if (code < 0)
116
	    return code;
117
	s->save_close = s_std_null;
118
	s->procs.close = stdio_close;
119
	/* allocate buffer */
120
	if (s->cbuf == 0) {
121
	    int len = STDIN_BUF_SIZE;
122
	    byte *buf = gs_alloc_bytes((gs_memory_t *)imemory_system,
123
	    		len, "stdin_open");
124
	    if (buf == 0)
125
		return_error(e_VMerror);
126
	    s->cbuf = buf;
127
	    s->srptr = s->srlimit = s->swptr = buf - 1;
128
	    s->swlimit = buf - 1 + len;
129
	    s->bsize = s->cbsize = len;
130
	}
131
	s->state->min_left = 0;
132
	make_file(&ref_stdin, a_read | avm_system, s->read_id, s);
133
	*ps = s;
134
	return 1;
135
    }
136
    *ps = s;
137
    return 0;
138
}
139
/* This is the public routine for getting the stdin stream. */
140
int
141
zget_stdin(i_ctx_t *i_ctx_p, stream ** ps)
142
{
143
    stream *s;
144
    gx_io_device *iodev;
145
    int code;
146
 
147
    if (file_is_valid(s, &ref_stdin)) {
148
	*ps = s;
149
	return 0;
150
    }
151
    iodev = gs_findiodevice((const byte *)"%stdin", 6);
152
    iodev->state = i_ctx_p;
153
    code = (*iodev->procs.open_device)(iodev, "r", ps, imemory_system);
154
    iodev->state = NULL;
155
    return min(code, 0);
156
}
157
/* Test whether a stream is stdin. */
158
bool
159
zis_stdin(const stream *s)
160
{
161
    /* Only stdin should be a procedure based stream, opened for
162
     * reading and with a literal 0 as the procedure.
163
     */
164
    if (s_is_valid(s) && s_is_reading(s) && s_is_proc(s)) {
165
        stream_proc_state *state = (stream_proc_state *)s->state;
166
	if ((r_type(&(state->proc)) == t_integer) &&
167
		(state->proc.value.intval == 0))
168
	    return true;
169
    }
170
    return false;
171
}
172
 
173
/* stdout stream implemented as procedure */
174
private int
175
stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
176
	    gs_memory_t * mem)
177
{
178
    i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state;	/* see above */
179
    stream *s;
180
    int code;
181
 
182
    if (!streq1(access, 'w'))
183
	return_error(e_invalidfileaccess);
184
    if (file_is_invalid(s, &ref_stdout)) {
185
	/* procedure source */
186
	gs_ref_memory_t *imem = (gs_ref_memory_t *)imemory_system;
187
	ref rint;
188
 
189
	/* The procedure isn't used. */
190
	/* Set it to literal 1 to recognised stdout. */
191
	make_int(&rint, 1);
192
 
193
	/* implement stdout as a procedure */
194
	code = swrite_proc(&rint, &s, imem);
195
	if (code < 0)
196
	    return code;
197
	s->save_close = s->procs.flush;
198
	s->procs.close = stdio_close;
199
	/* allocate buffer */
200
	if (s->cbuf == 0) {
201
	    int len = STDOUT_BUF_SIZE;
202
	    byte *buf = gs_alloc_bytes((gs_memory_t *)imemory_system,
203
	    		len, "stdout_open");
204
	    if (buf == 0)
205
		return_error(e_VMerror);
206
	    s->cbuf = buf;
207
	    s->srptr = s->srlimit = s->swptr = buf - 1;
208
	    s->swlimit = buf - 1 + len;
209
	    s->bsize = s->cbsize = len;
210
	}
211
	make_file(&ref_stdout, a_write | avm_system, s->write_id, s);
212
	*ps = s;
213
	return 1;
214
    }
215
    *ps = s;
216
    return 0;
217
}
218
/* This is the public routine for getting the stdout stream. */
219
int
220
zget_stdout(i_ctx_t *i_ctx_p, stream ** ps)
221
{
222
    stream *s;
223
    gx_io_device *iodev;
224
    int code;
225
 
226
    if (file_is_valid(s, &ref_stdout)) {
227
	*ps = s;
228
	return 0;
229
    }
230
    iodev = gs_findiodevice((const byte *)"%stdout", 7);
231
    iodev->state = i_ctx_p;
232
    code = (*iodev->procs.open_device)(iodev, "w", ps, imemory_system);
233
    iodev->state = NULL;
234
    return min(code, 0);
235
}
236
 
237
/* stderr stream implemented as procedure */
238
private int
239
stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
240
	    gs_memory_t * mem)
241
{
242
    i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state;	/* see above */
243
    stream *s;
244
    int code;
245
 
246
    if (!streq1(access, 'w'))
247
	return_error(e_invalidfileaccess);
248
    if (file_is_invalid(s, &ref_stderr)) {
249
	/* procedure source */
250
	gs_ref_memory_t *imem = (gs_ref_memory_t *)imemory_system;
251
	ref rint;
252
 
253
	/* The procedure isn't used. */
254
	/* Set it to literal 2 to recognised stderr. */
255
	make_int(&rint, 2);
256
 
257
	/* implement stderr as a procedure */
258
	code = swrite_proc(&rint, &s, imem);
259
	if (code < 0)
260
	    return code;
261
	s->save_close = s->procs.flush;
262
	s->procs.close = stdio_close;
263
	/* allocate buffer */
264
	if (s->cbuf == 0) {
265
	    int len = STDERR_BUF_SIZE;
266
	    byte *buf = gs_alloc_bytes((gs_memory_t *)imemory_system,
267
	    		len, "stderr_open");
268
	    if (buf == 0)
269
		return_error(e_VMerror);
270
	    s->cbuf = buf;
271
	    s->srptr = s->srlimit = s->swptr = buf - 1;
272
	    s->swlimit = buf - 1 + len;
273
	    s->bsize = s->cbsize = len;
274
	}
275
	make_file(&ref_stderr, a_write | avm_system, s->write_id, s);
276
	*ps = s;
277
	return 1;
278
    }
279
    *ps = s;
280
    return 0;
281
}
282
/* This is the public routine for getting the stderr stream. */
283
int
284
zget_stderr(i_ctx_t *i_ctx_p, stream ** ps)
285
{
286
    stream *s;
287
    gx_io_device *iodev;
288
    int code;
289
 
290
    if (file_is_valid(s, &ref_stderr)) {
291
	*ps = s;
292
	return 0;
293
    }
294
    iodev = gs_findiodevice((const byte *)"%stderr", 7);
295
    iodev->state = i_ctx_p;
296
    code = (*iodev->procs.open_device)(iodev, "w", ps, imemory_system);
297
    iodev->state = NULL;
298
    return min(code, 0);
299
}