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