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
zclosefile(i_ctx_t * i_ctx_p)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
zread(i_ctx_t * i_ctx_p)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
zwrite(i_ctx_t * i_ctx_p)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
zreadhexstring_at(i_ctx_t * i_ctx_p,os_ptr op,uint start)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
zreadhexstring(i_ctx_t * i_ctx_p)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
zreadhexstring_continue(i_ctx_t * i_ctx_p)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
zwritehexstring_at(i_ctx_t * i_ctx_p,os_ptr op,uint odd)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
zwritehexstring(i_ctx_t * i_ctx_p)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
zwritehexstring_continue(i_ctx_t * i_ctx_p)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
zreadstring_at(i_ctx_t * i_ctx_p,os_ptr op,uint start)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
zreadstring(i_ctx_t * i_ctx_p)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
zreadstring_continue(i_ctx_t * i_ctx_p)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
zwritestring(i_ctx_t * i_ctx_p)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
zreadline_at(i_ctx_t * i_ctx_p,os_ptr op,uint count,bool in_eol)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
zreadline(i_ctx_t * i_ctx_p)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
zreadline_continue(i_ctx_t * i_ctx_p)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
zreadline_from(stream * s,gs_string * buf,gs_memory_t * bufmem,uint * pcount,bool * pin_eol)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
zbytesavailable(i_ctx_t * i_ctx_p)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
zflush(i_ctx_t * i_ctx_p)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
zflushfile(i_ctx_t * i_ctx_p)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
zresetfile(i_ctx_t * i_ctx_p)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
zprint(i_ctx_t * i_ctx_p)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
zecho(i_ctx_t * i_ctx_p)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
zfileposition(i_ctx_t * i_ctx_p)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
zxfileposition(i_ctx_t * i_ctx_p)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
zsetfileposition(i_ctx_t * i_ctx_p)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
zfilename(i_ctx_t * i_ctx_p)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
zisprocfilter(i_ctx_t * i_ctx_p)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
zpeekstring(i_ctx_t * i_ctx_p)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
zunread(i_ctx_t * i_ctx_p)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
zwritecvp_at(i_ctx_t * i_ctx_p,os_ptr op,uint start,bool first)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
zwritecvp(i_ctx_t * i_ctx_p)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
zwritecvp_continue(i_ctx_t * i_ctx_p)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
zneedstdin(i_ctx_t * i_ctx_p)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
zneedstdout(i_ctx_t * i_ctx_p)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
zneedstderr(i_ctx_t * i_ctx_p)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
file_switch_to_read(const ref * op)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
file_switch_to_write(const ref * op)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
write_string(ref * op,stream * s)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
copy_error_string(i_ctx_t * i_ctx_p,const ref * fop)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
handle_read_status(i_ctx_t * i_ctx_p,int ch,const ref * fop,const uint * pindex,op_proc_t cont)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
handle_write_status(i_ctx_t * i_ctx_p,int ch,const ref * fop,const uint * pindex,op_proc_t cont)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 }
1021