From 2ef22003688c02f5f8fcef45429224bdace6ee02 Mon Sep 17 00:00:00 2001 From: Tim Waugh Date: Fri, 14 Jan 2011 17:21:20 +0000 Subject: [PATCH] Avoid symbol clash with scan_token (bug #590914). --- ghostscript-scan_token.patch | 8519 ++++++++++++++++++++++++++++++++++ ghostscript.spec | 9 +- 2 files changed, 8527 insertions(+), 1 deletion(-) create mode 100644 ghostscript-scan_token.patch diff --git a/ghostscript-scan_token.patch b/ghostscript-scan_token.patch new file mode 100644 index 0000000..8b6cc3e --- /dev/null +++ b/ghostscript-scan_token.patch @@ -0,0 +1,8519 @@ +diff -up ghostscript-9.00/psi/imainarg.c.scan_token ghostscript-9.00/psi/imainarg.c +--- ghostscript-9.00/psi/imainarg.c.scan_token 2010-05-04 19:47:12.000000000 +0100 ++++ ghostscript-9.00/psi/imainarg.c 2011-01-14 17:16:12.596867462 +0000 +@@ -1,6 +1,6 @@ + /* Copyright (C) 2001-2007 Artifex Software, Inc. + All Rights Reserved. +- ++ + This software is provided AS-IS with no warranty, either express or + implied. + +@@ -16,13 +16,13 @@ + #include "ctype_.h" + #include "memory_.h" + #include "string_.h" +-#include /* for qsort */ ++#include /* for qsort */ + + #include "ghost.h" + #include "gp.h" + #include "gsargs.h" + #include "gscdefs.h" +-#include "gsmalloc.h" /* for gs_malloc_limit */ ++#include "gsmalloc.h" /* for gs_malloc_limit */ + #include "gsmdebug.h" + #include "gxdevice.h" + #include "gxdevmem.h" +@@ -31,9 +31,9 @@ + #include "ierrors.h" + #include "estack.h" + #include "ialloc.h" +-#include "strimpl.h" /* for sfilter.h */ +-#include "sfilter.h" /* for iscan.h */ +-#include "ostack.h" /* must precede iscan.h */ ++#include "strimpl.h" /* for sfilter.h */ ++#include "sfilter.h" /* for iscan.h */ ++#include "ostack.h" /* must precede iscan.h */ + #include "iscan.h" + #include "iconf.h" + #include "imain.h" +@@ -42,7 +42,7 @@ + #include "iminst.h" + #include "iname.h" + #include "store.h" +-#include "files.h" /* requires stream.h */ ++#include "files.h" /* requires stream.h */ + #include "interp.h" + #include "iutil.h" + #include "ivmspace.h" +@@ -86,8 +86,8 @@ static void esc_strcat(char *, const cha + static int runarg(gs_main_instance *, const char *, const char *, const char *, int); + static int run_string(gs_main_instance *, const char *, int); + static int run_finish(gs_main_instance *, int, int, ref *); +-static int try_stdout_redirect(gs_main_instance * minst, +- const char *command, const char *filename); ++static int try_stdout_redirect(gs_main_instance * minst, ++ const char *command, const char *filename); + + /* Forward references for help printout */ + static void print_help(gs_main_instance *); +@@ -106,8 +106,8 @@ static FILE * + gs_main_arg_fopen(const char *fname, void *vminst) + { + gs_main_set_lib_paths((gs_main_instance *) vminst); +- return lib_fopen(&((gs_main_instance *)vminst)->lib_path, +- ((gs_main_instance *)vminst)->heap, fname); ++ return lib_fopen(&((gs_main_instance *)vminst)->lib_path, ++ ((gs_main_instance *)vminst)->heap, fname); + } + static void + set_debug_flags(const char *arg, char *flags) +@@ -115,7 +115,7 @@ set_debug_flags(const char *arg, char *f + byte value = (*arg == '-' ? (++arg, 0) : 0xff); + + while (*arg) +- flags[*arg++ & 127] = value; ++ flags[*arg++ & 127] = value; + } + + int +@@ -126,10 +126,10 @@ gs_main_init_with_args(gs_main_instance + int code; + + arg_init(&args, (const char **)argv, argc, +- gs_main_arg_fopen, (void *)minst); ++ gs_main_arg_fopen, (void *)minst); + code = gs_main_init0(minst, 0, 0, 0, GS_MAX_LIB_DIRS); + if (code < 0) +- return code; ++ return code; + /* This first check is not needed on VMS since GS_LIB evaluates to the same + value as that returned by gs_lib_default_path. Also, since GS_LIB is + defined as a searchlist logical and getenv only returns the first entry +@@ -138,42 +138,42 @@ gs_main_init_with_args(gs_main_instance + */ + #ifndef __VMS + { +- int len = 0; +- int code = gp_getenv(GS_LIB, (char *)0, &len); ++ int len = 0; ++ int code = gp_getenv(GS_LIB, (char *)0, &len); + +- if (code < 0) { /* key present, value doesn't fit */ +- char *path = (char *)gs_alloc_bytes(minst->heap, len, "GS_LIB"); ++ if (code < 0) { /* key present, value doesn't fit */ ++ char *path = (char *)gs_alloc_bytes(minst->heap, len, "GS_LIB"); + +- gp_getenv(GS_LIB, path, &len); /* can't fail */ +- minst->lib_path.env = path; +- } ++ gp_getenv(GS_LIB, path, &len); /* can't fail */ ++ minst->lib_path.env = path; ++ } + } + #endif /* __VMS */ + minst->lib_path.final = gs_lib_default_path; + code = gs_main_set_lib_paths(minst); + if (code < 0) +- return code; ++ return code; + /* Prescan the command line for --help and --version. */ + { +- int i; +- bool helping = false; ++ int i; ++ bool helping = false; + +- for (i = 1; i < argc; ++i) +- if (!strcmp(argv[i], "--")) { +- /* A PostScript program will be interpreting all the */ +- /* remaining switches, so stop scanning. */ +- helping = false; +- break; +- } else if (!strcmp(argv[i], "--help")) { +- print_help(minst); +- helping = true; +- } else if (!strcmp(argv[i], "--version")) { +- print_version(minst); +- puts(minst->heap, ""); /* \n */ +- helping = true; +- } +- if (helping) +- return e_Info; ++ for (i = 1; i < argc; ++i) ++ if (!strcmp(argv[i], "--")) { ++ /* A PostScript program will be interpreting all the */ ++ /* remaining switches, so stop scanning. */ ++ helping = false; ++ break; ++ } else if (!strcmp(argv[i], "--help")) { ++ print_help(minst); ++ helping = true; ++ } else if (!strcmp(argv[i], "--version")) { ++ print_version(minst); ++ puts(minst->heap, ""); /* \n */ ++ helping = true; ++ } ++ if (helping) ++ return e_Info; + } + /* Execute files named in the command line, */ + /* processing options along the way. */ +@@ -182,58 +182,58 @@ gs_main_init_with_args(gs_main_instance + minst->run_start = true; + + { +- int len = 0; +- int code = gp_getenv(GS_OPTIONS, (char *)0, &len); ++ int len = 0; ++ int code = gp_getenv(GS_OPTIONS, (char *)0, &len); + +- if (code < 0) { /* key present, value doesn't fit */ +- char *opts = +- (char *)gs_alloc_bytes(minst->heap, len, "GS_OPTIONS"); +- +- gp_getenv(GS_OPTIONS, opts, &len); /* can't fail */ +- if (arg_push_memory_string(&args, opts, false, minst->heap)) +- return e_Fatal; +- } ++ if (code < 0) { /* key present, value doesn't fit */ ++ char *opts = ++ (char *)gs_alloc_bytes(minst->heap, len, "GS_OPTIONS"); ++ ++ gp_getenv(GS_OPTIONS, opts, &len); /* can't fail */ ++ if (arg_push_memory_string(&args, opts, false, minst->heap)) ++ return e_Fatal; ++ } + } + while ((arg = arg_next(&args, &code)) != 0) { +- switch (*arg) { +- case '-': +- code = swproc(minst, arg, &args); +- if (code < 0) +- return code; +- if (code > 0) +- outprintf(minst->heap, "Unknown switch %s - ignoring\n", arg); +- if (gs_debug[':'] && arg[1] == 'Z') { +- int i; +- +- dprintf1("%% Init started, instance 0x%p, with args: ", minst); +- for (i=1; i 0) ++ outprintf(minst->heap, "Unknown switch %s - ignoring\n", arg); ++ if (gs_debug[':'] && arg[1] == 'Z') { ++ int i; ++ ++ dprintf1("%% Init started, instance 0x%p, with args: ", minst); ++ for (i=1; irun_start) +- return e_Quit; ++ return e_Quit; + return code ; + } + +@@ -259,417 +259,417 @@ swproc(gs_main_instance * minst, const c + i_initial_enter_name(minst->i_ctx_p, nstr, pvalue) + + make_true(&vtrue); +- arg += 2; /* skip - and letter */ ++ arg += 2; /* skip - and letter */ + switch (sw) { +- default: +- return 1; +- case 0: /* read stdin as a file char-by-char */ +- /* This is a ******HACK****** for Ghostview. */ +- minst->heap->gs_lib_ctx->stdin_is_interactive = true; +- goto run_stdin; +- case '_': /* read stdin with normal buffering */ +- minst->heap->gs_lib_ctx->stdin_is_interactive = false; ++ default: ++ return 1; ++ case 0: /* read stdin as a file char-by-char */ ++ /* This is a ******HACK****** for Ghostview. */ ++ minst->heap->gs_lib_ctx->stdin_is_interactive = true; ++ goto run_stdin; ++ case '_': /* read stdin with normal buffering */ ++ minst->heap->gs_lib_ctx->stdin_is_interactive = false; + run_stdin: +- minst->run_start = false; /* don't run 'start' */ +- /* Set NOPAUSE so showpage won't try to read from stdin. */ +- code = swproc(minst, "-dNOPAUSE", pal); +- if (code) +- return code; +- code = gs_main_init2(minst); /* Finish initialization */ +- if (code < 0) +- return code; +- +- code = run_string(minst, ".runstdin", runFlush); +- if (code < 0) +- return code; +- break; +- case '-': /* run with command line args */ +- case '+': +- pal->expand_ats = false; +- case '@': /* ditto with @-expansion */ +- { +- const char *psarg = arg_next(pal, &code); +- +- if (code < 0) +- return e_Fatal; +- if (psarg == 0) { +- outprintf(minst->heap, "Usage: gs ... -%c file.ps arg1 ... argn\n", sw); +- arg_finit(pal); +- return e_Fatal; +- } +- psarg = arg_copy(psarg, minst->heap); +- if (psarg == NULL) +- return e_Fatal; +- code = gs_main_init2(minst); +- if (code < 0) +- return code; +- code = run_string(minst, "userdict/ARGUMENTS[", 0); +- if (code < 0) +- return code; +- while ((arg = arg_next(pal, &code)) != 0) { +- char *fname = arg_copy(arg, minst->heap); +- if (fname == NULL) +- return e_Fatal; +- code = runarg(minst, "", fname, "", runInit); +- if (code < 0) +- return code; +- } +- if (code < 0) +- return e_Fatal; +- runarg(minst, "]put", psarg, ".runfile", runInit | runFlush); +- return e_Quit; +- } +- case 'A': /* trace allocator */ +- switch (*arg) { +- case 0: +- gs_alloc_debug = 1; +- break; +- case '-': +- gs_alloc_debug = 0; +- break; +- default: +- puts(minst->heap, "-A may only be followed by -"); +- return e_Fatal; +- } +- break; +- case 'B': /* set run_string buffer size */ +- if (*arg == '-') +- minst->run_buffer_size = 0; +- else { +- uint bsize; +- +- if (sscanf((const char *)arg, "%u", &bsize) != 1 || +- bsize <= 0 || bsize > MAX_BUFFERED_SIZE +- ) { +- outprintf(minst->heap, +- "-B must be followed by - or size between 1 and %u\n", +- MAX_BUFFERED_SIZE); +- return e_Fatal; +- } +- minst->run_buffer_size = bsize; +- } +- break; +- case 'c': /* code follows */ +- { +- bool ats = pal->expand_ats; +- +- code = gs_main_init2(minst); +- if (code < 0) +- return code; +- pal->expand_ats = false; +- while ((arg = arg_next(pal, &code)) != 0) { +- char *sarg; +- +- if (arg[0] == '@' || +- (arg[0] == '-' && !isdigit((unsigned char)arg[1])) +- ) +- break; +- sarg = arg_copy(arg, minst->heap); +- if (sarg == NULL) +- return e_Fatal; +- code = runarg(minst, "", sarg, ".runstring", 0); +- if (code < 0) +- return code; +- } +- if (code < 0) +- return e_Fatal; +- if (arg != 0) { +- char *p = arg_copy(arg, minst->heap); +- if (p == NULL) +- return e_Fatal; +- arg_push_string(pal, p, true); +- } +- pal->expand_ats = ats; +- break; +- } +- case 'E': /* log errors */ +- switch (*arg) { +- case 0: +- gs_log_errors = 1; +- break; +- case '-': +- gs_log_errors = 0; +- break; +- default: +- puts(minst->heap, "-E may only be followed by -"); +- return e_Fatal; +- } +- break; +- case 'f': /* run file of arbitrary name */ +- if (*arg != 0) { +- code = argproc(minst, arg); +- if (code < 0) +- return code; +- } +- break; +- case 'F': /* run file with buffer_size = 1 */ +- if (!*arg) { +- puts(minst->heap, "-F requires a file name"); +- return e_Fatal; +- } { +- uint bsize = minst->run_buffer_size; +- +- minst->run_buffer_size = 1; +- code = argproc(minst, arg); +- minst->run_buffer_size = bsize; +- if (code < 0) +- return code; +- } +- break; +- case 'g': /* define device geometry */ +- { +- long width, height; +- ref value; +- +- if ((code = gs_main_init1(minst)) < 0) +- return code; +- if (sscanf((const char *)arg, "%ldx%ld", &width, &height) != 2) { +- puts(minst->heap, "-g must be followed by x"); +- return e_Fatal; +- } +- make_int(&value, width); +- initial_enter_name("DEVICEWIDTH", &value); +- make_int(&value, height); +- initial_enter_name("DEVICEHEIGHT", &value); +- initial_enter_name("FIXEDMEDIA", &vtrue); +- break; +- } +- case 'h': /* print help */ +- case '?': /* ditto */ +- print_help(minst); +- return e_Info; /* show usage info on exit */ +- case 'I': /* specify search path */ +- { +- char *path = arg_copy(arg, minst->heap); +- if (path == NULL) +- return e_Fatal; +- gs_main_add_lib_path(minst, path); +- } +- break; +- case 'K': /* set malloc limit */ +- { +- long msize = 0; +- gs_malloc_memory_t *rawheap = gs_malloc_wrapped_contents(minst->heap); +- +- sscanf((const char *)arg, "%ld", &msize); +- if (msize <= 0 || msize > max_long >> 10) { +- outprintf(minst->heap, "-K must have 1 <= numK <= %ld\n", +- max_long >> 10); +- return e_Fatal; +- } +- rawheap->limit = msize << 10; +- } +- break; +- case 'M': /* set memory allocation increment */ +- { +- unsigned msize = 0; ++ minst->run_start = false; /* don't run 'start' */ ++ /* Set NOPAUSE so showpage won't try to read from stdin. */ ++ code = swproc(minst, "-dNOPAUSE", pal); ++ if (code) ++ return code; ++ code = gs_main_init2(minst); /* Finish initialization */ ++ if (code < 0) ++ return code; ++ ++ code = run_string(minst, ".runstdin", runFlush); ++ if (code < 0) ++ return code; ++ break; ++ case '-': /* run with command line args */ ++ case '+': ++ pal->expand_ats = false; ++ case '@': /* ditto with @-expansion */ ++ { ++ const char *psarg = arg_next(pal, &code); ++ ++ if (code < 0) ++ return e_Fatal; ++ if (psarg == 0) { ++ outprintf(minst->heap, "Usage: gs ... -%c file.ps arg1 ... argn\n", sw); ++ arg_finit(pal); ++ return e_Fatal; ++ } ++ psarg = arg_copy(psarg, minst->heap); ++ if (psarg == NULL) ++ return e_Fatal; ++ code = gs_main_init2(minst); ++ if (code < 0) ++ return code; ++ code = run_string(minst, "userdict/ARGUMENTS[", 0); ++ if (code < 0) ++ return code; ++ while ((arg = arg_next(pal, &code)) != 0) { ++ char *fname = arg_copy(arg, minst->heap); ++ if (fname == NULL) ++ return e_Fatal; ++ code = runarg(minst, "", fname, "", runInit); ++ if (code < 0) ++ return code; ++ } ++ if (code < 0) ++ return e_Fatal; ++ runarg(minst, "]put", psarg, ".runfile", runInit | runFlush); ++ return e_Quit; ++ } ++ case 'A': /* trace allocator */ ++ switch (*arg) { ++ case 0: ++ gs_alloc_debug = 1; ++ break; ++ case '-': ++ gs_alloc_debug = 0; ++ break; ++ default: ++ puts(minst->heap, "-A may only be followed by -"); ++ return e_Fatal; ++ } ++ break; ++ case 'B': /* set run_string buffer size */ ++ if (*arg == '-') ++ minst->run_buffer_size = 0; ++ else { ++ uint bsize; ++ ++ if (sscanf((const char *)arg, "%u", &bsize) != 1 || ++ bsize <= 0 || bsize > MAX_BUFFERED_SIZE ++ ) { ++ outprintf(minst->heap, ++ "-B must be followed by - or size between 1 and %u\n", ++ MAX_BUFFERED_SIZE); ++ return e_Fatal; ++ } ++ minst->run_buffer_size = bsize; ++ } ++ break; ++ case 'c': /* code follows */ ++ { ++ bool ats = pal->expand_ats; ++ ++ code = gs_main_init2(minst); ++ if (code < 0) ++ return code; ++ pal->expand_ats = false; ++ while ((arg = arg_next(pal, &code)) != 0) { ++ char *sarg; ++ ++ if (arg[0] == '@' || ++ (arg[0] == '-' && !isdigit((unsigned char)arg[1])) ++ ) ++ break; ++ sarg = arg_copy(arg, minst->heap); ++ if (sarg == NULL) ++ return e_Fatal; ++ code = runarg(minst, "", sarg, ".runstring", 0); ++ if (code < 0) ++ return code; ++ } ++ if (code < 0) ++ return e_Fatal; ++ if (arg != 0) { ++ char *p = arg_copy(arg, minst->heap); ++ if (p == NULL) ++ return e_Fatal; ++ arg_push_string(pal, p, true); ++ } ++ pal->expand_ats = ats; ++ break; ++ } ++ case 'E': /* log errors */ ++ switch (*arg) { ++ case 0: ++ gs_log_errors = 1; ++ break; ++ case '-': ++ gs_log_errors = 0; ++ break; ++ default: ++ puts(minst->heap, "-E may only be followed by -"); ++ return e_Fatal; ++ } ++ break; ++ case 'f': /* run file of arbitrary name */ ++ if (*arg != 0) { ++ code = argproc(minst, arg); ++ if (code < 0) ++ return code; ++ } ++ break; ++ case 'F': /* run file with buffer_size = 1 */ ++ if (!*arg) { ++ puts(minst->heap, "-F requires a file name"); ++ return e_Fatal; ++ } { ++ uint bsize = minst->run_buffer_size; ++ ++ minst->run_buffer_size = 1; ++ code = argproc(minst, arg); ++ minst->run_buffer_size = bsize; ++ if (code < 0) ++ return code; ++ } ++ break; ++ case 'g': /* define device geometry */ ++ { ++ long width, height; ++ ref value; ++ ++ if ((code = gs_main_init1(minst)) < 0) ++ return code; ++ if (sscanf((const char *)arg, "%ldx%ld", &width, &height) != 2) { ++ puts(minst->heap, "-g must be followed by x"); ++ return e_Fatal; ++ } ++ make_int(&value, width); ++ initial_enter_name("DEVICEWIDTH", &value); ++ make_int(&value, height); ++ initial_enter_name("DEVICEHEIGHT", &value); ++ initial_enter_name("FIXEDMEDIA", &vtrue); ++ break; ++ } ++ case 'h': /* print help */ ++ case '?': /* ditto */ ++ print_help(minst); ++ return e_Info; /* show usage info on exit */ ++ case 'I': /* specify search path */ ++ { ++ char *path = arg_copy(arg, minst->heap); ++ if (path == NULL) ++ return e_Fatal; ++ gs_main_add_lib_path(minst, path); ++ } ++ break; ++ case 'K': /* set malloc limit */ ++ { ++ long msize = 0; ++ gs_malloc_memory_t *rawheap = gs_malloc_wrapped_contents(minst->heap); ++ ++ sscanf((const char *)arg, "%ld", &msize); ++ if (msize <= 0 || msize > max_long >> 10) { ++ outprintf(minst->heap, "-K must have 1 <= numK <= %ld\n", ++ max_long >> 10); ++ return e_Fatal; ++ } ++ rawheap->limit = msize << 10; ++ } ++ break; ++ case 'M': /* set memory allocation increment */ ++ { ++ unsigned msize = 0; + +- sscanf((const char *)arg, "%u", &msize); ++ sscanf((const char *)arg, "%u", &msize); + #if ARCH_INTS_ARE_SHORT +- if (msize <= 0 || msize >= 64) { +- puts(minst->heap, "-M must be between 1 and 63"); +- return e_Fatal; +- } ++ if (msize <= 0 || msize >= 64) { ++ puts(minst->heap, "-M must be between 1 and 63"); ++ return e_Fatal; ++ } + #endif +- minst->memory_chunk_size = msize << 10; +- } +- break; +- case 'N': /* set size of name table */ +- { +- unsigned nsize = 0; ++ minst->memory_chunk_size = msize << 10; ++ } ++ break; ++ case 'N': /* set size of name table */ ++ { ++ unsigned nsize = 0; + +- sscanf((const char *)arg, "%d", &nsize); ++ sscanf((const char *)arg, "%d", &nsize); + #if ARCH_INTS_ARE_SHORT +- if (nsize < 2 || nsize > 64) { +- puts(minst->heap, "-N must be between 2 and 64"); +- return e_Fatal; +- } ++ if (nsize < 2 || nsize > 64) { ++ puts(minst->heap, "-N must be between 2 and 64"); ++ return e_Fatal; ++ } + #endif +- minst->name_table_size = (ulong) nsize << 10; +- } +- break; +- case 'o': /* set output file name and batch mode */ +- { +- const char *adef; +- char *str; +- ref value; +- int len; +- +- if (arg[0] == 0) { +- adef = arg_next(pal, &code); +- if (code < 0) +- return code; +- } else +- adef = arg; +- if ((code = gs_main_init1(minst)) < 0) +- return code; +- len = strlen(adef); +- str = (char *)gs_alloc_bytes(minst->heap, (uint)len, "-o"); +- memcpy(str, adef, len); +- make_const_string(&value, a_readonly | avm_foreign, +- len, (const byte *)str); +- initial_enter_name("OutputFile", &value); +- initial_enter_name("NOPAUSE", &vtrue); +- initial_enter_name("BATCH", &vtrue); +- } +- break; +- case 'P': /* choose whether search '.' first */ +- if (!strcmp(arg, "")) +- minst->search_here_first = true; +- else if (!strcmp(arg, "-")) +- minst->search_here_first = false; +- else { +- puts(minst->heap, "Only -P or -P- is allowed."); +- return e_Fatal; +- } +- break; +- case 'q': /* quiet startup */ +- if ((code = gs_main_init1(minst)) < 0) +- return code; +- initial_enter_name("QUIET", &vtrue); +- break; +- case 'r': /* define device resolution */ +- { +- float xres, yres; +- ref value; +- +- if ((code = gs_main_init1(minst)) < 0) +- return code; +- switch (sscanf((const char *)arg, "%fx%f", &xres, &yres)) { +- default: +- puts(minst->heap, "-r must be followed by or x"); +- return e_Fatal; +- case 1: /* -r */ +- yres = xres; +- case 2: /* -rx */ +- make_real(&value, xres); +- initial_enter_name("DEVICEXRESOLUTION", &value); +- make_real(&value, yres); +- initial_enter_name("DEVICEYRESOLUTION", &value); +- initial_enter_name("FIXEDRESOLUTION", &vtrue); +- } +- break; +- } +- case 'D': /* define name */ +- case 'd': +- case 'S': /* define name as string */ +- case 's': +- { +- char *adef = arg_copy(arg, minst->heap); +- char *eqp; +- bool isd = (sw == 'D' || sw == 'd'); +- ref value; +- +- if (adef == NULL) +- return e_Fatal; +- eqp = strchr(adef, '='); +- +- if (eqp == NULL) +- eqp = strchr(adef, '#'); +- /* Initialize the object memory, scanner, and */ +- /* name table now if needed. */ +- if ((code = gs_main_init1(minst)) < 0) +- return code; +- if (eqp == adef) { +- puts(minst->heap, "Usage: -dname, -dname=token, -sname=string"); +- return e_Fatal; +- } +- if (eqp == NULL) { +- if (isd) +- make_true(&value); +- else +- make_empty_string(&value, a_readonly); +- } else { +- int code; +- i_ctx_t *i_ctx_p = minst->i_ctx_p; +- uint space = icurrent_space; +- +- *eqp++ = 0; +- ialloc_set_space(idmemory, avm_system); +- if (isd) { +- stream astream; +- scanner_state state; +- +- s_init(&astream, NULL); +- sread_string(&astream, +- (const byte *)eqp, strlen(eqp)); +- scanner_init_stream(&state, &astream); +- code = scan_token(minst->i_ctx_p, &value, &state); +- if (code) { +- puts(minst->heap, "-dname= must be followed by a valid token"); +- return e_Fatal; +- } +- if (r_has_type_attrs(&value, t_name, +- a_executable)) { +- ref nsref; ++ minst->name_table_size = (ulong) nsize << 10; ++ } ++ break; ++ case 'o': /* set output file name and batch mode */ ++ { ++ const char *adef; ++ char *str; ++ ref value; ++ int len; ++ ++ if (arg[0] == 0) { ++ adef = arg_next(pal, &code); ++ if (code < 0) ++ return code; ++ } else ++ adef = arg; ++ if ((code = gs_main_init1(minst)) < 0) ++ return code; ++ len = strlen(adef); ++ str = (char *)gs_alloc_bytes(minst->heap, (uint)len, "-o"); ++ memcpy(str, adef, len); ++ make_const_string(&value, a_readonly | avm_foreign, ++ len, (const byte *)str); ++ initial_enter_name("OutputFile", &value); ++ initial_enter_name("NOPAUSE", &vtrue); ++ initial_enter_name("BATCH", &vtrue); ++ } ++ break; ++ case 'P': /* choose whether search '.' first */ ++ if (!strcmp(arg, "")) ++ minst->search_here_first = true; ++ else if (!strcmp(arg, "-")) ++ minst->search_here_first = false; ++ else { ++ puts(minst->heap, "Only -P or -P- is allowed."); ++ return e_Fatal; ++ } ++ break; ++ case 'q': /* quiet startup */ ++ if ((code = gs_main_init1(minst)) < 0) ++ return code; ++ initial_enter_name("QUIET", &vtrue); ++ break; ++ case 'r': /* define device resolution */ ++ { ++ float xres, yres; ++ ref value; ++ ++ if ((code = gs_main_init1(minst)) < 0) ++ return code; ++ switch (sscanf((const char *)arg, "%fx%f", &xres, &yres)) { ++ default: ++ puts(minst->heap, "-r must be followed by or x"); ++ return e_Fatal; ++ case 1: /* -r */ ++ yres = xres; ++ case 2: /* -rx */ ++ make_real(&value, xres); ++ initial_enter_name("DEVICEXRESOLUTION", &value); ++ make_real(&value, yres); ++ initial_enter_name("DEVICEYRESOLUTION", &value); ++ initial_enter_name("FIXEDRESOLUTION", &vtrue); ++ } ++ break; ++ } ++ case 'D': /* define name */ ++ case 'd': ++ case 'S': /* define name as string */ ++ case 's': ++ { ++ char *adef = arg_copy(arg, minst->heap); ++ char *eqp; ++ bool isd = (sw == 'D' || sw == 'd'); ++ ref value; ++ ++ if (adef == NULL) ++ return e_Fatal; ++ eqp = strchr(adef, '='); ++ ++ if (eqp == NULL) ++ eqp = strchr(adef, '#'); ++ /* Initialize the object memory, scanner, and */ ++ /* name table now if needed. */ ++ if ((code = gs_main_init1(minst)) < 0) ++ return code; ++ if (eqp == adef) { ++ puts(minst->heap, "Usage: -dname, -dname=token, -sname=string"); ++ return e_Fatal; ++ } ++ if (eqp == NULL) { ++ if (isd) ++ make_true(&value); ++ else ++ make_empty_string(&value, a_readonly); ++ } else { ++ int code; ++ i_ctx_t *i_ctx_p = minst->i_ctx_p; ++ uint space = icurrent_space; ++ ++ *eqp++ = 0; ++ ialloc_set_space(idmemory, avm_system); ++ if (isd) { ++ stream astream; ++ scanner_state state; ++ ++ s_init(&astream, NULL); ++ sread_string(&astream, ++ (const byte *)eqp, strlen(eqp)); ++ gs_scanner_init_stream(&state, &astream); ++ code = gs_scan_token(minst->i_ctx_p, &value, &state); ++ if (code) { ++ puts(minst->heap, "-dname= must be followed by a valid token"); ++ return e_Fatal; ++ } ++ if (r_has_type_attrs(&value, t_name, ++ a_executable)) { ++ ref nsref; + +- name_string_ref(minst->heap, &value, &nsref); ++ name_string_ref(minst->heap, &value, &nsref); + #define string_is(nsref, str, len)\ + (r_size(&(nsref)) == (len) &&\ + !strncmp((const char *)(nsref).value.const_bytes, str, (len))) +- if (string_is(nsref, "null", 4)) +- make_null(&value); +- else if (string_is(nsref, "true", 4)) +- make_true(&value); +- else if (string_is(nsref, "false", 5)) +- make_false(&value); +- else { +- puts(minst->heap, +- "-dvar=name requires name=null, true, or false"); +- return e_Fatal; +- } ++ if (string_is(nsref, "null", 4)) ++ make_null(&value); ++ else if (string_is(nsref, "true", 4)) ++ make_true(&value); ++ else if (string_is(nsref, "false", 5)) ++ make_false(&value); ++ else { ++ puts(minst->heap, ++ "-dvar=name requires name=null, true, or false"); ++ return e_Fatal; ++ } + #undef name_is_string +- } +- } else { +- int len = strlen(eqp); +- char *str = +- (char *)gs_alloc_bytes(minst->heap, +- (uint) len, "-s"); +- +- if (str == 0) { +- lprintf("Out of memory!\n"); +- return e_Fatal; +- } +- memcpy(str, eqp, len); +- make_const_string(&value, +- a_readonly | avm_foreign, +- len, (const byte *)str); +- if ((code = try_stdout_redirect(minst, adef, eqp)) < 0) +- return code; +- } +- ialloc_set_space(idmemory, space); +- } +- /* Enter the name in systemdict. */ +- initial_enter_name(adef, &value); +- break; +- } +- case 'T': ++ } ++ } else { ++ int len = strlen(eqp); ++ char *str = ++ (char *)gs_alloc_bytes(minst->heap, ++ (uint) len, "-s"); ++ ++ if (str == 0) { ++ lprintf("Out of memory!\n"); ++ return e_Fatal; ++ } ++ memcpy(str, eqp, len); ++ make_const_string(&value, ++ a_readonly | avm_foreign, ++ len, (const byte *)str); ++ if ((code = try_stdout_redirect(minst, adef, eqp)) < 0) ++ return code; ++ } ++ ialloc_set_space(idmemory, space); ++ } ++ /* Enter the name in systemdict. */ ++ initial_enter_name(adef, &value); ++ break; ++ } ++ case 'T': + set_debug_flags(arg, vd_flags); +- break; +- case 'u': /* undefine name */ +- if (!*arg) { +- puts(minst->heap, "-u requires a name to undefine."); +- return e_Fatal; +- } +- if ((code = gs_main_init1(minst)) < 0) +- return code; +- i_initial_remove_name(minst->i_ctx_p, arg); +- break; +- case 'v': /* print revision */ +- print_revision(minst); +- return e_Info; ++ break; ++ case 'u': /* undefine name */ ++ if (!*arg) { ++ puts(minst->heap, "-u requires a name to undefine."); ++ return e_Fatal; ++ } ++ if ((code = gs_main_init1(minst)) < 0) ++ return code; ++ i_initial_remove_name(minst->i_ctx_p, arg); ++ break; ++ case 'v': /* print revision */ ++ print_revision(minst); ++ return e_Info; + /*#ifdef DEBUG */ +- /* +- * Here we provide a place for inserting debugging code that can be +- * run in place of the normal interpreter code. +- */ +- case 'X': +- code = gs_main_init2(minst); +- if (code < 0) +- return code; +- { +- int xec; /* exit_code */ +- ref xeo; /* error_object */ ++ /* ++ * Here we provide a place for inserting debugging code that can be ++ * run in place of the normal interpreter code. ++ */ ++ case 'X': ++ code = gs_main_init2(minst); ++ if (code < 0) ++ return code; ++ { ++ int xec; /* exit_code */ ++ ref xeo; /* error_object */ + + #define start_x()\ + gs_main_run_string_begin(minst, 1, &xec, &xeo) +@@ -677,16 +677,16 @@ run_stdin: + gs_main_run_string_continue(minst, str, strlen(str), 1, &xec, &xeo) + #define stop_x()\ + gs_main_run_string_end(minst, 1, &xec, &xeo) +- start_x(); +- run_x("\216\003abc"); +- run_x("== flush\n"); +- stop_x(); +- } +- return e_Quit; ++ start_x(); ++ run_x("\216\003abc"); ++ run_x("== flush\n"); ++ stop_x(); ++ } ++ return e_Quit; + /*#endif */ +- case 'Z': ++ case 'Z': + set_debug_flags(arg, gs_debug); +- break; ++ break; + } + return 0; + } +@@ -709,10 +709,10 @@ esc_strcat(char *dest, const char *src) + + *d++ = '<'; + for (p = src; *p; p++) { +- byte c = (byte) * p; ++ byte c = (byte) * p; + +- *d++ = hex[c >> 4]; +- *d++ = hex[c & 0xf]; ++ *d++ = hex[c >> 4]; ++ *d++ = hex[c & 0xf]; + } + *d++ = '>'; + *d = 0; +@@ -722,7 +722,7 @@ esc_strcat(char *dest, const char *src) + static int + argproc(gs_main_instance * minst, const char *arg) + { +- int code = gs_main_init1(minst); /* need i_ctx_p to proceed */ ++ int code = gs_main_init1(minst); /* need i_ctx_p to proceed */ + char *filearg; + + if (code < 0) +@@ -731,11 +731,11 @@ argproc(gs_main_instance * minst, const + if (filearg == NULL) + return e_Fatal; + if (minst->run_buffer_size) { +- /* Run file with run_string. */ +- return run_buffered(minst, filearg); ++ /* Run file with run_string. */ ++ return run_buffered(minst, filearg); + } else { +- /* Run file directly in the normal way. */ +- return runarg(minst, "", filearg, ".runfile", runInit | runFlush); ++ /* Run file directly in the normal way. */ ++ return runarg(minst, "", filearg, ".runfile", runInit | runFlush); + } + } + static int +@@ -747,32 +747,32 @@ run_buffered(gs_main_instance * minst, c + int code; + + if (in == 0) { +- outprintf(minst->heap, "Unable to open %s for reading", arg); +- return_error(e_invalidfileaccess); ++ outprintf(minst->heap, "Unable to open %s for reading", arg); ++ return_error(e_invalidfileaccess); + } + code = gs_main_init2(minst); + if (code < 0) { + fclose(in); +- return code; ++ return code; + } + code = gs_main_run_string_begin(minst, minst->user_errors, +- &exit_code, &error_object); ++ &exit_code, &error_object); + if (!code) { +- char buf[MAX_BUFFERED_SIZE]; +- int count; ++ char buf[MAX_BUFFERED_SIZE]; ++ int count; + +- code = e_NeedInput; +- while ((count = fread(buf, 1, minst->run_buffer_size, in)) > 0) { +- code = gs_main_run_string_continue(minst, buf, count, +- minst->user_errors, +- &exit_code, &error_object); +- if (code != e_NeedInput) +- break; +- } +- if (code == e_NeedInput) { +- code = gs_main_run_string_end(minst, minst->user_errors, +- &exit_code, &error_object); +- } ++ code = e_NeedInput; ++ while ((count = fread(buf, 1, minst->run_buffer_size, in)) > 0) { ++ code = gs_main_run_string_continue(minst, buf, count, ++ minst->user_errors, ++ &exit_code, &error_object); ++ if (code != e_NeedInput) ++ break; ++ } ++ if (code == e_NeedInput) { ++ code = gs_main_run_string_end(minst, minst->user_errors, ++ &exit_code, &error_object); ++ } + } + fclose(in); + zflush(minst->i_ctx_p); +@@ -788,15 +788,15 @@ runarg(gs_main_instance * minst, const c + char *line; + + if (options & runInit) { +- code = gs_main_init2(minst); /* Finish initialization */ ++ code = gs_main_init2(minst); /* Finish initialization */ + +- if (code < 0) +- return code; ++ if (code < 0) ++ return code; + } + line = (char *)gs_alloc_bytes(minst->heap, len, "argproc"); + if (line == 0) { +- lprintf("Out of memory!\n"); +- return_error(e_VMerror); ++ lprintf("Out of memory!\n"); ++ return_error(e_VMerror); + } + strcpy(line, pre); + esc_strcat(line, arg); +@@ -812,29 +812,29 @@ run_string(gs_main_instance * minst, con + int exit_code; + ref error_object; + int code = gs_main_run_string(minst, str, minst->user_errors, +- &exit_code, &error_object); ++ &exit_code, &error_object); + + if ((options & runFlush) || code != 0) { +- zflush(minst->i_ctx_p); /* flush stdout */ +- zflushpage(minst->i_ctx_p); /* force display update */ ++ zflush(minst->i_ctx_p); /* flush stdout */ ++ zflushpage(minst->i_ctx_p); /* force display update */ + } + return run_finish(minst, code, exit_code, &error_object); + } + static int + run_finish(gs_main_instance *minst, int code, int exit_code, +- ref * perror_object) ++ ref * perror_object) + { + switch (code) { +- case e_Quit: +- case 0: +- break; +- case e_Fatal: +- emprintf1(minst->heap, ++ case e_Quit: ++ case 0: ++ break; ++ case e_Fatal: ++ emprintf1(minst->heap, + "Unrecoverable error, exit code %d\n", + exit_code); +- break; +- default: +- gs_main_dump_stack(minst, code, perror_object); ++ break; ++ default: ++ gs_main_dump_stack(minst, code, perror_object); + } + return code; + } +@@ -848,34 +848,34 @@ run_finish(gs_main_instance *minst, int + * File is closed at program exit (if not stdout/err) + * or when -sstdout is used again. + */ +-static int +-try_stdout_redirect(gs_main_instance * minst, ++static int ++try_stdout_redirect(gs_main_instance * minst, + const char *command, const char *filename) + { + if (strcmp(command, "stdout") == 0) { +- minst->heap->gs_lib_ctx->stdout_to_stderr = 0; +- minst->heap->gs_lib_ctx->stdout_is_redirected = 0; +- /* If stdout already being redirected and it is not stdout +- * or stderr, close it +- */ +- if (minst->heap->gs_lib_ctx->fstdout2 +- && (minst->heap->gs_lib_ctx->fstdout2 != minst->heap->gs_lib_ctx->fstdout) +- && (minst->heap->gs_lib_ctx->fstdout2 != minst->heap->gs_lib_ctx->fstderr)) { +- fclose(minst->heap->gs_lib_ctx->fstdout2); +- minst->heap->gs_lib_ctx->fstdout2 = (FILE *)NULL; +- } +- /* If stdout is being redirected, set minst->fstdout2 */ +- if ( (filename != 0) && strlen(filename) && +- strcmp(filename, "-") && strcmp(filename, "%stdout") ) { +- if (strcmp(filename, "%stderr") == 0) { +- minst->heap->gs_lib_ctx->stdout_to_stderr = 1; +- } +- else if ((minst->heap->gs_lib_ctx->fstdout2 = +- fopen(filename, "w")) == (FILE *)NULL) +- return_error(e_invalidfileaccess); +- minst->heap->gs_lib_ctx->stdout_is_redirected = 1; +- } +- return 0; ++ minst->heap->gs_lib_ctx->stdout_to_stderr = 0; ++ minst->heap->gs_lib_ctx->stdout_is_redirected = 0; ++ /* If stdout already being redirected and it is not stdout ++ * or stderr, close it ++ */ ++ if (minst->heap->gs_lib_ctx->fstdout2 ++ && (minst->heap->gs_lib_ctx->fstdout2 != minst->heap->gs_lib_ctx->fstdout) ++ && (minst->heap->gs_lib_ctx->fstdout2 != minst->heap->gs_lib_ctx->fstderr)) { ++ fclose(minst->heap->gs_lib_ctx->fstdout2); ++ minst->heap->gs_lib_ctx->fstdout2 = (FILE *)NULL; ++ } ++ /* If stdout is being redirected, set minst->fstdout2 */ ++ if ( (filename != 0) && strlen(filename) && ++ strcmp(filename, "-") && strcmp(filename, "%stdout") ) { ++ if (strcmp(filename, "%stderr") == 0) { ++ minst->heap->gs_lib_ctx->stdout_to_stderr = 1; ++ } ++ else if ((minst->heap->gs_lib_ctx->fstdout2 = ++ fopen(filename, "w")) == (FILE *)NULL) ++ return_error(e_invalidfileaccess); ++ minst->heap->gs_lib_ctx->stdout_is_redirected = 1; ++ } ++ return 0; + } + return 1; + } +@@ -919,13 +919,13 @@ print_help(gs_main_instance * minst) + print_paths(minst); + /* Check if we have the %rom device */ + for (i = 0; i < gx_io_device_table_count; i++) { +- const gx_io_device *iodev = gx_io_device_table[i]; +- const char *dname = iodev->dname; ++ const gx_io_device *iodev = gx_io_device_table[i]; ++ const char *dname = iodev->dname; + +- if (dname && strlen(dname) == 5 && !memcmp("%rom%", dname, 5)) { +- have_rom_device = 1; +- break; +- } ++ if (dname && strlen(dname) == 5 && !memcmp("%rom%", dname, 5)) { ++ have_rom_device = 1; ++ break; ++ } + } + if (have_rom_device) { + outprintf(minst->heap, "Initialization files are compiled into the executable.\n"); +@@ -939,10 +939,10 @@ print_revision(const gs_main_instance *m + { + printf_program_ident(minst->heap, gs_product, gs_revision); + outprintf(minst->heap, " (%d-%02d-%02d)\n%s\n", +- (int)(gs_revisiondate / 10000), +- (int)(gs_revisiondate / 100 % 100), +- (int)(gs_revisiondate % 100), +- gs_copyright); ++ (int)(gs_revisiondate / 10000), ++ (int)(gs_revisiondate / 100 % 100), ++ (int)(gs_revisiondate % 100), ++ gs_copyright); + } + + /* Print the version number. */ +@@ -975,41 +975,41 @@ print_devices(const gs_main_instance *mi + outprintf(minst->heap, " %s\n", gs_devicename(gs_getdefaultdevice())); + outprintf(minst->heap, "%s", help_devices); + { +- int i; +- int pos = 100; +- const gx_device *pdev; +- const char **names; +- size_t ndev = 0; +- +- for (i = 0; gs_getdevice(i) != 0; i++) +- ; +- ndev = (size_t)i; +- names = (const char **)gs_alloc_bytes(minst->heap, ndev * sizeof(const char*), "print_devices"); +- if (names == (const char **)NULL) { /* old-style unsorted device list */ +- for (i = 0; (pdev = gs_getdevice(i)) != 0; i++) { +- const char *dname = gs_devicename(pdev); +- int len = strlen(dname); +- +- if (pos + 1 + len > 76) +- outprintf(minst->heap, "\n "), pos = 2; +- outprintf(minst->heap, " %s", dname); +- pos += 1 + len; +- } +- } +- else { /* new-style sorted device list */ +- for (i = 0; (pdev = gs_getdevice(i)) != 0; i++) +- names[i] = gs_devicename(pdev); +- qsort((void*)names, ndev, sizeof(const char*), cmpstr); +- for (i = 0; i < ndev; i++) { +- int len = strlen(names[i]); +- +- if (pos + 1 + len > 76) +- outprintf(minst->heap, "\n "), pos = 2; +- outprintf(minst->heap, " %s", names[i]); +- pos += 1 + len; +- } +- gs_free(minst->heap, (char *)names, ndev * sizeof(const char*), 1, "print_devices"); +- } ++ int i; ++ int pos = 100; ++ const gx_device *pdev; ++ const char **names; ++ size_t ndev = 0; ++ ++ for (i = 0; gs_getdevice(i) != 0; i++) ++ ; ++ ndev = (size_t)i; ++ names = (const char **)gs_alloc_bytes(minst->heap, ndev * sizeof(const char*), "print_devices"); ++ if (names == (const char **)NULL) { /* old-style unsorted device list */ ++ for (i = 0; (pdev = gs_getdevice(i)) != 0; i++) { ++ const char *dname = gs_devicename(pdev); ++ int len = strlen(dname); ++ ++ if (pos + 1 + len > 76) ++ outprintf(minst->heap, "\n "), pos = 2; ++ outprintf(minst->heap, " %s", dname); ++ pos += 1 + len; ++ } ++ } ++ else { /* new-style sorted device list */ ++ for (i = 0; (pdev = gs_getdevice(i)) != 0; i++) ++ names[i] = gs_devicename(pdev); ++ qsort((void*)names, ndev, sizeof(const char*), cmpstr); ++ for (i = 0; i < ndev; i++) { ++ int len = strlen(names[i]); ++ ++ if (pos + 1 + len > 76) ++ outprintf(minst->heap, "\n "), pos = 2; ++ outprintf(minst->heap, " %s", names[i]); ++ pos += 1 + len; ++ } ++ gs_free(minst->heap, (char *)names, ndev * sizeof(const char*), 1, "print_devices"); ++ } + } + outprintf(minst->heap, "\n"); + } +@@ -1020,17 +1020,17 @@ print_emulators(const gs_main_instance * + { + outprintf(minst->heap, "%s", help_emulators); + { +- const ref *pes; ++ const ref *pes; + +- for (pes = gs_emulator_name_array; +- pes->value.const_bytes != 0; pes++ +- ) +- /* +- * Even though gs_emulator_name_array is declared and used as +- * an array of string refs, each string is actually a +- * (null terminated) C string. +- */ +- outprintf(minst->heap, " %s", (const char *)pes->value.const_bytes); ++ for (pes = gs_emulator_name_array; ++ pes->value.const_bytes != 0; pes++ ++ ) ++ /* ++ * Even though gs_emulator_name_array is declared and used as ++ * an array of string refs, each string is actually a ++ * (null terminated) C string. ++ */ ++ outprintf(minst->heap, " %s", (const char *)pes->value.const_bytes); + } + outprintf(minst->heap, "\n"); + } +@@ -1042,38 +1042,38 @@ print_paths(gs_main_instance * minst) + outprintf(minst->heap, "%s", help_paths); + gs_main_set_lib_paths(minst); + { +- uint count = r_size(&minst->lib_path.list); +- uint i; +- int pos = 100; +- char fsepr[3]; +- +- fsepr[0] = ' ', fsepr[1] = gp_file_name_list_separator, +- fsepr[2] = 0; +- for (i = 0; i < count; ++i) { +- const ref *prdir = +- minst->lib_path.list.value.refs + i; +- uint len = r_size(prdir); +- const char *sepr = (i == count - 1 ? "" : fsepr); +- +- if (1 + pos + strlen(sepr) + len > 76) +- outprintf(minst->heap, "\n "), pos = 2; +- outprintf(minst->heap, " "); +- /* +- * This is really ugly, but it's necessary because some +- * platforms rely on all console output being funneled through +- * outprintf. We wish we could just do: +- fwrite(prdir->value.bytes, 1, len, minst->fstdout); +- */ +- { +- const char *p = (const char *)prdir->value.bytes; +- uint j; +- +- for (j = len; j; j--) +- outprintf(minst->heap, "%c", *p++); +- } +- outprintf(minst->heap, "%s", sepr); +- pos += 1 + len + strlen(sepr); +- } ++ uint count = r_size(&minst->lib_path.list); ++ uint i; ++ int pos = 100; ++ char fsepr[3]; ++ ++ fsepr[0] = ' ', fsepr[1] = gp_file_name_list_separator, ++ fsepr[2] = 0; ++ for (i = 0; i < count; ++i) { ++ const ref *prdir = ++ minst->lib_path.list.value.refs + i; ++ uint len = r_size(prdir); ++ const char *sepr = (i == count - 1 ? "" : fsepr); ++ ++ if (1 + pos + strlen(sepr) + len > 76) ++ outprintf(minst->heap, "\n "), pos = 2; ++ outprintf(minst->heap, " "); ++ /* ++ * This is really ugly, but it's necessary because some ++ * platforms rely on all console output being funneled through ++ * outprintf. We wish we could just do: ++ fwrite(prdir->value.bytes, 1, len, minst->fstdout); ++ */ ++ { ++ const char *p = (const char *)prdir->value.bytes; ++ uint j; ++ ++ for (j = len; j; j--) ++ outprintf(minst->heap, "%c", *p++); ++ } ++ outprintf(minst->heap, "%s", sepr); ++ pos += 1 + len + strlen(sepr); ++ } + } + outprintf(minst->heap, "\n"); + } +@@ -1086,8 +1086,8 @@ print_help_trailer(const gs_main_instanc + const char *use_htm = "Use.htm", *p = buffer; + uint blen = sizeof(buffer); + +- if (gp_file_name_combine(gs_doc_directory, strlen(gs_doc_directory), +- use_htm, strlen(use_htm), false, buffer, &blen) != gp_combine_success) +- p = use_htm; ++ if (gp_file_name_combine(gs_doc_directory, strlen(gs_doc_directory), ++ use_htm, strlen(use_htm), false, buffer, &blen) != gp_combine_success) ++ p = use_htm; + outprintf(minst->heap, help_trailer, p); + } +diff -up ghostscript-9.00/psi/imain.c.scan_token ghostscript-9.00/psi/imain.c +--- ghostscript-9.00/psi/imain.c.scan_token 2010-05-04 19:47:12.000000000 +0100 ++++ ghostscript-9.00/psi/imain.c 2011-01-14 17:17:36.221792489 +0000 +@@ -1,6 +1,6 @@ + /* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. +- ++ + This software is provided AS-IS with no warranty, either express or + implied. + +@@ -18,51 +18,51 @@ + #include "string_.h" + #include "ghost.h" + #include "gp.h" +-#include "gscdefs.h" /* for gs_init_file */ ++#include "gscdefs.h" /* for gs_init_file */ + #include "gslib.h" +-#include "gsmatrix.h" /* for gxdevice.h */ +-#include "gsutil.h" /* for bytes_compare */ ++#include "gsmatrix.h" /* for gxdevice.h */ ++#include "gsutil.h" /* for bytes_compare */ + #include "gxdevice.h" + #include "gxalloc.h" +-#include "gxiodev.h" /* for iodev struct */ ++#include "gxiodev.h" /* for iodev struct */ + #include "gzstate.h" + #include "ierrors.h" + #include "oper.h" +-#include "iconf.h" /* for gs_init_* imports */ ++#include "iconf.h" /* for gs_init_* imports */ + #include "idebug.h" + #include "idict.h" +-#include "iname.h" /* for name_init */ ++#include "iname.h" /* for name_init */ + #include "dstack.h" + #include "estack.h" +-#include "ostack.h" /* put here for files.h */ +-#include "stream.h" /* for files.h */ ++#include "ostack.h" /* put here for files.h */ ++#include "stream.h" /* for files.h */ + #include "files.h" + #include "ialloc.h" + #include "iinit.h" +-#include "strimpl.h" /* for sfilter.h */ +-#include "sfilter.h" /* for iscan.h */ ++#include "strimpl.h" /* for sfilter.h */ ++#include "sfilter.h" /* for iscan.h */ + #include "iscan.h" + #include "main.h" + #include "store.h" +-#include "isave.h" /* for prototypes */ ++#include "isave.h" /* for prototypes */ + #include "interp.h" + #include "ivmspace.h" +-#include "idisp.h" /* for setting display device callback */ ++#include "idisp.h" /* for setting display device callback */ + #include "iplugin.h" + + /* ------ Exported data ------ */ + +-/** using backpointers retrieve minst from any memory pointer +- * ++/** using backpointers retrieve minst from any memory pointer ++ * + */ +-gs_main_instance* ++gs_main_instance* + get_minst_from_memory(const gs_memory_t *mem) + { + #ifdef PSI_INCLUDED + extern gs_main_instance *ps_impl_get_minst( const gs_memory_t *mem ); + return ps_impl_get_minst(mem); + #else +- return (gs_main_instance*)mem->gs_lib_ctx->top_of_system; ++ return (gs_main_instance*)mem->gs_lib_ctx->top_of_system; + #endif + } + +@@ -74,14 +74,14 @@ gs_main_alloc_instance(gs_memory_t *mem) + if (mem == NULL) + return NULL; + +- minst = (gs_main_instance *)gs_alloc_bytes_immovable(mem, ++ minst = (gs_main_instance *)gs_alloc_bytes_immovable(mem, + sizeof(gs_main_instance), + "init_main_instance"); + if (minst == NULL) + return NULL; + memcpy(minst, &gs_main_instance_init_values, sizeof(gs_main_instance_init_values)); + minst->heap = mem; +- ++ + # ifndef PSI_INCLUDED + mem->gs_lib_ctx->top_of_system = minst; + /* else top of system is pl_universe */ +@@ -116,14 +116,14 @@ get_local_op_array(const gs_memory_t *me + + static int gs_run_init_file(gs_main_instance *, int *, ref *); + void print_resource_usage(const gs_main_instance *, +- gs_dual_memory_t *, const char *); ++ gs_dual_memory_t *, const char *); + + /* ------ Initialization ------ */ + + /* Initialization to be done before anything else. */ + int + gs_main_init0(gs_main_instance * minst, FILE * in, FILE * out, FILE * err, +- int max_lib_paths) ++ int max_lib_paths) + { + ref *paths; + +@@ -133,11 +133,11 @@ gs_main_init0(gs_main_instance * minst, + /* on incompatible processors. */ + gp_init(); + +- /* Initialize the imager. */ ++ /* Initialize the imager. */ + # ifndef PSI_INCLUDED + /* Reset debugging flags */ + memset(gs_debug, 0, 128); +- gs_log_errors = 0; /* gs_debug['#'] = 0 */ ++ gs_log_errors = 0; /* gs_debug['#'] = 0 */ + # else + /* plmain settings remain in effect */ + # endif +@@ -145,16 +145,16 @@ gs_main_init0(gs_main_instance * minst, + + /* Initialize the file search paths. */ + paths = (ref *) gs_alloc_byte_array(minst->heap, max_lib_paths, sizeof(ref), +- "lib_path array"); ++ "lib_path array"); + if (paths == 0) { +- gs_lib_finit(1, e_VMerror, minst->heap); +- return_error(e_VMerror); ++ gs_lib_finit(1, e_VMerror, minst->heap); ++ return_error(e_VMerror); + } + make_array(&minst->lib_path.container, avm_foreign, max_lib_paths, +- (ref *) gs_alloc_byte_array(minst->heap, max_lib_paths, sizeof(ref), +- "lib_path array")); ++ (ref *) gs_alloc_byte_array(minst->heap, max_lib_paths, sizeof(ref), ++ "lib_path array")); + make_array(&minst->lib_path.list, avm_foreign | a_readonly, 0, +- minst->lib_path.container.value.refs); ++ minst->lib_path.container.value.refs); + minst->lib_path.env = 0; + minst->lib_path.final = 0; + minst->lib_path.count = 0; +@@ -171,42 +171,42 @@ gs_main_init1(gs_main_instance * minst) + extern init_proc(gs_iodev_init); + + if (minst->init_done < 1) { +- gs_dual_memory_t idmem; +- int code = +- ialloc_init(&idmem, minst->heap, +- minst->memory_chunk_size, gs_have_level2()); +- +- if (code < 0) +- return code; +- code = gs_lib_init1((gs_memory_t *)idmem.space_system); +- if (code < 0) +- return code; +- alloc_save_init(&idmem); +- { +- gs_memory_t *mem = (gs_memory_t *)idmem.space_system; +- name_table *nt = names_init(minst->name_table_size, +- idmem.space_system); +- +- if (nt == 0) +- return_error(e_VMerror); +- mem->gs_lib_ctx->gs_name_table = nt; +- code = gs_register_struct_root(mem, NULL, +- (void **)&mem->gs_lib_ctx->gs_name_table, +- "the_gs_name_table"); +- if (code < 0) +- return code; +- } +- code = obj_init(&minst->i_ctx_p, &idmem); /* requires name_init */ +- if (code < 0) +- return code; ++ gs_dual_memory_t idmem; ++ int code = ++ ialloc_init(&idmem, minst->heap, ++ minst->memory_chunk_size, gs_have_level2()); ++ ++ if (code < 0) ++ return code; ++ code = gs_lib_init1((gs_memory_t *)idmem.space_system); ++ if (code < 0) ++ return code; ++ alloc_save_init(&idmem); ++ { ++ gs_memory_t *mem = (gs_memory_t *)idmem.space_system; ++ name_table *nt = names_init(minst->name_table_size, ++ idmem.space_system); ++ ++ if (nt == 0) ++ return_error(e_VMerror); ++ mem->gs_lib_ctx->gs_name_table = nt; ++ code = gs_register_struct_root(mem, NULL, ++ (void **)&mem->gs_lib_ctx->gs_name_table, ++ "the_gs_name_table"); ++ if (code < 0) ++ return code; ++ } ++ code = obj_init(&minst->i_ctx_p, &idmem); /* requires name_init */ ++ if (code < 0) ++ return code; + code = i_plugin_init(minst->i_ctx_p); +- if (code < 0) +- return code; +- i_ctx_p = minst->i_ctx_p; +- code = gs_iodev_init(imemory); +- if (code < 0) +- return code; +- minst->init_done = 1; ++ if (code < 0) ++ return code; ++ i_ctx_p = minst->i_ctx_p; ++ code = gs_iodev_init(imemory); ++ if (code < 0) ++ return code; ++ minst->init_done = 1; + } + return 0; + } +@@ -220,7 +220,7 @@ init2_make_string_array(i_ctx_t *i_ctx_p + + for (; ifp->value.bytes != 0; ifp++); + make_tasv(&ifa, t_array, a_readonly | avm_foreign, +- ifp - srefs, const_refs, srefs); ++ ifp - srefs, const_refs, srefs); + initial_enter_name(aname, &ifa); + } + +@@ -229,16 +229,16 @@ init2_make_string_array(i_ctx_t *i_ctx_p + * callouts were handled here instead of in the stream processing. + */ + static int +-gs_main_interpret(gs_main_instance *minst, ref * pref, int user_errors, +- int *pexit_code, ref * perror_object) ++gs_main_interpret(gs_main_instance *minst, ref * pref, int user_errors, ++ int *pexit_code, ref * perror_object) + { + int code; + + /* set interpreter pointer to lib_path */ + minst->i_ctx_p->lib_path = &minst->lib_path; + +- code = gs_interpret(&minst->i_ctx_p, pref, +- user_errors, pexit_code, perror_object); ++ code = gs_interpret(&minst->i_ctx_p, pref, ++ user_errors, pexit_code, perror_object); + return code; + } + +@@ -249,53 +249,53 @@ gs_main_init2(gs_main_instance * minst) + int code = gs_main_init1(minst); + + if (code < 0) +- return code; ++ return code; + i_ctx_p = minst->i_ctx_p; + if (minst->init_done < 2) { +- int code, exit_code; +- ref error_object; ++ int code, exit_code; ++ ref error_object; + +- code = zop_init(i_ctx_p); +- if (code < 0) +- return code; +- code = op_init(i_ctx_p); /* requires obj_init */ +- if (code < 0) +- return code; +- +- /* Set up the array of additional initialization files. */ +- init2_make_string_array(i_ctx_p, gs_init_file_array, "INITFILES"); +- /* Set up the array of emulator names. */ +- init2_make_string_array(i_ctx_p, gs_emulator_name_array, "EMULATORS"); +- /* Pass the search path. */ +- code = initial_enter_name("LIBPATH", &minst->lib_path.list); +- if (code < 0) +- return code; +- +- /* Execute the standard initialization file. */ +- code = gs_run_init_file(minst, &exit_code, &error_object); +- if (code < 0) +- return code; +- minst->init_done = 2; +- i_ctx_p = minst->i_ctx_p; /* init file may change it */ +- /* NB this is to be done with device parameters +- * both minst->display and display_set_callback() are going away +- */ +- if (minst->display) +- if ((code = display_set_callback(minst, minst->display)) < 0) +- return code; ++ code = zop_init(i_ctx_p); ++ if (code < 0) ++ return code; ++ code = op_init(i_ctx_p); /* requires obj_init */ ++ if (code < 0) ++ return code; ++ ++ /* Set up the array of additional initialization files. */ ++ init2_make_string_array(i_ctx_p, gs_init_file_array, "INITFILES"); ++ /* Set up the array of emulator names. */ ++ init2_make_string_array(i_ctx_p, gs_emulator_name_array, "EMULATORS"); ++ /* Pass the search path. */ ++ code = initial_enter_name("LIBPATH", &minst->lib_path.list); ++ if (code < 0) ++ return code; ++ ++ /* Execute the standard initialization file. */ ++ code = gs_run_init_file(minst, &exit_code, &error_object); ++ if (code < 0) ++ return code; ++ minst->init_done = 2; ++ i_ctx_p = minst->i_ctx_p; /* init file may change it */ ++ /* NB this is to be done with device parameters ++ * both minst->display and display_set_callback() are going away ++ */ ++ if (minst->display) ++ if ((code = display_set_callback(minst, minst->display)) < 0) ++ return code; + + #ifndef PSI_INCLUDED +- if ((code = gs_main_run_string(minst, +- "JOBSERVER " +- " { false 0 .startnewjob } " +- " { NOOUTERSAVE not { save pop } if } " +- "ifelse", 0, &exit_code, +- &error_object)) < 0) +- return code; ++ if ((code = gs_main_run_string(minst, ++ "JOBSERVER " ++ " { false 0 .startnewjob } " ++ " { NOOUTERSAVE not { save pop } if } " ++ "ifelse", 0, &exit_code, ++ &error_object)) < 0) ++ return code; + #endif /* PSI_INCLUDED */ + } + if (gs_debug_c(':')) +- print_resource_usage(minst, &gs_imemory, "Start"); ++ print_resource_usage(minst, &gs_imemory, "Start"); + gp_readline_init(&minst->readline_data, imemory_system); + return 0; + } +@@ -311,23 +311,23 @@ file_path_add(gs_file_path * pfp, const + const char *dpath = dirs; + + if (dirs == 0) +- return 0; +- for (;;) { /* Find the end of the next directory name. */ +- const char *npath = dpath; +- +- while (*npath != 0 && *npath != gp_file_name_list_separator) +- npath++; +- if (npath > dpath) { +- if (len == r_size(&pfp->container)) +- return_error(e_limitcheck); +- make_const_string(&pfp->container.value.refs[len], +- avm_foreign | a_readonly, +- npath - dpath, (const byte *)dpath); +- ++len; +- } +- if (!*npath) +- break; +- dpath = npath + 1; ++ return 0; ++ for (;;) { /* Find the end of the next directory name. */ ++ const char *npath = dpath; ++ ++ while (*npath != 0 && *npath != gp_file_name_list_separator) ++ npath++; ++ if (npath > dpath) { ++ if (len == r_size(&pfp->container)) ++ return_error(e_limitcheck); ++ make_const_string(&pfp->container.value.refs[len], ++ avm_foreign | a_readonly, ++ npath - dpath, (const byte *)dpath); ++ ++len; ++ } ++ if (!*npath) ++ break; ++ dpath = npath + 1; + } + r_set_size(&pfp->list, len); + return 0; +@@ -340,17 +340,17 @@ gs_main_add_lib_path(gs_main_instance * + /* Account for the possibility that the first element */ + /* is gp_current_directory name added by set_lib_paths. */ + int first_is_here = +- (r_size(&minst->lib_path.list) != 0 && +- minst->lib_path.container.value.refs[0].value.bytes == +- (const byte *)gp_current_directory_name ? 1 : 0); ++ (r_size(&minst->lib_path.list) != 0 && ++ minst->lib_path.container.value.refs[0].value.bytes == ++ (const byte *)gp_current_directory_name ? 1 : 0); + int code; + + r_set_size(&minst->lib_path.list, minst->lib_path.count + +- first_is_here); ++ first_is_here); + code = file_path_add(&minst->lib_path, lpath); + minst->lib_path.count = r_size(&minst->lib_path.list) - first_is_here; + if (code < 0) +- return code; ++ return code; + return gs_main_set_lib_paths(minst); + } + +@@ -366,49 +366,49 @@ gs_main_set_lib_paths(gs_main_instance * + { + ref *paths = minst->lib_path.container.value.refs; + int first_is_here = +- (r_size(&minst->lib_path.list) != 0 && +- paths[0].value.bytes == (const byte *)gp_current_directory_name ? 1 : 0); ++ (r_size(&minst->lib_path.list) != 0 && ++ paths[0].value.bytes == (const byte *)gp_current_directory_name ? 1 : 0); + int code = 0; + int count = minst->lib_path.count; + int i, have_rom_device = 0; + + if (minst->search_here_first) { +- if (!(first_is_here || +- (r_size(&minst->lib_path.list) != 0 && +- !bytes_compare((const byte *)gp_current_directory_name, +- strlen(gp_current_directory_name), +- paths[0].value.bytes, +- r_size(&paths[0])))) +- ) { +- memmove(paths + 1, paths, count * sizeof(*paths)); +- make_const_string(paths, avm_foreign | a_readonly, +- strlen(gp_current_directory_name), +- (const byte *)gp_current_directory_name); +- } ++ if (!(first_is_here || ++ (r_size(&minst->lib_path.list) != 0 && ++ !bytes_compare((const byte *)gp_current_directory_name, ++ strlen(gp_current_directory_name), ++ paths[0].value.bytes, ++ r_size(&paths[0])))) ++ ) { ++ memmove(paths + 1, paths, count * sizeof(*paths)); ++ make_const_string(paths, avm_foreign | a_readonly, ++ strlen(gp_current_directory_name), ++ (const byte *)gp_current_directory_name); ++ } + } else { +- if (first_is_here) +- memmove(paths, paths + 1, count * sizeof(*paths)); ++ if (first_is_here) ++ memmove(paths, paths + 1, count * sizeof(*paths)); + } + r_set_size(&minst->lib_path.list, +- count + (minst->search_here_first ? 1 : 0)); ++ count + (minst->search_here_first ? 1 : 0)); + if (minst->lib_path.env != 0) +- code = file_path_add(&minst->lib_path, minst->lib_path.env); ++ code = file_path_add(&minst->lib_path, minst->lib_path.env); + /* now put the %rom%lib/ device path before the gs_lib_default_path on the list */ + for (i = 0; i < gx_io_device_table_count; i++) { +- const gx_io_device *iodev = gx_io_device_table[i]; +- const char *dname = iodev->dname; ++ const gx_io_device *iodev = gx_io_device_table[i]; ++ const char *dname = iodev->dname; + +- if (dname && strlen(dname) == 5 && !memcmp("%rom%", dname, 5)) { +- have_rom_device = 1; +- break; +- } ++ if (dname && strlen(dname) == 5 && !memcmp("%rom%", dname, 5)) { ++ have_rom_device = 1; ++ break; ++ } + } + if (have_rom_device && code >= 0) { +- code = file_path_add(&minst->lib_path, "%rom%Resource/Init/"); +- code = file_path_add(&minst->lib_path, "%rom%lib/"); ++ code = file_path_add(&minst->lib_path, "%rom%Resource/Init/"); ++ code = file_path_add(&minst->lib_path, "%rom%lib/"); + } + if (minst->lib_path.final != 0 && code >= 0) +- code = file_path_add(&minst->lib_path, minst->lib_path.final); ++ code = file_path_add(&minst->lib_path, minst->lib_path.final); + return code; + } + +@@ -424,9 +424,9 @@ gs_main_lib_open(gs_main_instance * mins + uint len; + + return lib_file_open(&minst->lib_path, imemory, +- NULL, /* Don't check permissions here, because permlist +- isn't ready running init files. */ +- file_name, strlen(file_name), fn, maxfn, &len, pfile); ++ NULL, /* Don't check permissions here, because permlist ++ isn't ready running init files. */ ++ file_name, strlen(file_name), fn, maxfn, &len, pfile); + } + + /* Open and execute a file. */ +@@ -437,19 +437,19 @@ gs_main_run_file(gs_main_instance * mins + int code = gs_main_run_file_open(minst, file_name, &initial_file); + + if (code < 0) +- return code; ++ return code; + return gs_main_interpret(minst, &initial_file, user_errors, +- pexit_code, perror_object); ++ pexit_code, perror_object); + } + int + gs_main_run_file_open(gs_main_instance * minst, const char *file_name, ref * pfref) + { + gs_main_set_lib_paths(minst); + if (gs_main_lib_open(minst, file_name, pfref) < 0) { +- emprintf1(minst->heap, ++ emprintf1(minst->heap, + "Can't find initialization file %s.\n", + file_name); +- return_error(e_Fatal); ++ return_error(e_Fatal); + } + r_set_attrs(pfref, a_execute + a_executable); + return 0; +@@ -468,57 +468,57 @@ gs_run_init_file(gs_main_instance * mins + gs_main_set_lib_paths(minst); + code = gs_main_run_file_open(minst, gs_init_file, &ifile); + if (code < 0) { +- *pexit_code = 255; +- return code; ++ *pexit_code = 255; ++ return code; + } + /* Check to make sure the first token is an integer */ + /* (for the version number check.) */ +- scanner_init(&state, &ifile); +- code = scan_token(i_ctx_p, &first_token, &state); ++ gs_scanner_init(&state, &ifile); ++ code = gs_scan_token(i_ctx_p, &first_token, &state); + if (code != 0 || !r_has_type(&first_token, t_integer)) { +- emprintf1(minst->heap, ++ emprintf1(minst->heap, + "Initialization file %s does not begin with an integer.\n", + gs_init_file); +- *pexit_code = 255; +- return_error(e_Fatal); ++ *pexit_code = 255; ++ return_error(e_Fatal); + } + *++osp = first_token; + r_set_attrs(&ifile, a_executable); + return gs_main_interpret(minst, &ifile, minst->user_errors, +- pexit_code, perror_object); ++ pexit_code, perror_object); + } + + /* Run a string. */ + int + gs_main_run_string(gs_main_instance * minst, const char *str, int user_errors, +- int *pexit_code, ref * perror_object) ++ int *pexit_code, ref * perror_object) + { + return gs_main_run_string_with_length(minst, str, (uint) strlen(str), +- user_errors, +- pexit_code, perror_object); ++ user_errors, ++ pexit_code, perror_object); + } + int + gs_main_run_string_with_length(gs_main_instance * minst, const char *str, +- uint length, int user_errors, int *pexit_code, ref * perror_object) ++ uint length, int user_errors, int *pexit_code, ref * perror_object) + { + int code; + + code = gs_main_run_string_begin(minst, user_errors, +- pexit_code, perror_object); ++ pexit_code, perror_object); + if (code < 0) +- return code; ++ return code; + code = gs_main_run_string_continue(minst, str, length, user_errors, +- pexit_code, perror_object); ++ pexit_code, perror_object); + if (code != e_NeedInput) +- return code; ++ return code; + return gs_main_run_string_end(minst, user_errors, +- pexit_code, perror_object); ++ pexit_code, perror_object); + } + + /* Set up for a suspendable run_string. */ + int + gs_main_run_string_begin(gs_main_instance * minst, int user_errors, +- int *pexit_code, ref * perror_object) ++ int *pexit_code, ref * perror_object) + { + const char *setup = ".runstringbegin"; + ref rstr; +@@ -526,35 +526,35 @@ gs_main_run_string_begin(gs_main_instanc + + gs_main_set_lib_paths(minst); + make_const_string(&rstr, avm_foreign | a_readonly | a_executable, +- strlen(setup), (const byte *)setup); ++ strlen(setup), (const byte *)setup); + code = gs_main_interpret(minst, &rstr, user_errors, pexit_code, +- perror_object); ++ perror_object); + return (code == e_NeedInput ? 0 : code == 0 ? e_Fatal : code); + } + /* Continue running a string with the option of suspending. */ + int + gs_main_run_string_continue(gs_main_instance * minst, const char *str, +- uint length, int user_errors, int *pexit_code, ref * perror_object) ++ uint length, int user_errors, int *pexit_code, ref * perror_object) + { + ref rstr; + + if (length == 0) +- return 0; /* empty string signals EOF */ ++ return 0; /* empty string signals EOF */ + make_const_string(&rstr, avm_foreign | a_readonly, length, +- (const byte *)str); ++ (const byte *)str); + return gs_main_interpret(minst, &rstr, user_errors, pexit_code, +- perror_object); ++ perror_object); + } + /* Signal EOF when suspended. */ + int + gs_main_run_string_end(gs_main_instance * minst, int user_errors, +- int *pexit_code, ref * perror_object) ++ int *pexit_code, ref * perror_object) + { + ref rstr; + + make_empty_const_string(&rstr, avm_foreign | a_readonly); + return gs_main_interpret(minst, &rstr, user_errors, pexit_code, +- perror_object); ++ perror_object); + } + + /* ------ Operand stack access ------ */ +@@ -568,7 +568,7 @@ push_value(gs_main_instance *minst, ref + int code = ref_stack_push(&o_stack, 1); + + if (code < 0) +- return code; ++ return code; + *ref_stack_index(&o_stack, 0L) = *pvalue; + return 0; + } +@@ -602,12 +602,12 @@ gs_push_real(gs_main_instance * minst, f + + int + gs_push_string(gs_main_instance * minst, byte * chars, uint length, +- bool read_only) ++ bool read_only) + { + ref vref; + + make_string(&vref, avm_foreign | (read_only ? a_readonly : a_all), +- length, (byte *) chars); ++ length, (byte *) chars); + return push_value(minst, &vref); + } + +@@ -615,7 +615,7 @@ static int + pop_value(i_ctx_t *i_ctx_p, ref * pvalue) + { + if (!ref_stack_count(&o_stack)) +- return_error(e_stackunderflow); ++ return_error(e_stackunderflow); + *pvalue = *ref_stack_index(&o_stack, 0L); + return 0; + } +@@ -628,7 +628,7 @@ gs_pop_boolean(gs_main_instance * minst, + int code = pop_value(i_ctx_p, &vref); + + if (code < 0) +- return code; ++ return code; + check_type_only(vref, t_boolean); + *result = vref.value.boolval; + ref_stack_pop(&o_stack, 1); +@@ -643,7 +643,7 @@ gs_pop_integer(gs_main_instance * minst, + int code = pop_value(i_ctx_p, &vref); + + if (code < 0) +- return code; ++ return code; + check_type_only(vref, t_integer); + *result = vref.value.intval; + ref_stack_pop(&o_stack, 1); +@@ -658,16 +658,16 @@ gs_pop_real(gs_main_instance * minst, fl + int code = pop_value(i_ctx_p, &vref); + + if (code < 0) +- return code; ++ return code; + switch (r_type(&vref)) { +- case t_real: +- *result = vref.value.realval; +- break; +- case t_integer: +- *result = (float)(vref.value.intval); +- break; +- default: +- return_error(e_typecheck); ++ case t_real: ++ *result = vref.value.realval; ++ break; ++ case t_integer: ++ *result = (float)(vref.value.intval); ++ break; ++ default: ++ return_error(e_typecheck); + } + ref_stack_pop(&o_stack, 1); + return 0; +@@ -681,19 +681,19 @@ gs_pop_string(gs_main_instance * minst, + int code = pop_value(i_ctx_p, &vref); + + if (code < 0) +- return code; ++ return code; + switch (r_type(&vref)) { +- case t_name: +- name_string_ref(minst->heap, &vref, &vref); +- code = 1; +- goto rstr; +- case t_string: +- code = (r_has_attr(&vref, a_write) ? 0 : 1); +- rstr:result->data = vref.value.bytes; +- result->size = r_size(&vref); +- break; +- default: +- return_error(e_typecheck); ++ case t_name: ++ name_string_ref(minst->heap, &vref, &vref); ++ code = 1; ++ goto rstr; ++ case t_string: ++ code = (r_has_attr(&vref, a_write) ? 0 : 1); ++ rstr:result->data = vref.value.bytes; ++ result->size = r_size(&vref); ++ break; ++ default: ++ return_error(e_typecheck); + } + ref_stack_pop(&o_stack, 1); + return code; +@@ -702,10 +702,10 @@ gs_pop_string(gs_main_instance * minst, + /* ------ Termination ------ */ + + /* Get the names of temporary files. +- * Each name is null terminated, and the last name is ++ * Each name is null terminated, and the last name is + * terminated by a double null. + * We retrieve the names of temporary files just before +- * the interpreter finishes, and then delete the files ++ * the interpreter finishes, and then delete the files + * after the interpreter has closed all files. + */ + static char *gs_main_tempnames(gs_main_instance *minst) +@@ -713,7 +713,7 @@ static char *gs_main_tempnames(gs_main_i + i_ctx_t *i_ctx_p = minst->i_ctx_p; + ref *SAFETY; + ref *tempfiles; +- ref keyval[2]; /* for key and value */ ++ ref keyval[2]; /* for key and value */ + char *tempnames = NULL; + int i; + int idict; +@@ -722,29 +722,29 @@ static char *gs_main_tempnames(gs_main_i + uint size; + if (minst->init_done >= 2) { + if (dict_find_string(systemdict, "SAFETY", &SAFETY) <= 0 || +- dict_find_string(SAFETY, "tempfiles", &tempfiles) <= 0) +- return NULL; +- /* get lengths of temporary filenames */ +- idict = dict_first(tempfiles); +- while ((idict = dict_next(tempfiles, idict, &keyval[0])) >= 0) { +- if (obj_string_data(minst->heap, &keyval[0], &data, &size) >= 0) +- len += size + 1; +- } +- if (len != 0) +- tempnames = (char *)malloc(len+1); +- if (tempnames) { +- memset(tempnames, 0, len+1); +- /* copy temporary filenames */ +- idict = dict_first(tempfiles); +- i = 0; +- while ((idict = dict_next(tempfiles, idict, &keyval[0])) >= 0) { +- if (obj_string_data(minst->heap, &keyval[0], &data, &size) >= 0) { +- memcpy(tempnames+i, (const char *)data, size); +- i+= size; +- tempnames[i++] = '\0'; +- } +- } +- } ++ dict_find_string(SAFETY, "tempfiles", &tempfiles) <= 0) ++ return NULL; ++ /* get lengths of temporary filenames */ ++ idict = dict_first(tempfiles); ++ while ((idict = dict_next(tempfiles, idict, &keyval[0])) >= 0) { ++ if (obj_string_data(minst->heap, &keyval[0], &data, &size) >= 0) ++ len += size + 1; ++ } ++ if (len != 0) ++ tempnames = (char *)malloc(len+1); ++ if (tempnames) { ++ memset(tempnames, 0, len+1); ++ /* copy temporary filenames */ ++ idict = dict_first(tempfiles); ++ i = 0; ++ while ((idict = dict_next(tempfiles, idict, &keyval[0])) >= 0) { ++ if (obj_string_data(minst->heap, &keyval[0], &data, &size) >= 0) { ++ memcpy(tempnames+i, (const char *)data, size); ++ i+= size; ++ tempnames[i++] = '\0'; ++ } ++ } ++ } + } + return tempnames; + } +@@ -768,7 +768,7 @@ gs_main_finit(gs_main_instance * minst, + * alloc_restore_all will close dynamically allocated devices. + */ + tempnames = gs_main_tempnames(minst); +- /* ++ /* + * Close the "main" device, because it may need to write out + * data before destruction. pdfwrite needs so. + */ +@@ -876,7 +876,7 @@ gs_abort(const gs_memory_t *mem) + * but more often than not, that will trip another abort and create + * an infinite recursion. So just abort without trying to cleanup. + */ +- gp_do_exit(1); ++ gp_do_exit(1); + } + + /* ------ Debugging ------ */ +@@ -884,38 +884,38 @@ gs_abort(const gs_memory_t *mem) + /* Print resource usage statistics. */ + void + print_resource_usage(const gs_main_instance * minst, gs_dual_memory_t * dmem, +- const char *msg) ++ const char *msg) + { + ulong allocated = 0, used = 0; + long utime[2]; + + gp_get_realtime(utime); + { +- int i; ++ int i; + +- for (i = 0; i < countof(dmem->spaces_indexed); ++i) { +- gs_ref_memory_t *mem = dmem->spaces_indexed[i]; ++ for (i = 0; i < countof(dmem->spaces_indexed); ++i) { ++ gs_ref_memory_t *mem = dmem->spaces_indexed[i]; + +- if (mem != 0 && (i == 0 || mem != dmem->spaces_indexed[i - 1])) { +- gs_memory_status_t status; +- gs_ref_memory_t *mem_stable = +- (gs_ref_memory_t *)gs_memory_stable((gs_memory_t *)mem); +- +- gs_memory_status((gs_memory_t *)mem, &status); +- allocated += status.allocated; +- used += status.used; +- if (mem_stable != mem) { +- gs_memory_status((gs_memory_t *)mem_stable, &status); +- allocated += status.allocated; +- used += status.used; +- } +- } +- } ++ if (mem != 0 && (i == 0 || mem != dmem->spaces_indexed[i - 1])) { ++ gs_memory_status_t status; ++ gs_ref_memory_t *mem_stable = ++ (gs_ref_memory_t *)gs_memory_stable((gs_memory_t *)mem); ++ ++ gs_memory_status((gs_memory_t *)mem, &status); ++ allocated += status.allocated; ++ used += status.used; ++ if (mem_stable != mem) { ++ gs_memory_status((gs_memory_t *)mem_stable, &status); ++ allocated += status.allocated; ++ used += status.used; ++ } ++ } ++ } + } + dprintf4("%% %s time = %g, memory allocated = %lu, used = %lu\n", +- msg, utime[0] - minst->base_time[0] + +- (utime[1] - minst->base_time[1]) / 1000000000.0, +- allocated, used); ++ msg, utime[0] - minst->base_time[0] + ++ (utime[1] - minst->base_time[1]) / 1000000000.0, ++ allocated, used); + } + + /* Dump the stacks after interpretation */ +@@ -924,12 +924,12 @@ gs_main_dump_stack(gs_main_instance *min + { + i_ctx_t *i_ctx_p = minst->i_ctx_p; + +- zflush(i_ctx_p); /* force out buffered output */ ++ zflush(i_ctx_p); /* force out buffered output */ + dprintf1("\nUnexpected interpreter error %d.\n", code); + if (perror_object != 0) { +- dputs("Error object: "); +- debug_print_ref(minst->heap, perror_object); +- dputc('\n'); ++ dputs("Error object: "); ++ debug_print_ref(minst->heap, perror_object); ++ dputc('\n'); + } + debug_dump_stack(minst->heap, &o_stack, "Operand stack"); + debug_dump_stack(minst->heap, &e_stack, "Execution stack"); +diff -up ghostscript-9.00/psi/interp.c.scan_token ghostscript-9.00/psi/interp.c +--- ghostscript-9.00/psi/interp.c.scan_token 2010-05-06 17:00:28.000000000 +0100 ++++ ghostscript-9.00/psi/interp.c 2011-01-14 17:16:12.602867532 +0000 +@@ -16,8 +16,8 @@ + #include "memory_.h" + #include "string_.h" + #include "ghost.h" +-#include "gsstruct.h" /* for iastruct.h */ +-#include "gserrors.h" /* for gpcheck.h */ ++#include "gsstruct.h" /* for iastruct.h */ ++#include "gserrors.h" /* for gpcheck.h */ + #include "stream.h" + #include "ierrors.h" + #include "estack.h" +@@ -26,24 +26,24 @@ + #include "icontext.h" + #include "icremap.h" + #include "idebug.h" +-#include "igstate.h" /* for handling e_RemapColor */ ++#include "igstate.h" /* for handling e_RemapColor */ + #include "inamedef.h" +-#include "iname.h" /* for the_name_table */ ++#include "iname.h" /* for the_name_table */ + #include "interp.h" + #include "ipacked.h" +-#include "ostack.h" /* must precede iscan.h */ +-#include "strimpl.h" /* for sfilter.h */ +-#include "sfilter.h" /* for iscan.h */ ++#include "ostack.h" /* must precede iscan.h */ ++#include "strimpl.h" /* for sfilter.h */ ++#include "sfilter.h" /* for iscan.h */ + #include "iscan.h" + #include "iddict.h" + #include "isave.h" + #include "istack.h" + #include "itoken.h" +-#include "iutil.h" /* for array_get */ ++#include "iutil.h" /* for array_get */ + #include "ivmspace.h" + #include "iinit.h" + #include "dstack.h" +-#include "files.h" /* for file_check_read */ ++#include "files.h" /* for file_check_read */ + #include "oper.h" + #include "store.h" + #include "gpcheck.h" +@@ -86,16 +86,16 @@ call_operator(op_proc_t op_proc, i_ctx_t + if_debug1('!', "[!]operator %s\n", op_get_name_string(op_proc)); + # else + if_debug3('!', "[!][es=%d os=%d]operator %s\n", +- esp-i_ctx_p->exec_stack.stack.bot, +- osp-i_ctx_p->op_stack.stack.bot, +- op_get_name_string(op_proc)); ++ esp-i_ctx_p->exec_stack.stack.bot, ++ osp-i_ctx_p->op_stack.stack.bot, ++ op_get_name_string(op_proc)); + # endif + # endif + code = op_proc(i_ctx_p); + # if defined(DEBUG_TRACE_PS_OPERATORS) && defined(SHOW_STACK_DEPTHS) + if_debug2('!', "[!][es=%d os=%d]\n", +- esp-i_ctx_p->exec_stack.stack.bot, +- osp-i_ctx_p->op_stack.stack.bot); ++ esp-i_ctx_p->exec_stack.stack.bot, ++ osp-i_ctx_p->op_stack.stack.bot); + # endif + return code; /* A good place for a conditional breakpoint. */ + } +@@ -109,10 +109,10 @@ struct stats_interp_s { + long top; + long lit, lit_array, exec_array, exec_operator, exec_name; + long x_add, x_def, x_dup, x_exch, x_if, x_ifelse, +- x_index, x_pop, x_roll, x_sub; ++ x_index, x_pop, x_roll, x_sub; + long find_name, name_lit, name_proc, name_oparray, name_operator; + long p_full, p_exec_operator, p_exec_oparray, p_exec_non_x_operator, +- p_integer, p_lit_name, p_exec_name; ++ p_integer, p_lit_name, p_exec_name; + long p_find_name, p_name_lit, p_name_proc; + } stats_interp; + # define INCR(v) (++(stats_interp.v)) +@@ -156,7 +156,7 @@ static int zcurrentstackprotect(i_ctx_t + * and therefore pushes 16 values). + */ + #define MIN_BLOCK_OSTACK 16 +-const int gs_interp_max_op_num_args = MIN_BLOCK_OSTACK; /* for iinit.c */ ++const int gs_interp_max_op_num_args = MIN_BLOCK_OSTACK; /* for iinit.c */ + + /* + * Define the initial maximum size of the execution stack (MaxExecStack +@@ -235,7 +235,7 @@ typedef enum { + } special_op_types; + + #define num_special_ops ((int)tx_next_op - tx_op) +-const int gs_interp_num_special_ops = num_special_ops; /* for iinit.c */ ++const int gs_interp_num_special_ops = num_special_ops; /* for iinit.c */ + const int tx_next_index = tx_next_op; + + /* +@@ -279,16 +279,16 @@ const op_def interp2_op_defs[] = { + /* Initialize the interpreter. */ + int + gs_interp_init(i_ctx_t **pi_ctx_p, const ref *psystem_dict, +- gs_dual_memory_t *dmem) ++ gs_dual_memory_t *dmem) + { + /* Create and initialize a context state. */ + gs_context_state_t *pcst = 0; + int code = context_state_alloc(&pcst, psystem_dict, dmem); + + if (code >= 0) +- code = context_state_load(pcst); ++ code = context_state_load(pcst); + if (code < 0) +- lprintf1("Fatal error %d in gs_interp_init!", code); ++ lprintf1("Fatal error %d in gs_interp_init!", code); + *pi_ctx_p = pcst; + return code; + } +@@ -300,51 +300,51 @@ int + gs_interp_alloc_stacks(gs_ref_memory_t *mem, gs_context_state_t * pcst) + { + gs_ref_memory_t *smem = +- (gs_ref_memory_t *)gs_memory_stable((gs_memory_t *)mem); ++ (gs_ref_memory_t *)gs_memory_stable((gs_memory_t *)mem); + ref stk; + + #define REFS_SIZE_OSTACK OS_REFS_SIZE(MAX_OSTACK) + #define REFS_SIZE_ESTACK ES_REFS_SIZE(MAX_ESTACK) + #define REFS_SIZE_DSTACK DS_REFS_SIZE(MAX_DSTACK) + gs_alloc_ref_array(smem, &stk, 0, +- REFS_SIZE_OSTACK + REFS_SIZE_ESTACK + +- REFS_SIZE_DSTACK, "gs_interp_alloc_stacks"); ++ REFS_SIZE_OSTACK + REFS_SIZE_ESTACK + ++ REFS_SIZE_DSTACK, "gs_interp_alloc_stacks"); + + { +- ref_stack_t *pos = &pcst->op_stack.stack; ++ ref_stack_t *pos = &pcst->op_stack.stack; + +- r_set_size(&stk, REFS_SIZE_OSTACK); +- ref_stack_init(pos, &stk, OS_GUARD_UNDER, OS_GUARD_OVER, NULL, +- smem, NULL); +- ref_stack_set_error_codes(pos, e_stackunderflow, e_stackoverflow); +- ref_stack_set_max_count(pos, MAX_OSTACK); +- stk.value.refs += REFS_SIZE_OSTACK; ++ r_set_size(&stk, REFS_SIZE_OSTACK); ++ ref_stack_init(pos, &stk, OS_GUARD_UNDER, OS_GUARD_OVER, NULL, ++ smem, NULL); ++ ref_stack_set_error_codes(pos, e_stackunderflow, e_stackoverflow); ++ ref_stack_set_max_count(pos, MAX_OSTACK); ++ stk.value.refs += REFS_SIZE_OSTACK; + } + + { +- ref_stack_t *pes = &pcst->exec_stack.stack; +- ref euop; ++ ref_stack_t *pes = &pcst->exec_stack.stack; ++ ref euop; + +- r_set_size(&stk, REFS_SIZE_ESTACK); +- make_oper(&euop, 0, estack_underflow); +- ref_stack_init(pes, &stk, ES_GUARD_UNDER, ES_GUARD_OVER, &euop, +- smem, NULL); +- ref_stack_set_error_codes(pes, e_ExecStackUnderflow, +- e_execstackoverflow); +- /**************** E-STACK EXPANSION IS NYI. ****************/ +- ref_stack_allow_expansion(pes, false); +- ref_stack_set_max_count(pes, MAX_ESTACK); +- stk.value.refs += REFS_SIZE_ESTACK; ++ r_set_size(&stk, REFS_SIZE_ESTACK); ++ make_oper(&euop, 0, estack_underflow); ++ ref_stack_init(pes, &stk, ES_GUARD_UNDER, ES_GUARD_OVER, &euop, ++ smem, NULL); ++ ref_stack_set_error_codes(pes, e_ExecStackUnderflow, ++ e_execstackoverflow); ++ /**************** E-STACK EXPANSION IS NYI. ****************/ ++ ref_stack_allow_expansion(pes, false); ++ ref_stack_set_max_count(pes, MAX_ESTACK); ++ stk.value.refs += REFS_SIZE_ESTACK; + } + + { +- ref_stack_t *pds = &pcst->dict_stack.stack; ++ ref_stack_t *pds = &pcst->dict_stack.stack; + +- r_set_size(&stk, REFS_SIZE_DSTACK); +- ref_stack_init(pds, &stk, 0, 0, NULL, smem, NULL); +- ref_stack_set_error_codes(pds, e_dictstackunderflow, +- e_dictstackoverflow); +- ref_stack_set_max_count(pds, MAX_DSTACK); ++ r_set_size(&stk, REFS_SIZE_DSTACK); ++ ref_stack_init(pds, &stk, 0, 0, NULL, smem, NULL); ++ ref_stack_set_error_codes(pds, e_dictstackunderflow, ++ e_dictstackoverflow); ++ ref_stack_set_max_count(pds, MAX_DSTACK); + } + + #undef REFS_SIZE_OSTACK +@@ -393,11 +393,11 @@ gs_interp_make_oper(ref * opref, op_proc + int i; + + for (i = num_special_ops; i > 0 && proc != interp1_op_defs[i].proc; --i) +- DO_NOTHING; ++ DO_NOTHING; + if (i > 0) +- make_tasv(opref, tx_op + (i - 1), a_executable, i, opproc, proc); ++ make_tasv(opref, tx_op + (i - 1), a_executable, i, opproc, proc); + else +- make_tasv(opref, t_operator, a_executable, idx, opproc, proc); ++ make_tasv(opref, t_operator, a_executable, idx, opproc, proc); + } + + /* +@@ -411,9 +411,9 @@ interp_reclaim(i_ctx_t **pi_ctx_p, int s + int code; + + gs_register_struct_root(imemory_system, &ctx_root, +- (void **)pi_ctx_p, "interp_reclaim(pi_ctx_p)"); ++ (void **)pi_ctx_p, "interp_reclaim(pi_ctx_p)"); + code = (*idmemory->reclaim)(idmemory, space); +- i_ctx_p = *pi_ctx_p; /* may have moved */ ++ i_ctx_p = *pi_ctx_p; /* may have moved */ + gs_unregister_root(imemory_system, &ctx_root, "interp_reclaim(pi_ctx_p)"); + return code; + } +@@ -431,16 +431,16 @@ interp_reclaim(i_ctx_t **pi_ctx_p, int s + static int gs_call_interp(i_ctx_t **, ref *, int, int *, ref *); + int + gs_interpret(i_ctx_t **pi_ctx_p, ref * pref, int user_errors, int *pexit_code, +- ref * perror_object) ++ ref * perror_object) + { + i_ctx_t *i_ctx_p = *pi_ctx_p; + gs_gc_root_t error_root; + int code; + + gs_register_ref_root(imemory_system, &error_root, +- (void **)&perror_object, "gs_interpret"); ++ (void **)&perror_object, "gs_interpret"); + code = gs_call_interp(pi_ctx_p, pref, user_errors, pexit_code, +- perror_object); ++ perror_object); + i_ctx_p = *pi_ctx_p; + gs_unregister_root(imemory_system, &error_root, "gs_interpret"); + /* Avoid a dangling reference to a stack-allocated GC signal. */ +@@ -449,7 +449,7 @@ gs_interpret(i_ctx_t **pi_ctx_p, ref * p + } + static int + gs_call_interp(i_ctx_t **pi_ctx_p, ref * pref, int user_errors, +- int *pexit_code, ref * perror_object) ++ int *pexit_code, ref * perror_object) + { + ref *epref = pref; + ref doref; +@@ -466,181 +466,181 @@ again: + /* Avoid a dangling error object that might get traced by a future GC. */ + make_null(perror_object); + o_stack.requested = e_stack.requested = d_stack.requested = 0; +- while (gc_signal) { /* Some routine below triggered a GC. */ +- gs_gc_root_t epref_root; ++ while (gc_signal) { /* Some routine below triggered a GC. */ ++ gs_gc_root_t epref_root; + +- gc_signal = 0; +- /* Make sure that doref will get relocated properly if */ +- /* a garbage collection happens with epref == &doref. */ +- gs_register_ref_root(imemory_system, &epref_root, +- (void **)&epref, "gs_call_interp(epref)"); +- code = interp_reclaim(pi_ctx_p, -1); +- i_ctx_p = *pi_ctx_p; +- gs_unregister_root(imemory_system, &epref_root, +- "gs_call_interp(epref)"); +- if (code < 0) +- return code; ++ gc_signal = 0; ++ /* Make sure that doref will get relocated properly if */ ++ /* a garbage collection happens with epref == &doref. */ ++ gs_register_ref_root(imemory_system, &epref_root, ++ (void **)&epref, "gs_call_interp(epref)"); ++ code = interp_reclaim(pi_ctx_p, -1); ++ i_ctx_p = *pi_ctx_p; ++ gs_unregister_root(imemory_system, &epref_root, ++ "gs_call_interp(epref)"); ++ if (code < 0) ++ return code; + } + code = interp(pi_ctx_p, epref, perror_object); + i_ctx_p = *pi_ctx_p; + if (!r_has_type(&i_ctx_p->error_object, t__invalid)) { +- *perror_object = i_ctx_p->error_object; +- make_t(&i_ctx_p->error_object, t__invalid); ++ *perror_object = i_ctx_p->error_object; ++ make_t(&i_ctx_p->error_object, t__invalid); + } + /* Prevent a dangling reference to the GC signal in ticks_left */ + /* in the frame of interp, but be prepared to do a GC if */ + /* an allocation in this routine asks for it. */ + set_gc_signal(i_ctx_p, &gc_signal, 1); +- if (esp < esbot) /* popped guard entry */ +- esp = esbot; ++ if (esp < esbot) /* popped guard entry */ ++ esp = esbot; + switch (code) { +- case e_Fatal: +- *pexit_code = 255; +- return code; +- case e_Quit: +- *perror_object = osp[-1]; +- *pexit_code = code = osp->value.intval; +- osp -= 2; +- return +- (code == 0 ? e_Quit : +- code < 0 && code > -100 ? code : e_Fatal); +- case e_InterpreterExit: +- return 0; +- case e_ExecStackUnderflow: ++ case e_Fatal: ++ *pexit_code = 255; ++ return code; ++ case e_Quit: ++ *perror_object = osp[-1]; ++ *pexit_code = code = osp->value.intval; ++ osp -= 2; ++ return ++ (code == 0 ? e_Quit : ++ code < 0 && code > -100 ? code : e_Fatal); ++ case e_InterpreterExit: ++ return 0; ++ case e_ExecStackUnderflow: + /****** WRONG -- must keep mark blocks intact ******/ +- ref_stack_pop_block(&e_stack); +- doref = *perror_object; +- epref = &doref; +- goto again; +- case e_VMreclaim: +- /* Do the GC and continue. */ +- code = interp_reclaim(pi_ctx_p, +- (osp->value.intval == 2 ? +- avm_global : avm_local)); +- i_ctx_p = *pi_ctx_p; +- /****** What if code < 0? ******/ +- make_oper(&doref, 0, zpop); +- epref = &doref; +- goto again; +- case e_NeedInput: +- case e_interrupt: +- return code; ++ ref_stack_pop_block(&e_stack); ++ doref = *perror_object; ++ epref = &doref; ++ goto again; ++ case e_VMreclaim: ++ /* Do the GC and continue. */ ++ code = interp_reclaim(pi_ctx_p, ++ (osp->value.intval == 2 ? ++ avm_global : avm_local)); ++ i_ctx_p = *pi_ctx_p; ++ /****** What if code < 0? ******/ ++ make_oper(&doref, 0, zpop); ++ epref = &doref; ++ goto again; ++ case e_NeedInput: ++ case e_interrupt: ++ return code; + } + /* Adjust osp in case of operand stack underflow */ + if (osp < osbot - 1) +- osp = osbot - 1; ++ osp = osbot - 1; + /* We have to handle stack over/underflow specially, because */ + /* we might be able to recover by adding or removing a block. */ + switch (code) { +- case e_dictstackoverflow: +- /* We don't have to handle this specially: */ +- /* The only places that could generate it */ +- /* use check_dstack, which does a ref_stack_extend, */ +- /* so if` we get this error, it's a real one. */ +- if (osp >= ostop) { +- if ((ccode = ref_stack_extend(&o_stack, 1)) < 0) +- return ccode; +- } ++ case e_dictstackoverflow: ++ /* We don't have to handle this specially: */ ++ /* The only places that could generate it */ ++ /* use check_dstack, which does a ref_stack_extend, */ ++ /* so if` we get this error, it's a real one. */ ++ if (osp >= ostop) { ++ if ((ccode = ref_stack_extend(&o_stack, 1)) < 0) ++ return ccode; ++ } + /* Skip system dictionaries for CET 20-02-02 */ +- ccode = copy_stack(i_ctx_p, &d_stack, min_dstack_size, &saref); +- if (ccode < 0) +- return ccode; +- ref_stack_pop_to(&d_stack, min_dstack_size); +- dict_set_top(); +- *++osp = saref; +- break; +- case e_dictstackunderflow: +- if (ref_stack_pop_block(&d_stack) >= 0) { +- dict_set_top(); +- doref = *perror_object; +- epref = &doref; +- goto again; +- } +- break; +- case e_execstackoverflow: +- /* We don't have to handle this specially: */ +- /* The only places that could generate it */ +- /* use check_estack, which does a ref_stack_extend, */ +- /* so if we get this error, it's a real one. */ +- if (osp >= ostop) { +- if ((ccode = ref_stack_extend(&o_stack, 1)) < 0) +- return ccode; +- } +- ccode = copy_stack(i_ctx_p, &e_stack, 0, &saref); +- if (ccode < 0) +- return ccode; +- { +- uint count = ref_stack_count(&e_stack); +- uint limit = ref_stack_max_count(&e_stack) - ES_HEADROOM; +- +- if (count > limit) { +- /* +- * If there is an e-stack mark within MIN_BLOCK_ESTACK of +- * the new top, cut the stack back to remove the mark. +- */ +- int skip = count - limit; +- int i; +- +- for (i = skip; i < skip + MIN_BLOCK_ESTACK; ++i) { +- const ref *ep = ref_stack_index(&e_stack, i); +- +- if (r_has_type_attrs(ep, t_null, a_executable)) { +- skip = i + 1; +- break; +- } +- } +- pop_estack(i_ctx_p, skip); +- } +- } +- *++osp = saref; +- break; +- case e_stackoverflow: +- if (ref_stack_extend(&o_stack, o_stack.requested) >= 0) { /* We can't just re-execute the object, because */ +- /* it might be a procedure being pushed as a */ +- /* literal. We check for this case specially. */ +- doref = *perror_object; +- if (r_is_proc(&doref)) { +- *++osp = doref; +- make_null_proc(&doref); +- } +- epref = &doref; +- goto again; +- } +- ccode = copy_stack(i_ctx_p, &o_stack, 0, &saref); +- if (ccode < 0) +- return ccode; +- ref_stack_clear(&o_stack); +- *++osp = saref; +- break; +- case e_stackunderflow: +- if (ref_stack_pop_block(&o_stack) >= 0) { +- doref = *perror_object; +- epref = &doref; +- goto again; +- } +- break; ++ ccode = copy_stack(i_ctx_p, &d_stack, min_dstack_size, &saref); ++ if (ccode < 0) ++ return ccode; ++ ref_stack_pop_to(&d_stack, min_dstack_size); ++ dict_set_top(); ++ *++osp = saref; ++ break; ++ case e_dictstackunderflow: ++ if (ref_stack_pop_block(&d_stack) >= 0) { ++ dict_set_top(); ++ doref = *perror_object; ++ epref = &doref; ++ goto again; ++ } ++ break; ++ case e_execstackoverflow: ++ /* We don't have to handle this specially: */ ++ /* The only places that could generate it */ ++ /* use check_estack, which does a ref_stack_extend, */ ++ /* so if we get this error, it's a real one. */ ++ if (osp >= ostop) { ++ if ((ccode = ref_stack_extend(&o_stack, 1)) < 0) ++ return ccode; ++ } ++ ccode = copy_stack(i_ctx_p, &e_stack, 0, &saref); ++ if (ccode < 0) ++ return ccode; ++ { ++ uint count = ref_stack_count(&e_stack); ++ uint limit = ref_stack_max_count(&e_stack) - ES_HEADROOM; ++ ++ if (count > limit) { ++ /* ++ * If there is an e-stack mark within MIN_BLOCK_ESTACK of ++ * the new top, cut the stack back to remove the mark. ++ */ ++ int skip = count - limit; ++ int i; ++ ++ for (i = skip; i < skip + MIN_BLOCK_ESTACK; ++i) { ++ const ref *ep = ref_stack_index(&e_stack, i); ++ ++ if (r_has_type_attrs(ep, t_null, a_executable)) { ++ skip = i + 1; ++ break; ++ } ++ } ++ pop_estack(i_ctx_p, skip); ++ } ++ } ++ *++osp = saref; ++ break; ++ case e_stackoverflow: ++ if (ref_stack_extend(&o_stack, o_stack.requested) >= 0) { /* We can't just re-execute the object, because */ ++ /* it might be a procedure being pushed as a */ ++ /* literal. We check for this case specially. */ ++ doref = *perror_object; ++ if (r_is_proc(&doref)) { ++ *++osp = doref; ++ make_null_proc(&doref); ++ } ++ epref = &doref; ++ goto again; ++ } ++ ccode = copy_stack(i_ctx_p, &o_stack, 0, &saref); ++ if (ccode < 0) ++ return ccode; ++ ref_stack_clear(&o_stack); ++ *++osp = saref; ++ break; ++ case e_stackunderflow: ++ if (ref_stack_pop_block(&o_stack) >= 0) { ++ doref = *perror_object; ++ epref = &doref; ++ goto again; ++ } ++ break; + } + if (user_errors < 0) +- return code; ++ return code; + if (gs_errorname(i_ctx_p, code, &error_name) < 0) +- return code; /* out-of-range error code! */ ++ return code; /* out-of-range error code! */ + /* + * For greater Adobe compatibility, only the standard PostScript errors + * are defined in errordict; the rest are in gserrordict. + */ + if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || +- (dict_find(perrordict, &error_name, &epref) <= 0 && +- (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || +- dict_find(perrordict, &error_name, &epref) <= 0)) +- ) +- return code; /* error name not in errordict??? */ ++ (dict_find(perrordict, &error_name, &epref) <= 0 && ++ (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || ++ dict_find(perrordict, &error_name, &epref) <= 0)) ++ ) ++ return code; /* error name not in errordict??? */ + doref = *epref; + epref = &doref; + /* Push the error object on the operand stack if appropriate. */ + if (!ERROR_IS_INTERRUPT(code)) { +- /* Replace the error object if within an oparray or .errorexec. */ +- *++osp = *perror_object; +- errorexec_find(i_ctx_p, osp); ++ /* Replace the error object if within an oparray or .errorexec. */ ++ *++osp = *perror_object; ++ errorexec_find(i_ctx_p, osp); + } + goto again; + } +@@ -658,21 +658,21 @@ set_gc_signal(i_ctx_t *i_ctx_p, int *psi + int i; + + for (i = 0; i < countof(idmemory->spaces_indexed); i++) { +- gs_ref_memory_t *mem = idmemory->spaces_indexed[i]; +- gs_ref_memory_t *mem_stable; ++ gs_ref_memory_t *mem = idmemory->spaces_indexed[i]; ++ gs_ref_memory_t *mem_stable; + +- if (mem == 0) +- continue; +- for (;; mem = mem_stable) { +- mem_stable = (gs_ref_memory_t *) +- gs_memory_stable((gs_memory_t *)mem); +- gs_memory_gc_status(mem, &stat); +- stat.psignal = psignal; +- stat.signal_value = value; +- gs_memory_set_gc_status(mem, &stat); +- if (mem_stable == mem) +- break; +- } ++ if (mem == 0) ++ continue; ++ for (;; mem = mem_stable) { ++ mem_stable = (gs_ref_memory_t *) ++ gs_memory_stable((gs_memory_t *)mem); ++ gs_memory_gc_status(mem, &stat); ++ stat.psignal = psignal; ++ stat.signal_value = value; ++ gs_memory_set_gc_status(mem, &stat); ++ if (mem_stable == mem) ++ break; ++ } + } + } + +@@ -691,8 +691,8 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_s + ialloc_set_space(idmemory, avm_local); + code = ialloc_ref_array(arr, a_all, size, "copy_stack"); + if (code >= 0) +- code = ref_stack_store(pstack, arr, size, 0, 1, true, idmemory, +- "copy_stack"); ++ code = ref_stack_store(pstack, arr, size, 0, 1, true, idmemory, ++ "copy_stack"); + ialloc_set_space(idmemory, save_space); + return code; + } +@@ -704,9 +704,9 @@ gs_errorname(i_ctx_t *i_ctx_p, int code, + ref *perrordict, *pErrorNames; + + if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || +- dict_find_string(systemdict, "ErrorNames", &pErrorNames) <= 0 +- ) +- return_error(e_undefined); /* errordict or ErrorNames not found?! */ ++ dict_find_string(systemdict, "ErrorNames", &pErrorNames) <= 0 ++ ) ++ return_error(e_undefined); /* errordict or ErrorNames not found?! */ + return array_get(imemory, pErrorNames, (long)(-code - 1), perror_name); + } + +@@ -720,12 +720,12 @@ gs_errorinfo_put_string(i_ctx_t *i_ctx_p + int code = string_to_ref(str, &rstr, iimemory, "gs_errorinfo_put_string"); + + if (code < 0) +- return code; ++ return code; + if (dict_find_string(systemdict, "$error", &pderror) <= 0 || +- !r_has_type(pderror, t_dictionary) || +- idict_put_string(pderror, "errorinfo", &rstr) < 0 +- ) +- return_error(e_Fatal); ++ !r_has_type(pderror, t_dictionary) || ++ idict_put_string(pderror, "errorinfo", &rstr) < 0 ++ ) ++ return_error(e_Fatal); + return 0; + } + +@@ -764,14 +764,14 @@ interp(i_ctx_t **pi_ctx_p /* context for + # define IREF ((const ref *)iref_packed) + #endif + #define SET_IREF(rp) (iref_packed = (const ref_packed *)(rp)) +- register int icount = 0; /* # of consecutive tokens at iref */ +- register os_ptr iosp = osp; /* private copy of osp */ +- register es_ptr iesp = esp; /* private copy of esp */ ++ register int icount = 0; /* # of consecutive tokens at iref */ ++ register os_ptr iosp = osp; /* private copy of osp */ ++ register es_ptr iesp = esp; /* private copy of esp */ + int code; +- ref token; /* token read from file or string, */ +- /* must be declared in this scope */ ++ ref token; /* token read from file or string, */ ++ /* must be declared in this scope */ + register const ref *pvalue = 0; +- uint opindex; /* needed for oparrays */ ++ uint opindex; /* needed for oparrays */ + os_ptr whichp; + + /* +@@ -783,10 +783,10 @@ interp(i_ctx_t **pi_ctx_p /* context for + * will remain available on Intel processors. + */ + struct interp_error_s { +- int code; +- int line; +- const ref *obj; +- ref full; ++ int code; ++ int line; ++ const ref *obj; ++ ref full; + } ierror; + + /* +@@ -866,51 +866,51 @@ interp(i_ctx_t **pi_ctx_p /* context for + /* so we push the argument on the estack and enter */ + /* the loop at the bottom. */ + if (iesp >= estop) +- return_with_error(e_execstackoverflow, pref); ++ return_with_error(e_execstackoverflow, pref); + ++iesp; + ref_assign_inline(iesp, pref); + goto bot; + top: +- /* +- * This is the top of the interpreter loop. +- * iref points to the ref being interpreted. +- * Note that this might be an element of a packed array, +- * not a real ref: we carefully arranged the first 16 bits of +- * a ref and of a packed array element so they could be distinguished +- * from each other. (See ghost.h and packed.h for more detail.) +- */ ++ /* ++ * This is the top of the interpreter loop. ++ * iref points to the ref being interpreted. ++ * Note that this might be an element of a packed array, ++ * not a real ref: we carefully arranged the first 16 bits of ++ * a ref and of a packed array element so they could be distinguished ++ * from each other. (See ghost.h and packed.h for more detail.) ++ */ + INCR(top); + #ifdef DEBUG + /* Do a little validation on the top o-stack entry. */ + if (iosp >= osbot && +- (r_type(iosp) == t__invalid || r_type(iosp) >= tx_next_op) +- ) { +- lprintf("Invalid value on o-stack!\n"); +- return_with_error_iref(e_Fatal); ++ (r_type(iosp) == t__invalid || r_type(iosp) >= tx_next_op) ++ ) { ++ lprintf("Invalid value on o-stack!\n"); ++ return_with_error_iref(e_Fatal); + } + if (gs_debug['I'] || +- (gs_debug['i'] && +- (r_is_packed(iref_packed) ? +- r_packed_is_name(iref_packed) : +- r_has_type(IREF, t_name))) +- ) { +- os_ptr save_osp = osp; /* avoid side-effects */ +- es_ptr save_esp = esp; +- +- osp = iosp; +- esp = iesp; +- dlprintf5("d%u,e%u<%u>0x%lx(%d): ", +- ref_stack_count(&d_stack), ref_stack_count(&e_stack), +- ref_stack_count(&o_stack), (ulong)IREF, icount); +- debug_print_ref(imemory, IREF); +- if (iosp >= osbot) { +- dputs(" // "); +- debug_print_ref(imemory, iosp); +- } +- dputc('\n'); +- osp = save_osp; +- esp = save_esp; +- dflush(); ++ (gs_debug['i'] && ++ (r_is_packed(iref_packed) ? ++ r_packed_is_name(iref_packed) : ++ r_has_type(IREF, t_name))) ++ ) { ++ os_ptr save_osp = osp; /* avoid side-effects */ ++ es_ptr save_esp = esp; ++ ++ osp = iosp; ++ esp = iesp; ++ dlprintf5("d%u,e%u<%u>0x%lx(%d): ", ++ ref_stack_count(&d_stack), ref_stack_count(&e_stack), ++ ref_stack_count(&o_stack), (ulong)IREF, icount); ++ debug_print_ref(imemory, IREF); ++ if (iosp >= osbot) { ++ dputs(" // "); ++ debug_print_ref(imemory, iosp); ++ } ++ dputc('\n'); ++ osp = save_osp; ++ esp = save_esp; ++ dflush(); + } + #endif + /* Objects that have attributes (arrays, dictionaries, files, and strings) */ +@@ -927,23 +927,23 @@ interp(i_ctx_t **pi_ctx_p /* context for + * What a nuisance! + */ + switch (r_type_xe(iref_packed)) { +- /* Access errors. */ ++ /* Access errors. */ + #define cases_invalid()\ + case plain(t__invalid): case plain_exec(t__invalid) +- cases_invalid(): +- return_with_error_iref(e_Fatal); ++ cases_invalid(): ++ return_with_error_iref(e_Fatal); + #define cases_nox()\ + case nox_exec(t_array): case nox_exec(t_dictionary):\ + case nox_exec(t_file): case nox_exec(t_string):\ + case nox_exec(t_mixedarray): case nox_exec(t_shortarray) +- cases_nox(): +- return_with_error_iref(e_invalidaccess); +- /* +- * Literal objects. We have to enumerate all the types. +- * In fact, we have to include some extra plain_exec entries +- * just to populate the switch. We break them up into groups +- * to avoid overflowing some preprocessors. +- */ ++ cases_nox(): ++ return_with_error_iref(e_invalidaccess); ++ /* ++ * Literal objects. We have to enumerate all the types. ++ * In fact, we have to include some extra plain_exec entries ++ * just to populate the switch. We break them up into groups ++ * to avoid overflowing some preprocessors. ++ */ + #define cases_lit_1()\ + case lit(t_array): case nox(t_array):\ + case plain(t_boolean): case plain_exec(t_boolean):\ +@@ -968,673 +968,673 @@ interp(i_ctx_t **pi_ctx_p /* context for + case plain(t_device): case plain_exec(t_device):\ + case plain(t_struct): case plain_exec(t_struct):\ + case plain(t_astruct): case plain_exec(t_astruct) +- /* Executable arrays are treated as literals in direct execution. */ ++ /* Executable arrays are treated as literals in direct execution. */ + #define cases_lit_array()\ + case exec(t_array): case exec(t_mixedarray): case exec(t_shortarray) +- cases_lit_1(): +- cases_lit_2(): +- cases_lit_3(): +- cases_lit_4(): +- cases_lit_5(): +- INCR(lit); +- break; +- cases_lit_array(): +- INCR(lit_array); +- break; +- /* Special operators. */ +- case plain_exec(tx_op_add): +-x_add: INCR(x_add); +- if ((code = zop_add(iosp)) < 0) +- return_with_error_tx_op(code); +- iosp--; +- next_either(); +- case plain_exec(tx_op_def): +-x_def: INCR(x_def); +- osp = iosp; /* sync o_stack */ +- if ((code = zop_def(i_ctx_p)) < 0) +- return_with_error_tx_op(code); +- iosp -= 2; +- next_either(); +- case plain_exec(tx_op_dup): +-x_dup: INCR(x_dup); +- if (iosp < osbot) +- return_with_error_tx_op(e_stackunderflow); +- if (iosp >= ostop) { +- o_stack.requested = 1; ++ cases_lit_1(): ++ cases_lit_2(): ++ cases_lit_3(): ++ cases_lit_4(): ++ cases_lit_5(): ++ INCR(lit); ++ break; ++ cases_lit_array(): ++ INCR(lit_array); ++ break; ++ /* Special operators. */ ++ case plain_exec(tx_op_add): ++x_add: INCR(x_add); ++ if ((code = zop_add(iosp)) < 0) ++ return_with_error_tx_op(code); ++ iosp--; ++ next_either(); ++ case plain_exec(tx_op_def): ++x_def: INCR(x_def); ++ osp = iosp; /* sync o_stack */ ++ if ((code = zop_def(i_ctx_p)) < 0) ++ return_with_error_tx_op(code); ++ iosp -= 2; ++ next_either(); ++ case plain_exec(tx_op_dup): ++x_dup: INCR(x_dup); ++ if (iosp < osbot) ++ return_with_error_tx_op(e_stackunderflow); ++ if (iosp >= ostop) { ++ o_stack.requested = 1; + return_with_error_tx_op(e_stackoverflow); + } +- iosp++; +- ref_assign_inline(iosp, iosp - 1); +- next_either(); +- case plain_exec(tx_op_exch): +-x_exch: INCR(x_exch); +- if (iosp <= osbot) +- return_with_error_tx_op(e_stackunderflow); +- ref_assign_inline(&token, iosp); +- ref_assign_inline(iosp, iosp - 1); +- ref_assign_inline(iosp - 1, &token); +- next_either(); +- case plain_exec(tx_op_if): +-x_if: INCR(x_if); +- if (!r_is_proc(iosp)) +- return_with_error_tx_op(check_proc_failed(iosp)); +- if (!r_has_type(iosp - 1, t_boolean)) +- return_with_error_tx_op((iosp <= osbot ? +- e_stackunderflow : e_typecheck)); +- if (!iosp[-1].value.boolval) { +- iosp -= 2; +- next_either(); +- } +- if (iesp >= estop) +- return_with_error_tx_op(e_execstackoverflow); +- store_state_either(iesp); +- whichp = iosp; +- iosp -= 2; +- goto ifup; +- case plain_exec(tx_op_ifelse): ++ iosp++; ++ ref_assign_inline(iosp, iosp - 1); ++ next_either(); ++ case plain_exec(tx_op_exch): ++x_exch: INCR(x_exch); ++ if (iosp <= osbot) ++ return_with_error_tx_op(e_stackunderflow); ++ ref_assign_inline(&token, iosp); ++ ref_assign_inline(iosp, iosp - 1); ++ ref_assign_inline(iosp - 1, &token); ++ next_either(); ++ case plain_exec(tx_op_if): ++x_if: INCR(x_if); ++ if (!r_is_proc(iosp)) ++ return_with_error_tx_op(check_proc_failed(iosp)); ++ if (!r_has_type(iosp - 1, t_boolean)) ++ return_with_error_tx_op((iosp <= osbot ? ++ e_stackunderflow : e_typecheck)); ++ if (!iosp[-1].value.boolval) { ++ iosp -= 2; ++ next_either(); ++ } ++ if (iesp >= estop) ++ return_with_error_tx_op(e_execstackoverflow); ++ store_state_either(iesp); ++ whichp = iosp; ++ iosp -= 2; ++ goto ifup; ++ case plain_exec(tx_op_ifelse): + x_ifelse: INCR(x_ifelse); +- if (!r_is_proc(iosp)) +- return_with_error_tx_op(check_proc_failed(iosp)); +- if (!r_is_proc(iosp - 1)) +- return_with_error_tx_op(check_proc_failed(iosp - 1)); +- if (!r_has_type(iosp - 2, t_boolean)) +- return_with_error_tx_op((iosp < osbot + 2 ? +- e_stackunderflow : e_typecheck)); +- if (iesp >= estop) +- return_with_error_tx_op(e_execstackoverflow); +- store_state_either(iesp); +- whichp = (iosp[-2].value.boolval ? iosp - 1 : iosp); +- iosp -= 3; +- /* Open code "up" for the array case(s) */ +- ifup:if ((icount = r_size(whichp) - 1) <= 0) { +- if (icount < 0) +- goto up; /* 0-element proc */ +- SET_IREF(whichp->value.refs); /* 1-element proc */ +- if (--ticks_left > 0) +- goto top; +- } +- ++iesp; +- /* Do a ref_assign, but also set iref. */ +- iesp->tas = whichp->tas; +- SET_IREF(iesp->value.refs = whichp->value.refs); +- if (--ticks_left > 0) +- goto top; +- goto slice; +- case plain_exec(tx_op_index): ++ if (!r_is_proc(iosp)) ++ return_with_error_tx_op(check_proc_failed(iosp)); ++ if (!r_is_proc(iosp - 1)) ++ return_with_error_tx_op(check_proc_failed(iosp - 1)); ++ if (!r_has_type(iosp - 2, t_boolean)) ++ return_with_error_tx_op((iosp < osbot + 2 ? ++ e_stackunderflow : e_typecheck)); ++ if (iesp >= estop) ++ return_with_error_tx_op(e_execstackoverflow); ++ store_state_either(iesp); ++ whichp = (iosp[-2].value.boolval ? iosp - 1 : iosp); ++ iosp -= 3; ++ /* Open code "up" for the array case(s) */ ++ ifup:if ((icount = r_size(whichp) - 1) <= 0) { ++ if (icount < 0) ++ goto up; /* 0-element proc */ ++ SET_IREF(whichp->value.refs); /* 1-element proc */ ++ if (--ticks_left > 0) ++ goto top; ++ } ++ ++iesp; ++ /* Do a ref_assign, but also set iref. */ ++ iesp->tas = whichp->tas; ++ SET_IREF(iesp->value.refs = whichp->value.refs); ++ if (--ticks_left > 0) ++ goto top; ++ goto slice; ++ case plain_exec(tx_op_index): + x_index: INCR(x_index); +- osp = iosp; /* zindex references o_stack */ +- if ((code = zindex(i_ctx_p)) < 0) +- return_with_error_tx_op(code); +- next_either(); +- case plain_exec(tx_op_pop): +-x_pop: INCR(x_pop); +- if (iosp < osbot) +- return_with_error_tx_op(e_stackunderflow); +- iosp--; +- next_either(); +- case plain_exec(tx_op_roll): +-x_roll: INCR(x_roll); +- osp = iosp; /* zroll references o_stack */ +- if ((code = zroll(i_ctx_p)) < 0) +- return_with_error_tx_op(code); +- iosp -= 2; +- next_either(); +- case plain_exec(tx_op_sub): +-x_sub: INCR(x_sub); +- if ((code = zop_sub(iosp)) < 0) +- return_with_error_tx_op(code); +- iosp--; +- next_either(); +- /* Executable types. */ +- case plain_exec(t_null): +- goto bot; +- case plain_exec(t_oparray): +- /* Replace with the definition and go again. */ +- INCR(exec_array); +- opindex = op_index(IREF); +- pvalue = IREF->value.const_refs; +- opst: /* Prepare to call a t_oparray procedure in *pvalue. */ +- store_state(iesp); +- oppr: /* Record the stack depths in case of failure. */ +- if (iesp >= estop - 4) +- return_with_error_iref(e_execstackoverflow); +- iesp += 5; +- osp = iosp; /* ref_stack_count_inline needs this */ +- make_mark_estack(iesp - 4, es_other, oparray_cleanup); +- make_int(iesp - 3, opindex); /* for .errorexec effect */ +- make_int(iesp - 2, ref_stack_count_inline(&o_stack)); +- make_int(iesp - 1, ref_stack_count_inline(&d_stack)); +- make_op_estack(iesp, oparray_pop); +- goto pr; +- prst: /* Prepare to call the procedure (array) in *pvalue. */ +- store_state(iesp); +- pr: /* Call the array in *pvalue. State has been stored. */ +- if ((icount = r_size(pvalue) - 1) <= 0) { +- if (icount < 0) +- goto up; /* 0-element proc */ +- SET_IREF(pvalue->value.refs); /* 1-element proc */ +- if (--ticks_left > 0) +- goto top; +- } +- if (iesp >= estop) +- return_with_error_iref(e_execstackoverflow); +- ++iesp; +- /* Do a ref_assign, but also set iref. */ +- iesp->tas = pvalue->tas; +- SET_IREF(iesp->value.refs = pvalue->value.refs); +- if (--ticks_left > 0) +- goto top; +- goto slice; +- case plain_exec(t_operator): +- INCR(exec_operator); +- if (--ticks_left <= 0) { /* The following doesn't work, */ +- /* and I can't figure out why. */ ++ osp = iosp; /* zindex references o_stack */ ++ if ((code = zindex(i_ctx_p)) < 0) ++ return_with_error_tx_op(code); ++ next_either(); ++ case plain_exec(tx_op_pop): ++x_pop: INCR(x_pop); ++ if (iosp < osbot) ++ return_with_error_tx_op(e_stackunderflow); ++ iosp--; ++ next_either(); ++ case plain_exec(tx_op_roll): ++x_roll: INCR(x_roll); ++ osp = iosp; /* zroll references o_stack */ ++ if ((code = zroll(i_ctx_p)) < 0) ++ return_with_error_tx_op(code); ++ iosp -= 2; ++ next_either(); ++ case plain_exec(tx_op_sub): ++x_sub: INCR(x_sub); ++ if ((code = zop_sub(iosp)) < 0) ++ return_with_error_tx_op(code); ++ iosp--; ++ next_either(); ++ /* Executable types. */ ++ case plain_exec(t_null): ++ goto bot; ++ case plain_exec(t_oparray): ++ /* Replace with the definition and go again. */ ++ INCR(exec_array); ++ opindex = op_index(IREF); ++ pvalue = IREF->value.const_refs; ++ opst: /* Prepare to call a t_oparray procedure in *pvalue. */ ++ store_state(iesp); ++ oppr: /* Record the stack depths in case of failure. */ ++ if (iesp >= estop - 4) ++ return_with_error_iref(e_execstackoverflow); ++ iesp += 5; ++ osp = iosp; /* ref_stack_count_inline needs this */ ++ make_mark_estack(iesp - 4, es_other, oparray_cleanup); ++ make_int(iesp - 3, opindex); /* for .errorexec effect */ ++ make_int(iesp - 2, ref_stack_count_inline(&o_stack)); ++ make_int(iesp - 1, ref_stack_count_inline(&d_stack)); ++ make_op_estack(iesp, oparray_pop); ++ goto pr; ++ prst: /* Prepare to call the procedure (array) in *pvalue. */ ++ store_state(iesp); ++ pr: /* Call the array in *pvalue. State has been stored. */ ++ if ((icount = r_size(pvalue) - 1) <= 0) { ++ if (icount < 0) ++ goto up; /* 0-element proc */ ++ SET_IREF(pvalue->value.refs); /* 1-element proc */ ++ if (--ticks_left > 0) ++ goto top; ++ } ++ if (iesp >= estop) ++ return_with_error_iref(e_execstackoverflow); ++ ++iesp; ++ /* Do a ref_assign, but also set iref. */ ++ iesp->tas = pvalue->tas; ++ SET_IREF(iesp->value.refs = pvalue->value.refs); ++ if (--ticks_left > 0) ++ goto top; ++ goto slice; ++ case plain_exec(t_operator): ++ INCR(exec_operator); ++ if (--ticks_left <= 0) { /* The following doesn't work, */ ++ /* and I can't figure out why. */ + /****** goto sst; ******/ +- } +- esp = iesp; /* save for operator */ +- osp = iosp; /* ditto */ +- /* Operator routines take osp as an argument. */ +- /* This is just a convenience, since they adjust */ +- /* osp themselves to reflect the results. */ +- /* Operators that (net) push information on the */ +- /* operand stack must check for overflow: */ +- /* this normally happens automatically through */ +- /* the push macro (in oper.h). */ +- /* Operators that do not typecheck their operands, */ +- /* or take a variable number of arguments, */ +- /* must check explicitly for stack underflow. */ +- /* (See oper.h for more detail.) */ +- /* Note that each case must set iosp = osp: */ +- /* this is so we can switch on code without having to */ +- /* store it and reload it (for dumb compilers). */ +- switch (code = call_operator(real_opproc(IREF), i_ctx_p)) { +- case 0: /* normal case */ +- case 1: /* alternative success case */ +- iosp = osp; +- next(); +- case o_push_estack: /* store the state and go to up */ +- store_state(iesp); +- opush:iosp = osp; +- iesp = esp; +- if (--ticks_left > 0) +- goto up; +- goto slice; +- case o_pop_estack: /* just go to up */ +- opop:iosp = osp; +- if (esp == iesp) +- goto bot; +- iesp = esp; +- goto up; +- case o_reschedule: +- store_state(iesp); +- goto res; +- case e_RemapColor: +-oe_remap: store_state(iesp); +-remap: if (iesp + 2 >= estop) { +- esp = iesp; +- code = ref_stack_extend(&e_stack, 2); +- if (code < 0) +- return_with_error_iref(code); +- iesp = esp; +- } +- packed_get(imemory, iref_packed, iesp + 1); +- make_oper(iesp + 2, 0, +- r_ptr(&istate->remap_color_info, +- int_remap_color_info_t)->proc); +- iesp += 2; +- goto up; +- } +- iosp = osp; +- iesp = esp; +- return_with_code_iref(); +- case plain_exec(t_name): +- INCR(exec_name); +- pvalue = IREF->value.pname->pvalue; +- if (!pv_valid(pvalue)) { +- uint nidx = names_index(int_nt, IREF); +- uint htemp; +- +- INCR(find_name); +- if ((pvalue = dict_find_name_by_index_inline(nidx, htemp)) == 0) +- return_with_error_iref(e_undefined); +- } +- /* Dispatch on the type of the value. */ +- /* Again, we have to over-populate the switch. */ +- switch (r_type_xe(pvalue)) { +- cases_invalid(): +- return_with_error_iref(e_Fatal); +- cases_nox(): /* access errors */ +- return_with_error_iref(e_invalidaccess); +- cases_lit_1(): +- cases_lit_2(): +- cases_lit_3(): +- cases_lit_4(): +- cases_lit_5(): +- INCR(name_lit); +- /* Just push the value */ +- if (iosp >= ostop) +- return_with_stackoverflow(pvalue); +- ++iosp; +- ref_assign_inline(iosp, pvalue); +- next(); +- case exec(t_array): +- case exec(t_mixedarray): +- case exec(t_shortarray): +- INCR(name_proc); +- /* This is an executable procedure, execute it. */ +- goto prst; +- case plain_exec(tx_op_add): +- goto x_add; +- case plain_exec(tx_op_def): +- goto x_def; +- case plain_exec(tx_op_dup): +- goto x_dup; +- case plain_exec(tx_op_exch): +- goto x_exch; +- case plain_exec(tx_op_if): +- goto x_if; +- case plain_exec(tx_op_ifelse): +- goto x_ifelse; +- case plain_exec(tx_op_index): +- goto x_index; +- case plain_exec(tx_op_pop): +- goto x_pop; +- case plain_exec(tx_op_roll): +- goto x_roll; +- case plain_exec(tx_op_sub): +- goto x_sub; +- case plain_exec(t_null): +- goto bot; +- case plain_exec(t_oparray): +- INCR(name_oparray); +- opindex = op_index(pvalue); +- pvalue = (const ref *)pvalue->value.const_refs; +- goto opst; +- case plain_exec(t_operator): +- INCR(name_operator); +- { /* Shortcut for operators. */ +- /* See above for the logic. */ +- if (--ticks_left <= 0) { /* The following doesn't work, */ +- /* and I can't figure out why. */ ++ } ++ esp = iesp; /* save for operator */ ++ osp = iosp; /* ditto */ ++ /* Operator routines take osp as an argument. */ ++ /* This is just a convenience, since they adjust */ ++ /* osp themselves to reflect the results. */ ++ /* Operators that (net) push information on the */ ++ /* operand stack must check for overflow: */ ++ /* this normally happens automatically through */ ++ /* the push macro (in oper.h). */ ++ /* Operators that do not typecheck their operands, */ ++ /* or take a variable number of arguments, */ ++ /* must check explicitly for stack underflow. */ ++ /* (See oper.h for more detail.) */ ++ /* Note that each case must set iosp = osp: */ ++ /* this is so we can switch on code without having to */ ++ /* store it and reload it (for dumb compilers). */ ++ switch (code = call_operator(real_opproc(IREF), i_ctx_p)) { ++ case 0: /* normal case */ ++ case 1: /* alternative success case */ ++ iosp = osp; ++ next(); ++ case o_push_estack: /* store the state and go to up */ ++ store_state(iesp); ++ opush:iosp = osp; ++ iesp = esp; ++ if (--ticks_left > 0) ++ goto up; ++ goto slice; ++ case o_pop_estack: /* just go to up */ ++ opop:iosp = osp; ++ if (esp == iesp) ++ goto bot; ++ iesp = esp; ++ goto up; ++ case o_reschedule: ++ store_state(iesp); ++ goto res; ++ case e_RemapColor: ++oe_remap: store_state(iesp); ++remap: if (iesp + 2 >= estop) { ++ esp = iesp; ++ code = ref_stack_extend(&e_stack, 2); ++ if (code < 0) ++ return_with_error_iref(code); ++ iesp = esp; ++ } ++ packed_get(imemory, iref_packed, iesp + 1); ++ make_oper(iesp + 2, 0, ++ r_ptr(&istate->remap_color_info, ++ int_remap_color_info_t)->proc); ++ iesp += 2; ++ goto up; ++ } ++ iosp = osp; ++ iesp = esp; ++ return_with_code_iref(); ++ case plain_exec(t_name): ++ INCR(exec_name); ++ pvalue = IREF->value.pname->pvalue; ++ if (!pv_valid(pvalue)) { ++ uint nidx = names_index(int_nt, IREF); ++ uint htemp; ++ ++ INCR(find_name); ++ if ((pvalue = dict_find_name_by_index_inline(nidx, htemp)) == 0) ++ return_with_error_iref(e_undefined); ++ } ++ /* Dispatch on the type of the value. */ ++ /* Again, we have to over-populate the switch. */ ++ switch (r_type_xe(pvalue)) { ++ cases_invalid(): ++ return_with_error_iref(e_Fatal); ++ cases_nox(): /* access errors */ ++ return_with_error_iref(e_invalidaccess); ++ cases_lit_1(): ++ cases_lit_2(): ++ cases_lit_3(): ++ cases_lit_4(): ++ cases_lit_5(): ++ INCR(name_lit); ++ /* Just push the value */ ++ if (iosp >= ostop) ++ return_with_stackoverflow(pvalue); ++ ++iosp; ++ ref_assign_inline(iosp, pvalue); ++ next(); ++ case exec(t_array): ++ case exec(t_mixedarray): ++ case exec(t_shortarray): ++ INCR(name_proc); ++ /* This is an executable procedure, execute it. */ ++ goto prst; ++ case plain_exec(tx_op_add): ++ goto x_add; ++ case plain_exec(tx_op_def): ++ goto x_def; ++ case plain_exec(tx_op_dup): ++ goto x_dup; ++ case plain_exec(tx_op_exch): ++ goto x_exch; ++ case plain_exec(tx_op_if): ++ goto x_if; ++ case plain_exec(tx_op_ifelse): ++ goto x_ifelse; ++ case plain_exec(tx_op_index): ++ goto x_index; ++ case plain_exec(tx_op_pop): ++ goto x_pop; ++ case plain_exec(tx_op_roll): ++ goto x_roll; ++ case plain_exec(tx_op_sub): ++ goto x_sub; ++ case plain_exec(t_null): ++ goto bot; ++ case plain_exec(t_oparray): ++ INCR(name_oparray); ++ opindex = op_index(pvalue); ++ pvalue = (const ref *)pvalue->value.const_refs; ++ goto opst; ++ case plain_exec(t_operator): ++ INCR(name_operator); ++ { /* Shortcut for operators. */ ++ /* See above for the logic. */ ++ if (--ticks_left <= 0) { /* The following doesn't work, */ ++ /* and I can't figure out why. */ + /****** goto sst; ******/ +- } +- esp = iesp; +- osp = iosp; +- switch (code = call_operator(real_opproc(pvalue), +- i_ctx_p) +- ) { +- case 0: /* normal case */ +- case 1: /* alternative success case */ +- iosp = osp; +- next(); +- case o_push_estack: +- store_state(iesp); +- goto opush; +- case o_pop_estack: +- goto opop; +- case o_reschedule: +- store_state(iesp); +- goto res; +- case e_RemapColor: +- goto oe_remap; +- } +- iosp = osp; +- iesp = esp; +- return_with_error(code, pvalue); +- } +- case plain_exec(t_name): +- case exec(t_file): +- case exec(t_string): +- default: +- /* Not a procedure, reinterpret it. */ +- store_state(iesp); +- icount = 0; +- SET_IREF(pvalue); +- goto top; +- } +- case exec(t_file): +- { /* Executable file. Read the next token and interpret it. */ +- stream *s; +- scanner_state sstate; +- +- check_read_known_file(i_ctx_p, s, IREF, return_with_error_iref); +- rt: +- if (iosp >= ostop) /* check early */ +- return_with_stackoverflow_iref(); +- osp = iosp; /* scan_token uses ostack */ +- scanner_init_options(&sstate, IREF, i_ctx_p->scanner_options); +- again: +- code = scan_token(i_ctx_p, &token, &sstate); +- iosp = osp; /* ditto */ +- switch (code) { +- case 0: /* read a token */ +- /* It's worth checking for literals, which make up */ +- /* the majority of input tokens, before storing the */ +- /* state on the e-stack. Note that because of //, */ +- /* the token may have *any* type and attributes. */ +- /* Note also that executable arrays aren't executed */ +- /* at the top level -- they're treated as literals. */ +- if (!r_has_attr(&token, a_executable) || +- r_is_array(&token) +- ) { /* If scan_token used the o-stack, */ +- /* we know we can do a push now; if not, */ +- /* the pre-check is still valid. */ +- iosp++; +- ref_assign_inline(iosp, &token); +- goto rt; +- } +- store_state(iesp); +- /* Push the file on the e-stack */ +- if (iesp >= estop) +- return_with_error_iref(e_execstackoverflow); +- esfile_set_cache(++iesp); +- ref_assign_inline(iesp, IREF); +- SET_IREF(&token); +- icount = 0; +- goto top; +- case e_undefined: /* //name undefined */ +- scanner_error_object(i_ctx_p, &sstate, &token); +- return_with_error(code, &token); +- case scan_EOF: /* end of file */ +- esfile_clear_cache(); +- goto bot; +- case scan_BOS: +- /* Binary object sequences */ +- /* ARE executed at the top level. */ +- store_state(iesp); +- /* Push the file on the e-stack */ +- if (iesp >= estop) +- return_with_error_iref(e_execstackoverflow); +- esfile_set_cache(++iesp); +- ref_assign_inline(iesp, IREF); +- pvalue = &token; +- goto pr; +- case scan_Refill: +- store_state(iesp); +- /* iref may point into the exec stack; */ +- /* save its referent now. */ +- ref_assign_inline(&token, IREF); +- /* Push the file on the e-stack */ +- if (iesp >= estop) +- return_with_error_iref(e_execstackoverflow); +- ++iesp; +- ref_assign_inline(iesp, &token); +- esp = iesp; +- osp = iosp; +- code = scan_handle_refill(i_ctx_p, &sstate, true, +- ztokenexec_continue); +- scan_cont: +- iosp = osp; +- iesp = esp; +- switch (code) { +- case 0: +- iesp--; /* don't push the file */ +- goto again; /* stacks are unchanged */ +- case o_push_estack: +- esfile_clear_cache(); +- if (--ticks_left > 0) +- goto up; +- goto slice; +- } +- /* must be an error */ +- iesp--; /* don't push the file */ +- return_with_code_iref(); +- case scan_Comment: +- case scan_DSC_Comment: { +- /* See scan_Refill above for comments. */ +- ref file_token; +- +- store_state(iesp); +- ref_assign_inline(&file_token, IREF); +- if (iesp >= estop) +- return_with_error_iref(e_execstackoverflow); +- ++iesp; +- ref_assign_inline(iesp, &file_token); +- esp = iesp; +- osp = iosp; +- code = ztoken_handle_comment(i_ctx_p, +- &sstate, &token, +- code, true, true, +- ztokenexec_continue); +- } +- goto scan_cont; +- default: /* error */ +- ref_assign_inline(&token, IREF); +- scanner_error_object(i_ctx_p, &sstate, &token); +- return_with_error(code, &token); +- } +- } +- case exec(t_string): +- { /* Executable string. Read a token and interpret it. */ +- stream ss; +- scanner_state sstate; +- +- s_init(&ss, NULL); +- sread_string(&ss, IREF->value.bytes, r_size(IREF)); +- scanner_init_stream_options(&sstate, &ss, SCAN_FROM_STRING); +- osp = iosp; /* scan_token uses ostack */ +- code = scan_token(i_ctx_p, &token, &sstate); +- iosp = osp; /* ditto */ +- switch (code) { +- case 0: /* read a token */ +- case scan_BOS: /* binary object sequence */ +- store_state(iesp); +- /* If the updated string isn't empty, push it back */ +- /* on the e-stack. */ +- { +- uint size = sbufavailable(&ss); +- +- if (size) { +- if (iesp >= estop) +- return_with_error_iref(e_execstackoverflow); +- ++iesp; +- iesp->tas.type_attrs = IREF->tas.type_attrs; +- iesp->value.const_bytes = sbufptr(&ss); +- r_set_size(iesp, size); +- } +- } +- if (code == 0) { +- SET_IREF(&token); +- icount = 0; +- goto top; +- } +- /* Handle BOS specially */ +- pvalue = &token; +- goto pr; +- case scan_EOF: /* end of string */ +- goto bot; +- case scan_Refill: /* error */ +- code = gs_note_error(e_syntaxerror); +- default: /* error */ +- ref_assign_inline(&token, IREF); +- scanner_error_object(i_ctx_p, &sstate, &token); +- return_with_error(code, &token); +- } +- } +- /* Handle packed arrays here by re-dispatching. */ +- /* This also picks up some anomalous cases of non-packed arrays. */ +- default: +- { +- uint index; +- +- switch (*iref_packed >> r_packed_type_shift) { +- case pt_full_ref: +- case pt_full_ref + 1: +- INCR(p_full); +- if (iosp >= ostop) +- return_with_stackoverflow_iref(); +- /* We know this can't be an executable object */ +- /* requiring special handling, so we just push it. */ +- ++iosp; +- /* We know that refs are properly aligned: */ +- /* see packed.h for details. */ +- ref_assign_inline(iosp, IREF); +- next(); +- case pt_executable_operator: +- index = *iref_packed & packed_value_mask; +- if (--ticks_left <= 0) { /* The following doesn't work, */ +- /* and I can't figure out why. */ ++ } ++ esp = iesp; ++ osp = iosp; ++ switch (code = call_operator(real_opproc(pvalue), ++ i_ctx_p) ++ ) { ++ case 0: /* normal case */ ++ case 1: /* alternative success case */ ++ iosp = osp; ++ next(); ++ case o_push_estack: ++ store_state(iesp); ++ goto opush; ++ case o_pop_estack: ++ goto opop; ++ case o_reschedule: ++ store_state(iesp); ++ goto res; ++ case e_RemapColor: ++ goto oe_remap; ++ } ++ iosp = osp; ++ iesp = esp; ++ return_with_error(code, pvalue); ++ } ++ case plain_exec(t_name): ++ case exec(t_file): ++ case exec(t_string): ++ default: ++ /* Not a procedure, reinterpret it. */ ++ store_state(iesp); ++ icount = 0; ++ SET_IREF(pvalue); ++ goto top; ++ } ++ case exec(t_file): ++ { /* Executable file. Read the next token and interpret it. */ ++ stream *s; ++ scanner_state sstate; ++ ++ check_read_known_file(i_ctx_p, s, IREF, return_with_error_iref); ++ rt: ++ if (iosp >= ostop) /* check early */ ++ return_with_stackoverflow_iref(); ++ osp = iosp; /* gs_scan_token uses ostack */ ++ gs_scanner_init_options(&sstate, IREF, i_ctx_p->scanner_options); ++ again: ++ code = gs_scan_token(i_ctx_p, &token, &sstate); ++ iosp = osp; /* ditto */ ++ switch (code) { ++ case 0: /* read a token */ ++ /* It's worth checking for literals, which make up */ ++ /* the majority of input tokens, before storing the */ ++ /* state on the e-stack. Note that because of //, */ ++ /* the token may have *any* type and attributes. */ ++ /* Note also that executable arrays aren't executed */ ++ /* at the top level -- they're treated as literals. */ ++ if (!r_has_attr(&token, a_executable) || ++ r_is_array(&token) ++ ) { /* If gs_scan_token used the o-stack, */ ++ /* we know we can do a push now; if not, */ ++ /* the pre-check is still valid. */ ++ iosp++; ++ ref_assign_inline(iosp, &token); ++ goto rt; ++ } ++ store_state(iesp); ++ /* Push the file on the e-stack */ ++ if (iesp >= estop) ++ return_with_error_iref(e_execstackoverflow); ++ esfile_set_cache(++iesp); ++ ref_assign_inline(iesp, IREF); ++ SET_IREF(&token); ++ icount = 0; ++ goto top; ++ case e_undefined: /* //name undefined */ ++ gs_scanner_error_object(i_ctx_p, &sstate, &token); ++ return_with_error(code, &token); ++ case scan_EOF: /* end of file */ ++ esfile_clear_cache(); ++ goto bot; ++ case scan_BOS: ++ /* Binary object sequences */ ++ /* ARE executed at the top level. */ ++ store_state(iesp); ++ /* Push the file on the e-stack */ ++ if (iesp >= estop) ++ return_with_error_iref(e_execstackoverflow); ++ esfile_set_cache(++iesp); ++ ref_assign_inline(iesp, IREF); ++ pvalue = &token; ++ goto pr; ++ case scan_Refill: ++ store_state(iesp); ++ /* iref may point into the exec stack; */ ++ /* save its referent now. */ ++ ref_assign_inline(&token, IREF); ++ /* Push the file on the e-stack */ ++ if (iesp >= estop) ++ return_with_error_iref(e_execstackoverflow); ++ ++iesp; ++ ref_assign_inline(iesp, &token); ++ esp = iesp; ++ osp = iosp; ++ code = gs_scan_handle_refill(i_ctx_p, &sstate, true, ++ ztokenexec_continue); ++ scan_cont: ++ iosp = osp; ++ iesp = esp; ++ switch (code) { ++ case 0: ++ iesp--; /* don't push the file */ ++ goto again; /* stacks are unchanged */ ++ case o_push_estack: ++ esfile_clear_cache(); ++ if (--ticks_left > 0) ++ goto up; ++ goto slice; ++ } ++ /* must be an error */ ++ iesp--; /* don't push the file */ ++ return_with_code_iref(); ++ case scan_Comment: ++ case scan_DSC_Comment: { ++ /* See scan_Refill above for comments. */ ++ ref file_token; ++ ++ store_state(iesp); ++ ref_assign_inline(&file_token, IREF); ++ if (iesp >= estop) ++ return_with_error_iref(e_execstackoverflow); ++ ++iesp; ++ ref_assign_inline(iesp, &file_token); ++ esp = iesp; ++ osp = iosp; ++ code = ztoken_handle_comment(i_ctx_p, ++ &sstate, &token, ++ code, true, true, ++ ztokenexec_continue); ++ } ++ goto scan_cont; ++ default: /* error */ ++ ref_assign_inline(&token, IREF); ++ gs_scanner_error_object(i_ctx_p, &sstate, &token); ++ return_with_error(code, &token); ++ } ++ } ++ case exec(t_string): ++ { /* Executable string. Read a token and interpret it. */ ++ stream ss; ++ scanner_state sstate; ++ ++ s_init(&ss, NULL); ++ sread_string(&ss, IREF->value.bytes, r_size(IREF)); ++ gs_scanner_init_stream_options(&sstate, &ss, SCAN_FROM_STRING); ++ osp = iosp; /* gs_scan_token uses ostack */ ++ code = gs_scan_token(i_ctx_p, &token, &sstate); ++ iosp = osp; /* ditto */ ++ switch (code) { ++ case 0: /* read a token */ ++ case scan_BOS: /* binary object sequence */ ++ store_state(iesp); ++ /* If the updated string isn't empty, push it back */ ++ /* on the e-stack. */ ++ { ++ uint size = sbufavailable(&ss); ++ ++ if (size) { ++ if (iesp >= estop) ++ return_with_error_iref(e_execstackoverflow); ++ ++iesp; ++ iesp->tas.type_attrs = IREF->tas.type_attrs; ++ iesp->value.const_bytes = sbufptr(&ss); ++ r_set_size(iesp, size); ++ } ++ } ++ if (code == 0) { ++ SET_IREF(&token); ++ icount = 0; ++ goto top; ++ } ++ /* Handle BOS specially */ ++ pvalue = &token; ++ goto pr; ++ case scan_EOF: /* end of string */ ++ goto bot; ++ case scan_Refill: /* error */ ++ code = gs_note_error(e_syntaxerror); ++ default: /* error */ ++ ref_assign_inline(&token, IREF); ++ gs_scanner_error_object(i_ctx_p, &sstate, &token); ++ return_with_error(code, &token); ++ } ++ } ++ /* Handle packed arrays here by re-dispatching. */ ++ /* This also picks up some anomalous cases of non-packed arrays. */ ++ default: ++ { ++ uint index; ++ ++ switch (*iref_packed >> r_packed_type_shift) { ++ case pt_full_ref: ++ case pt_full_ref + 1: ++ INCR(p_full); ++ if (iosp >= ostop) ++ return_with_stackoverflow_iref(); ++ /* We know this can't be an executable object */ ++ /* requiring special handling, so we just push it. */ ++ ++iosp; ++ /* We know that refs are properly aligned: */ ++ /* see packed.h for details. */ ++ ref_assign_inline(iosp, IREF); ++ next(); ++ case pt_executable_operator: ++ index = *iref_packed & packed_value_mask; ++ if (--ticks_left <= 0) { /* The following doesn't work, */ ++ /* and I can't figure out why. */ + /****** goto sst_short; ******/ +- } +- if (!op_index_is_operator(index)) { +- INCR(p_exec_oparray); +- store_state_short(iesp); +- opindex = index; +- /* Call the operator procedure. */ +- index -= op_def_count; +- pvalue = (const ref *) +- (index < r_size(&i_ctx_p->op_array_table_global.table) ? +- i_ctx_p->op_array_table_global.table.value.const_refs + +- index : +- i_ctx_p->op_array_table_local.table.value.const_refs + +- (index - r_size(&i_ctx_p->op_array_table_global.table))); +- goto oppr; +- } +- INCR(p_exec_operator); +- /* See the main plain_exec(t_operator) case */ +- /* for details of what happens here. */ ++ } ++ if (!op_index_is_operator(index)) { ++ INCR(p_exec_oparray); ++ store_state_short(iesp); ++ opindex = index; ++ /* Call the operator procedure. */ ++ index -= op_def_count; ++ pvalue = (const ref *) ++ (index < r_size(&i_ctx_p->op_array_table_global.table) ? ++ i_ctx_p->op_array_table_global.table.value.const_refs + ++ index : ++ i_ctx_p->op_array_table_local.table.value.const_refs + ++ (index - r_size(&i_ctx_p->op_array_table_global.table))); ++ goto oppr; ++ } ++ INCR(p_exec_operator); ++ /* See the main plain_exec(t_operator) case */ ++ /* for details of what happens here. */ + #if PACKED_SPECIAL_OPS +- /* +- * We arranged in iinit.c that the special ops +- * have operator indices starting at 1. +- * +- * The (int) cast in the next line is required +- * because some compilers don't allow arithmetic +- * involving two different enumerated types. +- */ ++ /* ++ * We arranged in iinit.c that the special ops ++ * have operator indices starting at 1. ++ * ++ * The (int) cast in the next line is required ++ * because some compilers don't allow arithmetic ++ * involving two different enumerated types. ++ */ + # define case_xop(xop) case xop - (int)tx_op + 1 +- switch (index) { +- case_xop(tx_op_add):goto x_add; +- case_xop(tx_op_def):goto x_def; +- case_xop(tx_op_dup):goto x_dup; +- case_xop(tx_op_exch):goto x_exch; +- case_xop(tx_op_if):goto x_if; +- case_xop(tx_op_ifelse):goto x_ifelse; +- case_xop(tx_op_index):goto x_index; +- case_xop(tx_op_pop):goto x_pop; +- case_xop(tx_op_roll):goto x_roll; +- case_xop(tx_op_sub):goto x_sub; +- case 0: /* for dumb compilers */ +- default: +- ; +- } ++ switch (index) { ++ case_xop(tx_op_add):goto x_add; ++ case_xop(tx_op_def):goto x_def; ++ case_xop(tx_op_dup):goto x_dup; ++ case_xop(tx_op_exch):goto x_exch; ++ case_xop(tx_op_if):goto x_if; ++ case_xop(tx_op_ifelse):goto x_ifelse; ++ case_xop(tx_op_index):goto x_index; ++ case_xop(tx_op_pop):goto x_pop; ++ case_xop(tx_op_roll):goto x_roll; ++ case_xop(tx_op_sub):goto x_sub; ++ case 0: /* for dumb compilers */ ++ default: ++ ; ++ } + # undef case_xop + #endif +- INCR(p_exec_non_x_operator); +- esp = iesp; +- osp = iosp; +- switch (code = call_operator(op_index_proc(index), i_ctx_p)) { +- case 0: +- case 1: +- iosp = osp; +- next_short(); +- case o_push_estack: +- store_state_short(iesp); +- goto opush; +- case o_pop_estack: +- iosp = osp; +- if (esp == iesp) { +- next_short(); +- } +- iesp = esp; +- goto up; +- case o_reschedule: +- store_state_short(iesp); +- goto res; +- case e_RemapColor: +- store_state_short(iesp); +- goto remap; +- } +- iosp = osp; +- iesp = esp; +- return_with_code_iref(); +- case pt_integer: +- INCR(p_integer); +- if (iosp >= ostop) +- return_with_stackoverflow_iref(); +- ++iosp; +- make_int(iosp, +- ((int)*iref_packed & packed_int_mask) + +- packed_min_intval); +- next_short(); +- case pt_literal_name: +- INCR(p_lit_name); +- { +- uint nidx = *iref_packed & packed_value_mask; +- +- if (iosp >= ostop) +- return_with_stackoverflow_iref(); +- ++iosp; +- name_index_ref_inline(int_nt, nidx, iosp); +- next_short(); +- } +- case pt_executable_name: +- INCR(p_exec_name); +- { +- uint nidx = *iref_packed & packed_value_mask; +- +- pvalue = name_index_ptr_inline(int_nt, nidx)->pvalue; +- if (!pv_valid(pvalue)) { +- uint htemp; +- +- INCR(p_find_name); +- if ((pvalue = dict_find_name_by_index_inline(nidx, htemp)) == 0) { +- names_index_ref(int_nt, nidx, &token); +- return_with_error(e_undefined, &token); +- } +- } +- if (r_has_masked_attrs(pvalue, a_execute, a_execute + a_executable)) { /* Literal, push it. */ +- INCR(p_name_lit); +- if (iosp >= ostop) +- return_with_stackoverflow_iref(); +- ++iosp; +- ref_assign_inline(iosp, pvalue); +- next_short(); +- } +- if (r_is_proc(pvalue)) { /* This is an executable procedure, */ +- /* execute it. */ +- INCR(p_name_proc); +- store_state_short(iesp); +- goto pr; +- } +- /* Not a literal or procedure, reinterpret it. */ +- store_state_short(iesp); +- icount = 0; +- SET_IREF(pvalue); +- goto top; +- } +- /* default can't happen here */ +- } +- } ++ INCR(p_exec_non_x_operator); ++ esp = iesp; ++ osp = iosp; ++ switch (code = call_operator(op_index_proc(index), i_ctx_p)) { ++ case 0: ++ case 1: ++ iosp = osp; ++ next_short(); ++ case o_push_estack: ++ store_state_short(iesp); ++ goto opush; ++ case o_pop_estack: ++ iosp = osp; ++ if (esp == iesp) { ++ next_short(); ++ } ++ iesp = esp; ++ goto up; ++ case o_reschedule: ++ store_state_short(iesp); ++ goto res; ++ case e_RemapColor: ++ store_state_short(iesp); ++ goto remap; ++ } ++ iosp = osp; ++ iesp = esp; ++ return_with_code_iref(); ++ case pt_integer: ++ INCR(p_integer); ++ if (iosp >= ostop) ++ return_with_stackoverflow_iref(); ++ ++iosp; ++ make_int(iosp, ++ ((int)*iref_packed & packed_int_mask) + ++ packed_min_intval); ++ next_short(); ++ case pt_literal_name: ++ INCR(p_lit_name); ++ { ++ uint nidx = *iref_packed & packed_value_mask; ++ ++ if (iosp >= ostop) ++ return_with_stackoverflow_iref(); ++ ++iosp; ++ name_index_ref_inline(int_nt, nidx, iosp); ++ next_short(); ++ } ++ case pt_executable_name: ++ INCR(p_exec_name); ++ { ++ uint nidx = *iref_packed & packed_value_mask; ++ ++ pvalue = name_index_ptr_inline(int_nt, nidx)->pvalue; ++ if (!pv_valid(pvalue)) { ++ uint htemp; ++ ++ INCR(p_find_name); ++ if ((pvalue = dict_find_name_by_index_inline(nidx, htemp)) == 0) { ++ names_index_ref(int_nt, nidx, &token); ++ return_with_error(e_undefined, &token); ++ } ++ } ++ if (r_has_masked_attrs(pvalue, a_execute, a_execute + a_executable)) { /* Literal, push it. */ ++ INCR(p_name_lit); ++ if (iosp >= ostop) ++ return_with_stackoverflow_iref(); ++ ++iosp; ++ ref_assign_inline(iosp, pvalue); ++ next_short(); ++ } ++ if (r_is_proc(pvalue)) { /* This is an executable procedure, */ ++ /* execute it. */ ++ INCR(p_name_proc); ++ store_state_short(iesp); ++ goto pr; ++ } ++ /* Not a literal or procedure, reinterpret it. */ ++ store_state_short(iesp); ++ icount = 0; ++ SET_IREF(pvalue); ++ goto top; ++ } ++ /* default can't happen here */ ++ } ++ } + } + /* Literal type, just push it. */ + if (iosp >= ostop) +- return_with_stackoverflow_iref(); ++ return_with_stackoverflow_iref(); + ++iosp; + ref_assign_inline(iosp, IREF); + bot:next(); +- out: /* At most 1 more token in the current procedure. */ ++ out: /* At most 1 more token in the current procedure. */ + /* (We already decremented icount.) */ + if (!icount) { +- /* Pop the execution stack for tail recursion. */ +- iesp--; +- iref_packed = IREF_NEXT(iref_packed); +- goto top; ++ /* Pop the execution stack for tail recursion. */ ++ iesp--; ++ iref_packed = IREF_NEXT(iref_packed); ++ goto top; + } + up:if (--ticks_left < 0) +- goto slice; ++ goto slice; + /* See if there is anything left on the execution stack. */ + if (!r_is_proc(iesp)) { +- SET_IREF(iesp--); +- icount = 0; +- goto top; ++ SET_IREF(iesp--); ++ icount = 0; ++ goto top; + } +- SET_IREF(iesp->value.refs); /* next element of array */ ++ SET_IREF(iesp->value.refs); /* next element of array */ + icount = r_size(iesp) - 1; +- if (icount <= 0) { /* <= 1 more elements */ +- iesp--; /* pop, or tail recursion */ +- if (icount < 0) +- goto up; ++ if (icount <= 0) { /* <= 1 more elements */ ++ iesp--; /* pop, or tail recursion */ ++ if (icount < 0) ++ goto up; + } + goto top; + res: +@@ -1643,46 +1643,46 @@ res: + *pi_ctx_p = i_ctx_p; + code = (*i_ctx_p->reschedule_proc)(pi_ctx_p); + i_ctx_p = *pi_ctx_p; +- sched: /* We've just called a scheduling procedure. */ ++ sched: /* We've just called a scheduling procedure. */ + /* The interpreter state is in memory; iref is not current. */ + if (code < 0) { +- set_error(code); +- /* +- * We need a real object to return as the error object. +- * (It only has to last long enough to store in +- * *perror_object.) +- */ +- make_null_proc(&ierror.full); +- SET_IREF(ierror.obj = &ierror.full); +- goto error_exit; ++ set_error(code); ++ /* ++ * We need a real object to return as the error object. ++ * (It only has to last long enough to store in ++ * *perror_object.) ++ */ ++ make_null_proc(&ierror.full); ++ SET_IREF(ierror.obj = &ierror.full); ++ goto error_exit; + } + /* Reload state information from memory. */ + iosp = osp; + iesp = esp; + goto up; +-#if 0 /****** ****** ***** */ +- sst: /* Time-slice, but push the current object first. */ ++#if 0 /****** ****** ***** */ ++ sst: /* Time-slice, but push the current object first. */ + store_state(iesp); + if (iesp >= estop) +- return_with_error_iref(e_execstackoverflow); ++ return_with_error_iref(e_execstackoverflow); + iesp++; + ref_assign_inline(iesp, iref); + #endif /****** ****** ***** */ +- slice: /* It's time to time-slice or garbage collect. */ ++ slice: /* It's time to time-slice or garbage collect. */ + /* iref is not live, so we don't need to do a store_state. */ + osp = iosp; + esp = iesp; + /* If ticks_left <= -100, we need to GC now. */ +- if (ticks_left <= -100) { /* We need to garbage collect now. */ +- *pi_ctx_p = i_ctx_p; +- code = interp_reclaim(pi_ctx_p, -1); +- i_ctx_p = *pi_ctx_p; ++ if (ticks_left <= -100) { /* We need to garbage collect now. */ ++ *pi_ctx_p = i_ctx_p; ++ code = interp_reclaim(pi_ctx_p, -1); ++ i_ctx_p = *pi_ctx_p; + } else if (i_ctx_p->time_slice_proc != NULL) { +- *pi_ctx_p = i_ctx_p; +- code = (*i_ctx_p->time_slice_proc)(pi_ctx_p); +- i_ctx_p = *pi_ctx_p; ++ *pi_ctx_p = i_ctx_p; ++ code = (*i_ctx_p->time_slice_proc)(pi_ctx_p); ++ i_ctx_p = *pi_ctx_p; + } else +- code = 0; ++ code = 0; + ticks_left = i_ctx_p->time_slice_ticks; + set_code_on_interrupt(imemory, &code); + goto sched; +@@ -1695,38 +1695,38 @@ res: + ierror.obj = IREF; + rwe: + if (!r_is_packed(iref_packed)) +- store_state(iesp); ++ store_state(iesp); + else { +- /* +- * We need a real object to return as the error object. +- * (It only has to last long enough to store in *perror_object.) +- */ +- packed_get(imemory, (const ref_packed *)ierror.obj, &ierror.full); +- store_state_short(iesp); +- if (IREF == ierror.obj) +- SET_IREF(&ierror.full); +- ierror.obj = &ierror.full; ++ /* ++ * We need a real object to return as the error object. ++ * (It only has to last long enough to store in *perror_object.) ++ */ ++ packed_get(imemory, (const ref_packed *)ierror.obj, &ierror.full); ++ store_state_short(iesp); ++ if (IREF == ierror.obj) ++ SET_IREF(&ierror.full); ++ ierror.obj = &ierror.full; + } + error_exit: +- if (ERROR_IS_INTERRUPT(ierror.code)) { /* We must push the current object being interpreted */ +- /* back on the e-stack so it will be re-executed. */ +- /* Currently, this is always an executable operator, */ +- /* but it might be something else someday if we check */ +- /* for interrupts in the interpreter loop itself. */ +- if (iesp >= estop) +- code = e_execstackoverflow; +- else { +- iesp++; +- ref_assign_inline(iesp, IREF); +- } ++ if (ERROR_IS_INTERRUPT(ierror.code)) { /* We must push the current object being interpreted */ ++ /* back on the e-stack so it will be re-executed. */ ++ /* Currently, this is always an executable operator, */ ++ /* but it might be something else someday if we check */ ++ /* for interrupts in the interpreter loop itself. */ ++ if (iesp >= estop) ++ code = e_execstackoverflow; ++ else { ++ iesp++; ++ ref_assign_inline(iesp, IREF); ++ } + } + esp = iesp; + osp = iosp; + ref_assign_inline(perror_object, ierror.obj); + #ifdef DEBUG + if (ierror.code == e_InterpreterExit) { +- /* Do not call gs_log_error to reduce the noise. */ +- return e_InterpreterExit; ++ /* Do not call gs_log_error to reduce the noise. */ ++ return e_InterpreterExit; + } + #endif + return gs_log_error(ierror.code, __FILE__, ierror.line); +@@ -1744,7 +1744,7 @@ oparray_pop(i_ctx_t *i_ctx_p) + /* This procedure is called only from pop_estack. */ + static int + oparray_cleanup(i_ctx_t *i_ctx_p) +-{ /* esp points just below the cleanup procedure. */ ++{ /* esp points just below the cleanup procedure. */ + es_ptr ep = esp; + uint ocount_old = (uint) ep[3].value.intval; + uint dcount_old = (uint) ep[4].value.intval; +@@ -1752,10 +1752,10 @@ oparray_cleanup(i_ctx_t *i_ctx_p) + uint dcount = ref_stack_count(&d_stack); + + if (ocount > ocount_old) +- ref_stack_pop(&o_stack, ocount - ocount_old); ++ ref_stack_pop(&o_stack, ocount - ocount_old); + if (dcount > dcount_old) { +- ref_stack_pop(&d_stack, dcount - dcount_old); +- dict_set_top(); ++ ref_stack_pop(&d_stack, dcount - dcount_old); ++ dict_set_top(); + } + return 0; + } +@@ -1775,11 +1775,11 @@ oparray_find(i_ctx_t *i_ctx_p) + ref *ep; + + for (i = 0; (ep = ref_stack_index(&e_stack, i)) != 0; ++i) { +- if (r_is_estack_mark(ep) && +- (ep->value.opproc == oparray_cleanup || +- ep->value.opproc == oparray_no_cleanup) +- ) +- return ep; ++ if (r_is_estack_mark(ep) && ++ (ep->value.opproc == oparray_cleanup || ++ ep->value.opproc == oparray_no_cleanup) ++ ) ++ return ep; + } + return 0; + } +@@ -1794,15 +1794,15 @@ zerrorexec(i_ctx_t *i_ctx_p) + int code; + + check_op(2); +- check_estack(4); /* mark/cleanup, errobj, pop, obj */ ++ check_estack(4); /* mark/cleanup, errobj, pop, obj */ + push_mark_estack(es_other, errorexec_cleanup); + *++esp = op[-1]; + push_op_estack(errorexec_pop); + code = zexec(i_ctx_p); + if (code >= 0) +- pop(1); ++ pop(1); + else +- esp -= 3; /* undo our additions to estack */ ++ esp -= 3; /* undo our additions to estack */ + return code; + } + +@@ -1817,12 +1817,12 @@ zfinderrorobject(i_ctx_t *i_ctx_p) + ref errobj; + + if (errorexec_find(i_ctx_p, &errobj)) { +- push(2); +- op[-1] = errobj; +- make_true(op); ++ push(2); ++ op[-1] = errobj; ++ make_true(op); + } else { +- push(1); +- make_false(op); ++ push(1); ++ make_false(op); + } + return 0; + } +@@ -1839,24 +1839,24 @@ errorexec_find(i_ctx_t *i_ctx_p, ref *pe + const ref *ep; + + for (i = 0; (ep = ref_stack_index(&e_stack, i)) != 0; ++i) { +- if (r_is_estack_mark(ep)) { +- if (ep->value.opproc == oparray_cleanup) { +- /* See oppr: above. */ +- uint opindex = (uint)ep[1].value.intval; +- if (opindex == 0) /* internal operator, ignore */ +- continue; +- op_index_ref(imemory, opindex, perror_object); +- return 1; +- } +- if (ep->value.opproc == oparray_no_cleanup) +- return 0; /* protection disabled */ +- if (ep->value.opproc == errorexec_cleanup) { +- if (r_has_type(ep + 1, t_null)) +- return 0; +- *perror_object = ep[1]; /* see .errorexec above */ +- return 1; +- } +- } ++ if (r_is_estack_mark(ep)) { ++ if (ep->value.opproc == oparray_cleanup) { ++ /* See oppr: above. */ ++ uint opindex = (uint)ep[1].value.intval; ++ if (opindex == 0) /* internal operator, ignore */ ++ continue; ++ op_index_ref(imemory, opindex, perror_object); ++ return 1; ++ } ++ if (ep->value.opproc == oparray_no_cleanup) ++ return 0; /* protection disabled */ ++ if (ep->value.opproc == errorexec_cleanup) { ++ if (r_has_type(ep + 1, t_null)) ++ return 0; ++ *perror_object = ep[1]; /* see .errorexec above */ ++ return 1; ++ } ++ } + } + return 0; + } +@@ -1886,9 +1886,9 @@ zsetstackprotect(i_ctx_t *i_ctx_p) + + check_type(*op, t_boolean); + if (ep == 0) +- return_error(e_rangecheck); ++ return_error(e_rangecheck); + ep->value.opproc = +- (op->value.boolval ? oparray_cleanup : oparray_no_cleanup); ++ (op->value.boolval ? oparray_cleanup : oparray_no_cleanup); + pop(1); + return 0; + } +@@ -1902,7 +1902,7 @@ zcurrentstackprotect(i_ctx_t *i_ctx_p) + ref *ep = oparray_find(i_ctx_p); + + if (ep == 0) +- return_error(e_rangecheck); ++ return_error(e_rangecheck); + push(1); + make_bool(op, ep->value.opproc == oparray_cleanup); + return 0; +diff -up ghostscript-9.00/psi/iscan.c.scan_token ghostscript-9.00/psi/iscan.c +--- ghostscript-9.00/psi/iscan.c.scan_token 2010-04-26 16:29:28.000000000 +0100 ++++ ghostscript-9.00/psi/iscan.c 2011-01-14 17:16:12.610867620 +0000 +@@ -1,6 +1,6 @@ + /* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. +- ++ + This software is provided AS-IS with no warranty, either express or + implied. + +@@ -18,25 +18,25 @@ + #include "string_.h" + #include "stream.h" + #include "ierrors.h" +-#include "btoken.h" /* for ref_binary_object_format */ +-#include "files.h" /* for fptr */ ++#include "btoken.h" /* for ref_binary_object_format */ ++#include "files.h" /* for fptr */ + #include "ialloc.h" +-#include "idict.h" /* for //name lookup */ +-#include "dstack.h" /* ditto */ ++#include "idict.h" /* for //name lookup */ ++#include "dstack.h" /* ditto */ + #include "ilevel.h" + #include "iname.h" + #include "ipacked.h" + #include "iparray.h" +-#include "strimpl.h" /* for string decoding */ +-#include "sa85d.h" /* ditto */ +-#include "sfilter.h" /* ditto */ +-#include "ostack.h" /* for accumulating proc bodies; */ +- /* must precede iscan.h */ +-#include "iscan.h" /* defines interface */ ++#include "strimpl.h" /* for string decoding */ ++#include "sa85d.h" /* ditto */ ++#include "sfilter.h" /* ditto */ ++#include "ostack.h" /* for accumulating proc bodies; */ ++ /* must precede iscan.h */ ++#include "iscan.h" /* defines interface */ + #include "iscanbin.h" + #include "iscannum.h" + #include "istream.h" +-#include "istruct.h" /* for RELOC_REF_VAR */ ++#include "istruct.h" /* for RELOC_REF_VAR */ + #include "iutil.h" + #include "ivmspace.h" + #include "store.h" +@@ -47,13 +47,13 @@ + + /* Procedure for handling DSC comments if desired. */ + /* Set at initialization if a DSC handling module is included. */ +-int (*scan_dsc_proc) (const byte *, uint) = NULL; ++int (*gs_scan_dsc_proc) (const byte *, uint) = NULL; + + /* Procedure for handling all comments if desired. */ + /* Set at initialization if a comment handling module is included. */ +-/* If both scan_comment_proc and scan_dsc_proc are set, */ ++/* If both gs_scan_comment_proc and gs_scan_dsc_proc are set, */ + /* scan_comment_proc is called only for non-DSC comments. */ +-int (*scan_comment_proc) (const byte *, uint) = NULL; ++int (*gs_scan_comment_proc) (const byte *, uint) = NULL; + + /* + * Level 2 includes some changes in the scanner: +@@ -63,7 +63,7 @@ int (*scan_comment_proc) (const byte *, + * - Character codes above 127 introduce binary objects. + * We explicitly enable or disable these changes here. + */ +-#define scan_enable_level2 level2_enabled /* from ilevel.h */ ++#define scan_enable_level2 level2_enabled /* from ilevel.h */ + + /* ------ Dynamic strings ------ */ + +@@ -82,7 +82,7 @@ static void + dynamic_free(da_ptr pda) + { + if (pda->is_dynamic) +- gs_free_string(pda->memory, pda->base, da_size(pda), "scanner"); ++ gs_free_string(pda->memory, pda->base, da_size(pda), "scanner"); + } + + /* Resize a dynamic string. */ +@@ -96,16 +96,16 @@ dynamic_resize(da_ptr pda, uint new_size + byte *base; + + if (pda->is_dynamic) { +- base = gs_resize_string(mem, pda->base, old_size, +- new_size, "scanner"); +- if (base == 0) +- return_error(e_VMerror); +- } else { /* switching from static to dynamic */ +- base = gs_alloc_string(mem, new_size, "scanner"); +- if (base == 0) +- return_error(e_VMerror); +- memcpy(base, pda->base, min(old_size, new_size)); +- pda->is_dynamic = true; ++ base = gs_resize_string(mem, pda->base, old_size, ++ new_size, "scanner"); ++ if (base == 0) ++ return_error(e_VMerror); ++ } else { /* switching from static to dynamic */ ++ base = gs_alloc_string(mem, new_size, "scanner"); ++ if (base == 0) ++ return_error(e_VMerror); ++ memcpy(base, pda->base, min(old_size, new_size)); ++ pda->is_dynamic = true; + } + pda->base = base; + pda->next = base + pos; +@@ -122,17 +122,17 @@ dynamic_grow(da_ptr pda, byte * next, ui + { + uint old_size = da_size(pda); + uint new_size = (old_size < 10 ? 20 : +- old_size >= (max_size >> 1) ? max_size : +- old_size << 1); ++ old_size >= (max_size >> 1) ? max_size : ++ old_size << 1); + int code; + + pda->next = next; + if (old_size >= max_size) +- return_error(e_limitcheck); ++ return_error(e_limitcheck); + while ((code = dynamic_resize(pda, new_size)) < 0 && +- new_size > old_size +- ) { /* Try trimming down the requested new size. */ +- new_size -= (new_size - old_size + 1) >> 1; ++ new_size > old_size ++ ) { /* Try trimming down the requested new size. */ ++ new_size -= (new_size - old_size + 1) >> 1; + } + return code; + } +@@ -145,11 +145,11 @@ dynamic_save(da_ptr pda) + if (!pda->is_dynamic && pda->base != pda->buf) { + int len = da_size(pda); + +- if (len > sizeof(pda->buf)) ++ if (len > sizeof(pda->buf)) + len = sizeof(pda->buf); + memcpy(pda->buf, pda->base, len); +- pda->next = pda->buf + len; +- pda->base = pda->buf; ++ pda->next = pda->buf + len; ++ pda->base = pda->buf; + } + } + +@@ -161,10 +161,10 @@ dynamic_make_string(i_ctx_t *i_ctx_p, re + int code = dynamic_resize(pda, size); + + if (code < 0) +- return code; ++ return code; + make_tasv_new(pref, t_string, +- a_all | imemory_space((gs_ref_memory_t *) pda->memory), +- size, bytes, pda->base); ++ a_all | imemory_space((gs_ref_memory_t *) pda->memory), ++ size, bytes, pda->base); + return 0; + } + +@@ -172,7 +172,7 @@ dynamic_make_string(i_ctx_t *i_ctx_p, re + + /* GC procedures */ + #define ssarray ssptr->s_ss.binary.bin_array +-static ++static + CLEAR_MARKS_PROC(scanner_clear_marks) + { + scanner_state *const ssptr = vptr; +@@ -181,7 +181,7 @@ CLEAR_MARKS_PROC(scanner_clear_marks) + r_clear_attrs(&ssarray, l_mark); + r_clear_attrs(&ssptr->s_error.object, l_mark); + } +-static ++static + ENUM_PTRS_WITH(scanner_enum_ptrs, scanner_state *ssptr) return 0; + case 0: + ENUM_RETURN_REF(&ssptr->s_file); +@@ -189,13 +189,13 @@ case 1: + ENUM_RETURN_REF(&ssptr->s_error.object); + case 2: + if (ssptr->s_scan_type == scanning_none || +- !ssptr->s_da.is_dynamic +- ) +- ENUM_RETURN(0); ++ !ssptr->s_da.is_dynamic ++ ) ++ ENUM_RETURN(0); + return ENUM_STRING2(ssptr->s_da.base, da_size(&ssptr->s_da)); + case 3: + if (ssptr->s_scan_type != scanning_binary) +- return 0; ++ return 0; + ENUM_RETURN_REF(&ssarray); + ENUM_PTRS_END + static RELOC_PTRS_WITH(scanner_reloc_ptrs, scanner_state *ssptr) +@@ -203,18 +203,18 @@ static RELOC_PTRS_WITH(scanner_reloc_ptr + RELOC_REF_VAR(ssptr->s_file); + r_clear_attrs(&ssptr->s_file, l_mark); + if (ssptr->s_scan_type != scanning_none && ssptr->s_da.is_dynamic) { +- gs_string sda; ++ gs_string sda; + +- sda.data = ssptr->s_da.base; +- sda.size = da_size(&ssptr->s_da); +- RELOC_STRING_VAR(sda); +- ssptr->s_da.limit = sda.data + sda.size; +- ssptr->s_da.next = sda.data + (ssptr->s_da.next - ssptr->s_da.base); +- ssptr->s_da.base = sda.data; ++ sda.data = ssptr->s_da.base; ++ sda.size = da_size(&ssptr->s_da); ++ RELOC_STRING_VAR(sda); ++ ssptr->s_da.limit = sda.data + sda.size; ++ ssptr->s_da.next = sda.data + (ssptr->s_da.next - ssptr->s_da.base); ++ ssptr->s_da.base = sda.data; + } + if (ssptr->s_scan_type == scanning_binary) { +- RELOC_REF_VAR(ssarray); +- r_clear_attrs(&ssarray, l_mark); ++ RELOC_REF_VAR(ssarray); ++ r_clear_attrs(&ssarray, l_mark); + } + RELOC_REF_VAR(ssptr->s_error.object); + r_clear_attrs(&ssptr->s_error.object, l_mark); +@@ -225,7 +225,7 @@ public_st_scanner_state_dynamic(); + + /* Initialize a scanner. */ + void +-scanner_init_options(scanner_state *sstate, const ref *fop, int options) ++gs_scanner_init_options(scanner_state *sstate, const ref *fop, int options) + { + ref_assign(&sstate->s_file, fop); + sstate->s_scan_type = scanning_none; +@@ -233,8 +233,8 @@ scanner_init_options(scanner_state *ssta + sstate->s_options = options; + SCAN_INIT_ERROR(sstate); + } +-void scanner_init_stream_options(scanner_state *sstate, stream *s, +- int options) ++void gs_scanner_init_stream_options(scanner_state *sstate, stream *s, ++ int options) + { + /* + * The file 'object' will never be accessed, but it must be in correct +@@ -243,7 +243,7 @@ void scanner_init_stream_options(scanner + ref fobj; + + make_file(&fobj, a_read, 0, s); +- scanner_init_options(sstate, &fobj, options); ++ gs_scanner_init_options(sstate, &fobj, options); + } + + /* +@@ -251,42 +251,42 @@ void scanner_init_stream_options(scanner + * --token--, if any, or <0 if no special error object is available. + */ + int +-scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate, +- ref *pseo) ++gs_scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate, ++ ref *pseo) + { + if (!r_has_type(&pstate->s_error.object, t__invalid)) { +- ref_assign(pseo, &pstate->s_error.object); +- return 0; ++ ref_assign(pseo, &pstate->s_error.object); ++ return 0; + } + if (pstate->s_error.string[0]) { +- int len = strlen(pstate->s_error.string); ++ int len = strlen(pstate->s_error.string); + +- if (pstate->s_error.is_name) { +- int code = name_ref(imemory, (const byte *)pstate->s_error.string, len, pseo, 1); ++ if (pstate->s_error.is_name) { ++ int code = name_ref(imemory, (const byte *)pstate->s_error.string, len, pseo, 1); + +- if (code < 0) +- return code; +- r_set_attrs(pseo, a_executable); /* Adobe compatibility */ +- return 0; +- } else { +- byte *estr = ialloc_string(len, "scanner_error_object"); +- +- if (estr == 0) +- return -1; /* VMerror */ +- memcpy(estr, (const byte *)pstate->s_error.string, len); +- make_string(pseo, a_all | icurrent_space, len, estr); +- return 0; +- } ++ if (code < 0) ++ return code; ++ r_set_attrs(pseo, a_executable); /* Adobe compatibility */ ++ return 0; ++ } else { ++ byte *estr = ialloc_string(len, "gs_scanner_error_object"); ++ ++ if (estr == 0) ++ return -1; /* VMerror */ ++ memcpy(estr, (const byte *)pstate->s_error.string, len); ++ make_string(pseo, a_all | icurrent_space, len, estr); ++ return 0; ++ } + } +- return -1; /* no error object */ ++ return -1; /* no error object */ + } + +-/* Handle a scan_Refill return from scan_token. */ +-/* This may return o_push_estack, 0 (meaning just call scan_token again), */ +-/* or an error code. */ ++/* Handle a scan_Refill return from gs_scan_token. */ ++/* This may return o_push_estack, 0 (meaning just call gs_scan_token */ ++/* again), or an error code. */ + int +-scan_handle_refill(i_ctx_t *i_ctx_p, scanner_state * sstate, +- bool save, op_proc_t cont) ++gs_scan_handle_refill(i_ctx_t *i_ctx_p, scanner_state * sstate, ++ bool save, op_proc_t cont) + { + const ref *const fop = &sstate->s_file; + stream *s = fptr(fop); +@@ -294,41 +294,41 @@ scan_handle_refill(i_ctx_t *i_ctx_p, sca + int status; + + if (s->end_status == EOFC) { +- /* More data needed, but none available, so this is a syntax error. */ +- return_error(e_syntaxerror); ++ /* More data needed, but none available, so this is a syntax error. */ ++ return_error(e_syntaxerror); + } + status = s_process_read_buf(s); + if (sbufavailable(s) > avail) +- return 0; ++ return 0; + if (status == 0) +- status = s->end_status; ++ status = s->end_status; + switch (status) { +- case EOFC: +- /* We just discovered that we're at EOF. */ +- /* Let the caller find this out. */ +- return 0; +- case ERRC: +- return_error(e_ioerror); +- case INTC: +- case CALLC: +- { +- ref rstate[1]; +- scanner_state *pstate; +- +- if (save) { +- pstate = (scanner_state *) +- ialloc_struct(scanner_state_dynamic, &st_scanner_state_dynamic, +- "scan_handle_refill"); +- if (pstate == 0) +- return_error(e_VMerror); +- ((scanner_state_dynamic *)pstate)->mem = imemory; +- *pstate = *sstate; +- } else +- pstate = sstate; +- make_istruct(&rstate[0], 0, pstate); +- return s_handle_read_exception(i_ctx_p, status, fop, +- rstate, 1, cont); +- } ++ case EOFC: ++ /* We just discovered that we're at EOF. */ ++ /* Let the caller find this out. */ ++ return 0; ++ case ERRC: ++ return_error(e_ioerror); ++ case INTC: ++ case CALLC: ++ { ++ ref rstate[1]; ++ scanner_state *pstate; ++ ++ if (save) { ++ pstate = (scanner_state *) ++ ialloc_struct(scanner_state_dynamic, &st_scanner_state_dynamic, ++ "gs_scan_handle_refill"); ++ if (pstate == 0) ++ return_error(e_VMerror); ++ ((scanner_state_dynamic *)pstate)->mem = imemory; ++ *pstate = *sstate; ++ } else ++ pstate = sstate; ++ make_istruct(&rstate[0], 0, pstate); ++ return s_handle_read_exception(i_ctx_p, status, fop, ++ rstate, 1, cont); ++ } + } + /* No more data available, but no exception. */ + /* A filter is consuming headers but returns nothing. */ +@@ -341,7 +341,7 @@ scan_handle_refill(i_ctx_t *i_ctx_p, sca + */ + static int + scan_comment(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate, +- const byte * base, const byte * end, bool saved) ++ const byte * base, const byte * end, bool saved) + { + uint len = (uint) (end - base); + int code; +@@ -350,50 +350,50 @@ scan_comment(i_ctx_t *i_ctx_p, ref *pref + #endif + + if (len > 1 && (base[1] == '%' || base[1] == '!')) { +- /* Process as a DSC comment if requested. */ ++ /* Process as a DSC comment if requested. */ + #ifdef DEBUG +- if (gs_debug_c('%')) { +- dlprintf2("[%%%%%s%c]", sstr, (len >= 3 ? '+' : '-')); +- debug_print_string(base, len); +- dputs("\n"); +- } ++ if (gs_debug_c('%')) { ++ dlprintf2("[%%%%%s%c]", sstr, (len >= 3 ? '+' : '-')); ++ debug_print_string(base, len); ++ dputs("\n"); ++ } + #endif +- if (scan_dsc_proc != NULL) { +- code = scan_dsc_proc(base, len); +- return (code < 0 ? code : 0); +- } +- if (pstate->s_options & SCAN_PROCESS_DSC_COMMENTS) { +- code = scan_DSC_Comment; +- goto comment; +- } +- /* Treat as an ordinary comment. */ ++ if (gs_scan_dsc_proc != NULL) { ++ code = gs_scan_dsc_proc(base, len); ++ return (code < 0 ? code : 0); ++ } ++ if (pstate->s_options & SCAN_PROCESS_DSC_COMMENTS) { ++ code = scan_DSC_Comment; ++ goto comment; ++ } ++ /* Treat as an ordinary comment. */ + } + #ifdef DEBUG + else { +- if (gs_debug_c('%')) { +- dlprintf2("[%% %s%c]", sstr, (len >= 2 ? '+' : '-')); +- debug_print_string(base, len); +- dputs("\n"); +- } ++ if (gs_debug_c('%')) { ++ dlprintf2("[%% %s%c]", sstr, (len >= 2 ? '+' : '-')); ++ debug_print_string(base, len); ++ dputs("\n"); ++ } + } + #endif +- if (scan_comment_proc != NULL) { +- code = scan_comment_proc(base, len); +- return (code < 0 ? code : 0); ++ if (gs_scan_comment_proc != NULL) { ++ code = gs_scan_comment_proc(base, len); ++ return (code < 0 ? code : 0); + } + if (pstate->s_options & SCAN_PROCESS_COMMENTS) { +- code = scan_Comment; +- goto comment; ++ code = scan_Comment; ++ goto comment; + } + return 0; + comment: + { +- byte *cstr = ialloc_string(len, "scan_comment"); ++ byte *cstr = ialloc_string(len, "scan_comment"); + +- if (cstr == 0) +- return_error(e_VMerror); +- memcpy(cstr, base, len); +- make_string(pref, a_all | icurrent_space, len, cstr); ++ if (cstr == 0) ++ return_error(e_VMerror); ++ memcpy(cstr, base, len); ++ make_string(pref, a_all | icurrent_space, len, cstr); + } + return code; + } +@@ -402,8 +402,8 @@ scan_comment(i_ctx_t *i_ctx_p, ref *pref + /* Update the string if succesful. */ + /* Store the error object in i_ctx_p->error_object if not. */ + int +-scan_string_token_options(i_ctx_t *i_ctx_p, ref * pstr, ref * pref, +- int options) ++gs_scan_string_token_options(i_ctx_t *i_ctx_p, ref * pstr, ref * pref, ++ int options) + { + stream st; + stream *s = &st; +@@ -411,31 +411,31 @@ scan_string_token_options(i_ctx_t *i_ctx + int code; + + if (!r_has_attr(pstr, a_read)) +- return_error(e_invalidaccess); ++ return_error(e_invalidaccess); + s_init(s, NULL); + sread_string(s, pstr->value.bytes, r_size(pstr)); +- scanner_init_stream_options(&state, s, options | SCAN_FROM_STRING); +- switch (code = scan_token(i_ctx_p, pref, &state)) { +- default: /* error or comment */ +- if (code < 0) +- break; +- /* falls through */ +- case 0: /* read a token */ +- case scan_BOS: +- { +- uint pos = stell(s); +- +- pstr->value.bytes += pos; +- r_dec_size(pstr, pos); +- } +- break; +- case scan_Refill: /* error */ +- code = gs_note_error(e_syntaxerror); +- case scan_EOF: +- break; ++ gs_scanner_init_stream_options(&state, s, options | SCAN_FROM_STRING); ++ switch (code = gs_scan_token(i_ctx_p, pref, &state)) { ++ default: /* error or comment */ ++ if (code < 0) ++ break; ++ /* falls through */ ++ case 0: /* read a token */ ++ case scan_BOS: ++ { ++ uint pos = stell(s); ++ ++ pstr->value.bytes += pos; ++ r_dec_size(pstr, pos); ++ } ++ break; ++ case scan_Refill: /* error */ ++ code = gs_note_error(e_syntaxerror); ++ case scan_EOF: ++ break; + } + if (code < 0) +- scanner_error_object(i_ctx_p, &state, &i_ctx_p->error_object); ++ gs_scanner_error_object(i_ctx_p, &state, &i_ctx_p->error_object); + return code; + } + +@@ -448,7 +448,7 @@ scan_string_token_options(i_ctx_t *i_ctx + * as well as for scan_Refill. + */ + int +-scan_token(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate) ++gs_scan_token(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate) + { + stream *const s = pstate->s_file.value.pfile; + ref *myref = pref; +@@ -474,7 +474,7 @@ scan_token(i_ctx_t *i_ctx_p, ref * pref, + if ( osp >= osbot ) osp--;\ + else ref_stack_pop(&o_stack, 1) + int max_name_ctype = +- (recognize_btokens()? ctype_name : ctype_btoken); ++ (recognize_btokens()? ctype_name : ctype_btoken); + + #define scan_sign(sign, ptr)\ + switch ( *ptr ) {\ +@@ -512,42 +512,42 @@ scan_token(i_ctx_t *i_ctx_p, ref * pref, + + sptr = endptr = NULL; /* Quiet compiler */ + if (pstate->s_pstack != 0) { +- if_not_spush1() +- return retcode; +- myref = osp; ++ if_not_spush1() ++ return retcode; ++ myref = osp; + } + /* Check whether we are resuming after an interruption. */ + if (pstate->s_scan_type != scanning_none) { +- sstate = *pstate; +- if (!da.is_dynamic && da.base != da.buf) { +- /* The da contains some self-referencing pointers. */ +- /* Fix them up now. */ +- uint next = da.next - da.base; +- uint limit = da.limit - da.base; +- +- da.base = da.buf; +- da.next = da.buf + next; +- da.limit = da.buf + limit; +- } +- daptr = da.next; +- switch (scan_type) { +- case scanning_binary: +- retcode = (*sstate.s_ss.binary.cont) +- (i_ctx_p, myref, &sstate); +- scan_begin_inline(); +- if (retcode == scan_Refill) +- goto pause; +- goto sret; +- case scanning_comment: +- scan_begin_inline(); +- goto cont_comment; +- case scanning_name: +- goto cont_name; +- case scanning_string: +- goto cont_string; +- default: +- return_error(e_Fatal); +- } ++ sstate = *pstate; ++ if (!da.is_dynamic && da.base != da.buf) { ++ /* The da contains some self-referencing pointers. */ ++ /* Fix them up now. */ ++ uint next = da.next - da.base; ++ uint limit = da.limit - da.base; ++ ++ da.base = da.buf; ++ da.next = da.buf + next; ++ da.limit = da.buf + limit; ++ } ++ daptr = da.next; ++ switch (scan_type) { ++ case scanning_binary: ++ retcode = (*sstate.s_ss.binary.cont) ++ (i_ctx_p, myref, &sstate); ++ scan_begin_inline(); ++ if (retcode == scan_Refill) ++ goto pause; ++ goto sret; ++ case scanning_comment: ++ scan_begin_inline(); ++ goto cont_comment; ++ case scanning_name: ++ goto cont_name; ++ case scanning_string: ++ goto cont_string; ++ default: ++ return_error(e_Fatal); ++ } + } + /* Fetch any state variables that are relevant even if */ + /* scan_type == scanning_none. */ +@@ -564,658 +564,658 @@ scan_token(i_ctx_t *i_ctx_p, ref * pref, + top:c = scan_getc(); + if_debug1('S', (c >= 32 && c <= 126 ? "`%c'" : c >= 0 ? "`\\%03o'" : "`%d'"), c); + switch (c) { +- case ' ': +- case '\f': +- case '\t': +- case char_CR: +- case char_EOL: +- case char_NULL: +- goto top; +- case 0x04: /* see ctrld above */ +- if (c == ctrld) /* treat as ordinary name char */ +- goto begin_name; +- case '[': +- case ']': +- s1[0] = (byte) c; +- retcode = name_ref(imemory, s1, 1, myref, 1); /* can't fail */ +- r_set_attrs(myref, a_executable); +- break; +- case '<': +- if (scan_enable_level2) { +- ensure2(scanning_none); +- c = scan_getc(); +- switch (c) { +- case '<': +- scan_putback(); +- name_type = 0; +- try_number = false; +- goto try_funny_name; +- case '~': +- s_A85D_init_inline(&sstate.s_ss.a85d); +- sstate.s_ss.st.template = &s_A85D_template; +- goto str; +- } +- scan_putback(); +- } +- s_AXD_init_inline(&sstate.s_ss.axd); +- sstate.s_ss.st.template = &s_AXD_template; +- str:scan_end_inline(); +- dynamic_init(&da, imemory); +- cont_string:for (;;) { +- stream_cursor_write w; +- +- w.ptr = da.next - 1; +- w.limit = da.limit - 1; +- status = (*sstate.s_ss.st.template->process) +- (&sstate.s_ss.st, &s->cursor.r, &w, +- s->end_status == EOFC); +- if (!check_only) +- da.next = w.ptr + 1; +- switch (status) { +- case 0: +- status = s->end_status; +- if (status < 0) { +- if (status == EOFC) { +- if (check_only) { +- retcode = scan_Refill; +- scan_type = scanning_string; +- goto suspend; +- } else +- sreturn(e_syntaxerror); +- } +- break; +- } +- s_process_read_buf(s); +- continue; +- case 1: +- if (!check_only) { +- retcode = dynamic_grow(&da, da.next, max_string_size); +- if (retcode == e_VMerror) { +- scan_type = scanning_string; +- goto suspend; +- } else if (retcode < 0) +- sreturn(retcode); +- } +- continue; +- } +- break; +- } +- scan_begin_inline(); +- switch (status) { +- default: +- /*case ERRC: */ +- sreturn(e_syntaxerror); +- case INTC: +- case CALLC: +- scan_type = scanning_string; +- goto pause; +- case EOFC: +- ; +- } +- retcode = dynamic_make_string(i_ctx_p, myref, &da, da.next); +- if (retcode < 0) { /* VMerror */ +- sputback(s); /* rescan ) */ +- scan_type = scanning_string; +- goto suspend; +- } +- break; +- case '(': +- sstate.s_ss.pssd.from_string = +- ((pstate->s_options & SCAN_FROM_STRING) != 0) && +- !scan_enable_level2; +- s_PSSD_partially_init_inline(&sstate.s_ss.pssd); +- sstate.s_ss.st.template = &s_PSSD_template; +- goto str; +- case '{': +- if (pstack == 0) { /* outermost procedure */ +- if_not_spush1() { +- scan_putback(); +- scan_type = scanning_none; +- goto pause_ret; +- } +- pdepth = ref_stack_count_inline(&o_stack); +- } +- make_int(osp, pstack); +- pstack = ref_stack_count_inline(&o_stack); +- if_debug3('S', "[S{]d=%d, s=%d->%d\n", +- pdepth, (int)osp->value.intval, pstack); +- goto snext; +- case '>': +- if (scan_enable_level2) { +- ensure2(scanning_none); +- name_type = 0; +- try_number = false; +- goto try_funny_name; +- } +- /* falls through */ +- case ')': +- sreturn(e_syntaxerror); +- case '}': +- if (pstack == 0) +- sreturn(e_syntaxerror); +- osp--; +- { +- uint size = ref_stack_count_inline(&o_stack) - pstack; +- ref arr; +- +- if_debug4('S', "[S}]d=%d, s=%d->%d, c=%d\n", +- pdepth, pstack, +- (pstack == pdepth ? 0 : +- ref_stack_index(&o_stack, size)->value.intval), +- size + pstack); +- myref = (pstack == pdepth ? pref : &arr); +- if (check_only) { +- make_empty_array(myref, 0); +- ref_stack_pop(&o_stack, size); +- } else if (ref_array_packing.value.boolval) { +- retcode = make_packed_array(myref, &o_stack, size, +- idmemory, "scanner(packed)"); +- if (retcode < 0) { /* must be VMerror */ +- osp++; +- scan_putback(); +- scan_type = scanning_none; +- goto pause_ret; +- } +- r_set_attrs(myref, a_executable); +- } else { +- retcode = ialloc_ref_array(myref, +- a_executable + a_all, size, +- "scanner(proc)"); +- if (retcode < 0) { /* must be VMerror */ +- osp++; +- scan_putback(); +- scan_type = scanning_none; +- goto pause_ret; +- } +- retcode = ref_stack_store(&o_stack, myref, size, 0, 1, +- false, idmemory, "scanner"); +- if (retcode < 0) { +- ifree_ref_array(myref, "scanner(proc)"); +- sreturn(retcode); +- } +- ref_stack_pop(&o_stack, size); +- } +- if (pstack == pdepth) { /* This was the top-level procedure. */ +- spop1(); +- pstack = 0; +- } else { +- if (osp < osbot) +- ref_stack_pop_block(&o_stack); +- pstack = osp->value.intval; +- *osp = arr; +- goto snext; +- } +- } +- break; +- case '/': +- /* +- * If the last thing in the input is a '/', don't try to read +- * any more data. +- */ +- if (sptr >= endptr && s->end_status != EOFC) { +- refill2(scanning_none); +- } +- c = scan_getc(); +- if (!PDFScanRules && (c == '/')) { +- name_type = 2; +- c = scan_getc(); +- } else +- name_type = 1; +- try_number = false; +- switch (decoder[c]) { +- case ctype_name: +- default: +- goto do_name; +- case ctype_btoken: +- if (!recognize_btokens()) +- goto do_name; +- /* otherwise, an empty name */ +- case ctype_exception: +- case ctype_space: +- /* +- * Amazingly enough, the Adobe implementations don't accept +- * / or // followed by [, ], <<, or >>, so we do the same. +- * (Older versions of our code had a ctype_other case here +- * that handled these specially.) +- */ +- case ctype_other: +- if (c == ctrld) /* see above */ +- goto do_name; +- da.base = da.limit = daptr = 0; +- da.is_dynamic = false; +- goto nx; +- } +- case '%': +- { /* Scan as much as possible within the buffer. */ +- const byte *base = sptr; +- const byte *end; +- +- while (++sptr < endptr) /* stop 1 char early */ +- switch (*sptr) { +- case char_CR: +- end = sptr; +- if (sptr[1] == char_EOL) +- sptr++; +- cend: /* Check for externally processed comments. */ +- retcode = scan_comment(i_ctx_p, myref, &sstate, +- base, end, false); +- if (retcode != 0) +- goto comment; +- goto top; +- case char_EOL: +- case '\f': +- end = sptr; +- goto cend; +- } +- /* +- * We got to the end of the buffer while inside a comment. +- * If there is a possibility that we must pass the comment +- * to an external procedure, move what we have collected +- * so far into a private buffer now. +- */ ++ case ' ': ++ case '\f': ++ case '\t': ++ case char_CR: ++ case char_EOL: ++ case char_NULL: ++ goto top; ++ case 0x04: /* see ctrld above */ ++ if (c == ctrld) /* treat as ordinary name char */ ++ goto begin_name; ++ case '[': ++ case ']': ++ s1[0] = (byte) c; ++ retcode = name_ref(imemory, s1, 1, myref, 1); /* can't fail */ ++ r_set_attrs(myref, a_executable); ++ break; ++ case '<': ++ if (scan_enable_level2) { ++ ensure2(scanning_none); ++ c = scan_getc(); ++ switch (c) { ++ case '<': ++ scan_putback(); ++ name_type = 0; ++ try_number = false; ++ goto try_funny_name; ++ case '~': ++ s_A85D_init_inline(&sstate.s_ss.a85d); ++ sstate.s_ss.st.template = &s_A85D_template; ++ goto str; ++ } ++ scan_putback(); ++ } ++ s_AXD_init_inline(&sstate.s_ss.axd); ++ sstate.s_ss.st.template = &s_AXD_template; ++ str:scan_end_inline(); ++ dynamic_init(&da, imemory); ++ cont_string:for (;;) { ++ stream_cursor_write w; ++ ++ w.ptr = da.next - 1; ++ w.limit = da.limit - 1; ++ status = (*sstate.s_ss.st.template->process) ++ (&sstate.s_ss.st, &s->cursor.r, &w, ++ s->end_status == EOFC); ++ if (!check_only) ++ da.next = w.ptr + 1; ++ switch (status) { ++ case 0: ++ status = s->end_status; ++ if (status < 0) { ++ if (status == EOFC) { ++ if (check_only) { ++ retcode = scan_Refill; ++ scan_type = scanning_string; ++ goto suspend; ++ } else ++ sreturn(e_syntaxerror); ++ } ++ break; ++ } ++ s_process_read_buf(s); ++ continue; ++ case 1: ++ if (!check_only) { ++ retcode = dynamic_grow(&da, da.next, max_string_size); ++ if (retcode == e_VMerror) { ++ scan_type = scanning_string; ++ goto suspend; ++ } else if (retcode < 0) ++ sreturn(retcode); ++ } ++ continue; ++ } ++ break; ++ } ++ scan_begin_inline(); ++ switch (status) { ++ default: ++ /*case ERRC: */ ++ sreturn(e_syntaxerror); ++ case INTC: ++ case CALLC: ++ scan_type = scanning_string; ++ goto pause; ++ case EOFC: ++ ; ++ } ++ retcode = dynamic_make_string(i_ctx_p, myref, &da, da.next); ++ if (retcode < 0) { /* VMerror */ ++ sputback(s); /* rescan ) */ ++ scan_type = scanning_string; ++ goto suspend; ++ } ++ break; ++ case '(': ++ sstate.s_ss.pssd.from_string = ++ ((pstate->s_options & SCAN_FROM_STRING) != 0) && ++ !scan_enable_level2; ++ s_PSSD_partially_init_inline(&sstate.s_ss.pssd); ++ sstate.s_ss.st.template = &s_PSSD_template; ++ goto str; ++ case '{': ++ if (pstack == 0) { /* outermost procedure */ ++ if_not_spush1() { ++ scan_putback(); ++ scan_type = scanning_none; ++ goto pause_ret; ++ } ++ pdepth = ref_stack_count_inline(&o_stack); ++ } ++ make_int(osp, pstack); ++ pstack = ref_stack_count_inline(&o_stack); ++ if_debug3('S', "[S{]d=%d, s=%d->%d\n", ++ pdepth, (int)osp->value.intval, pstack); ++ goto snext; ++ case '>': ++ if (scan_enable_level2) { ++ ensure2(scanning_none); ++ name_type = 0; ++ try_number = false; ++ goto try_funny_name; ++ } ++ /* falls through */ ++ case ')': ++ sreturn(e_syntaxerror); ++ case '}': ++ if (pstack == 0) ++ sreturn(e_syntaxerror); ++ osp--; ++ { ++ uint size = ref_stack_count_inline(&o_stack) - pstack; ++ ref arr; ++ ++ if_debug4('S', "[S}]d=%d, s=%d->%d, c=%d\n", ++ pdepth, pstack, ++ (pstack == pdepth ? 0 : ++ ref_stack_index(&o_stack, size)->value.intval), ++ size + pstack); ++ myref = (pstack == pdepth ? pref : &arr); ++ if (check_only) { ++ make_empty_array(myref, 0); ++ ref_stack_pop(&o_stack, size); ++ } else if (ref_array_packing.value.boolval) { ++ retcode = make_packed_array(myref, &o_stack, size, ++ idmemory, "scanner(packed)"); ++ if (retcode < 0) { /* must be VMerror */ ++ osp++; ++ scan_putback(); ++ scan_type = scanning_none; ++ goto pause_ret; ++ } ++ r_set_attrs(myref, a_executable); ++ } else { ++ retcode = ialloc_ref_array(myref, ++ a_executable + a_all, size, ++ "scanner(proc)"); ++ if (retcode < 0) { /* must be VMerror */ ++ osp++; ++ scan_putback(); ++ scan_type = scanning_none; ++ goto pause_ret; ++ } ++ retcode = ref_stack_store(&o_stack, myref, size, 0, 1, ++ false, idmemory, "scanner"); ++ if (retcode < 0) { ++ ifree_ref_array(myref, "scanner(proc)"); ++ sreturn(retcode); ++ } ++ ref_stack_pop(&o_stack, size); ++ } ++ if (pstack == pdepth) { /* This was the top-level procedure. */ ++ spop1(); ++ pstack = 0; ++ } else { ++ if (osp < osbot) ++ ref_stack_pop_block(&o_stack); ++ pstack = osp->value.intval; ++ *osp = arr; ++ goto snext; ++ } ++ } ++ break; ++ case '/': ++ /* ++ * If the last thing in the input is a '/', don't try to read ++ * any more data. ++ */ ++ if (sptr >= endptr && s->end_status != EOFC) { ++ refill2(scanning_none); ++ } ++ c = scan_getc(); ++ if (!PDFScanRules && (c == '/')) { ++ name_type = 2; ++ c = scan_getc(); ++ } else ++ name_type = 1; ++ try_number = false; ++ switch (decoder[c]) { ++ case ctype_name: ++ default: ++ goto do_name; ++ case ctype_btoken: ++ if (!recognize_btokens()) ++ goto do_name; ++ /* otherwise, an empty name */ ++ case ctype_exception: ++ case ctype_space: ++ /* ++ * Amazingly enough, the Adobe implementations don't accept ++ * / or // followed by [, ], <<, or >>, so we do the same. ++ * (Older versions of our code had a ctype_other case here ++ * that handled these specially.) ++ */ ++ case ctype_other: ++ if (c == ctrld) /* see above */ ++ goto do_name; ++ da.base = da.limit = daptr = 0; ++ da.is_dynamic = false; ++ goto nx; ++ } ++ case '%': ++ { /* Scan as much as possible within the buffer. */ ++ const byte *base = sptr; ++ const byte *end; ++ ++ while (++sptr < endptr) /* stop 1 char early */ ++ switch (*sptr) { ++ case char_CR: ++ end = sptr; ++ if (sptr[1] == char_EOL) ++ sptr++; ++ cend: /* Check for externally processed comments. */ ++ retcode = scan_comment(i_ctx_p, myref, &sstate, ++ base, end, false); ++ if (retcode != 0) ++ goto comment; ++ goto top; ++ case char_EOL: ++ case '\f': ++ end = sptr; ++ goto cend; ++ } ++ /* ++ * We got to the end of the buffer while inside a comment. ++ * If there is a possibility that we must pass the comment ++ * to an external procedure, move what we have collected ++ * so far into a private buffer now. ++ */ + #define comment_line da.buf +- --sptr; +- comment_line[1] = 0; +- { +- /* Could be an externally processable comment. */ +- uint len = sptr + 1 - base; +- if (len > sizeof(comment_line)) +- len = sizeof(comment_line); +- +- memcpy(comment_line, base, len); +- daptr = comment_line + len; +- } +- da.base = comment_line; +- da.is_dynamic = false; +- } +- /* Enter here to continue scanning a comment. */ +- /* daptr must be set. */ +- cont_comment:for (;;) { +- switch ((c = scan_getc())) { +- default: +- if (c < 0) +- switch (c) { +- case INTC: +- case CALLC: +- da.next = daptr; +- scan_type = scanning_comment; +- goto pause; +- case EOFC: +- /* +- * One would think that an EOF in a comment +- * should be a syntax error, but there are +- * quite a number of files that end that way. +- */ +- goto end_comment; +- default: +- sreturn(e_syntaxerror); +- } +- if (daptr < comment_line + max_comment_line) +- *daptr++ = c; +- continue; +- case char_CR: +- case char_EOL: +- case '\f': +- end_comment: +- retcode = scan_comment(i_ctx_p, myref, &sstate, +- comment_line, daptr, true); +- if (retcode != 0) +- goto comment; +- goto top; +- } +- } ++ --sptr; ++ comment_line[1] = 0; ++ { ++ /* Could be an externally processable comment. */ ++ uint len = sptr + 1 - base; ++ if (len > sizeof(comment_line)) ++ len = sizeof(comment_line); ++ ++ memcpy(comment_line, base, len); ++ daptr = comment_line + len; ++ } ++ da.base = comment_line; ++ da.is_dynamic = false; ++ } ++ /* Enter here to continue scanning a comment. */ ++ /* daptr must be set. */ ++ cont_comment:for (;;) { ++ switch ((c = scan_getc())) { ++ default: ++ if (c < 0) ++ switch (c) { ++ case INTC: ++ case CALLC: ++ da.next = daptr; ++ scan_type = scanning_comment; ++ goto pause; ++ case EOFC: ++ /* ++ * One would think that an EOF in a comment ++ * should be a syntax error, but there are ++ * quite a number of files that end that way. ++ */ ++ goto end_comment; ++ default: ++ sreturn(e_syntaxerror); ++ } ++ if (daptr < comment_line + max_comment_line) ++ *daptr++ = c; ++ continue; ++ case char_CR: ++ case char_EOL: ++ case '\f': ++ end_comment: ++ retcode = scan_comment(i_ctx_p, myref, &sstate, ++ comment_line, daptr, true); ++ if (retcode != 0) ++ goto comment; ++ goto top; ++ } ++ } + #undef comment_line +- /*NOTREACHED */ +- case EOFC: +- if (pstack != 0) { +- if (check_only) +- goto pause; +- sreturn(e_syntaxerror); +- } +- retcode = scan_EOF; +- break; +- case ERRC: +- sreturn(e_ioerror); +- +- /* Check for a Level 2 funny name (<< or >>). */ +- /* c is '<' or '>'. We already did an ensure2. */ +- try_funny_name: +- { +- int c1 = scan_getc(); +- +- if (c1 == c) { +- s1[0] = s1[1] = c; +- name_ref(imemory, s1, 2, myref, 1); /* can't fail */ +- goto have_name; +- } +- scan_putback(); +- } +- sreturn(e_syntaxerror); +- +- /* Handle separately the names that might be a number. */ +- case '0': +- case '1': +- case '2': +- case '3': +- case '4': +- case '5': +- case '6': +- case '7': +- case '8': +- case '9': +- case '.': +- sign = 0; +- nr: /* +- * Skip a leading sign, if any, by conditionally passing +- * sptr + 1 rather than sptr. Also, if the last character +- * in the buffer is a CR, we must stop the scan 1 character +- * early, to be sure that we can test for CR+LF within the +- * buffer, by passing endptr rather than endptr + 1. +- */ +- retcode = scan_number(sptr + (sign & 1), +- endptr /*(*endptr == char_CR ? endptr : endptr + 1) */ , +- sign, myref, &newptr, i_ctx_p->scanner_options); +- if (retcode == 1 && decoder[newptr[-1]] == ctype_space) { +- sptr = newptr - 1; +- if (*sptr == char_CR && sptr[1] == char_EOL) +- sptr++; +- retcode = 0; +- ref_mark_new(myref); +- break; +- } +- name_type = 0; +- try_number = true; +- goto do_name; +- case '+': +- sign = 1; +- goto nr; +- case '-': +- sign = -1; +- goto nr; ++ /*NOTREACHED */ ++ case EOFC: ++ if (pstack != 0) { ++ if (check_only) ++ goto pause; ++ sreturn(e_syntaxerror); ++ } ++ retcode = scan_EOF; ++ break; ++ case ERRC: ++ sreturn(e_ioerror); ++ ++ /* Check for a Level 2 funny name (<< or >>). */ ++ /* c is '<' or '>'. We already did an ensure2. */ ++ try_funny_name: ++ { ++ int c1 = scan_getc(); ++ ++ if (c1 == c) { ++ s1[0] = s1[1] = c; ++ name_ref(imemory, s1, 2, myref, 1); /* can't fail */ ++ goto have_name; ++ } ++ scan_putback(); ++ } ++ sreturn(e_syntaxerror); ++ ++ /* Handle separately the names that might be a number. */ ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ case '.': ++ sign = 0; ++ nr: /* ++ * Skip a leading sign, if any, by conditionally passing ++ * sptr + 1 rather than sptr. Also, if the last character ++ * in the buffer is a CR, we must stop the scan 1 character ++ * early, to be sure that we can test for CR+LF within the ++ * buffer, by passing endptr rather than endptr + 1. ++ */ ++ retcode = scan_number(sptr + (sign & 1), ++ endptr /*(*endptr == char_CR ? endptr : endptr + 1) */ , ++ sign, myref, &newptr, i_ctx_p->scanner_options); ++ if (retcode == 1 && decoder[newptr[-1]] == ctype_space) { ++ sptr = newptr - 1; ++ if (*sptr == char_CR && sptr[1] == char_EOL) ++ sptr++; ++ retcode = 0; ++ ref_mark_new(myref); ++ break; ++ } ++ name_type = 0; ++ try_number = true; ++ goto do_name; ++ case '+': ++ sign = 1; ++ goto nr; ++ case '-': ++ sign = -1; ++ goto nr; + +- /* Check for a binary object */ ++ /* Check for a binary object */ + #define case4(c) case c: case c+1: case c+2: case c+3 +- case4(128): case4(132): case4(136): case4(140): +- case4(144): case4(148): case4(152): case4(156): ++ case4(128): case4(132): case4(136): case4(140): ++ case4(144): case4(148): case4(152): case4(156): + #undef case4 +- if (recognize_btokens()) { +- scan_end_inline(); +- retcode = scan_binary_token(i_ctx_p, myref, &sstate); +- scan_begin_inline(); +- if (retcode == scan_Refill) +- goto pause; +- break; +- } +- /* Not a binary object, fall through. */ +- +- /* The default is a name. */ +- default: +- if (c < 0) { +- dynamic_init(&da, name_memory(imemory)); /* da state must be clean */ +- scan_type = scanning_none; +- goto pause; +- } +- /* Populate the switch with enough cases to force */ +- /* simple compilers to use a dispatch rather than tests. */ +- case '!': +- case '"': +- case '#': +- case '$': +- case '&': +- case '\'': +- case '*': +- case ',': +- case '=': +- case ':': +- case ';': +- case '?': +- case '@': +- case 'A': +- case 'B': +- case 'C': +- case 'D': +- case 'E': +- case 'F': +- case 'G': +- case 'H': +- case 'I': +- case 'J': +- case 'K': +- case 'L': +- case 'M': +- case 'N': +- case 'O': +- case 'P': +- case 'Q': +- case 'R': +- case 'S': +- case 'T': +- case 'U': +- case 'V': +- case 'W': +- case 'X': +- case 'Y': +- case 'Z': +- case '\\': +- case '^': +- case '_': +- case '`': +- case 'a': +- case 'b': +- case 'c': +- case 'd': +- case 'e': +- case 'f': +- case 'g': +- case 'h': +- case 'i': +- case 'j': +- case 'k': +- case 'l': +- case 'm': +- case 'n': +- case 'o': +- case 'p': +- case 'q': +- case 'r': +- case 's': +- case 't': +- case 'u': +- case 'v': +- case 'w': +- case 'x': +- case 'y': +- case 'z': +- case '|': +- case '~': +- begin_name: +- /* Common code for scanning a name. */ +- /* try_number and name_type are already set. */ +- /* We know c has ctype_name (or maybe ctype_btoken, */ +- /* or is ^D) or is a digit. */ +- name_type = 0; +- try_number = false; +- do_name: +- /* Try to scan entirely within the stream buffer. */ +- /* We stop 1 character early, so we don't switch buffers */ +- /* looking ahead if the name is terminated by \r\n. */ +- da.base = (byte *) sptr; +- da.is_dynamic = false; +- { +- const byte *endp1 = endptr - 1; +- +- do { +- if (sptr >= endp1) /* stop 1 early! */ +- goto dyn_name; +- } +- while (decoder[*++sptr] <= max_name_ctype || *sptr == ctrld); /* digit or name */ +- } +- /* Name ended within the buffer. */ +- daptr = (byte *) sptr; +- c = *sptr; +- goto nx; +- dyn_name: /* Name extended past end of buffer. */ +- scan_end_inline(); +- /* Initialize the dynamic area. */ +- /* We have to do this before the next */ +- /* sgetc, which will overwrite the buffer. */ +- da.limit = (byte *)++ sptr; +- da.memory = name_memory(imemory); +- retcode = dynamic_grow(&da, da.limit, name_max_string); +- if (retcode < 0) { +- dynamic_save(&da); +- if (retcode != e_VMerror) +- sreturn(retcode); +- scan_type = scanning_name; +- goto pause_ret; +- } +- daptr = da.next; +- /* Enter here to continue scanning a name. */ +- /* daptr must be set. */ +- cont_name:scan_begin_inline(); +- while (decoder[c = scan_getc()] <= max_name_ctype || c == ctrld) { +- if (daptr == da.limit) { +- retcode = dynamic_grow(&da, daptr, +- name_max_string); +- if (retcode < 0) { +- dynamic_save(&da); +- if (retcode != e_VMerror) +- sreturn(retcode); +- scan_putback(); +- scan_type = scanning_name; +- goto pause_ret; +- } +- daptr = da.next; +- } +- *daptr++ = c; +- } +- nx:switch (decoder[c]) { +- case ctype_other: +- if (c == ctrld) /* see above */ +- break; +- case ctype_btoken: +- scan_putback(); +- break; +- case ctype_space: +- /* Check for \r\n */ +- if (c == char_CR) { +- if (sptr >= endptr) { /* ensure2 *//* We have to check specially for */ +- /* the case where the very last */ +- /* character of a file is a CR. */ +- if (s->end_status != EOFC) { +- sptr--; +- goto pause_name; +- } +- } else if (sptr[1] == char_EOL) +- sptr++; +- } +- break; +- case ctype_exception: +- switch (c) { +- case INTC: +- case CALLC: +- goto pause_name; +- case ERRC: +- sreturn(e_ioerror); +- case EOFC: +- break; +- } +- } +- /* Check for a number */ +- if (try_number) { +- const byte *base = da.base; +- +- scan_sign(sign, base); +- retcode = scan_number(base, daptr, sign, myref, &newptr, i_ctx_p->scanner_options); +- if (retcode == 1) { +- ref_mark_new(myref); +- retcode = 0; +- } else if (retcode != e_syntaxerror) { +- dynamic_free(&da); +- if (name_type == 2) +- sreturn(e_syntaxerror); +- break; /* might be e_limitcheck */ +- } +- } +- if (da.is_dynamic) { /* We've already allocated the string on the heap. */ +- uint size = daptr - da.base; +- +- retcode = name_ref(imemory, da.base, size, myref, -1); +- if (retcode >= 0) { +- dynamic_free(&da); +- } else { +- retcode = dynamic_resize(&da, size); +- if (retcode < 0) { /* VMerror */ +- if (c != EOFC) +- scan_putback(); +- scan_type = scanning_name; +- goto pause_ret; +- } +- retcode = name_ref(imemory, da.base, size, myref, 2); +- } +- } else { +- retcode = name_ref(imemory, da.base, (uint) (daptr - da.base), +- myref, !s->foreign); +- } +- /* Done scanning. Check for preceding /'s. */ +- if (retcode < 0) { +- if (retcode != e_VMerror) +- sreturn(retcode); +- if (!da.is_dynamic) { +- da.next = daptr; +- dynamic_save(&da); +- } +- if (c != EOFC) +- scan_putback(); +- scan_type = scanning_name; +- goto pause_ret; +- } +- have_name:switch (name_type) { +- case 0: /* ordinary executable name */ +- if (r_has_type(myref, t_name)) /* i.e., not a number */ +- r_set_attrs(myref, a_executable); +- case 1: /* quoted name */ +- break; +- case 2: /* immediate lookup */ +- { +- ref *pvalue; +- +- if (!r_has_type(myref, t_name) || +- (pvalue = dict_find_name(myref)) == 0) { +- ref_assign(&sstate.s_error.object, myref); +- r_set_attrs(&sstate.s_error.object, +- a_executable); /* Adobe compatibility */ +- sreturn(e_undefined); +- } +- if (pstack != 0 && +- r_space(pvalue) > ialloc_space(idmemory) +- ) +- sreturn(e_invalidaccess); +- ref_assign_new(myref, pvalue); +- } +- } ++ if (recognize_btokens()) { ++ scan_end_inline(); ++ retcode = scan_binary_token(i_ctx_p, myref, &sstate); ++ scan_begin_inline(); ++ if (retcode == scan_Refill) ++ goto pause; ++ break; ++ } ++ /* Not a binary object, fall through. */ ++ ++ /* The default is a name. */ ++ default: ++ if (c < 0) { ++ dynamic_init(&da, name_memory(imemory)); /* da state must be clean */ ++ scan_type = scanning_none; ++ goto pause; ++ } ++ /* Populate the switch with enough cases to force */ ++ /* simple compilers to use a dispatch rather than tests. */ ++ case '!': ++ case '"': ++ case '#': ++ case '$': ++ case '&': ++ case '\'': ++ case '*': ++ case ',': ++ case '=': ++ case ':': ++ case ';': ++ case '?': ++ case '@': ++ case 'A': ++ case 'B': ++ case 'C': ++ case 'D': ++ case 'E': ++ case 'F': ++ case 'G': ++ case 'H': ++ case 'I': ++ case 'J': ++ case 'K': ++ case 'L': ++ case 'M': ++ case 'N': ++ case 'O': ++ case 'P': ++ case 'Q': ++ case 'R': ++ case 'S': ++ case 'T': ++ case 'U': ++ case 'V': ++ case 'W': ++ case 'X': ++ case 'Y': ++ case 'Z': ++ case '\\': ++ case '^': ++ case '_': ++ case '`': ++ case 'a': ++ case 'b': ++ case 'c': ++ case 'd': ++ case 'e': ++ case 'f': ++ case 'g': ++ case 'h': ++ case 'i': ++ case 'j': ++ case 'k': ++ case 'l': ++ case 'm': ++ case 'n': ++ case 'o': ++ case 'p': ++ case 'q': ++ case 'r': ++ case 's': ++ case 't': ++ case 'u': ++ case 'v': ++ case 'w': ++ case 'x': ++ case 'y': ++ case 'z': ++ case '|': ++ case '~': ++ begin_name: ++ /* Common code for scanning a name. */ ++ /* try_number and name_type are already set. */ ++ /* We know c has ctype_name (or maybe ctype_btoken, */ ++ /* or is ^D) or is a digit. */ ++ name_type = 0; ++ try_number = false; ++ do_name: ++ /* Try to scan entirely within the stream buffer. */ ++ /* We stop 1 character early, so we don't switch buffers */ ++ /* looking ahead if the name is terminated by \r\n. */ ++ da.base = (byte *) sptr; ++ da.is_dynamic = false; ++ { ++ const byte *endp1 = endptr - 1; ++ ++ do { ++ if (sptr >= endp1) /* stop 1 early! */ ++ goto dyn_name; ++ } ++ while (decoder[*++sptr] <= max_name_ctype || *sptr == ctrld); /* digit or name */ ++ } ++ /* Name ended within the buffer. */ ++ daptr = (byte *) sptr; ++ c = *sptr; ++ goto nx; ++ dyn_name: /* Name extended past end of buffer. */ ++ scan_end_inline(); ++ /* Initialize the dynamic area. */ ++ /* We have to do this before the next */ ++ /* sgetc, which will overwrite the buffer. */ ++ da.limit = (byte *)++ sptr; ++ da.memory = name_memory(imemory); ++ retcode = dynamic_grow(&da, da.limit, name_max_string); ++ if (retcode < 0) { ++ dynamic_save(&da); ++ if (retcode != e_VMerror) ++ sreturn(retcode); ++ scan_type = scanning_name; ++ goto pause_ret; ++ } ++ daptr = da.next; ++ /* Enter here to continue scanning a name. */ ++ /* daptr must be set. */ ++ cont_name:scan_begin_inline(); ++ while (decoder[c = scan_getc()] <= max_name_ctype || c == ctrld) { ++ if (daptr == da.limit) { ++ retcode = dynamic_grow(&da, daptr, ++ name_max_string); ++ if (retcode < 0) { ++ dynamic_save(&da); ++ if (retcode != e_VMerror) ++ sreturn(retcode); ++ scan_putback(); ++ scan_type = scanning_name; ++ goto pause_ret; ++ } ++ daptr = da.next; ++ } ++ *daptr++ = c; ++ } ++ nx:switch (decoder[c]) { ++ case ctype_other: ++ if (c == ctrld) /* see above */ ++ break; ++ case ctype_btoken: ++ scan_putback(); ++ break; ++ case ctype_space: ++ /* Check for \r\n */ ++ if (c == char_CR) { ++ if (sptr >= endptr) { /* ensure2 *//* We have to check specially for */ ++ /* the case where the very last */ ++ /* character of a file is a CR. */ ++ if (s->end_status != EOFC) { ++ sptr--; ++ goto pause_name; ++ } ++ } else if (sptr[1] == char_EOL) ++ sptr++; ++ } ++ break; ++ case ctype_exception: ++ switch (c) { ++ case INTC: ++ case CALLC: ++ goto pause_name; ++ case ERRC: ++ sreturn(e_ioerror); ++ case EOFC: ++ break; ++ } ++ } ++ /* Check for a number */ ++ if (try_number) { ++ const byte *base = da.base; ++ ++ scan_sign(sign, base); ++ retcode = scan_number(base, daptr, sign, myref, &newptr, i_ctx_p->scanner_options); ++ if (retcode == 1) { ++ ref_mark_new(myref); ++ retcode = 0; ++ } else if (retcode != e_syntaxerror) { ++ dynamic_free(&da); ++ if (name_type == 2) ++ sreturn(e_syntaxerror); ++ break; /* might be e_limitcheck */ ++ } ++ } ++ if (da.is_dynamic) { /* We've already allocated the string on the heap. */ ++ uint size = daptr - da.base; ++ ++ retcode = name_ref(imemory, da.base, size, myref, -1); ++ if (retcode >= 0) { ++ dynamic_free(&da); ++ } else { ++ retcode = dynamic_resize(&da, size); ++ if (retcode < 0) { /* VMerror */ ++ if (c != EOFC) ++ scan_putback(); ++ scan_type = scanning_name; ++ goto pause_ret; ++ } ++ retcode = name_ref(imemory, da.base, size, myref, 2); ++ } ++ } else { ++ retcode = name_ref(imemory, da.base, (uint) (daptr - da.base), ++ myref, !s->foreign); ++ } ++ /* Done scanning. Check for preceding /'s. */ ++ if (retcode < 0) { ++ if (retcode != e_VMerror) ++ sreturn(retcode); ++ if (!da.is_dynamic) { ++ da.next = daptr; ++ dynamic_save(&da); ++ } ++ if (c != EOFC) ++ scan_putback(); ++ scan_type = scanning_name; ++ goto pause_ret; ++ } ++ have_name:switch (name_type) { ++ case 0: /* ordinary executable name */ ++ if (r_has_type(myref, t_name)) /* i.e., not a number */ ++ r_set_attrs(myref, a_executable); ++ case 1: /* quoted name */ ++ break; ++ case 2: /* immediate lookup */ ++ { ++ ref *pvalue; ++ ++ if (!r_has_type(myref, t_name) || ++ (pvalue = dict_find_name(myref)) == 0) { ++ ref_assign(&sstate.s_error.object, myref); ++ r_set_attrs(&sstate.s_error.object, ++ a_executable); /* Adobe compatibility */ ++ sreturn(e_undefined); ++ } ++ if (pstack != 0 && ++ r_space(pvalue) > ialloc_space(idmemory) ++ ) ++ sreturn(e_invalidaccess); ++ ref_assign_new(myref, pvalue); ++ } ++ } + } + sret:if (retcode < 0) { +- scan_end_inline(); +- pstate->s_error = sstate.s_error; +- if (pstack != 0) { +- if (retcode == e_undefined) +- *pref = *osp; /* return undefined name as error token */ +- ref_stack_pop(&o_stack, +- ref_stack_count(&o_stack) - (pdepth - 1)); +- } +- return retcode; ++ scan_end_inline(); ++ pstate->s_error = sstate.s_error; ++ if (pstack != 0) { ++ if (retcode == e_undefined) ++ *pref = *osp; /* return undefined name as error token */ ++ ref_stack_pop(&o_stack, ++ ref_stack_count(&o_stack) - (pdepth - 1)); ++ } ++ return retcode; + } + /* If we are at the top level, return the object, */ + /* otherwise keep going. */ + if (pstack == 0) { +- scan_end_inline(); +- return retcode; ++ scan_end_inline(); ++ return retcode; + } + snext:if_not_spush1() { +- scan_end_inline(); +- scan_type = scanning_none; +- goto save; ++ scan_end_inline(); ++ scan_type = scanning_none; ++ goto save; + } + myref = osp; + goto top; +@@ -1233,7 +1233,7 @@ scan_token(i_ctx_t *i_ctx_p, ref * pref, + scan_end_inline(); + suspend: + if (pstack != 0) +- osp--; /* myref */ ++ osp--; /* myref */ + save: + *pstate = sstate; + return retcode; +@@ -1241,7 +1241,7 @@ scan_token(i_ctx_t *i_ctx_p, ref * pref, + /* Handle a scanned comment. */ + comment: + if (retcode < 0) +- goto sret; ++ goto sret; + scan_end_inline(); + scan_type = scanning_none; + goto save; +diff -up ghostscript-9.00/psi/iscan.h.scan_token ghostscript-9.00/psi/iscan.h +--- ghostscript-9.00/psi/iscan.h.scan_token 2010-04-26 16:29:28.000000000 +0100 ++++ ghostscript-9.00/psi/iscan.h 2011-01-14 17:16:12.617867701 +0000 +@@ -1,6 +1,6 @@ + /* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. +- ++ + This software is provided AS-IS with no warranty, either express or + implied. + +@@ -23,7 +23,7 @@ + #include "inamestr.h" + + /* +- * Define the state of the scanner. Before calling scan_token initially, ++ * Define the state of the scanner. Before first calling gs_scan_token, + * the caller must initialize the state by calling scanner_state_init. + * Most of the state is only used if scanning is suspended because of + * an interrupt or a callout. +@@ -44,15 +44,16 @@ typedef struct scanner_state_s scanner_s + * Define a structure for dynamically growable strings. + * If is_dynamic is true, base/next/limit point to a string on the heap; + * if is_dynamic is false, base/next/limit point either to the local buffer +- * or (only while control is inside scan_token) into the source stream buffer. ++ * or (only while control is inside gs_scan_token) into the source stream ++ * buffer. + */ +-#define max_comment_line 255 /* max size of an externally processable comment */ ++#define max_comment_line 255 /* max size of an externally processable comment */ + typedef struct dynamic_area_s { + byte *base; + byte *next; + byte *limit; + bool is_dynamic; +- byte buf[max_name_string]; /* initial buffer, enough for a valid string */ ++ byte buf[max_name_string]; /* initial buffer, enough for a valid string */ + gs_memory_t *memory; + } dynamic_area; + +@@ -65,48 +66,48 @@ typedef struct scan_binary_state_s { + int (*cont)(i_ctx_t *, ref *, scanner_state *); + ref bin_array; + uint index; +- uint max_array_index; /* largest legal index in objects */ +- uint min_string_index; /* smallest legal index in strings */ ++ uint max_array_index; /* largest legal index in objects */ ++ uint min_string_index; /* smallest legal index in strings */ + uint top_size; + uint size; +- int token_type; /* binary token type for error reporting */ +- ulong lsize; /* b.o.s. size ibid. */ ++ int token_type; /* binary token type for error reporting */ ++ ulong lsize; /* b.o.s. size ibid. */ + } scan_binary_state; + + /* Define the scanner state. */ + struct scanner_state_s { +- ref s_file; /* source file */ +- uint s_pstack; /* stack depth when starting current */ +- /* procedure, after pushing old pstack */ +- uint s_pdepth; /* pstack for very first { encountered, */ +- /* for error recovery */ ++ ref s_file; /* source file */ ++ uint s_pstack; /* stack depth when starting current */ ++ /* procedure, after pushing old pstack */ ++ uint s_pdepth; /* pstack for very first { encountered, */ ++ /* for error recovery */ + int s_options; + enum { +- scanning_none, +- scanning_binary, +- scanning_comment, +- scanning_name, +- scanning_string ++ scanning_none, ++ scanning_binary, ++ scanning_comment, ++ scanning_name, ++ scanning_string + } s_scan_type; + dynamic_area s_da; +- union sss_ { /* scanning sub-state */ +- scan_binary_state binary; /* binary */ +- struct sns_ { /* name */ +- int s_name_type; /* number of /'s preceding a name */ +- bool s_try_number; /* true if should try scanning name */ +- /* as number */ +- } s_name; +- stream_state st; /* string */ +- stream_A85D_state a85d; /* string */ +- stream_AXD_state axd; /* string */ +- stream_PSSD_state pssd; /* string */ ++ union sss_ { /* scanning sub-state */ ++ scan_binary_state binary; /* binary */ ++ struct sns_ { /* name */ ++ int s_name_type; /* number of /'s preceding a name */ ++ bool s_try_number; /* true if should try scanning name */ ++ /* as number */ ++ } s_name; ++ stream_state st; /* string */ ++ stream_A85D_state a85d; /* string */ ++ stream_AXD_state axd; /* string */ ++ stream_PSSD_state pssd; /* string */ + } s_ss; + /* The following are used only to return information for errors. */ +- struct se_ { /* scanner error */ +- ref object; /* normally t__invalid */ +- bool is_name; /* true if 'string' is name, false if string */ ++ struct se_ { /* scanner error */ ++ ref object; /* normally t__invalid */ ++ bool is_name; /* true if 'string' is name, false if string */ + #define SCANNER_MAX_ERROR_STRING 120 /* adhoc, for Adobe-compatible messages */ +- char string[SCANNER_MAX_ERROR_STRING+1]; /* normally empty */ ++ char string[SCANNER_MAX_ERROR_STRING+1]; /* normally empty */ + } s_error; + #define SCAN_INIT_ERROR(pstate)\ + (make_t(&(pstate)->s_error.object, t__invalid),\ +@@ -122,81 +123,81 @@ typedef struct scanner_state_dynamic_s { + + /* The type descriptor is public only for checking. */ + extern_st(st_scanner_state_dynamic); +-#define public_st_scanner_state_dynamic() /* in iscan.c */\ ++#define public_st_scanner_state_dynamic() /* in iscan.c */\ + gs_public_st_complex_only(st_scanner_state_dynamic, scanner_state_dynamic, "scanner state",\ + scanner_clear_marks, scanner_enum_ptrs, scanner_reloc_ptrs, 0) + + /* Initialize a scanner with a given set of options. */ +-#define SCAN_FROM_STRING 1 /* true if string is source of data */ +- /* (for Level 1 `\' handling) */ +-#define SCAN_CHECK_ONLY 2 /* true if just checking for syntax errors */ +- /* and complete statements (no value) */ +-#define SCAN_PROCESS_COMMENTS 4 /* return scan_Comment for comments */ +- /* (all comments or only non-DSC) */ ++#define SCAN_FROM_STRING 1 /* true if string is source of data */ ++ /* (for Level 1 `\' handling) */ ++#define SCAN_CHECK_ONLY 2 /* true if just checking for syntax errors */ ++ /* and complete statements (no value) */ ++#define SCAN_PROCESS_COMMENTS 4 /* return scan_Comment for comments */ ++ /* (all comments or only non-DSC) */ + #define SCAN_PROCESS_DSC_COMMENTS 8 /* return scan_DSC_Comment */ +-#define SCAN_PDF_RULES 16 /* PDF scanning rules (for names) */ +-#define SCAN_PDF_INV_NUM 32 /* Adobe ignores invalid numbers */ +- /* This is for compatibility with Adobe */ +- /* Acrobat Reader */ ++#define SCAN_PDF_RULES 16 /* PDF scanning rules (for names) */ ++#define SCAN_PDF_INV_NUM 32 /* Adobe ignores invalid numbers */ ++ /* This is for compatibility with Adobe */ ++ /* Acrobat Reader */ + #define SCAN_PDF_UNSIGNED 64 /* Scan 2147483648..4294967295 as unsigned numbers */ + /* This is needed in some contexts for */ + /* compatibility with Adobe */ +-void scanner_init_options(scanner_state *sstate, const ref *fop, +- int options); +-#define scanner_init(sstate, fop)\ +- scanner_init_options(sstate, fop, 0) +-void scanner_init_stream_options(scanner_state *sstate, stream *s, +- int options); +-#define scanner_init_stream(sstate, s)\ +- scanner_init_stream_options(sstate, s, 0) ++void gs_scanner_init_options(scanner_state *sstate, const ref *fop, ++ int options); ++#define gs_scanner_init(sstate, fop)\ ++ gs_scanner_init_options(sstate, fop, 0) ++void gs_scanner_init_stream_options(scanner_state *sstate, stream *s, ++ int options); ++#define gs_scanner_init_stream(sstate, s)\ ++ gs_scanner_init_stream_options(sstate, s, 0) + + /* + * Read a token from a stream. As usual, 0 is a normal return, + * <0 is an error. There are also some special return codes: + */ +-#define scan_BOS 1 /* binary object sequence */ +-#define scan_EOF 2 /* end of stream */ +-#define scan_Refill 3 /* get more input data, then call again */ +-#define scan_Comment 4 /* comment, non-DSC if processing DSC */ +-#define scan_DSC_Comment 5 /* DSC comment */ +-int scan_token(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate); ++#define scan_BOS 1 /* binary object sequence */ ++#define scan_EOF 2 /* end of stream */ ++#define scan_Refill 3 /* get more input data, then call again */ ++#define scan_Comment 4 /* comment, non-DSC if processing DSC */ ++#define scan_DSC_Comment 5 /* DSC comment */ ++int gs_scan_token(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate); + + /* +- * Read a token from a string. Return like scan_token, but also ++ * Read a token from a string. Return like gs_scan_token, but also + * update the string to move past the token (if no error). + */ +-int scan_string_token_options(i_ctx_t *i_ctx_p, ref * pstr, ref * pref, +- int options); +-#define scan_string_token(i_ctx_p, pstr, pref)\ +- scan_string_token_options(i_ctx_p, pstr, pref, 0) ++int gs_scan_string_token_options(i_ctx_t *i_ctx_p, ref * pstr, ref * pref, ++ int options); ++#define gs_scan_string_token(i_ctx_p, pstr, pref)\ ++ gs_scan_string_token_options(i_ctx_p, pstr, pref, 0) + + /* + * Return the "error object" to be stored in $error.command instead of + * --token--, if any, or -1 if no special error object is required. + */ +-int scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate, +- ref *pseo); ++int gs_scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate, ++ ref *pseo); + + /* +- * Handle a scan_Refill return from scan_token. +- * This may return o_push_estack, 0 (meaning just call scan_token again), +- * or an error code. ++ * Handle a scan_Refill return from gs_scan_token. ++ * This may return o_push_estack, 0 (meaning just call gs_scan_token ++ * again), or an error code. + */ +-int scan_handle_refill(i_ctx_t *i_ctx_p, scanner_state * pstate, +- bool save, op_proc_t cont); ++int gs_scan_handle_refill(i_ctx_t *i_ctx_p, scanner_state * pstate, ++ bool save, op_proc_t cont); + + /* + * Define the procedure "hook" for parsing DSC comments. If not NULL, + * this procedure is called for every DSC comment seen by the scanner. + */ +-extern int (*scan_dsc_proc) (const byte *, uint); ++extern int (*gs_scan_dsc_proc) (const byte *, uint); + + /* + * Define the procedure "hook" for parsing general comments. If not NULL, + * this procedure is called for every comment seen by the scanner. +- * If both scan_dsc_proc and scan_comment_proc are set, +- * scan_comment_proc is called only for non-DSC comments. ++ * If both gs_scan_dsc_proc and gs_scan_comment_proc are set, ++ * gs_scan_comment_proc is called only for non-DSC comments. + */ +-extern int (*scan_comment_proc) (const byte *, uint); ++extern int (*gs_scan_comment_proc) (const byte *, uint); + + #endif /* iscan_INCLUDED */ +diff -up ghostscript-9.00/psi/itoken.h.scan_token ghostscript-9.00/psi/itoken.h +--- ghostscript-9.00/psi/itoken.h.scan_token 2008-08-28 23:48:19.000000000 +0100 ++++ ghostscript-9.00/psi/itoken.h 2011-01-14 17:16:12.618867712 +0000 +@@ -1,6 +1,6 @@ + /* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. +- ++ + This software is provided AS-IS with no warranty, either express or + implied. + +@@ -24,16 +24,16 @@ + int ztokenexec_continue(i_ctx_t *i_ctx_p); + + /* +- * Handle a scan_Comment or scan_DSC_Comment return from scan_token. ++ * Handle a scan_Comment or scan_DSC_Comment return from gs_scan_token. + */ + #ifndef scanner_state_DEFINED + # define scanner_state_DEFINED + typedef struct scanner_state_s scanner_state; + #endif + int ztoken_handle_comment(i_ctx_t *i_ctx_p, +- scanner_state *sstate, const ref *ptoken, +- int scan_code, bool save, bool push_file, +- op_proc_t cont); ++ scanner_state *sstate, const ref *ptoken, ++ int scan_code, bool save, bool push_file, ++ op_proc_t cont); + + /* + * Update the cached scanner_options in the context state after doing a +diff -up ghostscript-9.00/psi/ziodev.c.scan_token ghostscript-9.00/psi/ziodev.c +--- ghostscript-9.00/psi/ziodev.c.scan_token 2010-04-15 18:13:30.000000000 +0100 ++++ ghostscript-9.00/psi/ziodev.c 2011-01-14 17:16:12.620867730 +0000 +@@ -1,6 +1,6 @@ + /* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. +- ++ + This software is provided AS-IS with no warranty, either express or + implied. + +@@ -25,10 +25,10 @@ + #include "ialloc.h" + #include "iscan.h" + #include "ivmspace.h" +-#include "gxiodev.h" /* must come after stream.h */ +- /* and before files.h */ ++#include "gxiodev.h" /* must come after stream.h */ ++ /* and before files.h */ + #include "files.h" +-#include "scanchar.h" /* for char_EOL */ ++#include "scanchar.h" /* for char_EOL */ + #include "store.h" + #include "ierrors.h" + +@@ -38,11 +38,11 @@ extern const char iodev_dtype_stdio[]; + /* Define the special devices. */ + #define iodev_special(dname, init, open) {\ + dname, iodev_dtype_stdio,\ +- { init, open, iodev_no_open_file, iodev_no_fopen, iodev_no_fclose,\ +- iodev_no_delete_file, iodev_no_rename_file, iodev_no_file_status,\ +- iodev_no_enumerate_files, NULL, NULL,\ +- iodev_no_get_params, iodev_no_put_params\ +- }\ ++ { init, open, iodev_no_open_file, iodev_no_fopen, iodev_no_fclose,\ ++ iodev_no_delete_file, iodev_no_rename_file, iodev_no_file_status,\ ++ iodev_no_enumerate_files, NULL, NULL,\ ++ iodev_no_get_params, iodev_no_put_params\ ++ }\ + } + + /* +@@ -53,12 +53,12 @@ extern const char iodev_dtype_stdio[]; + * immediately afterwards so as not to wind up with dangling references. + */ + +-#define LINEEDIT_BUF_SIZE 20 /* initial size, not fixed size */ ++#define LINEEDIT_BUF_SIZE 20 /* initial size, not fixed size */ + /*static iodev_proc_open_device(lineedit_open);*/ /* no longer used */ + const gx_io_device gs_iodev_lineedit = + iodev_special("%lineedit%", iodev_no_init, iodev_no_open_device); + +-#define STATEMENTEDIT_BUF_SIZE 50 /* initial size, not fixed size */ ++#define STATEMENTEDIT_BUF_SIZE 50 /* initial size, not fixed size */ + /*static iodev_proc_open_device(statementedit_open);*/ /* no longer used */ + const gx_io_device gs_iodev_statementedit = + iodev_special("%statementedit%", iodev_no_init, iodev_no_open_device); +@@ -75,24 +75,24 @@ zgetiodevice(i_ctx_t *i_ctx_p) + + check_type(*op, t_integer); + iodev = gs_getiodevice(imemory, (int)(op->value.intval)); +- if (iodev == 0) /* index out of range */ +- return_error(e_rangecheck); ++ if (iodev == 0) /* index out of range */ ++ return_error(e_rangecheck); + dname = (const byte *)iodev->dname; + if (dname == 0) +- make_null(op); ++ make_null(op); + else +- make_const_string(op, a_readonly | avm_foreign, +- strlen((const char *)dname), dname); ++ make_const_string(op, a_readonly | avm_foreign, ++ strlen((const char *)dname), dname); + return 0; + } + + /* ------ %lineedit and %statementedit ------ */ + + /* .filelineedit */ +-/* This opens %statementedit% or %lineedit% and is also the ++/* This opens %statementedit% or %lineedit% and is also the + * continuation proc for callouts. + * Input: +- * string is the statement/line buffer, ++ * string is the statement/line buffer, + * int is the write index into string + * bool is true if %statementedit% + * file is stdin +@@ -100,7 +100,7 @@ zgetiodevice(i_ctx_t *i_ctx_p) + * 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 ++ * This could be increased by storing the input line in something + * other than a PostScript string. + */ + int +@@ -122,165 +122,165 @@ zfilelineedit(i_ctx_t *i_ctx_p) + */ + gs_string *const buf = &str; + +- check_type(*op, t_string); /* line assembled so far */ ++ 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 */ ++ check_type(*(op-1), t_integer); /* index */ + count = (op-1)->value.intval; +- check_type(*(op-2), t_boolean); /* statementedit/lineedit */ ++ check_type(*(op-2), t_boolean); /* statementedit/lineedit */ + statement = (op-2)->value.boolval; +- check_read_file(i_ctx_p, ins, op - 3); /* %stdin */ ++ check_read_file(i_ctx_p, 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); ++ 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); ++ 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; ++ 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); ++ /* 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; +- } ++ 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; ++ 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); ++ /* 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; +- } ++ gs_scanner_init_stream_options(&state, ts, SCAN_CHECK_ONLY); ++ code = gs_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)"); ++ "zfilelineedit(resize buffer)"); + if (buf->data == 0) +- return_error(e_VMerror); ++ 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); ++ 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; ++ : gs_iodev_lineedit.dname; + code = ssetfilename(s, (const byte *)filename, strlen(filename)+1); + if (code < 0) { +- sclose(s); +- return_error(e_VMerror); ++ sclose(s); ++ return_error(e_VMerror); + } + + pop(3); +diff -up ghostscript-9.00/psi/ztoken.c.scan_token ghostscript-9.00/psi/ztoken.c +--- ghostscript-9.00/psi/ztoken.c.scan_token 2010-04-26 16:29:28.000000000 +0100 ++++ ghostscript-9.00/psi/ztoken.c 2011-01-14 17:16:12.621867740 +0000 +@@ -1,6 +1,6 @@ + /* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. +- ++ + This software is provided AS-IS with no warranty, either express or + implied. + +@@ -17,19 +17,19 @@ + #include "stat_.h" /* get system header early to avoid name clash on Cygwin */ + #include "ghost.h" + #include "oper.h" +-#include "dstack.h" /* for dict_find_name */ ++#include "dstack.h" /* for dict_find_name */ + #include "estack.h" +-#include "gsstruct.h" /* for iscan.h */ ++#include "gsstruct.h" /* for iscan.h */ + #include "gsutil.h" + #include "stream.h" + #include "files.h" + #include "store.h" +-#include "strimpl.h" /* for sfilter.h */ +-#include "sfilter.h" /* for iscan.h */ ++#include "strimpl.h" /* for sfilter.h */ ++#include "sfilter.h" /* for iscan.h */ + #include "idict.h" + #include "iname.h" + #include "iscan.h" +-#include "itoken.h" /* for prototypes */ ++#include "itoken.h" /* for prototypes */ + + /* token -true- */ + /* token -true- */ +@@ -42,47 +42,47 @@ ztoken(i_ctx_t *i_ctx_p) + os_ptr op = osp; + + switch (r_type(op)) { +- default: +- return_op_typecheck(op); +- case t_file: { +- stream *s; +- scanner_state state; +- +- check_read_file(i_ctx_p, s, op); +- check_ostack(1); +- scanner_init(&state, op); +- return token_continue(i_ctx_p, &state, true); +- } +- case t_string: { +- ref token; +- /* -1 is to remove the string operand in case of error. */ +- int orig_ostack_depth = ref_stack_count(&o_stack) - 1; +- int code; +- +- /* Don't pop the operand in case of invalidaccess. */ +- if (!r_has_attr(op, a_read)) +- return_error(e_invalidaccess); +- code = scan_string_token(i_ctx_p, op, &token); +- switch (code) { +- case scan_EOF: /* no tokens */ +- make_false(op); +- return 0; +- default: +- if (code < 0) { +- /* +- * Clear anything that may have been left on the ostack, +- * including the string operand. +- */ +- if (orig_ostack_depth < ref_stack_count(&o_stack)) +- pop(ref_stack_count(&o_stack)- orig_ostack_depth); +- return code; +- } +- } +- push(2); +- op[-1] = token; +- make_true(op); +- return 0; +- } ++ default: ++ return_op_typecheck(op); ++ case t_file: { ++ stream *s; ++ scanner_state state; ++ ++ check_read_file(i_ctx_p, s, op); ++ check_ostack(1); ++ gs_scanner_init(&state, op); ++ return token_continue(i_ctx_p, &state, true); ++ } ++ case t_string: { ++ ref token; ++ /* -1 is to remove the string operand in case of error. */ ++ int orig_ostack_depth = ref_stack_count(&o_stack) - 1; ++ int code; ++ ++ /* Don't pop the operand in case of invalidaccess. */ ++ if (!r_has_attr(op, a_read)) ++ return_error(e_invalidaccess); ++ code = gs_scan_string_token(i_ctx_p, op, &token); ++ switch (code) { ++ case scan_EOF: /* no tokens */ ++ make_false(op); ++ return 0; ++ default: ++ if (code < 0) { ++ /* ++ * Clear anything that may have been left on the ostack, ++ * including the string operand. ++ */ ++ if (orig_ostack_depth < ref_stack_count(&o_stack)) ++ pop(ref_stack_count(&o_stack)- orig_ostack_depth); ++ return code; ++ } ++ } ++ push(2); ++ op[-1] = token; ++ make_true(op); ++ return 0; ++ } + } + } + /* Continue reading a token after an interrupt or callout. */ +@@ -105,42 +105,42 @@ token_continue(i_ctx_t *i_ctx_p, scanner + int code; + ref token; + +- /* Note that scan_token may change osp! */ +- pop(1); /* remove the file or scanner state */ ++ /* Note that gs_scan_token may change osp! */ ++ pop(1); /* remove the file or scanner state */ + again: +- code = scan_token(i_ctx_p, &token, pstate); ++ code = gs_scan_token(i_ctx_p, &token, pstate); + op = osp; + switch (code) { +- default: /* error */ +- if (code > 0) /* comment, not possible */ +- code = gs_note_error(e_syntaxerror); +- scanner_error_object(i_ctx_p, pstate, &i_ctx_p->error_object); +- break; +- case scan_BOS: +- code = 0; +- case 0: /* read a token */ +- push(2); +- ref_assign(op - 1, &token); +- make_true(op); +- break; +- case scan_EOF: /* no tokens */ +- push(1); +- make_false(op); +- code = 0; +- break; +- case scan_Refill: /* need more data */ +- code = scan_handle_refill(i_ctx_p, pstate, save, +- ztoken_continue); +- switch (code) { +- case 0: /* state is not copied to the heap */ +- goto again; +- case o_push_estack: +- return code; +- } +- break; /* error */ ++ default: /* error */ ++ if (code > 0) /* comment, not possible */ ++ code = gs_note_error(e_syntaxerror); ++ gs_scanner_error_object(i_ctx_p, pstate, &i_ctx_p->error_object); ++ break; ++ case scan_BOS: ++ code = 0; ++ case 0: /* read a token */ ++ push(2); ++ ref_assign(op - 1, &token); ++ make_true(op); ++ break; ++ case scan_EOF: /* no tokens */ ++ push(1); ++ make_false(op); ++ code = 0; ++ break; ++ case scan_Refill: /* need more data */ ++ code = gs_scan_handle_refill(i_ctx_p, pstate, save, ++ ztoken_continue); ++ switch (code) { ++ case 0: /* state is not copied to the heap */ ++ goto again; ++ case o_push_estack: ++ return code; ++ } ++ break; /* error */ + } +- if (code <= 0 && !save) { /* Deallocate the scanner state record. */ +- ifree_object(pstate, "token_continue"); ++ if (code <= 0 && !save) { /* Deallocate the scanner state record. */ ++ ifree_object(pstate, "token_continue"); + } + return code; + } +@@ -149,7 +149,7 @@ again: + /* Read a token and do what the interpreter would do with it. */ + /* This is different from token + exec because literal procedures */ + /* are not executed (although binary object sequences ARE executed). */ +-int ztokenexec_continue(i_ctx_t *); /* export for interpreter */ ++int ztokenexec_continue(i_ctx_t *); /* export for interpreter */ + static int tokenexec_continue(i_ctx_t *, scanner_state *, bool); + int + ztokenexec(i_ctx_t *i_ctx_p) +@@ -160,7 +160,7 @@ ztokenexec(i_ctx_t *i_ctx_p) + + check_read_file(i_ctx_p, s, op); + check_estack(1); +- scanner_init(&state, op); ++ gs_scanner_init(&state, op); + return tokenexec_continue(i_ctx_p, &state, true); + } + /* Continue reading a token for execution after an interrupt or callout. */ +@@ -183,61 +183,61 @@ tokenexec_continue(i_ctx_t *i_ctx_p, sca + { + os_ptr op; + int code; +- /* Note that scan_token may change osp! */ ++ /* Note that gs_scan_token may change osp! */ + pop(1); + again: + check_estack(1); +- code = scan_token(i_ctx_p, (ref *) (esp + 1), pstate); ++ code = gs_scan_token(i_ctx_p, (ref *) (esp + 1), pstate); + op = osp; + switch (code) { +- case 0: +- if (r_is_proc(esp + 1)) { /* Treat procedure as a literal. */ +- push(1); +- ref_assign(op, esp + 1); +- code = 0; +- break; +- } +- /* falls through */ +- case scan_BOS: +- ++esp; +- code = o_push_estack; +- break; +- case scan_EOF: /* no tokens */ +- code = 0; +- break; +- case scan_Refill: /* need more data */ +- code = scan_handle_refill(i_ctx_p, pstate, save, +- ztokenexec_continue); +- switch (code) { +- case 0: /* state is not copied to the heap */ +- goto again; +- case o_push_estack: +- return code; +- } +- break; /* error */ +- case scan_Comment: +- case scan_DSC_Comment: +- return ztoken_handle_comment(i_ctx_p, pstate, esp + 1, code, +- save, true, ztokenexec_continue); +- default: /* error */ +- scanner_error_object(i_ctx_p, pstate, &i_ctx_p->error_object); +- break; ++ case 0: ++ if (r_is_proc(esp + 1)) { /* Treat procedure as a literal. */ ++ push(1); ++ ref_assign(op, esp + 1); ++ code = 0; ++ break; ++ } ++ /* falls through */ ++ case scan_BOS: ++ ++esp; ++ code = o_push_estack; ++ break; ++ case scan_EOF: /* no tokens */ ++ code = 0; ++ break; ++ case scan_Refill: /* need more data */ ++ code = gs_scan_handle_refill(i_ctx_p, pstate, save, ++ ztokenexec_continue); ++ switch (code) { ++ case 0: /* state is not copied to the heap */ ++ goto again; ++ case o_push_estack: ++ return code; ++ } ++ break; /* error */ ++ case scan_Comment: ++ case scan_DSC_Comment: ++ return ztoken_handle_comment(i_ctx_p, pstate, esp + 1, code, ++ save, true, ztokenexec_continue); ++ default: /* error */ ++ gs_scanner_error_object(i_ctx_p, pstate, &i_ctx_p->error_object); ++ break; + } +- if (!save) { /* Deallocate the scanner state record. */ +- gs_free_object(((scanner_state_dynamic *)pstate)->mem, pstate, "token_continue"); ++ if (!save) { /* Deallocate the scanner state record. */ ++ gs_free_object(((scanner_state_dynamic *)pstate)->mem, pstate, "token_continue"); + } + return code; + } + + /* +- * Handle a scan_Comment or scan_DSC_Comment return from scan_token ++ * Handle a scan_Comment or scan_DSC_Comment return from gs_scan_token + * (scan_code) by calling out to %Process[DSC]Comment. The continuation + * procedure expects the scanner state on the o-stack. + */ + int + ztoken_handle_comment(i_ctx_t *i_ctx_p, scanner_state *sstate, +- const ref *ptoken, int scan_code, +- bool save, bool push_file, op_proc_t cont) ++ const ref *ptoken, int scan_code, ++ bool save, bool push_file, op_proc_t cont) + { + const char *proc_name; + scanner_state *pstate; +@@ -247,39 +247,39 @@ ztoken_handle_comment(i_ctx_t *i_ctx_p, + + switch (scan_code) { + case scan_Comment: +- proc_name = "%ProcessComment"; +- break; ++ proc_name = "%ProcessComment"; ++ break; + case scan_DSC_Comment: +- proc_name = "%ProcessDSCComment"; +- break; ++ proc_name = "%ProcessDSCComment"; ++ break; + default: +- return_error(e_Fatal); /* can't happen */ ++ return_error(e_Fatal); /* can't happen */ + } + /* + * We can't use check_ostack here, because it returns on overflow. + */ + /*check_ostack(2);*/ + if (ostop - osp < 2) { +- code = ref_stack_extend(&o_stack, 2); +- if (code < 0) +- return code; ++ code = ref_stack_extend(&o_stack, 2); ++ if (code < 0) ++ return code; + } + check_estack(3); + code = name_enter_string(imemory, proc_name, esp + 3); + if (code < 0) +- return code; ++ return code; + if (save) { +- pstate = (scanner_state *)ialloc_struct(scanner_state_dynamic, &st_scanner_state_dynamic, +- "ztoken_handle_comment"); +- if (pstate == 0) +- return_error(e_VMerror); +- ((scanner_state_dynamic *)pstate)->mem = imemory; +- *pstate = *sstate; ++ pstate = (scanner_state *)ialloc_struct(scanner_state_dynamic, &st_scanner_state_dynamic, ++ "ztoken_handle_comment"); ++ if (pstate == 0) ++ return_error(e_VMerror); ++ ((scanner_state_dynamic *)pstate)->mem = imemory; ++ *pstate = *sstate; + } else +- pstate = sstate; ++ pstate = sstate; + /* Save the token now -- it might be on the e-stack. */ + if (!pstate->s_pstack) +- osp[2] = *ptoken; ++ osp[2] = *ptoken; + /* + * Push the continuation, scanner state, file, and callout procedure + * on the e-stack. +@@ -288,28 +288,28 @@ ztoken_handle_comment(i_ctx_t *i_ctx_p, + make_istruct(esp + 2, 0, pstate); + ppcproc = dict_find_name(esp + 3); + if (ppcproc == 0) { +- /* +- * This can only happen during initialization. +- * Pop the comment string from the o-stack if needed (see below). +- */ +- if (pstate->s_pstack) +- --osp; +- esp += 2; /* do run the continuation */ ++ /* ++ * This can only happen during initialization. ++ * Pop the comment string from the o-stack if needed (see below). ++ */ ++ if (pstate->s_pstack) ++ --osp; ++ esp += 2; /* do run the continuation */ + } else { +- /* +- * Push the file and comment string on the o-stack. +- * If we were inside { }, the comment string is already on the stack. +- */ +- if (pstate->s_pstack) { +- op = ++osp; +- *op = op[-1]; +- } else { +- op = osp += 2; +- /* *op = *ptoken; */ /* saved above */ +- } +- op[-1] = pstate->s_file; +- esp[3] = *ppcproc; +- esp += 3; ++ /* ++ * Push the file and comment string on the o-stack. ++ * If we were inside { }, the comment string is already on the stack. ++ */ ++ if (pstate->s_pstack) { ++ op = ++osp; ++ *op = op[-1]; ++ } else { ++ op = osp += 2; ++ /* *op = *ptoken; */ /* saved above */ ++ } ++ op[-1] = pstate->s_file; ++ esp[3] = *ppcproc; ++ esp += 3; + } + return o_push_estack; + } +@@ -337,17 +337,17 @@ ztoken_scanner_options(const ref *upref, + int i; + + for (i = 0; i < countof(named_options); ++i) { +- const named_scanner_option_t *pnso = &named_options[i]; +- ref *ppcproc; +- int code = dict_find_string(upref, pnso->pname, &ppcproc); +- +- /* Update the options only if the parameter has changed. */ +- if (code >= 0) { +- if (r_has_type(ppcproc, t_null)) +- options &= ~pnso->option; +- else +- options |= pnso->option; +- } ++ const named_scanner_option_t *pnso = &named_options[i]; ++ ref *ppcproc; ++ int code = dict_find_string(upref, pnso->pname, &ppcproc); ++ ++ /* Update the options only if the parameter has changed. */ ++ if (code >= 0) { ++ if (r_has_type(ppcproc, t_null)) ++ options &= ~pnso->option; ++ else ++ options |= pnso->option; ++ } + } + return options; + } +@@ -361,11 +361,11 @@ ztoken_get_scanner_option(const ref *psr + const named_scanner_option_t *pnso; + + for (pnso = named_options + countof(named_options); pnso-- != named_options;) { +- if (!bytes_compare((const byte *)pnso->pname, strlen(pnso->pname), +- psref->value.const_bytes, r_size(psref))) { +- *pname = pnso->pname; +- return (options & pnso->option ? 1 : 0); +- } ++ if (!bytes_compare((const byte *)pnso->pname, strlen(pnso->pname), ++ psref->value.const_bytes, r_size(psref))) { ++ *pname = pnso->pname; ++ return (options & pnso->option ? 1 : 0); ++ } + } + return -1; + } +@@ -376,7 +376,7 @@ const op_def ztoken_op_defs[] = + { + {"1token", ztoken}, + {"1.tokenexec", ztokenexec}, +- /* Internal operators */ ++ /* Internal operators */ + {"2%ztoken_continue", ztoken_continue}, + {"2%ztokenexec_continue", ztokenexec_continue}, + op_def_end(0) +diff -up ghostscript-9.00/psi/ztype.c.scan_token ghostscript-9.00/psi/ztype.c +--- ghostscript-9.00/psi/ztype.c.scan_token 2009-06-05 06:55:54.000000000 +0100 ++++ ghostscript-9.00/psi/ztype.c 2011-01-14 17:16:12.623867766 +0000 +@@ -1,6 +1,6 @@ + /* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. +- ++ + This software is provided AS-IS with no warranty, either express or + implied. + +@@ -19,15 +19,15 @@ + #include "gsexit.h" + #include "ghost.h" + #include "oper.h" +-#include "imemory.h" /* for register_ref_root */ ++#include "imemory.h" /* for register_ref_root */ + #include "idict.h" + #include "iname.h" +-#include "stream.h" /* for iscan.h */ +-#include "strimpl.h" /* for sfilter.h for picky compilers */ +-#include "sfilter.h" /* ditto */ ++#include "stream.h" /* for iscan.h */ ++#include "strimpl.h" /* for sfilter.h for picky compilers */ ++#include "sfilter.h" /* ditto */ + #include "iscan.h" + #include "iutil.h" +-#include "dstack.h" /* for dict_set_top */ ++#include "dstack.h" /* for dict_set_top */ + #include "store.h" + + /* +@@ -69,23 +69,23 @@ ztype(i_ctx_t *i_ctx_p) + int code = array_get(imemory, op, (long)r_btype(op - 1), &tnref); + + if (code < 0) +- return code; ++ return code; + if (!r_has_type(&tnref, t_name)) { +- /* Must be either a stack underflow or a t_[a]struct. */ +- check_op(2); +- { /* Get the type name from the structure. */ +- const char *sname = +- gs_struct_type_name_string(gs_object_type(imemory, +- op[-1].value.pstruct)); +- int code = name_ref(imemory, (const byte *)sname, strlen(sname), +- (ref *) (op - 1), 0); +- +- if (code < 0) +- return code; +- } +- r_set_attrs(op - 1, a_executable); ++ /* Must be either a stack underflow or a t_[a]struct. */ ++ check_op(2); ++ { /* Get the type name from the structure. */ ++ const char *sname = ++ gs_struct_type_name_string(gs_object_type(imemory, ++ op[-1].value.pstruct)); ++ int code = name_ref(imemory, (const byte *)sname, strlen(sname), ++ (ref *) (op - 1), 0); ++ ++ if (code < 0) ++ return code; ++ } ++ r_set_attrs(op - 1, a_executable); + } else { +- ref_assign(op - 1, &tnref); ++ ref_assign(op - 1, &tnref); + } + pop(1); + return 0; +@@ -101,17 +101,17 @@ ztypenames(i_ctx_t *i_ctx_p) + + check_ostack(t_next_index); + for (i = 0; i < t_next_index; i++) { +- ref *const rtnp = op + 1 + i; ++ ref *const rtnp = op + 1 + i; + +- if (i >= countof(tnames) || tnames[i] == 0) +- make_null(rtnp); +- else { +- int code = name_enter_string(imemory, tnames[i], rtnp); +- +- if (code < 0) +- return code; +- r_set_attrs(rtnp, a_executable); +- } ++ if (i >= countof(tnames) || tnames[i] == 0) ++ make_null(rtnp); ++ else { ++ int code = name_enter_string(imemory, tnames[i], rtnp); ++ ++ if (code < 0) ++ return code; ++ r_set_attrs(rtnp, a_executable); ++ } + } + osp += t_next_index; + return 0; +@@ -144,10 +144,10 @@ zcvx(i_ctx_t *i_ctx_p) + * exist in executable form anywhere outside the e-stack. + */ + if (r_has_type(op, t_operator) && +- ((opidx = op_index(op)) == 0 || +- op_def_is_internal(op_index_def(opidx))) +- ) +- return_error(e_rangecheck); ++ ((opidx = op_index(op)) == 0 || ++ op_def_is_internal(op_index_def(opidx))) ++ ) ++ return_error(e_rangecheck); + aop = ACCESS_REF(op); + r_set_attrs(aop, a_executable); + return 0; +@@ -172,7 +172,7 @@ zexecuteonly(i_ctx_t *i_ctx_p) + + check_op(1); + if (r_has_type(op, t_dictionary)) +- return_error(e_typecheck); ++ return_error(e_typecheck); + return access_check(i_ctx_p, a_execute, true); + } + +@@ -184,20 +184,20 @@ znoaccess(i_ctx_t *i_ctx_p) + + check_op(1); + if (r_has_type(op, t_dictionary)) { +- ref *aop = dict_access_ref(op); +- +- /* CPSI throws invalidaccess when seting noaccess to a readonly dictionary (CET 13-13-6) : */ +- if (!r_has_attrs(aop, a_write)) { +- if (!r_has_attrs(aop, a_read) && !r_has_attrs(aop, a_execute)) { +- /* Already noaccess - do nothing (CET 24-09-1). */ +- return 0; +- } +- return_error(e_invalidaccess); +- } +- +- /* Don't allow removing read access to permanent dictionaries. */ +- if (dict_is_permanent_on_dstack(op)) +- return_error(e_invalidaccess); ++ ref *aop = dict_access_ref(op); ++ ++ /* CPSI throws invalidaccess when seting noaccess to a readonly dictionary (CET 13-13-6) : */ ++ if (!r_has_attrs(aop, a_write)) { ++ if (!r_has_attrs(aop, a_read) && !r_has_attrs(aop, a_execute)) { ++ /* Already noaccess - do nothing (CET 24-09-1). */ ++ return 0; ++ } ++ return_error(e_invalidaccess); ++ } ++ ++ /* Don't allow removing read access to permanent dictionaries. */ ++ if (dict_is_permanent_on_dstack(op)) ++ return_error(e_invalidaccess); + } + return access_check(i_ctx_p, 0, true); + } +@@ -217,7 +217,7 @@ zrcheck(i_ctx_t *i_ctx_p) + int code = access_check(i_ctx_p, a_read, false); + + if (code >= 0) +- make_bool(op, code), code = 0; ++ make_bool(op, code), code = 0; + return code; + } + +@@ -229,7 +229,7 @@ zwcheck(i_ctx_t *i_ctx_p) + int code = access_check(i_ctx_p, a_write, false); + + if (code >= 0) +- make_bool(op, code), code = 0; ++ make_bool(op, code), code = 0; + return code; + } + +@@ -242,39 +242,39 @@ zcvi(i_ctx_t *i_ctx_p) + float fval; + + switch (r_type(op)) { +- case t_integer: +- return 0; +- case t_real: +- fval = op->value.realval; +- break; +- default: +- return_op_typecheck(op); +- case t_string: +- { +- ref str, token; +- int code; +- +- ref_assign(&str, op); +- code = scan_string_token(i_ctx_p, &str, &token); +- if (code > 0) /* anything other than a plain token */ +- code = gs_note_error(e_syntaxerror); +- if (code < 0) +- return code; +- switch (r_type(&token)) { +- case t_integer: +- *op = token; +- return 0; +- case t_real: +- fval = token.value.realval; +- break; +- default: +- return_error(e_typecheck); +- } +- } ++ case t_integer: ++ return 0; ++ case t_real: ++ fval = op->value.realval; ++ break; ++ default: ++ return_op_typecheck(op); ++ case t_string: ++ { ++ ref str, token; ++ int code; ++ ++ ref_assign(&str, op); ++ code = gs_scan_string_token(i_ctx_p, &str, &token); ++ if (code > 0) /* anything other than a plain token */ ++ code = gs_note_error(e_syntaxerror); ++ if (code < 0) ++ return code; ++ switch (r_type(&token)) { ++ case t_integer: ++ *op = token; ++ return 0; ++ case t_real: ++ fval = token.value.realval; ++ break; ++ default: ++ return_error(e_typecheck); ++ } ++ } + } + if (!REAL_CAN_BE_INT(fval)) +- return_error(e_rangecheck); +- make_int(op, (long)fval); /* truncates towards 0 */ ++ return_error(e_rangecheck); ++ make_int(op, (long)fval); /* truncates towards 0 */ + return 0; + } + +@@ -296,34 +296,34 @@ zcvr(i_ctx_t *i_ctx_p) + os_ptr op = osp; + + switch (r_type(op)) { +- case t_integer: +- make_real(op, (float)op->value.intval); +- case t_real: +- return 0; +- default: +- return_op_typecheck(op); +- case t_string: +- { +- ref str, token; +- int code; +- +- ref_assign(&str, op); +- code = scan_string_token(i_ctx_p, &str, &token); +- if (code > 0) /* anything other than a plain token */ +- code = gs_note_error(e_syntaxerror); +- if (code < 0) +- return code; +- switch (r_type(&token)) { +- case t_integer: +- make_real(op, (float)token.value.intval); +- return 0; +- case t_real: +- *op = token; +- return 0; +- default: +- return_error(e_typecheck); +- } +- } ++ case t_integer: ++ make_real(op, (float)op->value.intval); ++ case t_real: ++ return 0; ++ default: ++ return_op_typecheck(op); ++ case t_string: ++ { ++ ref str, token; ++ int code; ++ ++ ref_assign(&str, op); ++ code = gs_scan_string_token(i_ctx_p, &str, &token); ++ if (code > 0) /* anything other than a plain token */ ++ code = gs_note_error(e_syntaxerror); ++ if (code < 0) ++ return code; ++ switch (r_type(&token)) { ++ case t_integer: ++ make_real(op, (float)token.value.intval); ++ return 0; ++ case t_real: ++ *op = token; ++ return 0; ++ default: ++ return_error(e_typecheck); ++ } ++ } + } + } + +@@ -336,60 +336,60 @@ zcvrs(i_ctx_t *i_ctx_p) + + check_type(op[-1], t_integer); + if (op[-1].value.intval < 2 || op[-1].value.intval > 36) +- return_error(e_rangecheck); ++ return_error(e_rangecheck); + radix = op[-1].value.intval; + check_write_type(*op, t_string); + if (radix == 10) { +- switch (r_type(op - 2)) { +- case t_integer: +- case t_real: +- { +- int code = convert_to_string(imemory, op - 2, op); +- +- if (code < 0) +- return code; +- pop(2); +- return 0; +- } ++ switch (r_type(op - 2)) { ++ case t_integer: ++ case t_real: ++ { ++ int code = convert_to_string(imemory, op - 2, op); ++ ++ if (code < 0) ++ return code; ++ pop(2); ++ return 0; ++ } + case t__invalid: + return_error(e_stackunderflow); +- default: +- return_error(e_rangecheck); /* CET 24-05 wants rangecheck */ +- } ++ default: ++ return_error(e_rangecheck); /* CET 24-05 wants rangecheck */ ++ } + } else { +- uint ival; +- byte digits[sizeof(ulong) * 8]; +- byte *endp = &digits[countof(digits)]; +- byte *dp = endp; +- +- switch (r_type(op - 2)) { +- case t_integer: +- ival = (uint) op[-2].value.intval; +- break; +- case t_real: +- { +- float fval = op[-2].value.realval; +- +- if (!REAL_CAN_BE_INT(fval)) +- return_error(e_rangecheck); +- ival = (ulong) (long)fval; +- } break; ++ uint ival; ++ byte digits[sizeof(ulong) * 8]; ++ byte *endp = &digits[countof(digits)]; ++ byte *dp = endp; ++ ++ switch (r_type(op - 2)) { ++ case t_integer: ++ ival = (uint) op[-2].value.intval; ++ break; ++ case t_real: ++ { ++ float fval = op[-2].value.realval; ++ ++ if (!REAL_CAN_BE_INT(fval)) ++ return_error(e_rangecheck); ++ ival = (ulong) (long)fval; ++ } break; + case t__invalid: + return_error(e_stackunderflow); +- default: +- return_error(e_rangecheck); /* CET 24-05 wants rangecheck */ +- } +- do { +- int dit = ival % radix; +- +- *--dp = dit + (dit < 10 ? '0' : ('A' - 10)); +- ival /= radix; +- } +- while (ival); +- if (endp - dp > r_size(op)) +- return_error(e_rangecheck); +- memcpy(op->value.bytes, dp, (uint) (endp - dp)); +- r_set_size(op, endp - dp); ++ default: ++ return_error(e_rangecheck); /* CET 24-05 wants rangecheck */ ++ } ++ do { ++ int dit = ival % radix; ++ ++ *--dp = dit + (dit < 10 ? '0' : ('A' - 10)); ++ ival /= radix; ++ } ++ while (ival); ++ if (endp - dp > r_size(op)) ++ return_error(e_rangecheck); ++ memcpy(op->value.bytes, dp, (uint) (endp - dp)); ++ r_set_size(op, endp - dp); + } + op[-2] = *op; + pop(2); +@@ -407,7 +407,7 @@ zcvs(i_ctx_t *i_ctx_p) + check_op(2); + code = convert_to_string(imemory, op - 1, op); + if (code >= 0) +- pop(1); ++ pop(1); + return code; + } + +@@ -443,43 +443,43 @@ const op_def ztype_op_defs[] = + /* or if the object did not have the access already when modify=1. */ + static int + access_check(i_ctx_t *i_ctx_p, +- int access, /* mask for attrs */ +- bool modify) /* if true, reduce access */ ++ int access, /* mask for attrs */ ++ bool modify) /* if true, reduce access */ + { + os_ptr op = osp; + ref *aop; + + switch (r_type(op)) { +- case t_dictionary: +- aop = dict_access_ref(op); +- if (modify) { +- if (!r_has_attrs(aop, access)) +- return_error(e_invalidaccess); +- ref_save(op, aop, "access_check(modify)"); +- r_clear_attrs(aop, a_all); +- r_set_attrs(aop, access); +- dict_set_top(); +- return 0; +- } +- break; +- case t_array: +- case t_file: +- case t_string: +- case t_mixedarray: +- case t_shortarray: +- case t_astruct: +- case t_device:; +- if (modify) { +- if (!r_has_attrs(op, access)) +- return_error(e_invalidaccess); +- r_clear_attrs(op, a_all); +- r_set_attrs(op, access); +- return 0; +- } +- aop = op; +- break; +- default: +- return_op_typecheck(op); ++ case t_dictionary: ++ aop = dict_access_ref(op); ++ if (modify) { ++ if (!r_has_attrs(aop, access)) ++ return_error(e_invalidaccess); ++ ref_save(op, aop, "access_check(modify)"); ++ r_clear_attrs(aop, a_all); ++ r_set_attrs(aop, access); ++ dict_set_top(); ++ return 0; ++ } ++ break; ++ case t_array: ++ case t_file: ++ case t_string: ++ case t_mixedarray: ++ case t_shortarray: ++ case t_astruct: ++ case t_device:; ++ if (modify) { ++ if (!r_has_attrs(op, access)) ++ return_error(e_invalidaccess); ++ r_clear_attrs(op, a_all); ++ r_set_attrs(op, access); ++ return 0; ++ } ++ aop = op; ++ break; ++ default: ++ return_op_typecheck(op); + } + return (r_has_attrs(aop, access) ? 1 : 0); + } +@@ -495,29 +495,29 @@ convert_to_string(const gs_memory_t *mem + int code = obj_cvs(mem, op1, op->value.bytes, r_size(op), &len, &pstr); + + if (code < 0) { +- /* +- * Some common downloaded error handlers assume that +- * operator names don't exceed a certain fixed size. +- * To work around this bit of bad design, we implement +- * a special hack here: if we got a rangecheck, and +- * the object is an operator whose name begins with +- * %, ., or @, we just truncate the name. +- */ +- if (code == e_rangecheck) +- switch (r_btype(op1)) { +- case t_oparray: +- case t_operator: +- if (pstr != 0) +- switch (*pstr) { +- case '%': +- case '.': +- case '@': +- len = r_size(op); +- memcpy(op->value.bytes, pstr, len); +- goto ok; +- } +- } +- return code; ++ /* ++ * Some common downloaded error handlers assume that ++ * operator names don't exceed a certain fixed size. ++ * To work around this bit of bad design, we implement ++ * a special hack here: if we got a rangecheck, and ++ * the object is an operator whose name begins with ++ * %, ., or @, we just truncate the name. ++ */ ++ if (code == e_rangecheck) ++ switch (r_btype(op1)) { ++ case t_oparray: ++ case t_operator: ++ if (pstr != 0) ++ switch (*pstr) { ++ case '%': ++ case '.': ++ case '@': ++ len = r_size(op); ++ memcpy(op->value.bytes, pstr, len); ++ goto ok; ++ } ++ } ++ return code; + } + ok: + *op1 = *op; diff --git a/ghostscript.spec b/ghostscript.spec index 43d093b..0b85309 100644 --- a/ghostscript.spec +++ b/ghostscript.spec @@ -5,7 +5,7 @@ Summary: A PostScript interpreter and renderer Name: ghostscript Version: %{gs_ver} -Release: 9%{?dist} +Release: 10%{?dist} # Included CMap data is Redistributable, no modification permitted, # see http://bugzilla.redhat.com/487510 @@ -19,6 +19,7 @@ Source4: cidfmap Patch1: ghostscript-multilib.patch Patch2: ghostscript-scripts.patch Patch3: ghostscript-noopt.patch +Patch4: ghostscript-scan_token.patch Patch5: ghostscript-runlibfileifexists.patch Patch6: ghostscript-system-jasper.patch Patch7: ghostscript-pksmraw.patch @@ -114,6 +115,9 @@ rm -rf libpng zlib jpeg jasper # Build igcref.c with -O0 to work around bug #150771. %patch3 -p1 -b .noopt +# Avoid symbol clash with scan_token (bug #590914). +%patch4 -p1 -b .scan_token + # Define .runlibfileifexists. %patch5 -p1 @@ -340,6 +344,9 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/libgs.so %changelog +* Fri Jan 14 2011 Tim Waugh 9.00-10 +- Avoid symbol clash with scan_token (bug #590914). + * Mon Jan 10 2011 Tim Waugh 9.00-9 - Replaced width-and-height patch with the one actually used upstream.