/* Return 0, 1 (EOF), o_push_estack, or an error. */ static int handle_read_status(i_ctx_t *i_ctx_p, int ch, const ref * fop, const uint * pindex, op_proc_t cont) { switch (ch) { default: /* error */ return copy_error_string(i_ctx_p, fop); case EOFC: return 1; case INTC: case CALLC: if (pindex) { ref index; make_int(&index, *pindex); return s_handle_read_exception(i_ctx_p, ch, fop, &index, 1, cont); } else return s_handle_read_exception(i_ctx_p, ch, fop, NULL, 0, cont); } }
/* Continue processing data from an image with file data sources. */ static int image_file_continue(i_ctx_t *i_ctx_p) { gs_image_enum *penum = r_ptr(esp, gs_image_enum); int num_sources = ETOP_NUM_SOURCES(esp)->value.intval; for (;;) { uint min_avail = max_int; gs_const_string plane_data[gs_image_max_planes]; int code; int px; const ref *pp; bool at_eof = false; /* * Do a first pass through the files to ensure that at least * one has data available in its buffer. */ for (px = 0, pp = ETOP_SOURCE(esp, 0); px < num_sources; ++px, pp -= 2 ) { int num_aliases = pp[1].value.intval; stream *s = pp->value.pfile; int min_left; uint avail; if (num_aliases <= 0) num_aliases = ETOP_SOURCE(esp, -num_aliases)[1].value.intval; while ((avail = sbufavailable(s)) <= (min_left = sbuf_min_left(s)) + num_aliases - 1) { int next = s->end_status; switch (next) { case 0: s_process_read_buf(s); continue; case EOFC: at_eof = true; break; /* with no data available */ case INTC: case CALLC: return s_handle_read_exception(i_ctx_p, next, pp, NULL, 0, image_file_continue); default: /* case ERRC: */ return_error(e_ioerror); } break; /* for EOFC */ } /* * Note that in the EOF case, we can get here with no data * available. */ if (avail >= min_left) avail = (avail - min_left) / num_aliases; /* may be 0 */ if (avail < min_avail) min_avail = avail; plane_data[px].data = sbufptr(s); plane_data[px].size = avail; } /* * Now pass the available buffered data to the image processor. * Even if there is no available data, we must call * gs_image_next_planes one more time to finish processing any * retained data. */ { int pi; uint used[gs_image_max_planes]; code = gs_image_next_planes(penum, plane_data, used); /* Now that used has been set, update the streams. */ for (pi = 0, pp = ETOP_SOURCE(esp, 0); pi < num_sources; ++pi, pp -= 2 ) sbufskip(pp->value.pfile, used[pi]); if (code == e_RemapColor) return code; } if (at_eof) code = 1; if (code) { int code1; esp = zimage_pop_estack(esp); code1 = image_cleanup(i_ctx_p); return (code < 0 ? code : code1 < 0 ? code1 : o_pop_estack); } } }
/* This opens %statementedit% or %lineedit% and is also the * continuation proc for callouts. * Input: * string is the statement/line buffer, * int is the write index into string * bool is true if %statementedit% * file is stdin * Output: * file is a string based stream * We store the line being read in a PostScript string. * This limits the size to max_string_size (64k). * This could be increased by storing the input line in something * other than a PostScript string. */ int zfilelineedit(i_ctx_t *i_ctx_p) { uint count = 0; bool in_eol = false; int code; os_ptr op = osp; bool statement; stream *s; stream *ins; gs_string str; uint initial_buf_size; const char *filename; /* * buf exists only for stylistic parallelism: all occurrences of * buf-> could just as well be str. . */ gs_string *const buf = &str; check_type(*op, t_string); /* line assembled so far */ buf->data = op->value.bytes; buf->size = op->tas.rsize; check_type(*(op-1), t_integer); /* index */ count = (op-1)->value.intval; check_type(*(op-2), t_boolean); /* statementedit/lineedit */ statement = (op-2)->value.boolval; check_read_file(ins, op - 3); /* %stdin */ /* extend string */ initial_buf_size = statement ? STATEMENTEDIT_BUF_SIZE : LINEEDIT_BUF_SIZE; if (initial_buf_size > max_string_size) return_error(e_limitcheck); if (!buf->data || (buf->size < initial_buf_size)) { count = 0; buf->data = gs_alloc_string(imemory_system, initial_buf_size, "zfilelineedit(buffer)"); if (buf->data == 0) return_error(e_VMerror); op->value.bytes = buf->data; op->tas.rsize = buf->size = initial_buf_size; } rd: code = zreadline_from(ins, buf, imemory_system, &count, &in_eol); if (buf->size > max_string_size) { /* zreadline_from reallocated the buffer larger than * is valid for a PostScript string. * Return an error, but first realloc the buffer * back to a legal size. */ byte *nbuf = gs_resize_string(imemory_system, buf->data, buf->size, max_string_size, "zfilelineedit(shrink buffer)"); if (nbuf == 0) return_error(e_VMerror); op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = max_string_size; return_error(e_limitcheck); } op->value.bytes = buf->data; /* zreadline_from sometimes resizes the buffer. */ op->tas.rsize = buf->size; switch (code) { case EOFC: code = gs_note_error(e_undefinedfilename); /* falls through */ case 0: break; default: code = gs_note_error(e_ioerror); break; case CALLC: { ref rfile; (op-1)->value.intval = count; /* callout is for stdin */ make_file(&rfile, a_readonly | avm_system, ins->read_id, ins); code = s_handle_read_exception(i_ctx_p, code, &rfile, NULL, 0, zfilelineedit); } break; case 1: /* filled buffer */ { uint nsize = buf->size; byte *nbuf; if (nsize >= max_string_size) { code = gs_note_error(e_limitcheck); break; } else if (nsize >= max_string_size / 2) nsize= max_string_size; else nsize = buf->size * 2; nbuf = gs_resize_string(imemory_system, buf->data, buf->size, nsize, "zfilelineedit(grow buffer)"); if (nbuf == 0) { code = gs_note_error(e_VMerror); break; } op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = nsize; goto rd; } } if (code != 0) return code; if (statement) { /* If we don't have a complete token, keep going. */ stream st; stream *ts = &st; scanner_state state; ref ignore_value; uint depth = ref_stack_count(&o_stack); int code; /* Add a terminating EOL. */ if (count + 1 > buf->size) { uint nsize; byte *nbuf; nsize = buf->size + 1; if (nsize > max_string_size) { return_error(gs_note_error(e_limitcheck)); } else { nbuf = gs_resize_string(imemory_system, buf->data, buf->size, nsize, "zfilelineedit(grow buffer)"); if (nbuf == 0) { code = gs_note_error(e_VMerror); return_error(code); } op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = nsize; } } buf->data[count++] = char_EOL; s_init(ts, NULL); sread_string(ts, buf->data, count); sc: scanner_init_stream_options(&state, ts, SCAN_CHECK_ONLY); code = scan_token(i_ctx_p, &ignore_value, &state); ref_stack_pop_to(&o_stack, depth); if (code < 0) code = scan_EOF; /* stop on scanner error */ switch (code) { case 0: /* read a token */ case scan_BOS: goto sc; /* keep going until we run out of data */ case scan_Refill: goto rd; case scan_EOF: break; default: /* error */ return code; } } buf->data = gs_resize_string(imemory_system, buf->data, buf->size, count, "zfilelineedit(resize buffer)"); if (buf->data == 0) return_error(e_VMerror); op->value.bytes = buf->data; op->tas.rsize = buf->size; s = file_alloc_stream(imemory_system, "zfilelineedit(stream)"); if (s == 0) return_error(e_VMerror); sread_string(s, buf->data, count); s->save_close = s->procs.close; s->procs.close = file_close_disable; filename = statement ? gs_iodev_statementedit.dname : gs_iodev_lineedit.dname; code = ssetfilename(s, (const byte *)filename, strlen(filename)+1); if (code < 0) { sclose(s); return_error(e_VMerror); } pop(3); make_stream_file(osp, s, "r"); return code; }