[gs-cvs] rev 6912 - trunk/gs/src
ray at ghostscript.com
ray at ghostscript.com
Wed Jul 12 14:30:01 PDT 2006
Author: ray
Date: 2006-07-12 14:30:00 -0700 (Wed, 12 Jul 2006)
New Revision: 6912
Modified:
trunk/gs/src/files.h
trunk/gs/src/ierrors.h
trunk/gs/src/imain.c
trunk/gs/src/iminst.h
trunk/gs/src/interp.c
trunk/gs/src/zfileio.c
trunk/gs/src/zfproc.c
trunk/gs/src/ziodevs.c
trunk/gs/src/ziodevsc.c
Log:
Change stdio callback mechanism to call directly from the stream processing
function, not requiring a CALLC callout all the way back through the interp
to 'imain.c' This simplifies some of the calling and is more efficient.
DETAILS:
gsapi_ and/or gsdll_ clients will see no difference.
Modified: trunk/gs/src/files.h
===================================================================
--- trunk/gs/src/files.h 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/files.h 2006-07-12 21:30:00 UTC (rev 6912)
@@ -46,9 +46,6 @@
extern stream *const invalid_file_entry;
/* Make an invalid file object. */
void make_invalid_file(ref *);
-/* create a stream for a file object */
-int file_prepare_stream(const char *, uint, const char *,
- uint, stream **, char[4], gs_memory_t *);
/*
* Macros for checking file validity.
@@ -168,8 +165,4 @@
/* for zfile.c */
int zfilelineedit(i_ctx_t *i_ctx_p);
- /* for zfproc.c */
-int zneedstdin(i_ctx_t *i_ctx_p);
-int zneedstdout(i_ctx_t *i_ctx_p);
-int zneedstderr(i_ctx_t *i_ctx_p);
#endif /* files_INCLUDED */
Modified: trunk/gs/src/ierrors.h
===================================================================
--- trunk/gs/src/ierrors.h 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/ierrors.h 2006-07-12 21:30:00 UTC (rev 6912)
@@ -135,21 +135,6 @@
#define e_NeedInput (-106)
/*
- * Internal code for stdin callout.
- */
-#define e_NeedStdin (-107)
-
-/*
- * Internal code for stdout callout.
- */
-#define e_NeedStdout (-108)
-
-/*
- * Internal code for stderr callout.
- */
-#define e_NeedStderr (-109)
-
-/*
* Internal code for a normal exit when usage info is displayed.
* This allows Window versions of Ghostscript to pause until
* the message can be read.
Modified: trunk/gs/src/imain.c
===================================================================
--- trunk/gs/src/imain.c 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/imain.c 2006-07-12 21:30:00 UTC (rev 6912)
@@ -199,10 +199,8 @@
}
/*
- * Invoke the interpreter, handling stdio callouts
- * e_NeedStdin, e_NeedStdout and e_NeedStderr.
- * We don't yet pass callouts all the way out because they
- * occur within gs_main_init2() and swproc().
+ * Invoke the interpreter. This layer doesn't do much (previously stdio
+ * callouts were handled here instead of in the stream processing.
*/
private int
gs_main_interpret(gs_main_instance *minst, ref * pref, int user_errors,
@@ -218,96 +216,6 @@
code = gs_interpret(&minst->i_ctx_p, pref,
user_errors, pexit_code, perror_object);
- while ((code == e_NeedStdin) || (code == e_NeedStdout) ||
- (code == e_NeedStderr)) {
- i_ctx_p = minst->i_ctx_p;
- if (code == e_NeedStdout) {
- /*
- * On entry:
- * esp[0] = string, data to write to stdout
- * esp[-1] = bool, EOF (ignored)
- * esp[-2] = array, procedure (ignored)
- * esp[-3] = file, stdout stream
- * We print the string then pop these 4 items.
- */
- if (r_type(&esp[0]) == t_string) {
- const char *str = (const char *)(esp[0].value.const_bytes);
- int count = esp[0].tas.rsize;
- int rcode = 0;
- if (str != NULL)
- rcode = outwrite(imemory, str, count);
- if (rcode < 0)
- return_error(e_ioerror);
- }
-
- /* On return, we need to set
- * osp[-1] = string buffer,
- * osp[0] = file
- */
- gs_push_string(minst, (byte *)minst->stdout_buf,
- sizeof(minst->stdout_buf), false);
- gs_push_integer(minst, 0); /* push integer */
- osp[0] = esp[-3]; /* then replace with file */
- /* remove items from execution stack */
- esp -= 4;
- }
- else if (code == e_NeedStderr) {
- if (r_type(&esp[0]) == t_string) {
- const char *str = (const char *)(esp[0].value.const_bytes);
- int count = esp[0].tas.rsize;
- int rcode = 0;
- if (str != NULL)
- rcode = errwrite(str, count);
- if (rcode < 0)
- return_error(e_ioerror);
- }
- gs_push_string(minst, (byte *)minst->stderr_buf,
- sizeof(minst->stderr_buf), false);
- gs_push_integer(minst, 0);
- osp[0] = esp[-3];
- esp -= 4;
- }
- else if (code == e_NeedStdin) {
- int count = sizeof(minst->stdin_buf);
- /*
- * On entry:
- * esp[0] = array, procedure (ignored)
- * esp[-1] = file, stdin stream
- * We read from stdin then pop these 2 items.
- */
- if (minst->heap->gs_lib_ctx->stdin_fn)
- count = (*minst->heap->gs_lib_ctx->stdin_fn)
- (minst->heap->gs_lib_ctx->caller_handle,
- minst->stdin_buf, count);
- else
- count = gp_stdin_read(minst->stdin_buf, count,
- minst->heap->gs_lib_ctx->stdin_is_interactive,
- minst->heap->gs_lib_ctx->fstdin);
- if (count < 0)
- return_error(e_ioerror);
-
- /* On return, we need to set
- * osp[-1] = string buffer,
- * osp[0] = file
- */
- gs_push_string(minst, (byte *)minst->stdin_buf, count, false);
- gs_push_integer(minst, 0); /* push integer */
- osp[0] = esp[-1]; /* then replace with file */
- /* remove items from execution stack */
- esp -= 2;
- }
- /*
- * To resume the interpreter, we call gs_interpret with a null ref.
- * This copies the literal null onto the operand stack.
- * To remove this we push a zpop onto the execution stack.
- */
- make_null(&refnul);
- make_oper(&refpop, 0, zpop);
- esp += 1;
- *esp = refpop;
- code = gs_interpret(&minst->i_ctx_p, &refnul,
- user_errors, pexit_code, perror_object);
- }
return code;
}
Modified: trunk/gs/src/iminst.h
===================================================================
--- trunk/gs/src/iminst.h 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/iminst.h 2006-07-12 21:30:00 UTC (rev 6912)
@@ -72,7 +72,6 @@
gs_file_path lib_path; /* library search list (GS_LIB) */
long base_time[2]; /* starting usertime */
void *readline_data; /* data for gp_readline */
- char stdin_buf[STDIN_BUF_SIZE]; /* for e_NeedStdin callout */
char stdout_buf[STDOUT_BUF_SIZE]; /* for e_NeedStdout callout */
char stderr_buf[STDERR_BUF_SIZE]; /* for e_NeedStderr callout */
ref error_object; /* Use by gsapi_*() */
Modified: trunk/gs/src/interp.c
===================================================================
--- trunk/gs/src/interp.c 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/interp.c 2006-07-12 21:30:00 UTC (rev 6912)
@@ -520,9 +520,6 @@
epref = &doref;
goto again;
case e_NeedInput:
- case e_NeedStdin:
- case e_NeedStdout:
- case e_NeedStderr:
return code;
}
/* Adjust osp in case of operand stack underflow */
Modified: trunk/gs/src/zfileio.c
===================================================================
--- trunk/gs/src/zfileio.c 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/zfileio.c 2006-07-12 21:30:00 UTC (rev 6912)
@@ -816,32 +816,7 @@
return zwritecvp_at(i_ctx_p, op - 1, (uint) op->value.intval, false);
}
-/* Callout for stdin */
-/* - .needstdin - */
-int
-zneedstdin(i_ctx_t *i_ctx_p)
-{
- return e_NeedStdin; /* Interpreter will exit to caller. */
-}
-/* Callout for stdout */
-/* - .needstdout - */
-int
-zneedstdout(i_ctx_t *i_ctx_p)
-{
- return e_NeedStdout; /* Interpreter will exit to caller. */
-}
-
-/* Callout for stderr */
-/* - .needstderr - */
-int
-zneedstderr(i_ctx_t *i_ctx_p)
-{
- return e_NeedStderr; /* Interpreter will exit to caller. */
-}
-
-
-
/* ------ Initialization procedure ------ */
/* We need to split the table because of the 16-element limit. */
@@ -878,9 +853,6 @@
{"3%zreadstring_continue", zreadstring_continue},
{"4%zwritecvp_continue", zwritecvp_continue},
{"3%zwritehexstring_continue", zwritehexstring_continue},
- {"0.needstdin", zneedstdin},
- {"0.needstdout", zneedstdout},
- {"0.needstderr", zneedstderr},
op_def_end(0)
};
Modified: trunk/gs/src/zfproc.c
===================================================================
--- trunk/gs/src/zfproc.c 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/zfproc.c 2006-07-12 21:30:00 UTC (rev 6912)
@@ -205,14 +205,6 @@
esp[-1] = *fop;
r_clear_attrs(esp - 1, a_executable);
*esp = ((stream_proc_state *) ps->state)->proc;
-
- /* If stream is stdin, ask for callout. */
- zget_stdin(i_ctx_p, &psstdin);
- if (ps == psstdin) {
- check_estack(1);
- esp += 1;
- make_op_estack(esp, zneedstdin);
- }
return o_push_estack;
}
/* Continue a read operation after returning from a procedure callout. */
@@ -345,15 +337,6 @@
esp[-2] = psst->proc;
*esp = psst->data;
r_set_size(esp, psst->index);
-
- /* If stream is stdout/err, ask for callout. */
- zget_stdout(i_ctx_p, &psstdout);
- zget_stderr(i_ctx_p, &psstderr);
- if ((ps == psstderr) || (ps == psstdout)) {
- check_estack(1);
- esp += 1;
- make_op_estack(esp, (ps == psstderr) ? zneedstderr : zneedstdout);
- }
return o_push_estack;
}
/* Continue a write operation after returning from a procedure callout. */
Modified: trunk/gs/src/ziodevs.c
===================================================================
--- trunk/gs/src/ziodevs.c 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/ziodevs.c 2006-07-12 21:30:00 UTC (rev 6912)
@@ -157,6 +157,27 @@
}
private int
+ s_stdout_swrite_process(stream_state *, stream_cursor_read *,
+ stream_cursor_write *, bool);
+
+/* Write a buffer to stdout, potentially writing to callback */
+private int
+s_stdout_write_process(stream_state * st, stream_cursor_read * ignore_pr,
+ stream_cursor_write * pw, bool last)
+{
+ uint count = pr->limit - pr->ptr;
+ int written;
+
+ if (count == 0)
+ return 0;
+ written = outwrite(st->memory, pr->ptr + 1, count);
+ if (written < count) {
+ return ERRC;
+ pr->ptr += written;
+ return 0;
+}
+
+private int
stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
@@ -176,6 +197,7 @@
swrite_file(s, gs_stdout, buf, STDOUT_BUF_SIZE);
s->save_close = s->procs.flush;
s->procs.close = file_close_file;
+ s->procs.process = s_stdout_write_process;
make_file(&ref_stdout, a_write | avm_system, s->write_id, s);
*ps = s;
return 1;
Modified: trunk/gs/src/ziodevsc.c
===================================================================
--- trunk/gs/src/ziodevsc.c 2006-07-12 21:24:01 UTC (rev 6911)
+++ trunk/gs/src/ziodevsc.c 2006-07-12 21:30:00 UTC (rev 6912)
@@ -81,52 +81,78 @@
}
private int
+ s_stdin_read_process(stream_state *, stream_cursor_read *,
+ stream_cursor_write *, bool);
+
+private int
stdin_init(gx_io_device * iodev, gs_memory_t * mem)
{
mem->gs_lib_ctx->stdin_is_interactive = true;
return 0;
}
-/* stdin stream implemented as procedure */
+/* Read from stdin into the buffer. */
+/* If interactive, only read one character. */
private int
+s_stdin_read_process(stream_state * st, stream_cursor_read * ignore_pr,
+ stream_cursor_write * pw, bool last)
+{
+ int wcount = (int)(pw->limit - pw->ptr);
+ int count;
+ gs_memory_t *mem = st->memory;
+
+ if (wcount <= 0)
+ return 0;
+
+ /* do the callout */
+ if (mem->gs_lib_ctx->stdin_fn)
+ count = (*mem->gs_lib_ctx->stdin_fn)
+ (mem->gs_lib_ctx->caller_handle, (char *)pw->ptr + 1,
+ mem->gs_lib_ctx->stdin_is_interactive ? 1 : wcount);
+ else
+ count = gp_stdin_read(pw->ptr + 1, wcount,
+ mem->gs_lib_ctx->stdin_is_interactive,
+ mem->gs_lib_ctx->fstdin);
+
+ pw->ptr += (count < 0) ? 0 : count;
+ return ((count < 0) ? ERRC : (count == 0) ? EOFC : count);
+}
+
+private int
stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
- gs_memory_t * mem)
+ gs_memory_t * mem)
{
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
stream *s;
- int code;
if (!streq1(access, 'r'))
return_error(e_invalidfileaccess);
if (file_is_invalid(s, &ref_stdin)) {
- /* procedure source */
- gs_ref_memory_t *imem = (gs_ref_memory_t *)imemory_system;
- ref rint;
+ /****** stdin SHOULD NOT LINE-BUFFER ******/
+ gs_memory_t *mem = imemory_system;
+ byte *buf;
+ static const stream_procs p = {
+ s_std_noavailable, s_std_noseek, s_std_read_reset,
+ s_std_read_flush, file_close_file, s_stdin_read_process
+ };
- /* The procedure isn't used. */
- /* Set it to literal 0 to recognised stdin. */
- make_int(&rint, 0);
+ s = file_alloc_stream(mem, "stdin_open(stream)");
- /* implement stdin as a procedure */
- code = sread_proc(&rint, &s, imem);
- if (code < 0)
- return code;
+ /* We want stdin to read only one character at a time, */
+ /* but it must have a substantial buffer, in case it is used */
+ /* by a stream that requires more than one input byte */
+ /* to make progress. */
+ buf = gs_alloc_bytes(mem, STDIN_BUF_SIZE, "stdin_open(buffer)");
+ if (s == 0 || buf == 0)
+ return_error(e_VMerror);
+
+ s_std_init(s, buf, STDIN_BUF_SIZE, &p, s_mode_read);
+ s->file = 0;
+ s->file_modes = s->modes;
+ s->file_offset = 0;
+ s->file_limit = max_long;
s->save_close = s_std_null;
- s->procs.close = stdio_close;
- /* allocate buffer */
- if (s->cbuf == 0) {
- int len = STDIN_BUF_SIZE;
- byte *buf = gs_alloc_bytes((gs_memory_t *)imemory_system,
- len, "stdin_open");
- if (buf == 0)
- return_error(e_VMerror);
- s->cbuf = buf;
- s->srptr = s->srlimit = s->swptr = buf - 1;
- s->swlimit = buf - 1 + len;
- s->bsize = s->cbsize = len;
- }
- s->state->min_left = 0;
- make_file(&ref_stdin, a_read | avm_system, s->read_id, s);
+ make_file(&ref_stdin, a_readonly | avm_system, s->read_id, s);
*ps = s;
return 1;
}
@@ -151,60 +177,62 @@
iodev->state = NULL;
return min(code, 0);
}
+
/* Test whether a stream is stdin. */
bool
zis_stdin(const stream *s)
{
- /* Only stdin should be a procedure based stream, opened for
- * reading and with a literal 0 as the procedure.
- */
- if (s_is_valid(s) && s_is_reading(s) && s_is_proc(s)) {
- stream_proc_state *state = (stream_proc_state *)s->state;
- if ((r_type(&(state->proc)) == t_integer) &&
- (state->proc.value.intval == 0))
- return true;
- }
- return false;
+ return (s_is_valid(s) && s->procs.process == s_stdin_read_process);
}
-/* stdout stream implemented as procedure */
private int
+ s_stdout_swrite_process(stream_state *, stream_cursor_read *,
+ stream_cursor_write *, bool);
+
+/* Write a buffer to stdout, potentially writing to callback */
+private int
+s_stdout_write_process(stream_state * st, stream_cursor_read *pr,
+ stream_cursor_write *ignore_pw, bool last)
+{
+ uint count = pr->limit - pr->ptr;
+ int written;
+
+ if (count == 0)
+ return 0;
+ written = outwrite(st->memory, pr->ptr + 1, count);
+ if (written < count)
+ return ERRC;
+ pr->ptr += written;
+ return 0;
+}
+
+private int
stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
stream *s;
- int code;
if (!streq1(access, 'w'))
return_error(e_invalidfileaccess);
if (file_is_invalid(s, &ref_stdout)) {
- /* procedure source */
- gs_ref_memory_t *imem = (gs_ref_memory_t *)imemory_system;
- ref rint;
+ gs_memory_t *mem = imemory_system;
+ byte *buf;
+ static const stream_procs p = {
+ s_std_noavailable, s_std_noseek, s_std_write_reset,
+ s_std_write_flush, file_close_file, s_stdout_write_process
+ };
- /* The procedure isn't used. */
- /* Set it to literal 1 to recognised stdout. */
- make_int(&rint, 1);
-
- /* implement stdout as a procedure */
- code = swrite_proc(&rint, &s, imem);
- if (code < 0)
- return code;
+ s = file_alloc_stream(mem, "stdout_open(stream)");
+ buf = gs_alloc_bytes(mem, STDOUT_BUF_SIZE, "stdout_open(buffer)");
+ if (s == 0 || buf == 0)
+ return_error(e_VMerror);
+ s_std_init(s, buf, STDOUT_BUF_SIZE, &p, s_mode_write);
+ s->file = 0;
+ s->file_modes = s->modes;
+ s->file_offset = 0; /* in case we switch to reading later */
+ s->file_limit = max_long; /* ibid. */
s->save_close = s->procs.flush;
- s->procs.close = stdio_close;
- /* allocate buffer */
- if (s->cbuf == 0) {
- int len = STDOUT_BUF_SIZE;
- byte *buf = gs_alloc_bytes((gs_memory_t *)imemory_system,
- len, "stdout_open");
- if (buf == 0)
- return_error(e_VMerror);
- s->cbuf = buf;
- s->srptr = s->srlimit = s->swptr = buf - 1;
- s->swlimit = buf - 1 + len;
- s->bsize = s->cbsize = len;
- }
make_file(&ref_stdout, a_write | avm_system, s->write_id, s);
*ps = s;
return 1;
@@ -212,6 +240,7 @@
*ps = s;
return 0;
}
+
/* This is the public routine for getting the stdout stream. */
int
zget_stdout(i_ctx_t *i_ctx_p, stream ** ps)
@@ -231,44 +260,54 @@
return min(code, 0);
}
-/* stderr stream implemented as procedure */
private int
+ s_stderr_swrite_process(stream_state *, stream_cursor_read *,
+ stream_cursor_write *, bool);
+
+/* Write a buffer to stderr, potentially writing to callback */
+private int
+s_stderr_write_process(stream_state * st, stream_cursor_read *pr,
+ stream_cursor_write *ignore_pw, bool last)
+{
+ uint count = pr->limit - pr->ptr;
+ int written;
+
+ if (count == 0)
+ return 0;
+ written = errwrite((const char *)(pr->ptr + 1), count);
+ if (written < count)
+ return ERRC;
+ pr->ptr += written;
+ return 0;
+}
+
+private int
stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
gs_memory_t * mem)
{
i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */
stream *s;
- int code;
if (!streq1(access, 'w'))
return_error(e_invalidfileaccess);
if (file_is_invalid(s, &ref_stderr)) {
- /* procedure source */
- gs_ref_memory_t *imem = (gs_ref_memory_t *)imemory_system;
- ref rint;
+ gs_memory_t *mem = imemory_system;
+ byte *buf;
+ static const stream_procs p = {
+ s_std_noavailable, s_std_noseek, s_std_write_reset,
+ s_std_write_flush, file_close_file, s_stderr_write_process
+ };
- /* The procedure isn't used. */
- /* Set it to literal 2 to recognised stderr. */
- make_int(&rint, 2);
-
- /* implement stderr as a procedure */
- code = swrite_proc(&rint, &s, imem);
- if (code < 0)
- return code;
+ s = file_alloc_stream(mem, "stderr_open(stream)");
+ buf = gs_alloc_bytes(mem, STDERR_BUF_SIZE, "stderr_open(buffer)");
+ if (s == 0 || buf == 0)
+ return_error(e_VMerror);
+ s_std_init(s, buf, STDERR_BUF_SIZE, &p, s_mode_write);
+ s->file = 0;
+ s->file_modes = s->modes;
+ s->file_offset = 0; /* in case we switch to reading later */
+ s->file_limit = max_long; /* ibid. */
s->save_close = s->procs.flush;
- s->procs.close = stdio_close;
- /* allocate buffer */
- if (s->cbuf == 0) {
- int len = STDERR_BUF_SIZE;
- byte *buf = gs_alloc_bytes((gs_memory_t *)imemory_system,
- len, "stderr_open");
- if (buf == 0)
- return_error(e_VMerror);
- s->cbuf = buf;
- s->srptr = s->srlimit = s->swptr = buf - 1;
- s->swlimit = buf - 1 + len;
- s->bsize = s->cbsize = len;
- }
make_file(&ref_stderr, a_write | avm_system, s->write_id, s);
*ps = s;
return 1;
@@ -276,6 +315,7 @@
*ps = s;
return 0;
}
+
/* This is the public routine for getting the stderr stream. */
int
zget_stderr(i_ctx_t *i_ctx_p, stream ** ps)
More information about the gs-cvs
mailing list