diff options
author | Sam James <sam@gentoo.org> | 2022-03-29 10:27:10 +0100 |
---|---|---|
committer | Sam James <sam@gentoo.org> | 2022-04-17 12:53:05 +0100 |
commit | 085bde903b9e684c3c1160e4df912bea9a660997 (patch) | |
tree | c4f5e6e9f2422e869ca5bc0b944520d451001282 /psi | |
parent | Import Ghostscript 9.55 (diff) | |
download | ghostscript-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.h | 2 | ||||
-rw-r--r-- | psi/dmmain.c | 6 | ||||
-rw-r--r-- | psi/dpmain.c | 52 | ||||
-rw-r--r-- | psi/dscparse.c | 8 | ||||
-rw-r--r-- | psi/iapi.c | 51 | ||||
-rw-r--r-- | psi/iapi.h | 15 | ||||
-rw-r--r-- | psi/idebug.c | 4 | ||||
-rw-r--r-- | psi/idict.c | 4 | ||||
-rw-r--r-- | psi/idstack.c | 6 | ||||
-rw-r--r-- | psi/igc.c | 3 | ||||
-rw-r--r-- | psi/igcstr.c | 29 | ||||
-rw-r--r-- | psi/imain.c | 2 | ||||
-rw-r--r-- | psi/imainarg.c | 7 | ||||
-rw-r--r-- | psi/interp.c | 7 | ||||
-rw-r--r-- | psi/iparam.c | 4 | ||||
-rw-r--r-- | psi/iref.h | 8 | ||||
-rw-r--r-- | psi/iscan.c | 27 | ||||
-rw-r--r-- | psi/iscan.h | 16 | ||||
-rw-r--r-- | psi/iutil.c | 29 | ||||
-rw-r--r-- | psi/iutil2.c | 4 | ||||
-rw-r--r-- | psi/msvc.mak | 153 | ||||
-rw-r--r-- | psi/nsisinst.nsi | 37 | ||||
-rw-r--r-- | psi/os2.mak | 4 | ||||
-rw-r--r-- | psi/psapi.c | 27 | ||||
-rw-r--r-- | psi/winint.mak | 4 | ||||
-rw-r--r-- | psi/zbfont.c | 11 | ||||
-rw-r--r-- | psi/zcolor.c | 3 | ||||
-rw-r--r-- | psi/zdevice.c | 152 | ||||
-rw-r--r-- | psi/zdouble.c | 10 | ||||
-rw-r--r-- | psi/zfapi.c | 25 | ||||
-rw-r--r-- | psi/zfarc4.c | 3 | ||||
-rw-r--r-- | psi/zfile.c | 17 | ||||
-rw-r--r-- | psi/zfont2.c | 4 | ||||
-rw-r--r-- | psi/zht.c | 4 | ||||
-rw-r--r-- | psi/zpcolor.c | 4 | ||||
-rw-r--r-- | psi/zpdfops.c | 690 |
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; @@ -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(¶ms, 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); } @@ -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 * @@ -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"); @@ -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; @@ -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"); } |