summaryrefslogtreecommitdiff
path: root/psi
diff options
context:
space:
mode:
authorSam James <sam@gentoo.org>2022-03-29 10:27:10 +0100
committerSam James <sam@gentoo.org>2022-04-17 12:53:05 +0100
commit085bde903b9e684c3c1160e4df912bea9a660997 (patch)
treec4f5e6e9f2422e869ca5bc0b944520d451001282 /psi
parentImport Ghostscript 9.55 (diff)
downloadghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.tar.gz
ghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.tar.bz2
ghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.zip
Import Ghostscript 9.56.0ghostscript-9.56
Signed-off-by: Sam James <sam@gentoo.org>
Diffstat (limited to 'psi')
-rw-r--r--psi/bfont.h2
-rw-r--r--psi/dmmain.c6
-rw-r--r--psi/dpmain.c52
-rw-r--r--psi/dscparse.c8
-rw-r--r--psi/iapi.c51
-rw-r--r--psi/iapi.h15
-rw-r--r--psi/idebug.c4
-rw-r--r--psi/idict.c4
-rw-r--r--psi/idstack.c6
-rw-r--r--psi/igc.c3
-rw-r--r--psi/igcstr.c29
-rw-r--r--psi/imain.c2
-rw-r--r--psi/imainarg.c7
-rw-r--r--psi/interp.c7
-rw-r--r--psi/iparam.c4
-rw-r--r--psi/iref.h8
-rw-r--r--psi/iscan.c27
-rw-r--r--psi/iscan.h16
-rw-r--r--psi/iutil.c29
-rw-r--r--psi/iutil2.c4
-rw-r--r--psi/msvc.mak153
-rw-r--r--psi/nsisinst.nsi37
-rw-r--r--psi/os2.mak4
-rw-r--r--psi/psapi.c27
-rw-r--r--psi/winint.mak4
-rw-r--r--psi/zbfont.c11
-rw-r--r--psi/zcolor.c3
-rw-r--r--psi/zdevice.c152
-rw-r--r--psi/zdouble.c10
-rw-r--r--psi/zfapi.c25
-rw-r--r--psi/zfarc4.c3
-rw-r--r--psi/zfile.c17
-rw-r--r--psi/zfont2.c4
-rw-r--r--psi/zht.c4
-rw-r--r--psi/zpcolor.c4
-rw-r--r--psi/zpdfops.c690
36 files changed, 843 insertions, 589 deletions
diff --git a/psi/bfont.h b/psi/bfont.h
index 184c11f7..3e340e53 100644
--- a/psi/bfont.h
+++ b/psi/bfont.h
@@ -85,6 +85,6 @@ gs_glyph zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t ignored
int gs_font_map_glyph_to_unicode(gs_font *font, gs_glyph glyph, int ch, unsigned short *unicode_return, unsigned int length);
const ref *zfont_get_to_unicode_map(gs_font_dir *dir);
void get_GlyphNames2Unicode(i_ctx_t *i_ctx_p, gs_font *pfont, ref *pdref);
-void get_zfont_glyph_name( void **proc);
+void get_zfont_glyph_name(int (**proc)(gs_font *font, gs_glyph glyph, gs_const_string *pstr) );
#endif /* bfont_INCLUDED */
diff --git a/psi/dmmain.c b/psi/dmmain.c
index 1af0d787..7fee9157 100644
--- a/psi/dmmain.c
+++ b/psi/dmmain.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -640,8 +640,8 @@ void main(void)
argv[1] = ddevice;
argv[2] = dformat;
- gs_sprintf(ddevice, "-sDEVICE=display");
- gs_sprintf(dformat, "-dDisplayFormat=%d", display_format);
+ gs_snprintf(ddevice, sizeof(ddevice), "-sDEVICE=display");
+ gs_snprintf(dformat, sizeof(dformat), "-dDisplayFormat=%d", display_format);
/* Run Ghostscript */
if (gsapi_new_instance(&instance, NULL) < 0)
diff --git a/psi/dpmain.c b/psi/dpmain.c
index e862f378..50d39486 100644
--- a/psi/dpmain.c
+++ b/psi/dpmain.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -116,9 +116,9 @@ gs_free_dll(void)
return TRUE;
rc = DosFreeModule(gsdll.hmodule);
if (rc) {
- gs_sprintf(buf, "DosFreeModule returns %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "DosFreeModule returns %d\n", rc);
gs_addmess(buf);
- gs_sprintf(buf, "Unloaded GSDLL\n\n");
+ gs_snprintf(buf, sizeof(buf), "Unloaded GSDLL\n\n");
gs_addmess(buf);
}
return !rc;
@@ -166,7 +166,7 @@ gs_load_dll(void)
dllname = szDllName;
#ifdef DEBUG
if (debug) {
- gs_sprintf(buf, "Trying to load %s\n", dllname);
+ gs_snprintf(buf, sizeof(buf), "Trying to load %s\n", dllname);
gs_addmess(buf);
}
#endif
@@ -188,7 +188,7 @@ gs_load_dll(void)
dllname = fullname;
#ifdef DEBUG
if (debug) {
- gs_sprintf(buf, "Trying to load %s\n", dllname);
+ gs_snprintf(buf, sizeof(buf), "Trying to load %s\n", dllname);
gs_addmess(buf);
}
#endif
@@ -199,7 +199,7 @@ gs_load_dll(void)
dllname = shortname;
#ifdef DEBUG
if (debug) {
- gs_sprintf(buf, "Trying to load %s\n", dllname);
+ gs_snprintf(buf, sizeof(buf), "Trying to load %s\n", dllname);
gs_addmess(buf);
}
#endif
@@ -213,21 +213,21 @@ gs_load_dll(void)
#endif
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_REVISION",
(PFN *) (&gsdll.revision))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_REVISION, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_REVISION, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
/* check DLL version */
if (gsdll.revision(&rv, sizeof(rv)) != 0) {
- gs_sprintf(buf, "Unable to identify Ghostscript DLL revision - it must be newer than needed.\n");
+ gs_snprintf(buf, sizeof(buf), "Unable to identify Ghostscript DLL revision - it must be newer than needed.\n");
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
if (rv.revision != GS_REVISION) {
- gs_sprintf(buf, "Wrong version of DLL found.\n Found version %ld\n Need version %ld\n", rv.revision, (long)GS_REVISION);
+ gs_snprintf(buf, sizeof(buf), "Wrong version of DLL found.\n Found version %ld\n Need version %ld\n", rv.revision, (long)GS_REVISION);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
@@ -235,35 +235,35 @@ gs_load_dll(void)
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_NEW_INSTANCE",
(PFN *) (&gsdll.new_instance))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_NEW_INSTANCE, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_NEW_INSTANCE, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_DELETE_INSTANCE",
(PFN *) (&gsdll.delete_instance))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_DELETE_INSTANCE, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_DELETE_INSTANCE, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_SET_STDIO",
(PFN *) (&gsdll.set_stdio))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_SET_STDIO, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_SET_STDIO, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_SET_DISPLAY_CALLBACK",
(PFN *) (&gsdll.set_display_callback))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_SET_DISPLAY_CALLBACK, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_SET_DISPLAY_CALLBACK, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_SET_POLL",
(PFN *) (&gsdll.set_poll))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_SET_POLL, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_SET_POLL, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
@@ -271,27 +271,27 @@ gs_load_dll(void)
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0,
"GSAPI_INIT_WITH_ARGS",
(PFN *) (&gsdll.init_with_args))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_INIT_WITH_ARGS, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_INIT_WITH_ARGS, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_RUN_STRING",
(PFN *) (&gsdll.run_string))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_RUN_STRING, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_RUN_STRING, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
if ((rc = DosQueryProcAddr(gsdll.hmodule, 0, "GSAPI_EXIT",
(PFN *) (&gsdll.exit))) != 0) {
- gs_sprintf(buf, "Can't find GSAPI_EXIT, rc = %d\n", rc);
+ gs_snprintf(buf, sizeof(buf), "Can't find GSAPI_EXIT, rc = %d\n", rc);
gs_addmess(buf);
gs_load_dll_cleanup();
return FALSE;
}
} else {
- gs_sprintf(buf, "Can't load Ghostscript DLL %s \nDosLoadModule rc = %d\n",
+ gs_snprintf(buf, sizeof(buf), "Can't load Ghostscript DLL %s \nDosLoadModule rc = %d\n",
szDllName, rc);
gs_addmess(buf);
gs_load_dll_cleanup();
@@ -389,10 +389,10 @@ static int run_gspmdrv(IMAGE *img)
if (debug)
fprintf(stdout, "run_gspmdrv: starting\n");
#endif
- gs_sprintf(id, ID_NAME, img->pid, (ULONG)img->device);
+ gs_snprintf(id, sizeof(id), ID_NAME, img->pid, (ULONG)img->device);
/* Create termination queue - used to find out when gspmdrv terminates */
- gs_sprintf(term_queue_name, "\\QUEUES\\TERMQ_%s", id);
+ gs_snprintf(term_queue_name, sizeof(term_queue_name), "\\QUEUES\\TERMQ_%s", id);
if (DosCreateQueue(&(img->term_queue), QUE_FIFO, term_queue_name)) {
fprintf(stdout, "run_gspmdrv: failed to create termination queue\n");
return gs_error_limitcheck;
@@ -420,7 +420,7 @@ static int run_gspmdrv(IMAGE *img)
/* arguments are: */
/* (1) -d (display) option */
/* (2) id string */
- gs_sprintf(arg, "-d %s", id);
+ gs_snprintf(arg, sizeof(arg), "-d %s", id);
/* because gspmdrv.exe is a different EXE type to gs.exe,
* we must use start session not DosExecPgm() */
@@ -608,17 +608,17 @@ int display_open(void *handle, void *device)
return gs_error_limitcheck;
}
img->pid = pppib->pib_ulppid; /* use parent (CMD.EXE) pid */
- gs_sprintf(id, ID_NAME, img->pid, (ULONG) img->device);
+ gs_snprintf(id, sizeof(id), ID_NAME, img->pid, (ULONG) img->device);
/* Create update event semaphore */
- gs_sprintf(name, SYNC_NAME, id);
+ gs_snprintf(name, sizeof(name), SYNC_NAME, id);
if (DosCreateEventSem(name, &(img->sync_event), 0, FALSE)) {
fprintf(stdout, "display_open: failed to create event semaphore %s\n", name);
return gs_error_limitcheck;
}
/* Create mutex - used for preventing gspmdrv from accessing */
/* bitmap while we are changing the bitmap size. Initially unowned. */
- gs_sprintf(name, MUTEX_NAME, id);
+ gs_snprintf(name, sizeof(name), MUTEX_NAME, id);
if (DosCreateMutexSem(name, &(img->bmp_mutex), 0, FALSE)) {
DosCloseEventSem(img->sync_event);
fprintf(stdout, "display_open: failed to create mutex semaphore %s\n", name);
@@ -628,7 +628,7 @@ int display_open(void *handle, void *device)
/* Shared memory is common to all processes so we don't want to
* allocate too much.
*/
- gs_sprintf(name, SHARED_NAME, id);
+ gs_snprintf(name, sizeof(name), SHARED_NAME, id);
if (DosAllocSharedMem((PPVOID) & img->bitmap, name,
13 * 1024 * 1024, PAG_READ | PAG_WRITE)) {
fprintf(stdout, "display_open: failed allocating shared BMP memory %s\n", name);
@@ -1036,7 +1036,7 @@ main(int argc, char *argv[])
else if (depth >= 4)
format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE |
DISPLAY_DEPTH_4 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST;
- gs_sprintf(dformat, "-dDisplayFormat=%d", format);
+ gs_snprintf(dformat, sizeof(dformat), "-dDisplayFormat=%d", format);
}
nargc = argc + 1;
diff --git a/psi/dscparse.c b/psi/dscparse.c
index 630ab415..2de653d1 100644
--- a/psi/dscparse.c
+++ b/psi/dscparse.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -584,7 +584,7 @@ dsc_fixup(CDSC *dsc)
/* make sure all pages have a label */
for (i=0; i<dsc->page_count; i++) {
if (strlen(dsc->page[i].label) == 0) {
- gs_sprintf(buf, "%d", i+1);
+ gs_snprintf(buf, sizeof(buf), "%d", i+1);
if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, (int)strlen(buf)))
== (char *)NULL)
return CDSC_ERROR; /* no memory */
@@ -1178,7 +1178,7 @@ dsc_unknown(CDSC *dsc)
if (dsc->debug_print_fn) {
char line[DSC_LINE_LENGTH];
unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length);
- gs_sprintf(line, "Unknown in %s section at line %d:\n ",
+ gs_snprintf(line, DSC_LINE_LENGTH, "Unknown in %s section at line %d:\n ",
dsc_scan_section_name[dsc->scan_section], dsc->line_count);
dsc_debug_print(dsc, line);
strncpy(line, dsc->line, length);
@@ -2674,7 +2674,7 @@ dsc_check_match_prompt(CDSC *dsc, const char *str, int count)
if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1))
strncpy(buf, dsc->line, dsc->line_length);
- gs_sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
+ gs_snprintf(buf+strlen(buf), MAXSTR + MAXSTR - strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, (int)strlen(buf));
}
return CDSC_RESPONSE_CANCEL;
diff --git a/psi/iapi.c b/psi/iapi.c
index a172a6c7..7ca1b42c 100644
--- a/psi/iapi.c
+++ b/psi/iapi.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -74,6 +74,9 @@ gsapi_new_instance(void **pinstance, void *caller_handle)
GSDLLEXPORT void GSDLLAPI
gsapi_delete_instance(void *instance)
{
+ if (instance == NULL)
+ return;
+ gp_set_debug_mem_ptr(((gs_lib_ctx_t *)instance)->memory);
psapi_delete_instance(instance);
}
@@ -167,6 +170,7 @@ gsapi_set_display_callback(void *instance, display_callback *callback)
int code;
if (instance == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
minst = get_minst_from_memory(ctx->memory);
if (minst->display == NULL && callback != NULL) {
/* First registration. */
@@ -193,6 +197,7 @@ gsapi_register_callout(void *instance, gs_callout fn, void *handle)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (instance == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return gs_lib_ctx_register_callout(ctx->memory, fn, handle);
}
@@ -202,6 +207,7 @@ gsapi_deregister_callout(void *instance, gs_callout fn, void *handle)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (instance == NULL)
return;
+ gp_set_debug_mem_ptr(ctx->memory);
gs_lib_ctx_deregister_callout(ctx->memory, fn, handle);
}
@@ -212,6 +218,7 @@ gsapi_set_default_device_list(void *instance, const char *list, int listlen)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (instance == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return gs_lib_ctx_set_default_device_list(ctx->memory, list, listlen);
}
@@ -221,6 +228,7 @@ gsapi_get_default_device_list(void *instance, char **list, int *listlen)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (instance == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return gs_lib_ctx_get_default_device_list(ctx->memory, list, listlen);
}
@@ -229,6 +237,9 @@ GSDLLEXPORT int GSDLLAPI
gsapi_set_arg_encoding(void *instance, int encoding)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_set_arg_encoding(ctx, encoding);
}
@@ -236,6 +247,9 @@ GSDLLEXPORT int GSDLLAPI
gsapi_init_with_args(void *instance, int argc, char **argv)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_init_with_args(ctx, argc, argv);
}
@@ -251,6 +265,9 @@ gsapi_run_string_begin(void *instance,
int *pexit_code)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_run_string_begin(ctx, user_errors, pexit_code);
}
@@ -262,6 +279,9 @@ gsapi_run_string_continue(void *instance,
int *pexit_code)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_run_string_continue(ctx, str, length, user_errors, pexit_code);
}
@@ -271,6 +291,9 @@ gsapi_run_string_end(void *instance,
int *pexit_code)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_run_string_end(ctx, user_errors, pexit_code);
}
@@ -282,6 +305,9 @@ gsapi_run_string_with_length(void *instance,
int *pexit_code)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_run_string_with_length(ctx, str, length, user_errors, pexit_code);
}
@@ -292,6 +318,9 @@ gsapi_run_string(void *instance,
int *pexit_code)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_run_string_with_length(ctx,
str,
(unsigned int)strlen(str),
@@ -306,6 +335,9 @@ gsapi_run_file(void *instance,
int *pexit_code)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_run_file(ctx, file_name, user_errors, pexit_code);
}
@@ -321,6 +353,7 @@ gsapi_init_with_argsW(void *instance,
if (instance == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
old = gs_main_inst_get_arg_decode(get_minst_from_memory(ctx->memory));
code = psapi_set_arg_encoding(ctx, PS_ARG_ENCODING_UTF16LE);
if (code != 0)
@@ -341,6 +374,7 @@ gsapi_init_with_argsA(void *instance,
if (instance == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
old = gs_main_inst_get_arg_decode(get_minst_from_memory(ctx->memory));
code = psapi_set_arg_encoding(ctx, PS_ARG_ENCODING_LOCAL);
if (code != 0)
@@ -362,6 +396,7 @@ gsapi_run_fileW(void *instance,
if (instance == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
old = gs_main_inst_get_arg_decode(get_minst_from_memory(ctx->memory));
code = psapi_set_arg_encoding(ctx, PS_ARG_ENCODING_UTF16LE);
if (code != 0)
@@ -383,6 +418,7 @@ gsapi_run_fileA(void *instance,
if (instance == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
old = gs_main_inst_get_arg_decode(get_minst_from_memory(ctx->memory));
code = psapi_set_arg_encoding(ctx, PS_ARG_ENCODING_LOCAL);
if (code != 0)
@@ -398,6 +434,9 @@ GSDLLEXPORT int GSDLLAPI
gsapi_exit(void *instance)
{
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
+ if (instance == NULL)
+ return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return psapi_exit(ctx);
}
@@ -414,6 +453,7 @@ gsapi_set_param(void *lib, const char *param, const void *value, gs_set_param_ty
if (lib == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
minst = get_minst_from_memory(ctx->memory);
/* First off, ensure we have a param list to work with. */
@@ -518,6 +558,7 @@ gsapi_get_param(void *lib, const char *param, void *value, gs_set_param_type typ
if (lib == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
gs_c_param_list_write(&params, ctx->memory);
/* Should never be set, but clear the more to come bit anyway in case. */
@@ -673,6 +714,7 @@ gsapi_enumerate_params(void *instance, void **iter, const char **key, gs_set_par
if (ctx == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
minst = get_minst_from_memory(ctx->memory);
params = &minst->enum_params;
@@ -780,6 +822,7 @@ gsapi_add_control_path(void *instance, int type, const char *path)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (ctx == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return gs_add_control_path(ctx->memory, type, path);
}
@@ -789,6 +832,7 @@ gsapi_remove_control_path(void *instance, int type, const char *path)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (ctx == NULL)
return gs_error_Fatal;
+ gp_set_debug_mem_ptr(ctx->memory);
return gs_remove_control_path(ctx->memory, type, path);
}
@@ -798,6 +842,7 @@ gsapi_purge_control_paths(void *instance, int type)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (ctx == NULL)
return;
+ gp_set_debug_mem_ptr(ctx->memory);
gs_purge_control_paths(ctx->memory, type);
}
@@ -807,6 +852,7 @@ gsapi_activate_path_control(void *instance, int enable)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (ctx == NULL)
return;
+ gp_set_debug_mem_ptr(ctx->memory);
gs_activate_path_control(ctx->memory, enable);
}
@@ -816,6 +862,7 @@ gsapi_is_path_control_active(void *instance)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (ctx == NULL)
return 0;
+ gp_set_debug_mem_ptr(ctx->memory);
return gs_is_path_control_active(ctx->memory);
}
@@ -825,6 +872,7 @@ gsapi_add_fs(void *instance, gsapi_fs_t *fs, void *secret)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (ctx == NULL)
return 0;
+ gp_set_debug_mem_ptr(ctx->memory);
return gs_add_fs(ctx->memory, (gs_fs_t *)fs, secret);
}
@@ -834,6 +882,7 @@ gsapi_remove_fs(void *instance, gsapi_fs_t *fs, void *secret)
gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)instance;
if (ctx == NULL)
return;
+ gp_set_debug_mem_ptr(ctx->memory);
gs_remove_fs(ctx->memory, (gs_fs_t *)fs, secret);
}
diff --git a/psi/iapi.h b/psi/iapi.h
index 70033fa3..2c72a229 100644
--- a/psi/iapi.h
+++ b/psi/iapi.h
@@ -153,10 +153,10 @@ gsapi_revision(gsapi_revision_t *pr, int len);
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
- * Ghostscript supports only one instance.
- * The current implementation uses a global static instance
- * counter to make sure that only a single instance is used.
- * If you try to create two instances, the second attempt
+ * On non-threading capable platforms, Ghostscript supports only
+ * one instance. The current implementation uses a global static
+ * instance counter to make sure that only a single instance is
+ * used. If you try to create two instances, the second attempt
* will return < 0 and set pinstance to NULL.
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*/
@@ -170,9 +170,10 @@ gsapi_new_instance(void **pinstance, void *caller_handle);
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
- * Ghostscript supports only one instance.
- * The current implementation uses a global static instance
- * counter to make sure that only a single instance is used.
+ * On non-threading capable platforms, Ghostscript supports only
+ * one instance. The current implementation uses a global static
+ * instance counter to make sure that only a single instance is
+ * used.
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*/
/* Destroy an instance of Ghostscript
diff --git a/psi/idebug.c b/psi/idebug.c
index 796b5371..c1ce062c 100644
--- a/psi/idebug.c
+++ b/psi/idebug.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -74,7 +74,7 @@ debug_print_full_ref(const gs_memory_t *mem, const ref * pref)
dmprintf1(mem, "boolean %x", pref->value.boolval);
break;
case t_device:
- dmprintf1(mem, "device "PRI_INTPTR, (intptr_t) pref->value.pdevice);
+ dmprintf1(mem, "device "PRI_INTPTR, (intptr_t) pref->value.pdevice->device);
break;
case t_dictionary:
dmprintf3(mem, "dict(%u/%u)"PRI_INTPTR,
diff --git a/psi/idict.c b/psi/idict.c
index 1078dff7..d15c9b11 100644
--- a/psi/idict.c
+++ b/psi/idict.c
@@ -75,7 +75,9 @@ enum {
static int dict_create_contents(uint size, const ref * pdref, bool pack);
/* Debugging statistics - uses a static, so not threadsafe. */
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
+/* #define COLLECT_STATS_IDICT */
+
+#ifdef COLLECT_STATS_IDICT
struct stats_dict_s {
long lookups; /* total lookups */
long probe1; /* successful lookups on only 1 probe */
diff --git a/psi/idstack.c b/psi/idstack.c
index e43673c3..701cd8d0 100644
--- a/psi/idstack.c
+++ b/psi/idstack.c
@@ -30,7 +30,9 @@
*/
/* Debugging statistics */
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
+/* #define COLLECT_STATS_IDSTACK */
+
+#ifdef COLLECT_STATS_IDSTACK
#include "idebug.h"
#define MAX_STATS_DEPTH 6
struct stats_dstack_s {
@@ -43,7 +45,7 @@ struct stats_dstack_s {
# define INCR(v) DO_NOTHING
#endif
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
+#ifdef COLLECT_STATS_IDSTACK
/* Wrapper for dstack_find_name_by_index */
ref *real_dstack_find_name_by_index(dict_stack_t * pds, uint nidx);
ref *
diff --git a/psi/igc.c b/psi/igc.c
index 420a013a..373cdcc3 100644
--- a/psi/igc.c
+++ b/psi/igc.c
@@ -786,7 +786,8 @@ gc_trace_clump(const gs_memory_t *mem, clump_t * cp, gc_state_t * pstate, gc_mar
/* 1 if we completed and marked some new objects. */
static int gc_extend_stack(gc_mark_stack *, gc_state_t *);
static int
-gc_trace(gs_gc_root_t * rp, gc_state_t * pstate, gc_mark_stack * pmstack)
+gc_trace(gs_gc_root_t * rp, /* lgtm [cpp/use-of-goto] */
+ gc_state_t * pstate, gc_mark_stack * pmstack)
{
int min_trace = pstate->min_collect;
gc_mark_stack *pms = pmstack;
diff --git a/psi/igcstr.c b/psi/igcstr.c
index 4c4baf3c..0e10f74b 100644
--- a/psi/igcstr.c
+++ b/psi/igcstr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -35,7 +35,7 @@ gc_strings_set_marks(clump_t * cp, bool mark)
(intptr_t)cp->smark, cp->smark_size, (int)mark);
memset(cp->smark, 0, cp->smark_size);
if (mark)
- gc_mark_string(cp->sbase + HDR_ID_OFFSET, (cp->climit - cp->sbase) - HDR_ID_OFFSET, true, cp);
+ gc_mark_string(cp->sbase, (cp->climit - cp->sbase), true, cp);
}
}
@@ -63,11 +63,11 @@ typedef string_mark_unit bword;
static bool
gc_mark_string(const byte * ptr, uint size, bool set, const clump_t * cp)
{
- uint offset = (ptr - HDR_ID_OFFSET) - cp->sbase;
+ uint offset = ptr - cp->sbase;
bword *bp = (bword *) (cp->smark + ((offset & -bword_bits) >> 3));
uint bn = offset & (bword_bits - 1);
bword m = bword_1s << bn;
- uint left = size + HDR_ID_OFFSET;
+ uint left = size;
bword marks = 0;
bword_swap_bytes(m);
@@ -136,12 +136,12 @@ gc_string_mark(const byte * ptr, uint size, bool set, gc_state_t * gcst)
if (size == 0)
return false;
#define dmprintstr(mem)\
- dmputc(mem, '('); dmfwrite(mem, ptr - HDR_ID_OFFSET, min(size, 20));\
+ dmputc(mem, '('); dmfwrite(mem, ptr, min(size, 20));\
dmputs(mem, (size <= 20 ? ")" : "...)"))
- if (!(cp = gc_locate(ptr - HDR_ID_OFFSET, gcst))) { /* not in a clump */
+ if (!(cp = gc_locate(ptr, gcst))) { /* not in a clump */
#ifdef DEBUG
if (gs_debug_c('5')) {
- dmlprintf2(gcst->heap, "[5]"PRI_INTPTR"[%u]", (intptr_t)ptr - HDR_ID_OFFSET, size);
+ dmlprintf2(gcst->heap, "[5]"PRI_INTPTR"[%u]", (intptr_t)ptr, size);
dmprintstr(gcst->heap);
dmputs(gcst->heap, " not in a clump\n");
}
@@ -151,9 +151,9 @@ gc_string_mark(const byte * ptr, uint size, bool set, gc_state_t * gcst)
if (cp->smark == 0) /* not marking strings */
return false;
#ifdef DEBUG
- if (ptr - HDR_ID_OFFSET < cp->ctop) {
+ if (ptr < cp->ctop) {
lprintf4("String pointer "PRI_INTPTR"[%u] outside ["PRI_INTPTR".."PRI_INTPTR")\n",
- (intptr_t)ptr - HDR_ID_OFFSET, size, (intptr_t)cp->ctop, (intptr_t)cp->climit);
+ (intptr_t)ptr, size, (intptr_t)cp->ctop, (intptr_t)cp->climit);
return false;
} else if (ptr + size > cp->climit) { /*
* If this is the bottommost string in a clump that has
@@ -168,11 +168,11 @@ gc_string_mark(const byte * ptr, uint size, bool set, gc_state_t * gcst)
*/
const clump_t *scp = cp;
- while (ptr - HDR_ID_OFFSET == scp->climit && scp->outer != 0)
+ while (ptr == scp->climit && scp->outer != 0)
scp = scp->outer;
- if (ptr - HDR_ID_OFFSET + size > scp->climit) {
+ if (ptr + size > scp->climit) {
lprintf4("String pointer "PRI_INTPTR"[%u] outside ["PRI_INTPTR".."PRI_INTPTR")\n",
- (intptr_t)ptr - HDR_ID_OFFSET, size,
+ (intptr_t)ptr, size,
(intptr_t)scp->ctop, (intptr_t)scp->climit);
return false;
}
@@ -183,7 +183,7 @@ gc_string_mark(const byte * ptr, uint size, bool set, gc_state_t * gcst)
if (gs_debug_c('5')) {
dmlprintf4(gcst->heap, "[5]%s%smarked "PRI_INTPTR"[%u]",
(marks ? "" : "already "), (set ? "" : "un"),
- (intptr_t)ptr - HDR_ID_OFFSET, size);
+ (intptr_t)ptr, size);
dmprintstr(gcst->heap);
dmputc(gcst->heap, '\n');
}
@@ -291,7 +291,6 @@ igc_reloc_string(gs_string * sptr, gc_state_t * gcst)
return;
}
ptr = sptr->data;
- ptr -= HDR_ID_OFFSET;
if (!(cp = gc_locate(ptr, gcst))) /* not in a clump */
return;
@@ -322,7 +321,7 @@ igc_reloc_string(gs_string * sptr, gc_state_t * gcst)
reloc -= byte_count_one_bits(byt);
if_debug2('5', "[5]relocate string "PRI_INTPTR" to 0x%lx\n",
(intptr_t)ptr, (intptr_t)(cp->sdest - reloc));
- sptr->data = (cp->sdest - reloc) + HDR_ID_OFFSET;
+ sptr->data = (cp->sdest - reloc);
}
void
igc_reloc_const_string(gs_const_string * sptr, gc_state_t * gcst)
diff --git a/psi/imain.c b/psi/imain.c
index 72064aba..26585932 100644
--- a/psi/imain.c
+++ b/psi/imain.c
@@ -531,7 +531,7 @@ gs_main_init2(gs_main_instance * minst)
if (code >= 0) {
if (gs_debug_c(':'))
print_resource_usage(minst, &gs_imemory, "Start");
- gp_readline_init(&minst->readline_data, minst->heap);
+ gp_readline_init(&minst->readline_data, minst->heap); /* lgtm [cpp/useless-expression] */
}
fail:
diff --git a/psi/imainarg.c b/psi/imainarg.c
index f5fe1f3e..aaf41b6b 100644
--- a/psi/imainarg.c
+++ b/psi/imainarg.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -833,7 +833,10 @@ run_stdin:
if (strlen(adef) == 10 && strncmp(adef, "OutputFile", 10) == 0 && strlen(eqp) > 0) {
code = gs_add_outputfile_control_path(minst->heap, eqp);
- if (code < 0) return code;
+ if (code < 0) {
+ arg_free((char *)adef, minst->heap);
+ return code;
+ }
}
ialloc_set_space(idmemory, avm_system);
diff --git a/psi/interp.c b/psi/interp.c
index 2cf9d4a6..b577f129 100644
--- a/psi/interp.c
+++ b/psi/interp.c
@@ -116,7 +116,9 @@ do_call_operator_verbose(op_proc_t op_proc, i_ctx_t *i_ctx_p)
#endif
/* Define debugging statistics (not threadsafe as uses globals) */
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
+/* #define COLLECT_STATS_IDSTACK */
+
+#ifdef COLLECT_STATS_INTERP
struct stats_interp_s {
long top;
long lit, lit_array, exec_array, exec_operator, exec_name;
@@ -910,7 +912,8 @@ gs_errorinfo_put_string(i_ctx_t *i_ctx_p, const char *str)
/* If an error occurs, leave the current object in *perror_object */
/* and return a (negative) error code. */
static int
-interp(i_ctx_t **pi_ctx_p /* context for execution, updated if resched */,
+interp(/* lgtm [cpp/use-of-goto] */
+ i_ctx_t **pi_ctx_p /* context for execution, updated if resched */,
const ref * pref /* object to interpret */,
ref * perror_object)
{
diff --git a/psi/iparam.c b/psi/iparam.c
index 7fe1cb0d..c35b516e 100644
--- a/psi/iparam.c
+++ b/psi/iparam.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -65,7 +65,7 @@ ref_to_key(const ref * pref, gs_param_key_t * key, iparam_list *plist)
int len;
byte *buf;
- gs_sprintf(istr, "%"PRIpsint, pref->value.intval);
+ gs_snprintf(istr, sizeof(istr), "%"PRIpsint, pref->value.intval);
len = strlen(istr);
/* GC will take care of freeing this: */
buf = gs_alloc_string(plist->memory, len, "ref_to_key");
diff --git a/psi/iref.h b/psi/iref.h
index 099ff93b..85cc97cf 100644
--- a/psi/iref.h
+++ b/psi/iref.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -405,6 +405,10 @@ typedef int (*op_proc_t)(i_ctx_t *i_ctx_p);
/* real_opproc is a holdover.... */
#define real_opproc(pref) ((pref)->value.opproc)
+typedef struct psi_device_ref_s {
+ struct gx_device_s *device;
+} psi_device_ref;
+
/* Object reference */
/*
* Note that because of the way packed arrays are represented,
@@ -446,7 +450,7 @@ struct ref_s {
ref_packed *writable_packed;
op_proc_t opproc;
struct stream_s *pfile;
- struct gx_device_s *pdevice;
+ struct psi_device_ref_s *pdevice;
obj_header_t *pstruct;
uint64_t dummy; /* force 16-byte ref on 32-bit platforms */
} value;
diff --git a/psi/iscan.c b/psi/iscan.c
index 11947354..3fc14af4 100644
--- a/psi/iscan.c
+++ b/psi/iscan.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -44,16 +44,6 @@
#include "store.h"
#include "scanchar.h"
-/* Procedure for handling DSC comments if desired. */
-/* Set at initialization if a DSC handling module is included. */
-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 gs_scan_comment_proc and gs_scan_dsc_proc are set, */
-/* scan_comment_proc is called only for non-DSC comments. */
-int (*gs_scan_comment_proc) (const byte *, uint) = NULL;
-
/*
* Level 2 includes some changes in the scanner:
* - \ is always recognized in strings, regardless of the data source;
@@ -127,10 +117,11 @@ dynamic_grow(da_ptr pda, byte * next, uint max_size)
pda->next = next;
if (old_size >= max_size)
return_error(gs_error_limitcheck);
- while ((code = dynamic_resize(pda, new_size)) < 0 &&
- new_size > old_size
- ) { /* Try trimming down the requested new size. */
+ while ((code = dynamic_resize(pda, new_size)) < 0) {
+ /* Try trimming down the requested new size. */
new_size -= (new_size - old_size + 1) >> 1;
+ if (new_size <= old_size)
+ break;
}
return code;
}
@@ -355,10 +346,6 @@ scan_comment(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate,
dmputs(imemory, "\n");
}
#endif
- 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;
@@ -374,10 +361,6 @@ scan_comment(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate,
}
}
#endif
- 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;
diff --git a/psi/iscan.h b/psi/iscan.h
index 343239df..b23845d1 100644
--- a/psi/iscan.h
+++ b/psi/iscan.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -188,18 +188,4 @@ int gs_scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate,
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 (*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 gs_scan_dsc_proc and gs_scan_comment_proc are set,
- * gs_scan_comment_proc is called only for non-DSC comments.
- */
-extern int (*gs_scan_comment_proc) (const byte *, uint);
-
#endif /* iscan_INCLUDED */
diff --git a/psi/iutil.c b/psi/iutil.c
index ea582e6e..39a0a316 100644
--- a/psi/iutil.c
+++ b/psi/iutil.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -176,7 +176,7 @@ obj_eq(const gs_memory_t *mem, const ref * pref1, const ref * pref2)
return (!bytes_compare(pref1->value.bytes, r_size(pref1),
pref2->value.bytes, r_size(pref2)));
case t_device:
- return (pref1->value.pdevice == pref2->value.pdevice);
+ return (pref1->value.pdevice->device == pref2->value.pdevice->device);
case t_struct:
case t_astruct:
case t_pdfctx:
@@ -304,7 +304,7 @@ obj_string_data(const gs_memory_t *mem, const ref *op, const byte **pchars, uint
* repeatedly to print on a stream, which may require suspending at any
* point to handle stream callouts.
*/
-static void ensure_dot(char *);
+static void ensure_dot(char *, size_t);
int
obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
int full_print, uint start_pos, const gs_memory_t *mem, bool restart)
@@ -340,15 +340,15 @@ obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
*/
float value = op->value.realval;
float scanned;
- code = gs_sprintf(buf, "%g", value);
+ code = gs_snprintf(buf, sizeof(buf), "%g", value);
if (code <= 0)
return_error(gs_error_undefinedresult);
code = sscanf(buf, "%f", &scanned);
if (code <= 0)
return_error(gs_error_undefinedresult);
if (scanned != value)
- gs_sprintf(buf, "%.9g", value);
- ensure_dot(buf);
+ gs_snprintf(buf, sizeof(buf), "%.9g", value);
+ ensure_dot(buf, 256);
goto rs;
}
case t_operator:
@@ -502,7 +502,7 @@ other:
data = (const byte *)(op->value.boolval ? "true" : "false");
break;
case t_integer:
- gs_sprintf(buf, "%"PRIpsint, op->value.intval);
+ gs_snprintf(buf, sizeof(buf), "%"PRIpsint, op->value.intval);
break;
case t_string:
check_read(*op);
@@ -537,7 +537,7 @@ other:
break;
}
/* Internal operator, no name. */
- gs_sprintf(buf, "@"PRI_INTPTR, (intptr_t) op->value.opproc);
+ gs_snprintf(buf, sizeof(buf), "@"PRI_INTPTR, (intptr_t) op->value.opproc);
break;
}
case t_real:
@@ -548,11 +548,11 @@ other:
* library implementation. Work around this here.
*/
if (op->value.realval == (float)0.0001) {
- strcpy(buf, "0.0001");
+ strncpy(buf, "0.0001", 256);
} else {
- gs_sprintf(buf, "%g", op->value.realval);
+ gs_snprintf(buf, sizeof(buf), "%g", op->value.realval);
}
- ensure_dot(buf);
+ ensure_dot(buf, 256);
break;
default:
data = (const byte *)"--nostringval--";
@@ -573,17 +573,18 @@ nl: if (size < start_pos)
* Re-format the exponent to satisfy Genoa CET test.
*/
static void
-ensure_dot(char *buf)
+ensure_dot(char *buf, size_t buflen)
{
char *pe = strchr(buf, 'e');
if (pe) {
int i;
(void)sscanf(pe + 1, "%d", &i);
+ buflen -= (size_t)(pe - buf);
/* MSVC .net 2005 express doesn't support "%+02d" */
if (i >= 0)
- gs_sprintf(pe + 1, "+%02d", i);
+ gs_snprintf(pe + 1, buflen, "+%02d", i);
else
- gs_sprintf(pe + 1, "-%02d", -i);
+ gs_snprintf(pe + 1, buflen, "-%02d", -i);
} else if (strchr(buf, '.') == NULL) {
strcat(buf, ".0");
}
diff --git a/psi/iutil2.c b/psi/iutil2.c
index 77b09918..46a752f2 100644
--- a/psi/iutil2.c
+++ b/psi/iutil2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -56,7 +56,7 @@ param_read_password(gs_param_list * plist, const char *kstr, password * ppass)
code = param_read_long(plist, kstr, &ipass);
if (code != 0) /* error or missing */
return code;
- gs_sprintf((char *)ppass->data, "%ld", ipass);
+ gs_snprintf((char *)ppass->data, MAX_PASSWORD, "%ld", ipass);
ppass->size = strlen((char *)ppass->data);
return 0;
}
diff --git a/psi/msvc.mak b/psi/msvc.mak
index 478972b2..cdf30fa7 100644
--- a/psi/msvc.mak
+++ b/psi/msvc.mak
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2021 Artifex Software, Inc.
+# Copyright (C) 2001-2022 Artifex Software, Inc.
# All Rights Reserved.
#
# This software is provided AS-IS with no warranty, either express or
@@ -48,7 +48,7 @@ DEBUGSYM=1
DEBUG=0
!endif
!ifndef TDEBUG
-TDEBUG=1
+TDEBUG=0
!endif
!ifndef DEBUGSYM
DEBUGSYM=1
@@ -829,6 +829,10 @@ LCUPSBUILDTYPE=win
CUPS_CC=$(CC) $(CFLAGS) -DWIN32
!endif
+!ifndef LIBCUPSSRCDIR
+LIBCUPSSRCDIR=cups
+!endif
+
!ifndef LCUPSISRCDIR
SHARE_LCUPSI=0
LCUPSI_NAME=
@@ -1031,6 +1035,11 @@ MSVC_VERSION=14
MSVC_VERSION=15
MS_TOOLSET_VERSION=14.16.27034
!endif
+!if "$(_NMAKE_VER)" == "14.16.27043.0"
+# VS2017 or VS2019 (Toolset v141)
+MSVC_VERSION=15
+MS_TOOLSET_VERSION=14.16.27034
+!endif
!if "$(_NMAKE_VER)" == "14.24.28314.0"
# VS2019 (Toolset v142)
MSVC_VERSION=16
@@ -1121,6 +1130,26 @@ MS_TOOLSET_VERSION=14.29.30037
MSVC_VERSION=16
MS_TOOLSET_VERSION=14.29.30133
!endif
+!if "$(_NMAKE_VER)" == "14.29.30136.0"
+# VS2019 (Toolset v142)
+MSVC_VERSION=16
+MS_TOOLSET_VERSION=14.29.30133
+!endif
+!if "$(_NMAKE_VER)" == "14.29.30137.0"
+# VS2019 (Toolset v142)
+MSVC_VERSION=16
+MS_TOOLSET_VERSION=14.29.30133
+!endif
+!if "$(_NMAKE_VER)" == "14.29.30139.0"
+# VS2019 (Toolset v142)
+MSVC_VERSION=16
+MS_TOOLSET_VERSION=14.29.30133
+!endif
+!if "$(_NMAKE_VER)" == "14.29.30140.0"
+# VS2019 (Toolset v142)
+MSVC_VERSION=16
+MS_TOOLSET_VERSION=14.29.30133
+!endif
!endif
!ifndef MSVC_VERSION
@@ -1756,8 +1785,8 @@ DEVICE_DEVS9=$(DD)pbm.dev $(DD)pbmraw.dev $(DD)pgm.dev $(DD)pgmraw.dev $(DD)pgnm
DEVICE_DEVS10=$(DD)tiffcrle.dev $(DD)tiffg3.dev $(DD)tiffg32d.dev $(DD)tiffg4.dev $(DD)tifflzw.dev $(DD)tiffpack.dev
DEVICE_DEVS11=$(DD)bmpmono.dev $(DD)bmpgray.dev $(DD)bmp16.dev $(DD)bmp256.dev $(DD)bmp16m.dev $(DD)tiff12nc.dev $(DD)tiff24nc.dev $(DD)tiff48nc.dev $(DD)tiffgray.dev $(DD)tiff32nc.dev $(DD)tiff64nc.dev $(DD)tiffsep.dev $(DD)tiffsep1.dev $(DD)tiffscaled.dev $(DD)tiffscaled8.dev $(DD)tiffscaled24.dev $(DD)tiffscaled32.dev $(DD)tiffscaled4.dev
DEVICE_DEVS12=$(DD)bit.dev $(DD)bitrgb.dev $(DD)bitcmyk.dev $(DD)bitrgbtags.dev $(DD)chameleon.dev
-DEVICE_DEVS13=$(DD)pngmono.dev $(DD)pngmonod.dev $(DD)pnggray.dev $(DD)png16.dev $(DD)png256.dev $(DD)png48.dev $(DD)png16m.dev $(DD)pngalpha.dev $(DD)fpng.dev $(DD)psdcmykog.dev
-DEVICE_DEVS14=$(DD)jpeg.dev $(DD)jpeggray.dev $(DD)jpegcmyk.dev $(DD)pdfimage8.dev $(DD)pdfimage24.dev $(DD)pdfimage32.dev $(DD)PCLm.dev $(DD)imagen.dev
+DEVICE_DEVS13=$(DD)pngmono.dev $(DD)pngmonod.dev $(DD)pnggray.dev $(DD)png16.dev $(DD)png256.dev $(DD)png48.dev $(DD)png16m.dev $(DD)pngalpha.dev $(DD)png16malpha.dev $(DD)fpng.dev $(DD)psdcmykog.dev
+DEVICE_DEVS14=$(DD)jpeg.dev $(DD)jpeggray.dev $(DD)jpegcmyk.dev $(DD)pdfimage8.dev $(DD)pdfimage24.dev $(DD)pdfimage32.dev $(DD)PCLm.dev $(DD)PCLm8.dev $(DD)imagen.dev
DEVICE_DEVS15=$(DD)pdfwrite.dev $(DD)ps2write.dev $(DD)eps2write.dev $(DD)txtwrite.dev $(DD)pxlmono.dev $(DD)pxlcolor.dev $(DD)xpswrite.dev $(DD)inkcov.dev $(DD)ink_cov.dev $(EXTRACT_DEVS)
DEVICE_DEVS16=$(DD)bbox.dev $(DD)plib.dev $(DD)plibg.dev $(DD)plibm.dev $(DD)plibc.dev $(DD)plibk.dev $(DD)plan.dev $(DD)plang.dev $(DD)planm.dev $(DD)planc.dev $(DD)plank.dev $(DD)planr.dev
!if "$(WITH_CUPS)" == "1"
@@ -1775,7 +1804,7 @@ DEVICE_DEVS17=$(DD)ljet3.dev $(DD)ljet3d.dev $(DD)ljet4pjl.dev $(DD)ljet4.dev $(
DEVICE_DEVS18=$(DD)pj.dev $(DD)pjxl.dev $(DD)pjxl300.dev $(DD)jetp3852.dev $(DD)r4081.dev
DEVICE_DEVS19=$(DD)lbp8.dev $(DD)m8510.dev $(DD)necp6.dev $(DD)bjc600.dev $(DD)bjc800.dev
DEVICE_DEVS20=$(DD)pnm.dev $(DD)pnmraw.dev $(DD)ppm.dev $(DD)ppmraw.dev $(DD)pamcmyk32.dev $(DD)pamcmyk4.dev $(DD)pnmcmyk.dev $(DD)pam.dev
-DEVICE_DEVS21=$(DD)spotcmyk.dev $(DD)devicen.dev $(DD)bmpsep1.dev $(DD)bmpsep8.dev $(DD)bmp16m.dev $(DD)bmp32b.dev $(DD)psdcmyk.dev $(DD)psdrgb.dev $(DD)psdcmyk16.dev $(DD)psdrgb16.dev
+DEVICE_DEVS21=$(DD)spotcmyk.dev $(DD)devicen.dev $(DD)bmpsep1.dev $(DD)bmpsep8.dev $(DD)bmp16m.dev $(DD)bmp32b.dev $(DD)psdcmyk.dev $(DD)psdrgb.dev $(DD)psdcmyk16.dev $(DD)psdrgb16.dev $(DD)psdcmyktags.dev $(DD)psdcmyktags16.dev
!endif
CONTRIB_DEVS=$(DD)pcl3.dev $(DD)hpdjplus.dev $(DD)hpdjportable.dev $(DD)hpdj310.dev $(DD)hpdj320.dev $(DD)hpdj340.dev $(DD)hpdj400.dev $(DD)hpdj500.dev $(DD)hpdj500c.dev $(DD)hpdj510.dev $(DD)hpdj520.dev $(DD)hpdj540.dev $(DD)hpdj550c.dev $(DD)hpdj560c.dev $(DD)hpdj600.dev $(DD)hpdj660c.dev $(DD)hpdj670c.dev $(DD)hpdj680c.dev $(DD)hpdj690c.dev $(DD)hpdj850c.dev $(DD)hpdj855c.dev $(DD)hpdj870c.dev $(DD)hpdj890c.dev $(DD)hpdj1120c.dev $(DD)cdj670.dev $(DD)cdj850.dev $(DD)cdj880.dev $(DD)cdj890.dev $(DD)cdj970.dev $(DD)cdj1600.dev $(DD)cdnj500.dev $(DD)chp2200.dev $(DD)lips3.dev $(DD)lxm5700m.dev $(DD)lxm3200.dev $(DD)lex2050.dev $(DD)lxm3200.dev $(DD)lex5700.dev $(DD)lex7000.dev $(DD)okiibm.dev $(DD)oki182.dev $(DD)oki4w.dev $(DD)gdi.dev $(DD)samsunggdi.dev $(DD)dl2100.dev $(DD)la50.dev $(DD)la70.dev $(DD)la75.dev $(DD)la75plus.dev $(DD)ln03.dev $(DD)xes.dev $(DD)md2k.dev $(DD)md5k.dev $(DD)lips4.dev $(DD)lips4v.dev $(DD)bj10v.dev $(DD)bj10vh.dev $(DD)md50Mono.dev $(DD)md50Eco.dev $(DD)md1xMono.dev $(DD)lp2000.dev $(DD)escpage.dev $(DD)ap3250.dev $(DD)npdl.dev $(DD)rpdl.dev $(DD)fmpr.dev $(DD)fmlbp.dev $(DD)ml600.dev $(DD)jj100.dev $(DD)lbp310.dev $(DD)lbp320.dev $(DD)mj700v2c.dev $(DD)mj500c.dev $(DD)mj6000c.dev $(DD)mj8000c.dev $(DD)pr201.dev $(DD)pr150.dev $(DD)pr1000.dev $(DD)pr1000_4.dev $(DD)lips2p.dev $(DD)bjc880j.dev $(DD)bjcmono.dev $(DD)bjcgray.dev $(DD)bjccmyk.dev $(DD)bjccolor.dev $(DD)escp.dev $(DD)lp8000.dev $(DD)lq850.dev $(DD)photoex.dev $(DD)st800.dev $(DD)stcolor.dev $(DD)alc1900.dev $(DD)alc2000.dev $(DD)alc4000.dev $(DD)alc4100.dev $(DD)alc8500.dev $(DD)alc8600.dev $(DD)alc9100.dev $(DD)lp3000c.dev $(DD)lp8000c.dev $(DD)lp8200c.dev $(DD)lp8300c.dev $(DD)lp8500c.dev $(DD)lp8800c.dev $(DD)lp9000c.dev $(DD)lp9200c.dev $(DD)lp9500c.dev $(DD)lp9800c.dev $(DD)lps6500.dev $(DD)epl2050.dev $(DD)epl2050p.dev $(DD)epl2120.dev $(DD)epl2500.dev $(DD)epl2750.dev $(DD)epl5800.dev $(DD)epl5900.dev $(DD)epl6100.dev $(DD)epl6200.dev $(DD)lp1800.dev $(DD)lp1900.dev $(DD)lp2200.dev $(DD)lp2400.dev $(DD)lp2500.dev $(DD)lp7500.dev $(DD)lp7700.dev $(DD)lp7900.dev $(DD)lp8100.dev $(DD)lp8300f.dev $(DD)lp8400f.dev $(DD)lp8600.dev $(DD)lp8600f.dev $(DD)lp8700.dev $(DD)lp8900.dev $(DD)lp9000b.dev $(DD)lp9100.dev $(DD)lp9200b.dev $(DD)lp9300.dev $(DD)lp9400.dev $(DD)lp9600.dev $(DD)lp9600s.dev $(DD)lps4500.dev $(DD)eplcolor.dev $(DD)eplmono.dev $(DD)hl7x0.dev $(DD)hl1240.dev $(DD)hl1250.dev $(DD)appledmp.dev $(DD)iwhi.dev $(DD)iwlo.dev $(DD)iwlq.dev $(DD)atx23.dev $(DD)atx24.dev $(DD)atx38.dev $(DD)itk24i.dev $(DD)itk38.dev $(DD)coslw2p.dev $(DD)coslwxl.dev $(DD)ccr.dev $(DD)cif.dev $(DD)inferno.dev $(DD)mgr4.dev $(DD)mgr8.dev $(DD)mgrgray2.dev $(DD)mgrgray4.dev $(DD)mgrgray8.dev $(DD)mgrmono.dev $(DD)miff24.dev $(DD)plan9bm.dev $(DD)xcf.dev
@@ -1863,109 +1892,31 @@ INT_ARCHIVE_ALL=$(PSOBJ)imainarg.$(OBJ) $(PSOBJ)imain.$(OBJ) $(GLOBJ)iconfig.$(O
$(INT_ARCHIVE_SOME)
!if $(TDEBUG) != 0
-$(PSGEN)lib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(PSGEN)lib.rsp
- echo /NODEFAULTLIB:LIBCMT.lib >> $(PSGEN)lib.rsp
+WIN_LIBS=
!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(PSGEN)lib.rsp
-!else
- echo LIBCMTD.lib >> $(PSGEN)lib.rsp
+WIN_LIBS=$(WIN_LIBS) kernel32.lib runtimeobject.lib rpcrt4.lib
!endif
!else
-$(PSGEN)lib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(PSGEN)lib.rsp
- echo /NODEFAULTLIB:LIBCMTD.lib >> $(PSGEN)lib.rsp
+WIN_LIBS=
!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(PSGEN)lib.rsp
-!else
- echo LIBCMT.lib >> $(PSGEN)lib.rsp
+WIN_LIBS=$(WIN_LIBS) kernel32.lib runtimeobject.lib rpcrt4.lib
!endif
!endif
-# a bit naff - find some way to combine above and this....
-!if $(TDEBUG) != 0
-$(PCLGEN)pcllib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(PCLGEN)pcllib.rsp
- echo /NODEFAULTLIB:LIBCMT.lib >> $(PCLGEN)pcllib.rsp
-!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(PCLGEN)pcllib.rsp
-!else
- echo LIBCMTD.lib >> $(PCLGEN)pcllib.rsp
-!endif
-!else
-$(PCLGEN)pcllib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(PCLGEN)pcllib.rsp
- echo /NODEFAULTLIB:LIBCMTD.lib >> $(PCLGEN)pcllib.rsp
-!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(PCLGEN)pcllib.rsp
-!else
- echo LIBCMT.lib >> $(PCLGEN)pcllib.rsp
-!endif
-!endif
+$(PSGEN)lib.rsp: $(TOP_MAKEFILES)
+ echo "$(WIN_LIBS)" > $(PSGEN)lib.rsp
-!if $(TDEBUG) != 0
+$(PCLGEN)pcllib.rsp: $(TOP_MAKEFILES)
+ echo "$(WIN_LIBS)" > $(PCLGEN)pcllib.rsp
$(XPSGEN)xpslib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(XPSGEN)xpslib.rsp
- echo /NODEFAULTLIB:LIBCMT.lib >> $(XPSGEN)xpslib.rsp
-!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(XPSGEN)xpslib.rsp
-!else
- echo LIBCMTD.lib >> $(XPSGEN)xpslib.rsp
-!endif
-!else
-$(XPSGEN)xpslib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(XPSGEN)xpslib.rsp
- echo /NODEFAULTLIB:LIBCMTD.lib >> $(XPSGEN)xpslib.rsp
-!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(XPSGEN)xpslib.rsp
-!else
- echo LIBCMT.lib >> $(XPSGEN)xpslib.rsp
-!endif
-!endif
-
-!if $(TDEBUG) != 0
+ echo "$(WIN_LIBS)" > $(XPSGEN)xpslib.rsp
$(PDFGEN)pdflib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(PDFGEN)pdflib.rsp
- echo /NODEFAULTLIB:LIBCMT.lib >> $(PDFGEN)pdflib.rsp
-!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(PDFGEN)pdflib.rsp
-!else
- echo LIBCMTD.lib >> $(PDFGEN)pdflib.rsp
-!endif
-!else
-$(PDFGEN)pdflib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(PDFGEN)pdflib.rsp
- echo /NODEFAULTLIB:LIBCMTD.lib >> $(PDFGEN)pdflib.rsp
-!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(PDFGEN)pdflib.rsp
-!else
- echo LIBCMT.lib >> $(PDFGEN)pdflib.rsp
-!endif
-!endif
-
-!if $(TDEBUG) != 0
+ echo "$(WIN_LIBS)" > $(PDFGEN)pdflib.rsp
$(GPDLGEN)gpdllib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(XPSGEN)gpdllib.rsp
- echo /NODEFAULTLIB:LIBCMT.lib >> $(XPSGEN)gpdllib.rsp
-!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(XPSGEN)gpdllib.rsp
-!else
- echo LIBCMTD.lib >> $(XPSGEN)gpdllib.rsp
-!endif
-!else
-$(GPDLGEN)gpdllib.rsp: $(TOP_MAKEFILES)
- echo /NODEFAULTLIB:LIBC.lib > $(XPSGEN)gpdllib.rsp
- echo /NODEFAULTLIB:LIBCMTD.lib >> $(XPSGEN)gpdllib.rsp
-!ifdef METRO
- echo kernel32.lib runtimeobject.lib rpcrt4.lib >> $(XPSGEN)gpdllib.rsp
-!else
- echo LIBCMT.lib >> $(XPSGEN)gpdllib.rsp
-!endif
-!endif
-
+ echo "$(WIN_LIBS)" > $(GPDLGEN)gpdllib.rsp
!if $(MAKEDLL)
# The graphical small EXE loader
@@ -2120,7 +2071,8 @@ $(GPDF_XE): $(GPDFDLL_DLL) $(DWMAINOBJS) $(GS_OBJ).res $(TOP_MAKEFILES)
del $(PDFGEN)gpdfwin.rsp
-$(GPDLDLL_DLL): $(ECHOGS_XE) $(GSDLL_OBJ).res $(LIBCTR) $(LIB_ALL) $(PCL_DEVS_ALL) $(XPS_DEVS_ALL) $(GS_ALL) \
+$(GPDLDLL_DLL): $(ECHOGS_XE) $(GSDLL_OBJ).res $(LIBCTR) $(LIB_ALL) $(PCL_DEVS_ALL) $(XPS_DEVS_ALL) $(PDF_DEVS_ALL) \
+ $(GS_ALL) \
$(GPDLGEN)gpdllib.rsp \
$(GPDLOBJ)pdlromfs$(COMPILE_INITS).$(OBJ) \
$(GPDLOBJ)pdlromfs$(COMPILE_INITS)c0.$(OBJ) \
@@ -2128,11 +2080,11 @@ $(GPDLDLL_DLL): $(ECHOGS_XE) $(GSDLL_OBJ).res $(LIBCTR) $(LIB_ALL) $(PCL_DEVS_AL
$(GPDLOBJ)pdlromfs$(COMPILE_INITS)c2.$(OBJ) \
$(GPDLOBJ)pdlromfs$(COMPILE_INITS)c3.$(OBJ) \
$(ld_tr) $(gpdl_tr) $(MAIN_OBJ) $(XPS_TOP_OBJS) \
- $(GPDL_PSI_TOP_OBJS) $(PCL_PXL_TOP_OBJS) $(PSI_TOP_OBJ) $(XPS_TOP_OBJ) \
+ $(GPDL_PSI_TOP_OBJS) $(PCL_PXL_TOP_OBJS) $(PSI_TOP_OBJ) $(XPS_TOP_OBJ) $(PDF_TOP_OBJ) \
$(REALMAIN_OBJ) $(MAIN_OBJ) $(XOBJS) $(INT_ARCHIVE_SOME) $(TOP_MAKEFILES)
echo Linking $(GPDLDLL) $(GPDLDLL_DLL) $(METRO)
copy $(gpdlld_tr) $(GPDLGEN)gpdlwin.tr
- echo $(MAIN_OBJ) $(GPDL_PSI_TOP_OBJS) $(PCL_PXL_TOP_OBJS) $(PSI_TOP_OBJ) $(XPS_TOP_OBJ) $(XOBJS) >> $(GPDLGEN)gpdlwin.tr
+ echo $(MAIN_OBJ) $(GPDL_PSI_TOP_OBJS) $(PCL_PXL_TOP_OBJS) $(PSI_TOP_OBJ) $(XPS_TOP_OBJ) $(PDF_TOP_OBJ) $(XOBJS) >> $(GPDLGEN)gpdlwin.tr
echo $(PCLOBJ)pdlromfs$(COMPILE_INITS).$(OBJ) >> $(GPDLGEN)gpdlwin.tr
echo $(PCLOBJ)pdlromfs$(COMPILE_INITS)c0.$(OBJ) >> $(GPDLGEN)gpdlwin.tr
echo $(PCLOBJ)pdlromfs$(COMPILE_INITS)c1.$(OBJ) >> $(GPDLGEN)gpdlwin.tr
@@ -2263,13 +2215,14 @@ $(GPDF_XE): $(ECHOGS_XE) $(LIBCTR) $(LIB_ALL) $(WINMAINOBJS) $(PDF_DEVS_ALL) $(P
del $(XPSGEN)pdfwin.rsp
del $(XPSGEN)gpdfwin.tr
-$(GPDL_XE): $(ECHOGS_XE) $(ld_tr) $(gpdl_tr) $(LIBCTR) $(LIB_ALL) $(WINMAINOBJS) $(XPS_DEVS_ALL) $(PCL_DEVS_ALL) $(GS_ALL) \
+$(GPDL_XE): $(ECHOGS_XE) $(ld_tr) $(gpdl_tr) $(LIBCTR) $(LIB_ALL) $(WINMAINOBJS) $(XPS_DEVS_ALL) $(PCL_DEVS_ALL) $(PDF_DEVS_ALL) \
+ $(GS_ALL) \
$(GPDLGEN)gpdllib.rsp $(GPDLOBJ)pdlromfs$(COMPILE_INITS).$(OBJ) \
- $(GPDL_PSI_TOP_OBJS) $(PCL_PXL_TOP_OBJS) $(PSI_TOP_OBJ) $(XPS_TOP_OBJ) \
+ $(GPDL_PSI_TOP_OBJS) $(PCL_PXL_TOP_OBJS) $(PSI_TOP_OBJ) $(XPS_TOP_OBJ) $(PDF_TOP_OBJ) \
$(MAIN_OBJ) $(XOBJS) $(INT_ARCHIVE_SOME) \
$(TOP_MAKEFILES)
copy $(gpdlld_tr) $(GPDLGEN)gpdlwin.tr
- echo $(WINMAINOBJS) $(MAIN_OBJ) $(GPDL_PSI_TOP_OBJS) $(PCL_PXL_TOP_OBJS) $(PSI_TOP_OBJ) $(XPS_TOP_OBJ) $(XOBJS) >> $(GPDLGEN)gpdlwin.tr
+ echo $(WINMAINOBJS) $(MAIN_OBJ) $(GPDL_PSI_TOP_OBJS) $(PCL_PXL_TOP_OBJS) $(PSI_TOP_OBJ) $(XPS_TOP_OBJ) $(PDF_TOP_OBJ) $(XOBJS) >> $(GPDLGEN)gpdlwin.tr
echo $(PCLOBJ)pdlromfs$(COMPILE_INITS).$(OBJ) >> $(GPDLGEN)gpdlwin.tr
echo /SUBSYSTEM:CONSOLE$(SUBSUBSYS) > $(GPDLGEN)gpdlwin.rsp
!if "$(PROFILE)"=="1"
diff --git a/psi/nsisinst.nsi b/psi/nsisinst.nsi
index cd983927..404747b5 100644
--- a/psi/nsisinst.nsi
+++ b/psi/nsisinst.nsi
@@ -30,9 +30,19 @@
; hand, it removes the short-cuts on Uninstall (which the Winzipse-based
; installer doesn't do) and also does not leave behind empty directories.
+; Requirements:
+; NSIS 3.0+
+; EnVar plug-in from https://nsis.sourceforge.io/EnVar_plug-in
+
; Newer nsis releases deprecate ansi encoding, require Unicode
Unicode True
+!include 'LogicLib.nsh'
+
+SetCompressor /SOLID /FINAL lzma
+XPStyle on
+CRCCheck on
+
; the following is from: http://nsis.sourceforge.net/StrRep
!define StrRep "!insertmacro StrRep"
!macro StrRep output string old new
@@ -100,6 +110,16 @@ Unicode True
!macroend
!insertmacro Func_StrRep ""
+Function WritePath
+ EnVar::SetHKLM
+ EnVar::AddValue "PATH" "$INSTDIR\bin"
+FunctionEnd
+
+Function un.WritePath
+ EnVar::SetHKLM
+ EnVar::DeleteValue "PATH" "$INSTDIR\bin"
+FunctionEnd
+
!ifndef TARGET
!define TARGET gs899w32
!endif
@@ -113,10 +133,6 @@ Unicode True
!define COMPILE_INITS 0
!endif
-SetCompressor /SOLID /FINAL lzma
-XPStyle on
-CRCCheck on
-
!include "MUI2.nsh"
; for detecting if running on x64 machine.
!include "x64.nsh"
@@ -201,11 +217,11 @@ Section "" ; (default section)
SetOutPath "$INSTDIR"
CreateDirectory "$INSTDIR\bin"
; add files / whatever that need to be installed here.
-File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x lib /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib doc
-File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x lib /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib examples
-File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib /x lib/gssetgs.bat lib
-File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x lib /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib Resource
-File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x lib /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib iccprofiles
+File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x lib /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib /x tesseract /x leptonica /x extract /x cal doc
+File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x lib /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib /x tesseract /x leptonica /x extract /x cal examples
+File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib /x tesseract /x leptonica /x extract /x cal /x lib/gssetgs.bat lib
+File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x lib /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib /x tesseract /x leptonica /x extract /x cal Resource
+File /r /x arch /x base /x cups /x contrib /x devices /x expat /x freetype /x gpdl /x ijs /x ios /x jbig2dec /x jpeg /x jpegxr /x lcms2mt /x lib /x libpng /x man /x obj /x openjpeg /x pcl /x psi /x tiff /x toolbin /x windows /x xps /x zlib /x tesseract /x leptonica /x extract /x cal iccprofiles
File /oname=lib\gssetgs.bat .\lib\gssetgs${WINTYPE}.bat
@@ -235,11 +251,13 @@ WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninst
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\GPL Ghostscript ${VERSION}" "DisplayVersion" "${VERSION}"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\GPL Ghostscript ${VERSION}" "NoModify" "1"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\GPL Ghostscript ${VERSION}" "NoRepair" "1"
+
; write out uninstaller
WriteUninstaller "$INSTDIR\uninstgs.exe"
SectionEnd ; end of default section
Function .onInstSuccess
+ Call WritePath
SetShellVarContext all
CreateDirectory "$SMPROGRAMS\Ghostscript"
CreateShortCut "$SMPROGRAMS\Ghostscript\Ghostscript ${VERSION}.LNK" "$INSTDIR\bin\gswin${WINTYPE}.exe" '"-I$INSTDIR\lib;$INSTDIR\..\fonts"'
@@ -309,6 +327,7 @@ RMDir "$PROGRAMFILES64\gs"
!else
RMDir "$PROGRAMFILES\gs"
!endif
+Call un.WritePath
SectionEnd ; end of uninstall section
; eof
diff --git a/psi/os2.mak b/psi/os2.mak
index b58b90bf..d276ec7a 100644
--- a/psi/os2.mak
+++ b/psi/os2.mak
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2021 Artifex Software, Inc.
+# Copyright (C) 2001-2022 Artifex Software, Inc.
# All Rights Reserved.
#
# This software is provided AS-IS with no warranty, either express or
@@ -422,7 +422,7 @@ DEVICE_DEVS12=$(DD)bit.dev $(DD)bitrgb.dev $(DD)bitcmyk.dev
DEVICE_DEVS13=$(DD)pngmono.dev $(DD)pngmonod.dev $(DD)pnggray.dev $(DD)png16.dev $(DD)png256.dev $(DD)png16m.dev $(DD)pngalpha.dev
DEVICE_DEVS14=$(DD)jpeg.dev $(DD)jpeggray.dev $(DD)jpegcmyk.dev
DEVICE_DEVS15=$(DD)pdfwrite.dev $(DD)ps2write.dev $(DD)eps2write.dev $(DD)txtwrite.dev $(DD)pxlmono.dev $(DD)pxlcolor.dev
-DEVICE_DEVS16=$(DD)bbox.dev $(DD)pdfimage8.dev $(DD)pdfimage24.dev $(DD)pdfimage32.dev $(DD)PCLm.dev
+DEVICE_DEVS16=$(DD)bbox.dev $(DD)pdfimage8.dev $(DD)pdfimage24.dev $(DD)pdfimage32.dev $(DD)PCLm.dev $(DD)PCLm8.dev
# Overflow for DEVS3,4,5,6,9
DEVICE_DEVS17=$(DD)ljet3.dev $(DD)ljet3d.dev $(DD)ljet4.dev $(DD)ljet4d.dev
DEVICE_DEVS18=$(DD)pj.dev $(DD)pjxl.dev $(DD)pjxl300.dev $(DD)jetp3852.dev $(DD)r4081.dev
diff --git a/psi/psapi.c b/psi/psapi.c
index ae5796f5..9321f34a 100644
--- a/psi/psapi.c
+++ b/psi/psapi.c
@@ -39,13 +39,12 @@
#include "interp.h"
#include "gxgstate.h"
-#ifndef GS_THREADSAFE
-/* Number of threads to allow per process. Unless GS_THREADSAFE is defined
- * more than 1 is guaranteed to fail.
+/* This is the fallback for the number of threads to allow per process; i.e. just one.
+ * This is only ever used if the gp_get_globals function returns 0 (i.e. only for
+ * platforms that don't support threading).
*/
static int gsapi_instance_counter = 0;
static const int gsapi_instance_max = 1;
-#endif
#ifdef METRO
@@ -83,12 +82,15 @@ psapi_new_instance(gs_lib_ctx_t **pinstance,
if (pinstance == NULL)
return gs_error_Fatal;
-#ifndef GS_THREADSAFE
- /* limited to 1 instance, till it works :) */
- if ( gsapi_instance_counter >= gsapi_instance_max )
- return gs_error_Fatal;
- ++gsapi_instance_counter;
-#endif
+ if (gp_get_globals() == NULL) {
+ /* This platform does not support the thread safe instance
+ * handling. We'll drop back to the old mechanism we've used
+ * to handle limiting ourselves to 1 instance in the past,
+ * despite this being thread-unsafe itself. */
+ if ( gsapi_instance_counter >= gsapi_instance_max )
+ return gs_error_Fatal;
+ ++gsapi_instance_counter;
+ }
mem = gs_malloc_init_with_context(*pinstance);
if (mem == NULL)
@@ -159,9 +161,8 @@ psapi_delete_instance(gs_lib_ctx_t *ctx)
/* Release the memory (frees up everything) */
gs_malloc_release(mem);
-#ifndef GS_THREADSAFE
- --gsapi_instance_counter;
-#endif
+ if (gp_get_globals() == NULL)
+ --gsapi_instance_counter;
}
static int utf16le_get_codepoint(gp_file *file, const char **astr)
diff --git a/psi/winint.mak b/psi/winint.mak
index 6d74f80f..d6234089 100644
--- a/psi/winint.mak
+++ b/psi/winint.mak
@@ -26,9 +26,9 @@
# Define the location of the NSIS makensis installer utility
!ifndef MAKENSIS_XE
!if $(BUILD_SYSTEM) == 64
-MAKENSIS_XE="C:\Program Files (x86)\NSIS\makensis.exe"
+MAKENSIS_XE="C:\Program Files (x86)\NSIS-3.0\makensis.exe"
!else
-MAKENSIS_XE="C:\Program Files\NSIS\makensis.exe"
+MAKENSIS_XE="C:\Program Files\NSIS-3.0\makensis.exe"
!endif
!endif
diff --git a/psi/zbfont.c b/psi/zbfont.c
index 09589159..044f58a1 100644
--- a/psi/zbfont.c
+++ b/psi/zbfont.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -109,7 +109,7 @@ zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t gspace)
if (gspace == GLYPH_SPACE_NOGEN)
return GS_NO_GLYPH;
- gs_sprintf(buf, "j%ld", chr); /* 'j' is arbutrary. */
+ gs_snprintf(buf, sizeof(buf), "j%ld", chr); /* 'j' is arbutrary. */
code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
if (code < 0) {
/* Can't propagate the error due to interface limitation,
@@ -131,7 +131,7 @@ zfont_glyph_name(gs_font *font, gs_glyph index, gs_const_string *pstr)
char cid_name[sizeof(gs_glyph) * 3 + 1];
int code;
- gs_sprintf(cid_name, "%lu", (ulong) index);
+ gs_snprintf(cid_name, sizeof(cid_name), "%lu", (ulong) index);
code = name_ref(font->memory, (const byte *)cid_name, strlen(cid_name),
&nref, 1);
if (code < 0)
@@ -144,10 +144,7 @@ zfont_glyph_name(gs_font *font, gs_glyph index, gs_const_string *pstr)
return 0;
}
-#define font_proc_glyph_name1\
- int (gs_font *font, gs_glyph glyph, gs_const_string *pstr)
-
-void get_zfont_glyph_name( void **proc)
+void get_zfont_glyph_name( int (**proc)(gs_font *font, gs_glyph glyph, gs_const_string *pstr) )
{
*proc = zfont_glyph_name;
}
diff --git a/psi/zcolor.c b/psi/zcolor.c
index 64e0b8d0..c0d73c28 100644
--- a/psi/zcolor.c
+++ b/psi/zcolor.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -307,6 +307,7 @@ zsetcolor(i_ctx_t * i_ctx_p)
n_numeric_comps = n_comps;
/* gather the numeric operands */
+ check_op(num_offset + n_numeric_comps);
code = float_params(op - num_offset, n_numeric_comps, cc.paint.values);
if (code < 0)
return code;
diff --git a/psi/zdevice.c b/psi/zdevice.c
index b119a768..99beaff7 100644
--- a/psi/zdevice.c
+++ b/psi/zdevice.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -36,6 +36,47 @@
#include "gsicc_manage.h"
#include "gxdevsop.h"
+struct_proc_finalize(psi_device_ref_finalize);
+
+static
+ENUM_PTRS_WITH(psi_device_ref_enum_ptrs, psi_device_ref *devref)
+ {
+ return 0;
+ }
+ case 0:
+ {
+ if (devref->device->memory != NULL) {
+ ENUM_RETURN(gx_device_enum_ptr(devref->device));
+ }
+ return 0;
+ }
+ENUM_PTRS_END
+
+static
+RELOC_PTRS_WITH(psi_device_ref_reloc_ptrs, psi_device_ref *devref)
+ if (devref->device->memory != NULL) {
+ devref->device = gx_device_reloc_ptr(devref->device, gcst);
+ }
+RELOC_PTRS_END
+
+gs_private_st_composite_use_final(st_psi_device_ref, psi_device_ref, "psi_device_ref_t",
+ psi_device_ref_enum_ptrs, psi_device_ref_reloc_ptrs, psi_device_ref_finalize);
+
+void
+psi_device_ref_finalize(const gs_memory_t *cmem, void *vptr)
+{
+ psi_device_ref *pdref = (psi_device_ref *)vptr;
+ (void)cmem;
+
+ /* pdref->device->memory == NULL indicates either a device prototype
+ or a device allocated on the stack rather than the heap
+ */
+ if (pdref->device->memory != NULL)
+ rc_decrement(pdref->device, "psi_device_ref_finalize");
+
+ pdref->device = NULL;
+}
+
/* <device> <keep_open> .copydevice2 <newdevice> */
static int
zcopydevice2(i_ctx_t *i_ctx_p)
@@ -43,6 +84,7 @@ zcopydevice2(i_ctx_t *i_ctx_p)
os_ptr op = osp;
gx_device *new_dev;
int code;
+ psi_device_ref *psdev;
check_read_type(op[-1], t_device);
check_type(*op, t_boolean);
@@ -50,12 +92,20 @@ zcopydevice2(i_ctx_t *i_ctx_p)
/* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
return_error(gs_error_undefined);
- code = gs_copydevice2(&new_dev, op[-1].value.pdevice, op->value.boolval,
+ code = gs_copydevice2(&new_dev, op[-1].value.pdevice->device, op->value.boolval,
imemory);
if (code < 0)
return code;
new_dev->memory = imemory;
- make_tav(op - 1, t_device, icurrent_space | a_all, pdevice, new_dev);
+
+ psdev = gs_alloc_struct(imemory, psi_device_ref, &st_psi_device_ref, "zcopydevice2");
+ if (!psdev) {
+ rc_decrement(new_dev, "zcopydevice2");
+ return_error(gs_error_VMerror);
+ }
+ psdev->device = new_dev;
+
+ make_tav(op - 1, t_device, icurrent_space | a_all, pdevice, psdev);
pop(1);
return 0;
}
@@ -68,11 +118,17 @@ zcurrentdevice(i_ctx_t *i_ctx_p)
os_ptr op = osp;
gx_device *dev = gs_currentdevice(igs);
gs_ref_memory_t *mem = (gs_ref_memory_t *) dev->memory;
+ psi_device_ref *psdev;
+
+ psdev = gs_alloc_struct(dev->memory, psi_device_ref, &st_psi_device_ref, "zcurrentdevice");
+ if (!psdev) {
+ return_error(gs_error_VMerror);
+ }
+ psdev->device = dev;
+ rc_increment(dev);
push(1);
- make_tav(op, t_device,
- (mem == 0 ? avm_foreign : imemory_space(mem)) | a_all,
- pdevice, dev);
+ make_tav(op, t_device, imemory_space(mem) | a_all, pdevice, psdev);
return 0;
}
@@ -91,16 +147,22 @@ zcurrentoutputdevice(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
gx_device *odev = NULL, *dev = gs_currentdevice(igs);
+ psi_device_ref *psdev;
gs_ref_memory_t *mem = (gs_ref_memory_t *) dev->memory;
int code = dev_proc(dev, dev_spec_op)(dev,
gxdso_current_output_device, (void *)&odev, 0);
if (code < 0)
return code;
+ psdev = gs_alloc_struct(dev->memory, psi_device_ref, &st_psi_device_ref, "zcurrentdevice");
+ if (!psdev) {
+ return_error(gs_error_VMerror);
+ }
+ psdev->device = odev;
+ rc_increment(odev);
+
push(1);
- make_tav(op, t_device,
- (mem == 0 ? avm_foreign : imemory_space(mem)) | a_all,
- pdevice, odev);
+ make_tav(op, t_device, imemory_space(mem) | a_all, pdevice, psdev);
return 0;
}
@@ -116,7 +178,7 @@ zdevicename(i_ctx_t *i_ctx_p)
/* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
return_error(gs_error_undefined);
- dname = op->value.pdevice->dname;
+ dname = op->value.pdevice->device->dname;
make_const_string(op, avm_foreign | a_readonly, strlen(dname),
(const byte *)dname);
return 0;
@@ -164,11 +226,12 @@ zgetbitsrect(i_ctx_t *i_ctx_p)
int code;
check_read_type(op[-7], t_device);
- dev = op[-7].value.pdevice;
- if (dev == NULL)
+ if (op[-7].value.pdevice == NULL)
/* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
return_error(gs_error_undefined);
+ dev = op[-7].value.pdevice->device;
+
check_int_leu(op[-6], dev->width);
rect.p.x = op[-6].value.intval;
check_int_leu(op[-5], dev->height);
@@ -238,6 +301,7 @@ zgetdevice(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
const gx_device *dev;
+ psi_device_ref *psdev;
check_type(*op, t_integer);
if (op->value.intval != (int)(op->value.intval))
@@ -245,10 +309,16 @@ zgetdevice(i_ctx_t *i_ctx_p)
dev = gs_getdevice((int)(op->value.intval));
if (dev == 0) /* index out of range */
return_error(gs_error_rangecheck);
+
+ psdev = gs_alloc_struct(imemory, psi_device_ref, &st_psi_device_ref, "zgetdevice");
+ if (!psdev) {
+ return_error(gs_error_VMerror);
+ }
+ /* gs_getdevice() returns a device prototype, so no reference counting required */
+ psdev->device = (gx_device *)dev;
+
/* Device prototypes are read-only; */
- /* the cast is logically unnecessary. */
- make_tav(op, t_device, avm_foreign | a_readonly, pdevice,
- (gx_device *) dev);
+ make_tav(op, t_device, imemory_space(iimemory) | a_readonly, pdevice, psdev);
return 0;
}
@@ -258,13 +328,21 @@ zgetdefaultdevice(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
const gx_device *dev;
+ psi_device_ref *psdev;
dev = gs_getdefaultlibdevice(imemory);
if (dev == 0) /* couldn't find a default device */
return_error(gs_error_unknownerror);
+
+ psdev = gs_alloc_struct(imemory, psi_device_ref, &st_psi_device_ref, "zgetdefaultdevice");
+ if (!psdev) {
+ return_error(gs_error_VMerror);
+ }
+ /* gs_getdefaultlibdevice() returns a device prototype, so no reference counting required */
+ psdev->device = (gx_device *)dev;
+
push(1);
- make_tav(op, t_device, avm_foreign | a_readonly, pdevice,
- (gx_device *) dev);
+ make_tav(op, t_device, imemory_space(iimemory) | a_readonly, pdevice, psdev);
return 0;
}
@@ -285,10 +363,12 @@ zget_device_params(i_ctx_t *i_ctx_p, bool is_hardware)
check_type(*op, t_dictionary);
}
rkeys = *op;
- dev = op[-1].value.pdevice;
if (op[-1].value.pdevice == NULL)
/* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
return_error(gs_error_undefined);
+
+ dev = op[-1].value.pdevice->device;
+
ref_stack_pop(&o_stack, 1);
stack_param_list_write(&list, &o_stack, &rkeys, iimemory);
code = gs_get_device_or_hardware_params(dev, (gs_param_list *) & list,
@@ -333,6 +413,7 @@ zmakewordimagedevice(i_ctx_t *i_ctx_p)
const byte *colors;
int colors_size;
int code;
+ psi_device_ref *psdev;
check_int_leu(op[-3], max_uint >> 1); /* width */
check_int_leu(op[-2], max_uint >> 1); /* height */
@@ -368,30 +449,25 @@ zmakewordimagedevice(i_ctx_t *i_ctx_p)
op->value.boolval, true, imemory);
if (code == 0) {
new_dev->memory = imemory;
- make_tav(op - 4, t_device, imemory_space(iimemory) | a_all,
- pdevice, new_dev);
+
+ psdev = gs_alloc_struct(imemory, psi_device_ref, &st_psi_device_ref, "zcurrentdevice");
+ if (!psdev) {
+ rc_decrement(new_dev, "zmakewordimagedevice");
+ return_error(gs_error_VMerror);
+ }
+ psdev->device = new_dev;
+ make_tav(op - 4, t_device, imemory_space(iimemory) | a_all, pdevice, psdev);
pop(4);
}
return code;
}
-static void invalidate_stack_devices(i_ctx_t *i_ctx_p)
-{
- os_ptr op = osbot;
- while (op != ostop) {
- if (r_has_type(op, t_device))
- op->value.pdevice = 0;
- op++;
- }
-}
-
/* - nulldevice - */
/* Note that nulldevice clears the current pagedevice. */
static int
znulldevice(i_ctx_t *i_ctx_p)
{
int code = gs_nulldevice(igs);
- invalidate_stack_devices(i_ctx_p);
clear_pagedevice(istate);
return code;
}
@@ -457,7 +533,7 @@ zputdeviceparams(i_ctx_t *i_ctx_p)
return_error(gs_error_stackunderflow);
check_type_only(*prequire_all, t_boolean);
check_write_type_only(*pdev, t_device);
- dev = pdev->value.pdevice;
+ dev = pdev->value.pdevice->device;
if (dev == NULL)
/* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
return_error(gs_error_undefined);
@@ -509,11 +585,8 @@ zputdeviceparams(i_ctx_t *i_ctx_p)
int
zsetdevice_no_safer(i_ctx_t *i_ctx_p, gx_device *new_dev)
{
- gx_device *dev = gs_currentdevice(igs);
int code;
- dev->ShowpageCount = 0;
-
if (new_dev == NULL)
return gs_note_error(gs_error_undefined);
@@ -521,7 +594,6 @@ zsetdevice_no_safer(i_ctx_t *i_ctx_p, gx_device *new_dev)
if (code < 0)
return code;
- invalidate_stack_devices(i_ctx_p);
clear_pagedevice(istate);
return code;
}
@@ -548,10 +620,10 @@ zsetdevice(i_ctx_t *i_ctx_p)
* it's procs initialised, at this point - but we need to check
* whether we're being asked to change the device here
*/
- if (dev_proc((op->value.pdevice), dev_spec_op) == NULL)
- ndev = op->value.pdevice;
+ if (dev_proc((op->value.pdevice->device), dev_spec_op) == NULL)
+ ndev = op->value.pdevice->device;
else
- code = dev_proc((op->value.pdevice), dev_spec_op)(op->value.pdevice,
+ code = dev_proc((op->value.pdevice->device), dev_spec_op)(op->value.pdevice->device,
gxdso_current_output_device, (void *)&ndev, 0);
if (code < 0)
@@ -561,7 +633,7 @@ zsetdevice(i_ctx_t *i_ctx_p)
if(ndev != odev) /* don't allow a different device */
return_error(gs_error_invalidaccess);
}
- code = zsetdevice_no_safer(i_ctx_p, op->value.pdevice);
+ code = zsetdevice_no_safer(i_ctx_p, op->value.pdevice->device);
make_bool(op, code != 0); /* erase page if 1 */
return code;
}
diff --git a/psi/zdouble.c b/psi/zdouble.c
index e6e7bad6..ae439811 100644
--- a/psi/zdouble.c
+++ b/psi/zdouble.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -323,7 +323,7 @@ zcvsd(i_ctx_t *i_ctx_p)
len = r_size(op - 1);
if (len > MAX_CHARS)
return_error(gs_error_limitcheck);
- gs_sprintf(buf, "%f", 1.5);
+ gs_snprintf(buf, sizeof(buf), "%f", 1.5);
dot = buf[1]; /* locale-dependent */
memcpy(str, op[-1].value.bytes, len);
/*
@@ -406,7 +406,7 @@ zdcvs(i_ctx_t *i_ctx_p)
if (code < 0)
return code;
check_write_type(*op, t_string);
- gs_sprintf(str, "%f", 1.5);
+ gs_snprintf(str, sizeof(str), "%f", 1.5);
dot = str[1]; /* locale-dependent */
/*
* To get fully accurate output results for IEEE double-
@@ -420,10 +420,10 @@ zdcvs(i_ctx_t *i_ctx_p)
{
double scanned;
- gs_sprintf(str, "%g", num);
+ gs_snprintf(str, sizeof(str), "%g", num);
sscanf(str, "%lf", &scanned);
if (scanned != num)
- gs_sprintf(str, "%.16g", num);
+ gs_snprintf(str, sizeof(str), "%.16g", num);
}
len = strlen(str);
if (len > r_size(op))
diff --git a/psi/zfapi.c b/psi/zfapi.c
index 0b3ab1cf..6927e60e 100644
--- a/psi/zfapi.c
+++ b/psi/zfapi.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -189,8 +189,9 @@ sfnts_reader_seek(sfnts_reader *r, ulong pos)
}
static void
-sfnts_reader_init(sfnts_reader *r, ref *pdr)
+sfnts_reader_init(const gs_memory_t *mem, sfnts_reader *r, ref *pdr)
{
+ r->memory = mem;
r->rbyte = sfnts_reader_rbyte;
r->rword = sfnts_reader_rword;
r->rlong = sfnts_reader_rlong;
@@ -381,11 +382,11 @@ sfnts_copy_except_glyf(sfnts_reader *r, sfnts_writer *w)
}
static int
-true_type_size(ref *pdr, unsigned long int *length)
+true_type_size(const gs_memory_t *mem, ref *pdr, unsigned long int *length)
{
sfnts_reader r;
- sfnts_reader_init(&r, pdr);
+ sfnts_reader_init(mem, &r, pdr);
*length = sfnts_copy_except_glyf(&r, 0);
return r.error;
@@ -400,7 +401,7 @@ FAPI_FF_serialize_tt_font(gs_fapi_font *ff, void *buf, int buf_size)
w.buf_size = buf_size;
w.buf = w.p = buf;
- sfnts_reader_init(&r, pdr);
+ sfnts_reader_init(ff->memory, &r, pdr);
return sfnts_copy_except_glyf(&r, &w);
}
@@ -691,11 +692,11 @@ FAPI_FF_get_word(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, unsig
length += r_size(&string) + 1;
break;
case t_real:
- gs_sprintf(Buffer, "%f", Element.value.realval);
+ gs_snprintf(Buffer, sizeof(Buffer), "%f", Element.value.realval);
length += strlen(Buffer) + 1;
break;
case t_integer:
- gs_sprintf(Buffer, "%"PRIpsint, Element.value.intval);
+ gs_snprintf(Buffer, sizeof(Buffer), "%"PRIpsint, Element.value.intval);
length += strlen(Buffer) + 1;
break;
case t_operator:
@@ -1409,7 +1410,7 @@ FAPI_FF_get_long(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, unsig
}
break;
case gs_fapi_font_feature_TT_size:
- code = true_type_size(pdr, ret);
+ code = true_type_size(ff->memory, pdr, ret);
break;
}
return code;
@@ -1657,12 +1658,12 @@ FAPI_FF_get_proc(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index,
ptr += r_size(&string);
break;
case t_real:
- gs_sprintf(Buf, "%f", Element.value.realval);
+ gs_snprintf(Buf, sizeof(Buf), "%f", Element.value.realval);
strcpy(ptr, Buf);
ptr += strlen(Buf);
break;
case t_integer:
- gs_sprintf(Buf, "%"PRIpsint, Element.value.intval);
+ gs_snprintf(Buf, sizeof(Buf), "%"PRIpsint, Element.value.intval);
strcpy(ptr, Buf);
ptr += strlen(Buf);
break;
@@ -1902,7 +1903,7 @@ sfnt_get_glyph_offset(ref *pdr, gs_font_type42 *pfont42, int index,
ulong fullsize;
if (index < pfont42->data.trueNumGlyphs) {
- sfnts_reader_init(&r, pdr);
+ sfnts_reader_init(pfont42->memory, &r, pdr);
r.seek(&r, pfont42->data.loca + index * (ulong)glyf_elem_size);
*offset0 =
pfont42->data.glyf + (glyf_elem_size ==
@@ -2156,7 +2157,7 @@ FAPI_FF_get_glyph(gs_fapi_font *ff, gs_glyph char_code, byte *buf, int buf_lengt
if (buf != 0 && !error) {
sfnts_reader r;
- sfnts_reader_init(&r, pdr);
+ sfnts_reader_init(pfont42->memory, &r, pdr);
r.seek(&r, offset0);
length_read =
diff --git a/psi/zfarc4.c b/psi/zfarc4.c
index bbefe36d..0f41d592 100644
--- a/psi/zfarc4.c
+++ b/psi/zfarc4.c
@@ -51,7 +51,8 @@ z_arcfour_d(i_ctx_t * i_ctx_p)
if (!r_has_type(sop, t_string))
return_error(gs_error_typecheck);
- if ((code = s_arcfour_set_key(&state, sop->value.const_bytes, r_size(sop))) < 0)
+ code = s_arcfour_set_key(&state, sop->value.const_bytes, r_size(sop)); /* lgtm [cpp/weak-cryptographic-algorithm] */
+ if (code < 0)
return code;
/* we pass npop=0, since we've no arguments left to consume */
diff --git a/psi/zfile.c b/psi/zfile.c
index 46040701..fe3f7e9f 100644
--- a/psi/zfile.c
+++ b/psi/zfile.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -1285,6 +1285,7 @@ lib_fopen(const gs_file_path_ptr pfpath, const gs_memory_t *mem, const char *fna
uint fnamelen;
ref obj;
int code;
+ stream *s;
/* open the usual 'stream', then if successful, return the file */
code = lib_file_open(pfpath, mem, NULL, fname, strlen(fname),
@@ -1292,7 +1293,19 @@ lib_fopen(const gs_file_path_ptr pfpath, const gs_memory_t *mem, const char *fna
if (code < 0)
return NULL;
- file = ((stream *)(obj.value.pfile))->file;
+
+ /* This all seems a bit grotty. The above code has generated us a stream
+ * that wraps a file. We actually want the file. So we reach in, and steal
+ * the file pointer. Nasty. */
+ s = ((stream *)(obj.value.pfile));
+ file = s->file;
+ /* Historically we've then just abandoned the stream, resulting in blocks
+ * leaking. Let's free the leaked blocks (in rather hacky style). First,
+ * we clear the file reference, and then drop the stream. */
+ s->file = NULL;
+ sclose(s);
+ /* Then free the stream block itself. */
+ gs_free_object(s->memory, s, "lib_fopen");
return file;
}
diff --git a/psi/zfont2.c b/psi/zfont2.c
index ae5d29d0..2be4279a 100644
--- a/psi/zfont2.c
+++ b/psi/zfont2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -2705,7 +2705,7 @@ parse_font(i_ctx_t *i_ctx_p, ref *topdict,
return sid;
if ((code = make_name_from_sid(i_ctx_p, &name, strings, data, sid)) < 0) {
char buf[40];
- int len = gs_sprintf(buf, "sid-%d", sid);
+ int len = gs_snprintf(buf, sizeof(buf), "sid-%d", sid);
if ((code = name_ref(imemory, (unsigned char *)buf, len, &name, 1)) < 0)
return code;
diff --git a/psi/zht.c b/psi/zht.c
index f1cc8d94..96af0348 100644
--- a/psi/zht.c
+++ b/psi/zht.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -126,7 +126,7 @@ static int
zsetscreen(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
- gs_screen_halftone screen;
+ gs_screen_halftone screen = { 0 };
gx_ht_order order;
int code = zscreen_params(op, &screen);
gs_memory_t *mem;
diff --git a/psi/zpcolor.c b/psi/zpcolor.c
index 81a94ddf..93d6050a 100644
--- a/psi/zpcolor.c
+++ b/psi/zpcolor.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -245,7 +245,7 @@ pattern_paint_prepare(i_ctx_t *i_ctx_p)
gs_setdevice_no_init(pgs, (gx_device *)pdev);
if (pinst->templat.uses_transparency) {
if_debug0m('v', imemory, " pushing the pdf14 compositor device into this graphics state\n");
- if ((code = gs_push_pdf14trans_device(pgs, true, true, 0, 0)) < 0) /* FIXME: do we need spot_color_count ??? */
+ if ((code = gs_push_pdf14trans_device(pgs, true, true, 0, 0)) < 0) /* spot color count found from pdf14 target */
return code;
} else { /* not transparent */
if (pinst->templat.PaintType == 1 && !(pinst->is_clist)
diff --git a/psi/zpdfops.c b/psi/zpdfops.c
index 4c01de03..45bd7803 100644
--- a/psi/zpdfops.c
+++ b/psi/zpdfops.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -25,6 +25,7 @@
#include "iminst.h"
#include "dstack.h"
+#include "gsicc_profilecache.h"
#endif
#include "ghost.h"
@@ -272,51 +273,123 @@ zsaslprep(i_ctx_t *i_ctx_p)
#if defined(BUILD_PDF) && BUILD_PDF == 1
-/*
- This cannot fail. If gs doesn't have these settings it will never reach here.
- Because the lives of the string values here are all tied to the Postscript
- context, and the Postscript context *must* outlast the pdfi context, we can
- safely just take references, marking the strings as "persistent" so destroying
- the pdfi context doesn't try to free the string bodies.
- */
-static void zpdfi_populate_search_paths(i_ctx_t *i_ctx_p, pdf_context *ctx)
+static int zpdfi_populate_search_paths(i_ctx_t *i_ctx_p, pdf_context *ctx)
{
+ int code = 0;
/* This should only be called once per pdfi context
if the paths are already populated, just skip it.
*/
if (ctx->search_paths.resource_paths == NULL) {
ref *l2dictref, *grdref, *fpathref;
- int code, i;
+ int i;
const gs_file_path *pfpath = i_ctx_p->lib_path;
gs_main_instance *minst = get_minst_from_memory(imemory);
code = dict_find_string(systemdict, "pssystemparams", &l2dictref);
if (code >= 0 && r_has_type(l2dictref, t_dictionary)) {
code = dict_find_string(l2dictref, "GenericResourceDir", &grdref);
if (code >= 0 && r_has_type(grdref, t_string)) {
- ctx->search_paths.genericresourcedir.data = grdref->value.const_bytes;
+ ctx->search_paths.genericresourcedir.data = gs_alloc_bytes(ctx->memory, r_size(grdref), "zpdfi_populate_search_paths");
+ if (ctx->search_paths.genericresourcedir.data == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+ }
+ memcpy((char *)ctx->search_paths.genericresourcedir.data, grdref->value.const_bytes, r_size(grdref));
ctx->search_paths.genericresourcedir.size = r_size(grdref);
- ctx->search_paths.genericresourcedir.persistent = true;
+ ctx->search_paths.genericresourcedir.persistent = false;
}
}
+
ctx->search_paths.resource_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_param_string) * r_size(&pfpath->list), "array of paths");
+ if (ctx->search_paths.resource_paths == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+ }
+ memset(ctx->search_paths.resource_paths, 0x00, sizeof(gs_param_string) * r_size(&pfpath->list));
+
ctx->search_paths.num_resource_paths = r_size(&pfpath->list);
for (i = 0; i < r_size(&pfpath->list); i++) {
const ref *prdir = pfpath->list.value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
- ctx->search_paths.resource_paths[i].data = prdir->value.const_bytes;
+ ctx->search_paths.resource_paths[i].data = gs_alloc_bytes(ctx->memory, r_size(prdir), "zpdfi_populate_search_paths");
+ if (ctx->search_paths.resource_paths[i].data == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+ }
+ memcpy((char *)ctx->search_paths.resource_paths[i].data, prdir->value.const_bytes, r_size(prdir));
ctx->search_paths.resource_paths[i].size = r_size(prdir);
- ctx->search_paths.resource_paths[i].persistent = true;
+ ctx->search_paths.resource_paths[i].persistent = false;
}
code = dict_find_string(systemdict, "FONTPATH", &fpathref);
- ctx->search_paths.font_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_param_string) * r_size(fpathref), "array of font paths");
- ctx->search_paths.num_font_paths = r_size(fpathref);
- for (i = 0; i < r_size(fpathref); i++) {
- const ref *prdir = pfpath->list.value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
- ctx->search_paths.resource_paths[i].data = prdir->value.const_bytes;
- ctx->search_paths.resource_paths[i].size = r_size(prdir);
- ctx->search_paths.resource_paths[i].persistent = true;
+ if (code >= 0 && r_has_type(fpathref, t_array)) {
+ ctx->search_paths.font_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_param_string) * r_size(fpathref), "array of font paths");
+ memset(ctx->search_paths.font_paths, 0x00, sizeof(gs_param_string) * r_size(fpathref));
+
+ ctx->search_paths.num_font_paths = r_size(fpathref);
+ for (i = 0; i < r_size(fpathref); i++) {
+ const ref *prdir = fpathref->value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
+ ctx->search_paths.font_paths[i].data = gs_alloc_bytes(ctx->memory, r_size(prdir), "zpdfi_populate_search_paths");
+ if (ctx->search_paths.font_paths[i].data == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+ }
+ memcpy((char *)ctx->search_paths.font_paths[i].data, prdir->value.const_bytes, r_size(prdir));
+ ctx->search_paths.font_paths[i].size = r_size(prdir);
+ ctx->search_paths.font_paths[i].persistent = false;
+ }
}
ctx->search_paths.search_here_first = minst->search_here_first;
}
+done:
+ return code >= 0 ? 0 : code;
+}
+
+static int zpdfi_populate_fontmap_files(i_ctx_t *i_ctx_p, pdf_context *ctx)
+{
+ int code, i;
+ ref *fontmaps;
+
+ code = dict_find_string(systemdict, "FONTMAP", &fontmaps);
+ if (code >= 0 && r_has_type(fontmaps, t_array)) {
+ ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_string) * r_size(fontmaps), "array of fontmap files");
+ if (ctx->fontmapfiles != 0) {
+ memset(ctx->fontmapfiles, 0x00, sizeof(gs_string) * r_size(fontmaps));
+ ctx->num_fontmapfiles = r_size(fontmaps);
+ for (i = 0; i < r_size(fontmaps); i++) {
+ const ref *fmapfile = fontmaps->value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
+ ctx->fontmapfiles[i].data = gs_alloc_bytes(ctx->memory, r_size(fmapfile), "zpdfi_populate_fontmap_files");
+ if (ctx->fontmapfiles[i].data == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+ }
+ memcpy((char *)ctx->fontmapfiles[i].data, fmapfile->value.const_bytes, r_size(fmapfile));
+ ctx->fontmapfiles[i].size = r_size(fmapfile);
+ }
+ }
+ else {
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+ }
+ }
+ else if (code >= 0 && r_has_type(fontmaps, t_string)) {
+ ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_string), "array of fontmap files");
+ if (ctx->fontmapfiles != 0) {
+ ctx->num_fontmapfiles = 1;
+ ctx->fontmapfiles[0].data = gs_alloc_bytes(ctx->memory, r_size(fontmaps), "zpdfi_populate_fontmap_files");
+ if (ctx->fontmapfiles[0].data == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+ }
+ memcpy((char *)ctx->fontmapfiles[0].data, fontmaps->value.const_bytes, r_size(fontmaps));
+ ctx->fontmapfiles[0].size = r_size(fontmaps);
+ }
+ else {
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+ }
+ }
+ else
+ code = 0;
+done:
+ return code;
}
/*
@@ -329,8 +402,44 @@ typedef struct pdfctx_s {
gs_memory_t *pdf_memory; /* The 'wrapped' memory allocator used by the PDF interpreter. Not exposed to garbager */
gs_memory_t *pdf_stream_memory; /* The memory allocator used to copy the PostScript stream to pdf_stream. Not exposed to garbager */
stream *pdf_stream;
+ gsicc_profile_cache_t *profile_cache;
+ gs_memory_t *cache_memory; /* The memory allocator used to allocate the working (GC'ed) profile cache */
} pdfctx_t;
+/* There is some unfortunately necessary complication in the structure above regarding the ICC profile cache.
+ * Initially the problem was due to adding the colour space name to the 'interpreter data' part of the colour
+ * space, in order to be able to identify the case where we switch to the current colour space.
+ *
+ * This caused problems with ICC spaces, because these maintain a reference to the colour space. If the profile
+ * was stored in the PostScript profile cache (which it would be, because the profile cache is stored in the
+ * grapchis state, which we inherit from the PostScript interpreter) then it would outlive the PDF interpreter,
+ * and when we came to free the cache it would try to free the colour space, which would try to free the PDF
+ * name object, which had already been freed.
+ *
+ * To work around this we replaced the profile cache in the graphics state with the profile cache from the PDF
+ * interpreter. Now when we free the PDF profile cache, it frees the colour spaces, and the PDF names, while they
+ * are still valid.
+ *
+ * However, we then discovered that the garbage collector could reclaim the colour spaces. This happens because
+ * no GC-visible object declares it has a reference to the colour space. It doesn't matter that the colour
+ * space has been counted up, the GC frees it. Now the profile cache in pdfi is pointing to a colour space which
+ * has gone away....
+ *
+ * To get round this, we create a brand-new profile cache, using GC'ed memory (well actually the interpreter
+ * allocator, which is GC'ed for Ghostscript). When we switch to pdfi we replace the graphics state pdfi is
+ * using with the one from the PostScript environment, and at the same time we swap out the profile cache
+ * being used by that graphics state, so it uses our new one. On return to PostScript we swap them back.
+ * This allows the lifetime of the profiles in the profile cache to be correct, because they are visible to the
+ * garbage collector (the PDF context is a GC-visible object and enumerates it's member profile cache)
+ * When we finalize the PDF context we count down the profile cache which dereferences all its entries. This
+ * effectively frees the colour space (the memory may not be reclaimed yet) which calls the interpreter
+ * specific cleanup, which frees the (still valid at this point) PDF name object and sets the pointer to NULL.
+ *
+ * The net result is that we have the profiles visible to the garbage collector during their lifetime, but
+ * still have control over the cache, so we can empty it of the profiles created for pdfi when we close the
+ * PDF interpreter.
+ */
+
/* Structure descriptors */
static void pdfctx_finalize(const gs_memory_t *cmem, void *vptr);
@@ -339,11 +448,11 @@ gs_private_st_composite_final(st_pdfctx_t, pdfctx_t, "pdfctx_struct",\
static
ENUM_PTRS_BEGIN(pdfctx_enum_ptrs) return 0;
-ENUM_PTR2(0, pdfctx_t, ps_stream, pdf_stream);
+ENUM_PTR3(0, pdfctx_t, ps_stream, pdf_stream, profile_cache);
ENUM_PTRS_END
static RELOC_PTRS_BEGIN(pdfctx_reloc_ptrs);
-RELOC_PTR2(pdfctx_t, ps_stream, pdf_stream);
+RELOC_PTR3(pdfctx_t, ps_stream, pdf_stream, profile_cache);
RELOC_PTRS_END
static void
@@ -354,6 +463,10 @@ pdfctx_finalize(const gs_memory_t *cmem, void *vptr)
* on the same object - hence we null the entries.
*/
+ if (pdfctx->profile_cache != NULL) {
+ rc_decrement(pdfctx->profile_cache, "free the working profile cache");
+ pdfctx->profile_cache = NULL;
+ }
if (cmem != NULL) {
if (pdfctx->ctx != NULL) {
if (pdfctx->pdf_stream) {
@@ -385,9 +498,7 @@ static int zPDFstream(i_ctx_t *i_ctx_p)
int code = 0;
stream *s;
pdfctx_t *pdfctx;
- gs_gstate *pgs = NULL;
- gs_gstate_client_procs procs;
- void *client_data;
+ pdfi_switch_t i_switch;
check_op(2);
@@ -409,20 +520,13 @@ static int zPDFstream(i_ctx_t *i_ctx_p)
*(pdfctx->pdf_stream) = *(pdfctx->ps_stream);
- pgs = pdfctx->ctx->pgs;
- procs = igs->client_procs;
- client_data = igs->client_data;
- pdfi_gstate_from_PS(pdfctx->ctx, igs, &client_data, &procs);
- pdfctx->ctx->pgs = igs;
+ code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
- code = pdfi_set_input_stream(pdfctx->ctx, pdfctx->pdf_stream);
+ if (code >= 0) {
+ code = pdfi_set_input_stream(pdfctx->ctx, pdfctx->pdf_stream);
- pdfi_gstate_to_PS(pdfctx->ctx, igs, client_data, &procs);
- if (code == 0)
- code = gs_grestore(igs);
- else
- (void)gs_grestore(igs);
- pdfctx->ctx->pgs = pgs;
+ pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
+ }
if (code < 0) {
memset(pdfctx->pdf_stream, 0x00, sizeof(stream));
@@ -445,9 +549,7 @@ static int zPDFfile(i_ctx_t *i_ctx_p)
pdfctx_t *pdfctx;
char pdffilename[gp_file_name_sizeof];
int code = 0;
- gs_gstate *pgs = NULL;
- gs_gstate_client_procs procs;
- void *client_data;
+ pdfi_switch_t i_switch;
check_op(2);
@@ -467,20 +569,13 @@ static int zPDFfile(i_ctx_t *i_ctx_p)
memcpy(pdffilename, (op - 1)->value.bytes, r_size(op - 1));
pdffilename[r_size(op - 1)] = 0;
- pgs = pdfctx->ctx->pgs;
- procs = igs->client_procs;
- client_data = igs->client_data;
- pdfi_gstate_from_PS(pdfctx->ctx, igs, &client_data, &procs);
- pdfctx->ctx->pgs = igs;
+ code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
- code = pdfi_open_pdf_file(pdfctx->ctx, pdffilename);
+ if (code >= 0) {
+ code = pdfi_open_pdf_file(pdfctx->ctx, pdffilename);
- pdfi_gstate_to_PS(pdfctx->ctx, igs, client_data, &procs);
- if (code == 0)
- code = gs_grestore(igs);
- else
- (void)gs_grestore(igs);
- pdfctx->ctx->pgs = pgs;
+ pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
+ }
if (code < 0)
return code;
@@ -500,12 +595,18 @@ static int zPDFclose(i_ctx_t *i_ctx_p)
check_type(*op, t_pdfctx);
pdfctx = r_ptr(op, pdfctx_t);
+ if (pdfctx->profile_cache != NULL) {
+ rc_decrement(pdfctx->profile_cache, "free the working profile cache");
+ pdfctx->profile_cache = NULL;
+ }
+
if (pdfctx->ctx != NULL) {
+ pdfi_report_errors(pdfctx->ctx);
if (pdfctx->ps_stream) {
/* Detach the PostScript stream from the PDF context, otherwise the
* close code will close the main stream
*/
- pdfctx->ctx->main_stream = NULL;
+ pdfctx->ctx->main_stream->s = NULL;
}
code = pdfi_free_context(pdfctx->ctx);
pdfctx->ctx = NULL;
@@ -533,75 +634,79 @@ static int zPDFinfo(i_ctx_t *i_ctx_p)
check_type(*(op), t_pdfctx);
pdfctx = r_ptr(op, pdfctx_t);
- code = dict_create(4, op);
- if (code < 0)
- return code;
-
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
- if (code < 0)
- return code;
-
- make_int(&intref, pdfctx->ctx->num_pages);
+ if (pdfctx->pdf_stream != NULL) {
+ code = dict_create(4, op);
+ if (code < 0)
+ return code;
- code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
+ if (code < 0)
+ return code;
- /* Code to process Collections. The pdfi_prep_collection() function returns an
- * array of descriptions and filenames. Because the descriptions can contain
- * UTF16-BE encoded data we can't sue a NULL terminated string, so the description
- * strings are terminated with a triple-NULL sequence of bytes.
- * We copy the contents into a PostScript array, which we store in the info
- * dictionary using the /Collection key.
- */
- if (pdfctx->ctx->Collection != NULL) {
- code = pdfi_prep_collection(pdfctx->ctx, &TotalFiles, &names_array);
- if (code >= 0 && TotalFiles > 0) {
- uint size;
- ref collection, stringref;
+ make_int(&intref, pdfctx->ctx->num_pages);
- code = ialloc_ref_array(&collection, a_all, TotalFiles * 2, "names array");
- if (code < 0)
- goto error;
+ code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
+ if (code < 0)
+ return code;
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"Collection", 10, &nameref, 1);
- if (code < 0)
- goto error;
+ /* Code to process Collections. The pdfi_prep_collection() function returns an
+ * array of descriptions and filenames. Because the descriptions can contain
+ * UTF16-BE encoded data we can't sue a NULL terminated string, so the description
+ * strings are terminated with a triple-NULL sequence of bytes.
+ * We copy the contents into a PostScript array, which we store in the info
+ * dictionary using the /Collection key.
+ */
+ if (pdfctx->ctx->Collection != NULL) {
+ code = pdfi_prep_collection(pdfctx->ctx, &TotalFiles, &names_array);
+ if (code >= 0 && TotalFiles > 0) {
+ uint size;
+ ref collection, stringref;
+
+ code = ialloc_ref_array(&collection, a_all, TotalFiles * 2, "names array");
+ if (code < 0)
+ goto error;
- code = dict_put(op, &nameref, &collection, &i_ctx_p->dict_stack);
- if (code < 0)
- goto error;
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"Collection", 10, &nameref, 1);
+ if (code < 0)
+ goto error;
- for (ix=0; ix < TotalFiles * 2; ix++) {
- char *ptr = names_array[ix];
- byte *sbody;
- ref *pelement;
-
- size = 0;
- do {
- if (ptr[0] == 0x00 && ptr[1] == 0x00 && ptr[2] == 0x00)
- break;
- ptr++;
- size++;
- } while (1);
- sbody = ialloc_string(size, "string");
- if (sbody == 0) {
- code = gs_error_VMerror;
+ code = dict_put(op, &nameref, &collection, &i_ctx_p->dict_stack);
+ if (code < 0)
goto error;
+
+ for (ix=0; ix < TotalFiles * 2; ix++) {
+ char *ptr = names_array[ix];
+ byte *sbody;
+ ref *pelement;
+
+ size = 0;
+ do {
+ if (ptr[0] == 0x00 && ptr[1] == 0x00 && ptr[2] == 0x00)
+ break;
+ ptr++;
+ size++;
+ } while (1);
+ sbody = ialloc_string(size, "string");
+ if (sbody == 0) {
+ code = gs_error_VMerror;
+ goto error;
+ }
+ make_string(&stringref, a_all | icurrent_space, size, sbody);
+ memset(sbody, 0x00, size);
+ memcpy(sbody, names_array[ix], size);
+ gs_free_object(pdfctx->ctx->memory, names_array[ix], "free collection temporary filenames");
+ names_array[ix] = NULL;
+ pelement = collection.value.refs + ix;
+ ref_assign_old(&collection, pelement, &stringref, "put names string");
}
- make_string(&stringref, a_all | icurrent_space, size, sbody);
- memset(sbody, 0x00, size);
- memcpy(sbody, names_array[ix], size);
- gs_free_object(pdfctx->ctx->memory, names_array[ix], "free collection temporary filenames");
- names_array[ix] = NULL;
- pelement = collection.value.refs + ix;
- ref_assign_old(&collection, pelement, &stringref, "put names string");
}
+ gs_free_object(pdfctx->ctx->memory, names_array, "free collection temporary filenames");
+ code = 0;
}
- gs_free_object(pdfctx->ctx->memory, names_array, "free collection temporary filenames");
- code = 0;
}
-
+ else {
+ return_error(gs_error_ioerror);
+ }
return code;
error:
@@ -618,9 +723,7 @@ static int zPDFpageinfo(i_ctx_t *i_ctx_p)
int page = 0, code = 0, i;
pdfctx_t *pdfctx;
pdf_info_t info;
- gs_gstate *pgs = NULL;
- gs_gstate_client_procs procs;
- void *client_data;
+ pdfi_switch_t i_switch;
check_op(2);
@@ -630,163 +733,160 @@ static int zPDFpageinfo(i_ctx_t *i_ctx_p)
check_type(*(op - 1), t_pdfctx);
pdfctx = r_ptr(op - 1, pdfctx_t);
- pgs = pdfctx->ctx->pgs;
- procs = igs->client_procs;
- client_data = igs->client_data;
- pdfi_gstate_from_PS(pdfctx->ctx, igs, &client_data, &procs);
- pdfctx->ctx->pgs = igs;
-
- code = pdfi_page_info(pdfctx->ctx, (uint64_t)page, &info);
-
- pdfi_gstate_to_PS(pdfctx->ctx, igs, client_data, &procs);
- if (code == 0)
- code = gs_grestore(igs);
- else
- (void)gs_grestore(igs);
- pdfctx->ctx->pgs = pgs;
+ if (pdfctx->pdf_stream != NULL) {
+ code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
- if (code < 0)
- return code;
+ if (code >= 0) {
+ code = pdfi_page_info(pdfctx->ctx, (uint64_t)page, &info);
- pop(1);
- op = osp;
-
- code = dict_create(4, op);
- if (code < 0)
- return code;
-
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"HasAnnots", 9, &nameref, 1);
- if (code < 0)
- return code;
- make_bool(&boolref, false);
- code = dict_put(op, &nameref, &boolref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
+ pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
+ }
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"UsesTransparency", 16, &nameref, 1);
- if (code < 0)
- return code;
- make_bool(&boolref, info.HasTransparency);
- code = dict_put(op, &nameref, &boolref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
+ if (code < 0)
+ return code;
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumSpots", 8, &nameref, 1);
- if (code < 0)
- return code;
- make_int(&numref, info.NumSpots);
- code = dict_put(op, &nameref, &numref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
+ pop(1);
+ op = osp;
- if (info.boxes & MEDIA_BOX) {
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"MediaBox", 8, &nameref, 1);
+ code = dict_create(4, op);
if (code < 0)
return code;
- code = ialloc_ref_array(&aref, a_all, 4, "array");
+
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"HasAnnots", 9, &nameref, 1);
if (code < 0)
return code;
- refset_null(aref.value.refs, 4);
- for (i=0;i < 4;i++) {
- make_real(&numref, info.MediaBox[i]);
- eltp = aref.value.refs + i;
- ref_assign_old(&aref, eltp, &numref, "put");
- }
- code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
+ make_bool(&boolref, false);
+ code = dict_put(op, &nameref, &boolref, &i_ctx_p->dict_stack);
if (code < 0)
return code;
- }
- if (info.boxes & CROP_BOX) {
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"CropBox", 7, &nameref, 1);
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"UsesTransparency", 16, &nameref, 1);
if (code < 0)
return code;
- code = ialloc_ref_array(&aref, a_all, 4, "array");
+ make_bool(&boolref, info.HasTransparency);
+ code = dict_put(op, &nameref, &boolref, &i_ctx_p->dict_stack);
if (code < 0)
return code;
- refset_null(aref.value.refs, 4);
- for (i=0;i < 4;i++) {
- make_real(&numref, info.CropBox[i]);
- eltp = aref.value.refs + i;
- ref_assign_old(&aref, eltp, &numref, "put");
- }
- code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
- }
- if (info.boxes & TRIM_BOX) {
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"TrimBox", 7, &nameref, 1);
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumSpots", 8, &nameref, 1);
if (code < 0)
return code;
- code = ialloc_ref_array(&aref, a_all, 4, "array");
+ make_int(&numref, info.NumSpots);
+ code = dict_put(op, &nameref, &numref, &i_ctx_p->dict_stack);
if (code < 0)
return code;
- refset_null(aref.value.refs, 4);
- for (i=0;i < 4;i++) {
- make_real(&numref, info.TrimBox[i]);
- eltp = aref.value.refs + i;
- ref_assign_old(&aref, eltp, &numref, "put");
+
+ if (info.boxes & MEDIA_BOX) {
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"MediaBox", 8, &nameref, 1);
+ if (code < 0)
+ return code;
+ code = ialloc_ref_array(&aref, a_all, 4, "array");
+ if (code < 0)
+ return code;
+ refset_null(aref.value.refs, 4);
+ for (i=0;i < 4;i++) {
+ make_real(&numref, info.MediaBox[i]);
+ eltp = aref.value.refs + i;
+ ref_assign_old(&aref, eltp, &numref, "put");
+ }
+ code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
+ if (code < 0)
+ return code;
}
- code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
- }
- if (info.boxes & ART_BOX) {
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"ArtBox", 6, &nameref, 1);
- if (code < 0)
- return code;
- code = ialloc_ref_array(&aref, a_all, 4, "array");
- if (code < 0)
- return code;
- refset_null(aref.value.refs, 4);
- for (i=0;i < 4;i++) {
- make_real(&numref, info.ArtBox[i]);
- eltp = aref.value.refs + i;
- ref_assign_old(&aref, eltp, &numref, "put");
+ if (info.boxes & CROP_BOX) {
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"CropBox", 7, &nameref, 1);
+ if (code < 0)
+ return code;
+ code = ialloc_ref_array(&aref, a_all, 4, "array");
+ if (code < 0)
+ return code;
+ refset_null(aref.value.refs, 4);
+ for (i=0;i < 4;i++) {
+ make_real(&numref, info.CropBox[i]);
+ eltp = aref.value.refs + i;
+ ref_assign_old(&aref, eltp, &numref, "put");
+ }
+ code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
+ if (code < 0)
+ return code;
}
- code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
- }
- if (info.boxes & BLEED_BOX) {
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"BleedBox", 8, &nameref, 1);
- if (code < 0)
- return code;
- code = ialloc_ref_array(&aref, a_all, 4, "array");
- if (code < 0)
- return code;
- refset_null(aref.value.refs, 4);
- for (i=0;i < 4;i++) {
- make_real(&numref, info.BleedBox[i]);
- eltp = aref.value.refs + i;
- ref_assign_old(&aref, eltp, &numref, "put");
+ if (info.boxes & TRIM_BOX) {
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"TrimBox", 7, &nameref, 1);
+ if (code < 0)
+ return code;
+ code = ialloc_ref_array(&aref, a_all, 4, "array");
+ if (code < 0)
+ return code;
+ refset_null(aref.value.refs, 4);
+ for (i=0;i < 4;i++) {
+ make_real(&numref, info.TrimBox[i]);
+ eltp = aref.value.refs + i;
+ ref_assign_old(&aref, eltp, &numref, "put");
+ }
+ code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
+ if (code < 0)
+ return code;
}
- code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
- }
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"Rotate", 6, &nameref, 1);
- if (code < 0)
- return code;
- make_real(&numref, info.Rotate);
- code = dict_put(op, &nameref, &numref, &i_ctx_p->dict_stack);
- if (code < 0)
- return code;
+ if (info.boxes & ART_BOX) {
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"ArtBox", 6, &nameref, 1);
+ if (code < 0)
+ return code;
+ code = ialloc_ref_array(&aref, a_all, 4, "array");
+ if (code < 0)
+ return code;
+ refset_null(aref.value.refs, 4);
+ for (i=0;i < 4;i++) {
+ make_real(&numref, info.ArtBox[i]);
+ eltp = aref.value.refs + i;
+ ref_assign_old(&aref, eltp, &numref, "put");
+ }
+ code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
+ if (code < 0)
+ return code;
+ }
- if (info.UserUnit != 1) {
- code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"UserUnit", 8, &nameref, 1);
+ if (info.boxes & BLEED_BOX) {
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"BleedBox", 8, &nameref, 1);
+ if (code < 0)
+ return code;
+ code = ialloc_ref_array(&aref, a_all, 4, "array");
+ if (code < 0)
+ return code;
+ refset_null(aref.value.refs, 4);
+ for (i=0;i < 4;i++) {
+ make_real(&numref, info.BleedBox[i]);
+ eltp = aref.value.refs + i;
+ ref_assign_old(&aref, eltp, &numref, "put");
+ }
+ code = dict_put(op, &nameref, &aref, &i_ctx_p->dict_stack);
+ if (code < 0)
+ return code;
+ }
+
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"Rotate", 6, &nameref, 1);
if (code < 0)
return code;
- make_real(&numref, info.UserUnit);
+ make_real(&numref, info.Rotate);
code = dict_put(op, &nameref, &numref, &i_ctx_p->dict_stack);
if (code < 0)
return code;
- }
+ if (info.UserUnit != 1) {
+ code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"UserUnit", 8, &nameref, 1);
+ if (code < 0)
+ return code;
+ make_real(&numref, info.UserUnit);
+ code = dict_put(op, &nameref, &numref, &i_ctx_p->dict_stack);
+ if (code < 0)
+ return code;
+ }
+ }
+ else {
+ return_error(gs_error_ioerror);
+ }
return 0;
}
@@ -809,9 +909,7 @@ static int zPDFdrawpage(i_ctx_t *i_ctx_p)
int code = 0;
uint64_t page = 0;
pdfctx_t *pdfctx;
- gs_gstate *pgs = NULL;
- gs_gstate_client_procs procs;
- void *client_data;
+ pdfi_switch_t i_switch;
check_op(2);
@@ -821,27 +919,28 @@ static int zPDFdrawpage(i_ctx_t *i_ctx_p)
check_type(*(op - 1), t_pdfctx);
pdfctx = r_ptr(op - 1, pdfctx_t);
- code = gs_gsave(igs);
- if (code < 0)
- return code;
-
- pgs = pdfctx->ctx->pgs;
- procs = igs->client_procs;
- client_data = igs->client_data;
- pdfi_gstate_from_PS(pdfctx->ctx, igs, &client_data, &procs);
- pdfctx->ctx->pgs = igs;
+ if (pdfctx->pdf_stream != NULL) {
+ code = gs_gsave(igs);
+ if (code < 0)
+ return code;
- code = pdfi_page_render(pdfctx->ctx, page, false);
- if (code >= 0)
- pop(2);
+ code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
- pdfi_gstate_to_PS(pdfctx->ctx, igs, client_data, &procs);
- if (code == 0)
- code = gs_grestore(igs);
- else
- (void)gs_grestore(igs);
- pdfctx->ctx->pgs = pgs;
+ if (code >= 0) {
+ code = pdfi_page_render(pdfctx->ctx, page, false);
+ if (code >= 0)
+ pop(2);
+ pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
+ }
+ if (code == 0)
+ code = gs_grestore(igs);
+ else
+ (void)gs_grestore(igs);
+ }
+ else {
+ return_error(gs_error_ioerror);
+ }
return code;
}
@@ -906,6 +1005,12 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
pdfctx->ps_stream = NULL;
pdfctx->pdf_stream = NULL;
pdfctx->pdf_stream_memory = NULL;
+ pdfctx->profile_cache = gsicc_profilecache_new(imemory);
+ if (pdfctx->profile_cache == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto error;
+ }
+ pdfctx->cache_memory = imemory;
ctx = pdfi_create_context(cmem);
if (ctx == NULL) {
@@ -914,7 +1019,7 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
}
pdfctx->ctx = ctx;
- get_zfont_glyph_name((void **)&pdfctx->ctx->get_glyph_name);
+ get_zfont_glyph_name(&pdfctx->ctx->get_glyph_name);
pdfctx->ctx->get_glyph_index = zpdfi_glyph_index;
if (ref_stack_count(&o_stack) > 0 && r_has_type(op, t_dictionary)) {
@@ -984,7 +1089,7 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
pdfctx->ctx->args.last_page = pvalueref->value.intval;
}
- if (dict_find_string(pdictref, "NOCIDFALLBACK", &pvalueref) > 0) {
+ if (dict_find_string(pdictref, "PDFNOCIDFALLBACK", &pvalueref) > 0) {
if (!r_has_type(pvalueref, t_boolean))
goto error;
pdfctx->ctx->args.nocidfallback = pvalueref->value.boolval;
@@ -996,6 +1101,21 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
pdfctx->ctx->args.no_pdfmark_outlines = pvalueref->value.boolval;
}
+ /* This one can be a boolean OR an integer */
+ if (dict_find_string(pdictref, "UsePDFX3Profile", &pvalueref) > 0) {
+ if (!r_has_type(pvalueref, t_boolean)) {
+ if (!r_has_type(pvalueref, t_integer))
+ goto error;
+ else {
+ pdfctx->ctx->args.UsePDFX3Profile = true;
+ pdfctx->ctx->args.PDFX3Profile_num = pvalueref->value.intval;
+ }
+ } else {
+ pdfctx->ctx->args.UsePDFX3Profile = pvalueref->value.boolval;
+ pdfctx->ctx->args.PDFX3Profile_num = 0;
+ }
+ }
+
if (dict_find_string(pdictref, "NO_PDFMARK_DESTS", &pvalueref) > 0) {
if (!r_has_type(pvalueref, t_boolean))
goto error;
@@ -1056,6 +1176,12 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
pdfctx->ctx->args.preserveannots = pvalueref->value.boolval;
}
+ if (dict_find_string(pdictref, "PreserveMarkedContent", &pvalueref) > 0) {
+ if (!r_has_type(pvalueref, t_boolean))
+ goto error;
+ pdfctx->ctx->args.preservemarkedcontent = pvalueref->value.boolval;
+ }
+
if (dict_find_string(pdictref, "NoUserUnit", &pvalueref) > 0) {
if (!r_has_type(pvalueref, t_boolean))
goto error;
@@ -1091,21 +1217,57 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
if (code < 0)
goto error;
}
+ if (dict_find_string(pdictref, "CIDSubstPath", &pvalueref) > 0) {
+ if (!r_has_type(pvalueref, t_string))
+ goto error;
+ pdfctx->ctx->args.cidsubstpath.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, r_size(pvalueref) + 1, "PDF CIDSubstPath from zpdfops");
+ memcpy(pdfctx->ctx->args.cidsubstpath.data, pvalueref->value.const_bytes, r_size(pvalueref));
+ pdfctx->ctx->args.cidsubstpath.size = r_size(pvalueref);
+ }
+ if (dict_find_string(pdictref, "CIDSubstFont", &pvalueref) > 0) {
+ if (!r_has_type(pvalueref, t_string))
+ goto error;
+ pdfctx->ctx->args.cidsubstfont.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, r_size(pvalueref) + 1, "PDF CIDSubstPath from zpdfops");
+ memcpy(pdfctx->ctx->args.cidsubstfont.data, pvalueref->value.const_bytes, r_size(pvalueref));
+ pdfctx->ctx->args.cidsubstfont.size = r_size(pvalueref);
+ }
+ if (dict_find_string(pdictref, "IgnoreToUnicode", &pvalueref) > 0) {
+ if (!r_has_type(pvalueref, t_boolean))
+ goto error;
+ pdfctx->ctx->args.ignoretounicode = pvalueref->value.boolval;
+ }
+ if (dict_find_string(pdictref, "NONATIVEFONTMAP", &pvalueref) > 0) {
+ if (!r_has_type(pvalueref, t_boolean))
+ goto error;
+ pdfctx->ctx->args.nonativefontmap = pvalueref->value.boolval;
+ }
code = 0;
pop(1);
}
- zpdfi_populate_search_paths(i_ctx_p, ctx);
+ code = zpdfi_populate_search_paths(i_ctx_p, ctx);
+ if (code < 0)
+ goto error;
+
+ code = zpdfi_populate_fontmap_files(i_ctx_p, ctx);
+ if (code < 0)
+ goto error;
+
op = osp;
push(1);
make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx));
return 0;
error:
- if (ctx)
+ if (ctx != NULL)
pdfi_free_context(ctx);
/* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
(void)gs_memory_chunk_unwrap(cmem);
- if (pdfctx) {
+ if (pdfctx != NULL) {
+ pdfctx->ctx = NULL; /* Freed already above! */
+ if (pdfctx->profile_cache != NULL) {
+ gs_free_object(imemory, pdfctx->profile_cache, "discard temporary profile cache");
+ pdfctx->profile_cache = NULL;
+ }
pdfctx->pdf_memory = NULL;
gs_free_object(imemory, pdfctx, "PDFcontext");
}