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) 1989, 2000, 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: zfileio.c,v 1.18 2005/08/30 23:19:01 ray Exp $ */
18
/* File I/O operators */
19
#include "memory_.h"
20
#include "ghost.h"
21
#include "gp.h"
22
#include "oper.h"
23
#include "stream.h"
24
#include "files.h"
25
#include "store.h"
26
#include "strimpl.h"		/* for ifilter.h */
27
#include "ifilter.h"		/* for procedure streams */
28
#include "interp.h"		/* for gs_errorinfo_put_string */
29
#include "gsmatrix.h"		/* for gxdevice.h */
30
#include "gxdevice.h"
31
#include "gxdevmem.h"
32
#include "estack.h"
33
 
34
/* Forward references */
35
private int write_string(ref *, stream *);
36
private int handle_read_status(i_ctx_t *, int, const ref *, const uint *,
37
			       op_proc_t);
38
private int handle_write_status(i_ctx_t *, int, const ref *, const uint *,
39
				op_proc_t);
40
 
41
/* ------ Operators ------ */
42
 
43
/* <file> closefile - */
44
int
45
zclosefile(i_ctx_t *i_ctx_p)
46
{
47
    os_ptr op = osp;
48
    stream *s;
49
 
50
    check_type(*op, t_file);
51
    if (file_is_valid(s, op)) {	/* closing a closed file is a no-op */
52
	int status = sclose(s);
53
 
54
	if (status != 0 && status != EOFC) {
55
	    if (s_is_writing(s))
56
		return handle_write_status(i_ctx_p, status, op, NULL,
57
					   zclosefile);
58
	    else
59
		return handle_read_status(i_ctx_p, status, op, NULL,
60
					  zclosefile);
61
	}
62
    }
63
    pop(1);
64
    return 0;
65
}
66
 
67
/* <file> read <int> -true- */
68
/* <file> read -false- */
69
private int
70
zread(i_ctx_t *i_ctx_p)
71
{
72
    os_ptr op = osp;
73
    stream *s;
74
    int ch;
75
 
76
    check_read_file(s, op);
77
    /* We 'push' first in case of ostack block overflow and the */
78
    /* usual case is we will need to push anyway. If we get EOF */
79
    /* we will need to 'pop' and decrement the 'op' pointer.    */
80
    /* This is required since the 'push' macro might return with*/
81
    /* stackoverflow which will result in another stack block   */
82
    /* added on, then the operator being retried. We can't read */
83
    /* (sgetc) prior to having a place on the ostack to return  */
84
    /* the character.						*/
85
    push(1);
86
    ch = sgetc(s);
87
    if (ch >= 0) {
88
	make_int(op - 1, ch);
89
	make_bool(op, 1);
90
    } else {
91
	pop(1);		/* Adjust ostack back from preparatory 'pop' */
92
	op--;
93
	if (ch == EOFC) 
94
	make_bool(op, 0);
95
    else
96
	return handle_read_status(i_ctx_p, ch, op, NULL, zread);
97
    }
98
    return 0;
99
}
100
 
101
/* <file> <int> write - */
102
int
103
zwrite(i_ctx_t *i_ctx_p)
104
{
105
    os_ptr op = osp;
106
    stream *s;
107
    byte ch;
108
    int status;
109
 
110
    check_write_file(s, op - 1);
111
    check_type(*op, t_integer);
112
    ch = (byte) op->value.intval;
113
    status = sputc(s, (byte) ch);
114
    if (status >= 0) {
115
	pop(2);
116
	return 0;
117
    }
118
    return handle_write_status(i_ctx_p, status, op - 1, NULL, zwrite);
119
}
120
 
121
/* <file> <string> readhexstring <substring> <filled_bool> */
122
private int zreadhexstring_continue(i_ctx_t *);
123
 
124
/* We keep track of the odd digit in the next byte of the string */
125
/* beyond the bytes already used.  (This is just for convenience; */
126
/* we could do the same thing by passing 2 state parameters to the */
127
/* continuation procedure instead of 1.) */
128
private int
129
zreadhexstring_at(i_ctx_t *i_ctx_p, os_ptr op, uint start)
130
{
131
    stream *s;
132
    uint len, nread;
133
    byte *str;
134
    int odd;
135
    stream_cursor_write cw;
136
    int status;
137
 
138
    check_read_file(s, op - 1);
139
    /*check_write_type(*op, t_string); *//* done by caller */
140
    str = op->value.bytes;
141
    len = r_size(op);
142
    if (start < len) {
143
	odd = str[start];
144
	if (odd > 0xf)
145
	    odd = -1;
146
    } else
147
	odd = -1;
148
    cw.ptr = str + start - 1;
149
    cw.limit = str + len - 1;
150
    for (;;) {
151
	status = s_hex_process(&s->cursor.r, &cw, &odd,
152
			       hex_ignore_garbage);
153
	if (status == 1) {	/* filled the string */
154
	    ref_assign_inline(op - 1, op);
155
	    make_true(op);
156
	    return 0;
157
	} else if (status != 0)	/* error or EOF */
158
	    break;
159
	/* Didn't fill, keep going. */
160
	status = spgetc(s);
161
	if (status < 0)
162
	    break;
163
	sputback(s);
164
    }
165
    nread = cw.ptr + 1 - str;
166
    if (status != EOFC) {	/* Error */
167
	if (nread < len)
168
	    str[nread] = (odd < 0 ? 0x10 : odd);
169
	return handle_read_status(i_ctx_p, status, op - 1, &nread,
170
				  zreadhexstring_continue);
171
    }
172
    /* Reached end-of-file before filling the string. */
173
    /* Return an appropriate substring. */
174
    ref_assign_inline(op - 1, op);
175
    r_set_size(op - 1, nread);
176
    make_false(op);
177
    return 0;
178
}
179
private int
180
zreadhexstring(i_ctx_t *i_ctx_p)
181
{
182
    os_ptr op = osp;
183
 
184
    check_write_type(*op, t_string);
185
    if (r_size(op) > 0)
186
	*op->value.bytes = 0x10;
187
    return zreadhexstring_at(i_ctx_p, op, 0);
188
}
189
/* Continue a readhexstring operation after a callout. */
190
/* *op is the index within the string. */
191
private int
192
zreadhexstring_continue(i_ctx_t *i_ctx_p)
193
{
194
    os_ptr op = osp;
195
    int code;
196
 
197
    check_type(*op, t_integer);
198
    if (op->value.intval < 0 || op->value.intval > r_size(op - 1))
199
	return_error(e_rangecheck);
200
    check_write_type(op[-1], t_string);
201
    code = zreadhexstring_at(i_ctx_p, op - 1, (uint) op->value.intval);
202
    if (code >= 0)
203
	pop(1);
204
    return code;
205
}
206
 
207
/* <file> <string> writehexstring - */
208
private int zwritehexstring_continue(i_ctx_t *);
209
private int
210
zwritehexstring_at(i_ctx_t *i_ctx_p, os_ptr op, uint odd)
211
{
212
    register stream *s;
213
    register byte ch;
214
    register const byte *p;
215
    register const char *const hex_digits = "0123456789abcdef";
216
    register uint len;
217
    int status;
218
 
219
#define MAX_HEX 128
220
    byte buf[MAX_HEX];
221
 
222
    check_write_file(s, op - 1);
223
    check_read_type(*op, t_string);
224
    p = op->value.bytes;
225
    len = r_size(op);
226
    while (len) {
227
	uint len1 = min(len, MAX_HEX / 2);
228
	register byte *q = buf;
229
	uint count = len1;
230
	ref rbuf;
231
 
232
	do {
233
	    ch = *p++;
234
	    *q++ = hex_digits[ch >> 4];
235
	    *q++ = hex_digits[ch & 0xf];
236
	}
237
	while (--count);
238
	r_set_size(&rbuf, (len1 << 1) - odd);
239
	rbuf.value.bytes = buf + odd;
240
	status = write_string(&rbuf, s);
241
	switch (status) {
242
	    default:
243
		return_error(e_ioerror);
244
	    case 0:
245
		len -= len1;
246
		odd = 0;
247
		continue;
248
	    case INTC:
249
	    case CALLC:
250
		count = rbuf.value.bytes - buf;
251
		op->value.bytes += count >> 1;
252
		r_set_size(op, len - (count >> 1));
253
		count &= 1;
254
		return handle_write_status(i_ctx_p, status, op - 1, &count,
255
					   zwritehexstring_continue);
256
	}
257
    }
258
    pop(2);
259
    return 0;
260
#undef MAX_HEX
261
}
262
private int
263
zwritehexstring(i_ctx_t *i_ctx_p)
264
{
265
    os_ptr op = osp;
266
 
267
    return zwritehexstring_at(i_ctx_p, op, 0);
268
}
269
/* Continue a writehexstring operation after a callout. */
270
/* *op is the odd/even hex digit flag for the first byte. */
271
private int
272
zwritehexstring_continue(i_ctx_t *i_ctx_p)
273
{
274
    os_ptr op = osp;
275
    int code;
276
 
277
    check_type(*op, t_integer);
278
    if ((op->value.intval & ~1) != 0)
279
	return_error(e_rangecheck);
280
    code = zwritehexstring_at(i_ctx_p, op - 1, (uint) op->value.intval);
281
    if (code >= 0)
282
	pop(1);
283
    return code;
284
}
285
 
286
/* <file> <string> readstring <substring> <filled_bool> */
287
private int zreadstring_continue(i_ctx_t *);
288
private int
289
zreadstring_at(i_ctx_t *i_ctx_p, os_ptr op, uint start)
290
{
291
    stream *s;
292
    uint len, rlen;
293
    int status;
294
 
295
    check_read_file(s, op - 1);
296
    check_write_type(*op, t_string);
297
    len = r_size(op);
298
    status = sgets(s, op->value.bytes + start, len - start, &rlen);
299
    rlen += start;
300
    switch (status) {
301
	case EOFC:
302
	case 0:
303
	    break;
304
	default:
305
	    return handle_read_status(i_ctx_p, status, op - 1, &rlen,
306
				      zreadstring_continue);
307
    }
308
    /*
309
     * The most recent Adobe specification says that readstring
310
     * must signal a rangecheck if the string length is zero.
311
     * I can't imagine the motivation for this, but we emulate it.
312
     * It's safe to check it here, rather than earlier, because if
313
     * len is zero, sgets will return 0 immediately with rlen = 0.
314
     */
315
    if (len == 0)
316
	return_error(e_rangecheck);
317
    r_set_size(op, rlen);
318
    op[-1] = *op;
319
    make_bool(op, (rlen == len ? 1 : 0));
320
    return 0;
321
}
322
private int
323
zreadstring(i_ctx_t *i_ctx_p)
324
{
325
    os_ptr op = osp;
326
 
327
    return zreadstring_at(i_ctx_p, op, 0);
328
}
329
/* Continue a readstring operation after a callout. */
330
/* *op is the index within the string. */
331
private int
332
zreadstring_continue(i_ctx_t *i_ctx_p)
333
{
334
    os_ptr op = osp;
335
    int code;
336
 
337
    check_type(*op, t_integer);
338
    if (op->value.intval < 0 || op->value.intval > r_size(op - 1))
339
	return_error(e_rangecheck);
340
    code = zreadstring_at(i_ctx_p, op - 1, (uint) op->value.intval);
341
    if (code >= 0)
342
	pop(1);
343
    return code;
344
}
345
 
346
/* <file> <string> writestring - */
347
private int
348
zwritestring(i_ctx_t *i_ctx_p)
349
{
350
    os_ptr op = osp;
351
    stream *s;
352
    int status;
353
 
354
    check_write_file(s, op - 1);
355
    check_read_type(*op, t_string);
356
    status = write_string(op, s);
357
    if (status >= 0) {
358
	pop(2);
359
	return 0;
360
    }
361
    return handle_write_status(i_ctx_p, status, op - 1, NULL, zwritestring);
362
}
363
 
364
/* <file> <string> readline <substring> <bool> */
365
private int zreadline(i_ctx_t *);
366
private int zreadline_continue(i_ctx_t *);
367
 
368
/*
369
 * We could handle readline the same way as readstring,
370
 * except for the anomalous situation where we get interrupted
371
 * between the CR and the LF of an end-of-line marker.
372
 * We hack around this in the following way: if we get interrupted
373
 * before we've read any characters, we just restart the readline;
374
 * if we get interrupted at any other time, we use readline_continue;
375
 * we use start=0 (which we have just ruled out as a possible start value
376
 * for readline_continue) to indicate interruption after the CR.
377
 */
378
private int
379
zreadline_at(i_ctx_t *i_ctx_p, os_ptr op, uint count, bool in_eol)
380
{
381
    stream *s;
382
    int status;
383
    gs_string str;
384
 
385
    check_read_file(s, op - 1);
386
    check_write_type(*op, t_string);
387
    str.data = op->value.bytes;
388
    str.size = r_size(op);
389
    status = zreadline_from(s, &str, NULL, &count, &in_eol);
390
    switch (status) {
391
	case 0:
392
	case EOFC:
393
	    break;
394
	case 1:
395
	    return_error(e_rangecheck);
396
	default:
397
	    if (count == 0 && !in_eol)
398
		return handle_read_status(i_ctx_p, status, op - 1, NULL,
399
					  zreadline);
400
	    else {
401
		if (in_eol) {
402
		    r_set_size(op, count);
403
		    count = 0;
404
		}
405
		return handle_read_status(i_ctx_p, status, op - 1, &count,
406
					  zreadline_continue);
407
	    }
408
    }
409
    r_set_size(op, count);
410
    op[-1] = *op;
411
    make_bool(op, status == 0);
412
    return 0;
413
}
414
private int
415
zreadline(i_ctx_t *i_ctx_p)
416
{
417
    os_ptr op = osp;
418
 
419
    return zreadline_at(i_ctx_p, op, 0, false);
420
}
421
/* Continue a readline operation after a callout. */
422
/* *op is the index within the string, or 0 for an interrupt after a CR. */
423
private int
424
zreadline_continue(i_ctx_t *i_ctx_p)
425
{
426
    os_ptr op = osp;
427
    uint size = r_size(op - 1);
428
    uint start;
429
    int code;
430
 
431
    check_type(*op, t_integer);
432
    if (op->value.intval < 0 || op->value.intval > size)
433
	return_error(e_rangecheck);
434
    start = (uint) op->value.intval;
435
    code = (start == 0 ? zreadline_at(i_ctx_p, op - 1, size, true) :
436
	    zreadline_at(i_ctx_p, op - 1, start, false));
437
    if (code >= 0)
438
	pop(1);
439
    return code;
440
}
441
 
442
/* Internal readline routine. */
443
/* Returns a stream status value, or 1 if we overflowed the string. */
444
/* This is exported for %lineedit. */
445
int
446
zreadline_from(stream *s, gs_string *buf, gs_memory_t *bufmem,
447
	       uint *pcount, bool *pin_eol)
448
{
449
    sreadline_proc((*readline));
450
 
451
    if (zis_stdin(s))
452
	readline = gp_readline;
453
    else
454
	readline = sreadline;
455
    return readline(s, NULL, NULL /*WRONG*/, NULL, buf, bufmem,
456
		    pcount, pin_eol, zis_stdin);
457
}
458
 
459
/* <file> bytesavailable <int> */
460
private int
461
zbytesavailable(i_ctx_t *i_ctx_p)
462
{
463
    os_ptr op = osp;
464
    stream *s;
465
    long avail;
466
 
467
    check_read_file(s, op);
468
    switch (savailable(s, &avail)) {
469
	default:
470
	    return_error(e_ioerror);
471
	case EOFC:
472
	    avail = -1;
473
	case 0:
474
	    ;
475
    }
476
    make_int(op, avail);
477
    return 0;
478
}
479
 
480
/* - flush - */
481
int
482
zflush(i_ctx_t *i_ctx_p)
483
{
484
    stream *s;
485
    int status;
486
    ref rstdout;
487
    int code = zget_stdout(i_ctx_p, &s);
488
 
489
    if (code < 0)
490
	return code;
491
 
492
    make_stream_file(&rstdout, s, "w");
493
    status = sflush(s);
494
    if (status == 0 || status == EOFC) {
495
	return 0;
496
    }
497
    return
498
	(s_is_writing(s) ?
499
	 handle_write_status(i_ctx_p, status, &rstdout, NULL, zflush) :
500
	 handle_read_status(i_ctx_p, status, &rstdout, NULL, zflush));
501
}
502
 
503
/* <file> flushfile - */
504
private int
505
zflushfile(i_ctx_t *i_ctx_p)
506
{
507
    os_ptr op = osp;
508
    stream *s;
509
    int status;
510
 
511
    check_type(*op, t_file);
512
    /*
513
     * We think flushfile is a no-op on closed input files, but causes an
514
     * error on closed output files.
515
     */
516
    if (file_is_invalid(s, op)) {
517
	if (r_has_attr(op, a_write))
518
	    return_error(e_invalidaccess);
519
	pop(1);
520
	return 0;
521
    }
522
    status = sflush(s);
523
    if (status == 0 || status == EOFC) {
524
	pop(1);
525
	return 0;
526
    }
527
    return
528
	(s_is_writing(s) ?
529
	 handle_write_status(i_ctx_p, status, op, NULL, zflushfile) :
530
	 handle_read_status(i_ctx_p, status, op, NULL, zflushfile));
531
}
532
 
533
/* <file> resetfile - */
534
private int
535
zresetfile(i_ctx_t *i_ctx_p)
536
{
537
    os_ptr op = osp;
538
    stream *s;
539
 
540
    /* According to Adobe, resetfile is a no-op on closed files. */
541
    check_type(*op, t_file);
542
    if (file_is_valid(s, op))
543
	sreset(s);
544
    pop(1);
545
    return 0;
546
}
547
 
548
/* <string> print - */
549
private int
550
zprint(i_ctx_t *i_ctx_p)
551
{
552
    os_ptr op = osp;
553
    stream *s;
554
    int status;
555
    ref rstdout;
556
    int code;
557
 
558
    check_read_type(*op, t_string);
559
    code = zget_stdout(i_ctx_p, &s);
560
    if (code < 0)
561
	return code;
562
    status = write_string(op, s);
563
    if (status >= 0) {
564
	pop(1);
565
	return 0;
566
    }
567
    /* Convert print to writestring on the fly. */
568
    make_stream_file(&rstdout, s, "w");
569
    code = handle_write_status(i_ctx_p, status, &rstdout, NULL,
570
			       zwritestring);
571
    if (code != o_push_estack)
572
	return code;
573
    push(1);
574
    *op = op[-1];
575
    op[-1] = rstdout;
576
    return code;
577
}
578
 
579
/* <bool> echo - */
580
private int
581
zecho(i_ctx_t *i_ctx_p)
582
{
583
    os_ptr op = osp;
584
 
585
    check_type(*op, t_boolean);
586
    /****** NOT IMPLEMENTED YET ******/
587
    pop(1);
588
    return 0;
589
}
590
 
591
/* ------ Level 2 extensions ------ */
592
 
593
/* <file> fileposition <int> */
594
private int
595
zfileposition(i_ctx_t *i_ctx_p)
596
{
597
    os_ptr op = osp;
598
    stream *s;
599
 
600
    check_file(s, op);
601
    /*
602
     * The PLRM says fileposition must give an error for non-seekable
603
     * streams.
604
     */
605
    if (!s_can_seek(s))
606
	return_error(e_ioerror);
607
    make_int(op, stell(s));
608
    return 0;
609
}
610
/* <file> .fileposition <int> */
611
private int
612
zxfileposition(i_ctx_t *i_ctx_p)
613
{
614
    os_ptr op = osp;
615
    stream *s;
616
 
617
    check_file(s, op);
618
    /*
619
     * This version of fileposition doesn't give the error, so we can
620
     * use it to get the position of string or procedure streams.
621
     */
622
    make_int(op, stell(s));
623
    return 0;
624
}
625
 
626
/* <file> <int> setfileposition - */
627
private int
628
zsetfileposition(i_ctx_t *i_ctx_p)
629
{
630
    os_ptr op = osp;
631
    stream *s;
632
 
633
    check_file(s, op - 1);
634
    check_type(*op, t_integer);
635
    if (sseek(s, op->value.intval) < 0)
636
	return_error(e_ioerror);
637
    pop(2);
638
    return 0;
639
}
640
 
641
/* ------ Non-standard extensions ------ */
642
 
643
/* <file> .filename <string> true */
644
/* <file> .filename false */
645
private int
646
zfilename(i_ctx_t *i_ctx_p)
647
{
648
    os_ptr op = osp;
649
    stream *s;
650
    gs_const_string fname;
651
    byte *str;
652
 
653
    check_file(s, op);
654
    if (sfilename(s, &fname) < 0) {
655
	make_false(op);
656
	return 0;
657
    }
658
    check_ostack(1);
659
    str = ialloc_string(fname.size, "filename");
660
    if (str == 0)
661
	return_error(e_VMerror);
662
    memcpy(str, fname.data, fname.size);
663
    push(1);			/* can't fail */
664
    make_const_string( op - 1 , 
665
		      a_all | imemory_space((const struct gs_ref_memory_s*) imemory), 
666
		      fname.size, 
667
		      str);
668
    make_true(op);
669
    return 0;
670
}
671
 
672
/* <file> .isprocfilter <bool> */
673
private int
674
zisprocfilter(i_ctx_t *i_ctx_p)
675
{
676
    os_ptr op = osp;
677
    stream *s;
678
 
679
    check_file(s, op);
680
    while (s->strm != 0)
681
	s = s->strm;
682
    make_bool(op, s_is_proc(s));
683
    return 0;
684
}
685
 
686
/* <file> <string> .peekstring <substring> <filled_bool> */
687
private int
688
zpeekstring(i_ctx_t *i_ctx_p)
689
{
690
    os_ptr op = osp;
691
    stream *s;
692
    uint len, rlen;
693
 
694
    check_read_file(s, op - 1);
695
    check_write_type(*op, t_string);
696
    len = r_size(op);
697
    while ((rlen = sbufavailable(s)) < len) {
698
	int status = s->end_status;
699
 
700
	switch (status) {
701
	case EOFC:
702
	    break;
703
	case 0:
704
	    /*
705
	     * The following is a HACK.  It should reallocate the buffer to hold
706
	     * at least len bytes.  However, this raises messy problems about
707
	     * which allocator to use and how it should interact with restore.
708
	     */
709
	    if (len >= s->bsize)
710
		return_error(e_rangecheck);
711
	    s_process_read_buf(s);
712
	    continue;
713
	default:
714
	    return handle_read_status(i_ctx_p, status, op - 1, NULL,
715
				      zpeekstring);
716
	}
717
	break;
718
    }
719
    if (rlen > len)
720
	rlen = len;
721
    /* Don't remove the data from the buffer. */
722
    memcpy(op->value.bytes, sbufptr(s), rlen);
723
    r_set_size(op, rlen);
724
    op[-1] = *op;
725
    make_bool(op, (rlen == len ? 1 : 0));
726
    return 0;
727
}
728
 
729
/* <file> <int> .unread - */
730
private int
731
zunread(i_ctx_t *i_ctx_p)
732
{
733
    os_ptr op = osp;
734
    stream *s;
735
    ulong ch;
736
 
737
    check_read_file(s, op - 1);
738
    check_type(*op, t_integer);
739
    ch = op->value.intval;
740
    if (ch > 0xff)
741
	return_error(e_rangecheck);
742
    if (sungetc(s, (byte) ch) < 0)
743
	return_error(e_ioerror);
744
    pop(2);
745
    return 0;
746
}
747
 
748
/* <file> <obj> <==flag> .writecvp - */
749
private int zwritecvp_continue(i_ctx_t *);
750
private int
751
zwritecvp_at(i_ctx_t *i_ctx_p, os_ptr op, uint start, bool first)
752
{
753
    stream *s;
754
    byte str[100];		/* arbitrary */
755
    ref rstr;
756
    const byte *data = str;
757
    uint len;
758
    int code, status;
759
 
760
    check_write_file(s, op - 2);
761
    check_type(*op, t_integer);
762
    code = obj_cvp(op - 1, str, sizeof(str), &len, (int)op->value.intval,
763
		   start, imemory);
764
    if (code == e_rangecheck) {
765
        code = obj_string_data(imemory, op - 1, &data, &len);
766
	if (len < start)
767
	    return_error(e_rangecheck);
768
	data += start;
769
	len -= start;
770
    }
771
    if (code < 0)
772
	return code;
773
    r_set_size(&rstr, len);
774
    rstr.value.const_bytes = data;
775
    status = write_string(&rstr, s);
776
    switch (status) {
777
	default:
778
	    return_error(e_ioerror);
779
	case 0:
780
	    break;
781
	case INTC:
782
	case CALLC:
783
	    len = start + len - r_size(&rstr);
784
	    if (!first)
785
		--osp;		/* pop(1) without affecting op */
786
	    return handle_write_status(i_ctx_p, status, op - 2, &len,
787
				       zwritecvp_continue);
788
    }
789
    if (code == 1) {
790
	if (first)
791
	    check_ostack(1);
792
	push_op_estack(zwritecvp_continue);
793
	if (first)
794
	    push(1);
795
	make_int(osp, start + len);
796
	return o_push_estack;
797
    }
798
    if (first)			/* zwritecvp */
799
	pop(3);
800
    else			/* zwritecvp_continue */
801
	pop(4);
802
    return 0;
803
}
804
private int
805
zwritecvp(i_ctx_t *i_ctx_p)
806
{
807
    return zwritecvp_at(i_ctx_p, osp, 0, true);
808
}
809
/* Continue a .writecvp after a callout. */
810
/* *op is the index within the string. */
811
private int
812
zwritecvp_continue(i_ctx_t *i_ctx_p)
813
{
814
    os_ptr op = osp;
815
 
816
    check_type(*op, t_integer);
817
    if (op->value.intval != (uint) op->value.intval)
818
	return_error(e_rangecheck);
819
    return zwritecvp_at(i_ctx_p, op - 1, (uint) op->value.intval, false);
820
}
821
 
822
/* Callout for stdin */
823
/* - .needstdin - */
824
int
825
zneedstdin(i_ctx_t *i_ctx_p)
826
{
827
    return e_NeedStdin;		/* Interpreter will exit to caller. */
828
}
829
 
830
/* Callout for stdout */
831
/* - .needstdout - */
832
int
833
zneedstdout(i_ctx_t *i_ctx_p)
834
{
835
    return e_NeedStdout;	/* Interpreter will exit to caller. */
836
}
837
 
838
/* Callout for stderr */
839
/* - .needstderr - */
840
int
841
zneedstderr(i_ctx_t *i_ctx_p)
842
{
843
    return e_NeedStderr;	/* Interpreter will exit to caller. */
844
}
845
 
846
 
847
 
848
/* ------ Initialization procedure ------ */
849
 
850
/* We need to split the table because of the 16-element limit. */
851
const op_def zfileio1_op_defs[] = {
852
    {"1bytesavailable", zbytesavailable},
853
    {"1closefile", zclosefile},
854
		/* currentfile is in zcontrol.c */
855
    {"1echo", zecho},
856
    {"1.filename", zfilename},
857
    {"1.fileposition", zxfileposition},
858
    {"1fileposition", zfileposition},
859
    {"0flush", zflush},
860
    {"1flushfile", zflushfile},
861
    {"1.isprocfilter", zisprocfilter},
862
    {"2.peekstring", zpeekstring},
863
    {"1print", zprint},
864
    {"1read", zread},
865
    {"2readhexstring", zreadhexstring},
866
    {"2readline", zreadline},
867
    {"2readstring", zreadstring},
868
    op_def_end(0)
869
};
870
const op_def zfileio2_op_defs[] = {
871
    {"1resetfile", zresetfile},
872
    {"2setfileposition", zsetfileposition},
873
    {"2.unread", zunread},
874
    {"2write", zwrite},
875
    {"3.writecvp", zwritecvp},
876
    {"2writehexstring", zwritehexstring},
877
    {"2writestring", zwritestring},
878
		/* Internal operators */
879
    {"3%zreadhexstring_continue", zreadhexstring_continue},
880
    {"3%zreadline_continue", zreadline_continue},
881
    {"3%zreadstring_continue", zreadstring_continue},
882
    {"4%zwritecvp_continue", zwritecvp_continue},
883
    {"3%zwritehexstring_continue", zwritehexstring_continue},
884
    {"0.needstdin", zneedstdin},
885
    {"0.needstdout", zneedstdout},
886
    {"0.needstderr", zneedstderr},
887
    op_def_end(0)
888
};
889
 
890
/* ------ Non-operator routines ------ */
891
 
892
/* Switch a file open for read/write access but currently in write mode */
893
/* to read mode. */
894
int
895
file_switch_to_read(const ref * op)
896
{
897
    stream *s = fptr(op);
898
 
899
    if (s->write_id != r_size(op) || s->file == 0)	/* not valid */
900
	return_error(e_invalidaccess);
901
    if (sswitch(s, false) < 0)
902
	return_error(e_ioerror);
903
    s->read_id = s->write_id;	/* enable reading */
904
    s->write_id = 0;		/* disable writing */
905
    return 0;
906
}
907
 
908
/* Switch a file open for read/write access but currently in read mode */
909
/* to write mode. */
910
int
911
file_switch_to_write(const ref * op)
912
{
913
    stream *s = fptr(op);
914
 
915
    if (s->read_id != r_size(op) || s->file == 0)	/* not valid */
916
	return_error(e_invalidaccess);
917
    if (sswitch(s, true) < 0)
918
	return_error(e_ioerror);
919
    s->write_id = s->read_id;	/* enable writing */
920
    s->read_id = 0;		/* disable reading */
921
    return 0;
922
}
923
 
924
/* ------ Internal routines ------ */
925
 
926
/* Write a string on a file.  The file and string have been validated. */
927
/* If the status is INTC or CALLC, updates the string on the o-stack. */
928
private int
929
write_string(ref * op, stream * s)
930
{
931
    const byte *data = op->value.const_bytes;
932
    uint len = r_size(op);
933
    uint wlen;
934
    int status = sputs(s, data, len, &wlen);
935
 
936
    switch (status) {
937
	case INTC:
938
	case CALLC:
939
	    op->value.const_bytes = data + wlen;
940
	    r_set_size(op, len - wlen);
941
	    /* falls through */
942
	default:		/* 0, EOFC, ERRC */
943
	    return status;
944
    }
945
}
946
 
947
/*
948
 * Look for a stream error message that needs to be copied to
949
 * $error.errorinfo, if any.
950
 */
951
private int
952
copy_error_string(i_ctx_t *i_ctx_p, const ref *fop)
953
{
954
    stream *s;
955
 
956
    for (s = fptr(fop); s->strm != 0 && s->state->error_string[0] == 0;)
957
	s = s->strm;
958
    if (s->state->error_string[0]) {
959
	int code = gs_errorinfo_put_string(i_ctx_p, s->state->error_string);
960
 
961
	if (code < 0)
962
	    return code;
963
	s->state->error_string[0] = 0; /* just do it once */
964
    }
965
    return_error(e_ioerror);
966
}
967
 
968
/* Handle an exceptional status return from a read stream. */
969
/* fop points to the ref for the stream. */
970
/* ch may be any stream exceptional value. */
971
/* Return 0, 1 (EOF), o_push_estack, or an error. */
972
private int
973
handle_read_status(i_ctx_t *i_ctx_p, int ch, const ref * fop,
974
		   const uint * pindex, op_proc_t cont)
975
{
976
    switch (ch) {
977
	default:		/* error */
978
	    return copy_error_string(i_ctx_p, fop);
979
	case EOFC:
980
	    return 1;
981
	case INTC:
982
	case CALLC:
983
	    if (pindex) {
984
		ref index;
985
 
986
		make_int(&index, *pindex);
987
		return s_handle_read_exception(i_ctx_p, ch, fop, &index, 1,
988
					       cont);
989
	    } else
990
		return s_handle_read_exception(i_ctx_p, ch, fop, NULL, 0,
991
					       cont);
992
    }
993
}
994
 
995
/* Handle an exceptional status return from a write stream. */
996
/* fop points to the ref for the stream. */
997
/* ch may be any stream exceptional value. */
998
/* Return 0, 1 (EOF), o_push_estack, or an error. */
999
private int
1000
handle_write_status(i_ctx_t *i_ctx_p, int ch, const ref * fop,
1001
		    const uint * pindex, op_proc_t cont)
1002
{
1003
    switch (ch) {
1004
	default:		/* error */
1005
	    return copy_error_string(i_ctx_p, fop);
1006
	case EOFC:
1007
	    return 1;
1008
	case INTC:
1009
	case CALLC:
1010
	    if (pindex) {
1011
		ref index;
1012
 
1013
		make_int(&index, *pindex);
1014
		return s_handle_write_exception(i_ctx_p, ch, fop, &index, 1,
1015
						cont);
1016
	    } else
1017
		return s_handle_write_exception(i_ctx_p, ch, fop, NULL, 0,
1018
						cont);
1019
    }
1020
}