コード例 #1
0
/* 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);
    }
}
コード例 #2
0
/* 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);
	}
    }
}
コード例 #3
0
/* 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;
}