Coverage Report

Created: 2026-09-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/zpdfops.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Custom operators for PDF interpreter */
18
19
#if defined(BUILD_PDF) && BUILD_PDF == 1
20
#include "ghostpdf.h"
21
#include "pdf_page.h"
22
#include "gzht.h"
23
#include "gsrefct.h"
24
#include "pdf_misc.h"
25
#include "pdf_stack.h"
26
#include "pdf_dict.h"
27
#include "pdf_array.h"
28
#include "pdf_loop_detect.h"
29
30
#include "iminst.h"
31
#include "dstack.h"
32
#include "gsicc_profilecache.h"
33
#include "pagelist.h"
34
#endif
35
36
#include "ghost.h"
37
#include "gsmchunk.h"
38
#include "oper.h"
39
#include "igstate.h"
40
#include "istack.h"
41
#include "iutil.h"
42
#include "gspath.h"
43
#include "math_.h"
44
#include "ialloc.h"
45
#include "igc.h" /* needed for definition of gc_state for the ref_struct_clear_marks call */
46
#include "malloc_.h"
47
#include "string_.h"
48
#include "store.h"
49
#include "gxgstate.h"
50
#include "gxdevsop.h"
51
#include "idict.h"
52
#include "iname.h"
53
#include "bfont.h"
54
55
#if defined(BUILD_PDF) && BUILD_PDF == 1
56
57
static int zpdfi_populate_search_paths(i_ctx_t *i_ctx_p, pdf_context *ctx)
58
83.0k
{
59
83.0k
    int code = 0;
60
    /* This should only be called once per pdfi context
61
       if the paths are already populated, just skip it.
62
     */
63
83.0k
    if (ctx->search_paths.resource_paths == NULL) {
64
83.0k
        ref *l2dictref, *grdref, *fpathref;
65
83.0k
        int i;
66
83.0k
        const gs_file_path *pfpath = i_ctx_p->lib_path;
67
83.0k
        gs_main_instance *minst = get_minst_from_memory(imemory);
68
69
83.0k
        if (i_ctx_p->system_params.GenericResourceDir != NULL) {
70
83.0k
            ctx->search_paths.genericresourcedir.data = gs_alloc_bytes(ctx->memory, strlen(i_ctx_p->system_params.GenericResourceDir), "zpdfi_populate_search_paths");
71
83.0k
            if (ctx->search_paths.genericresourcedir.data == NULL) {
72
0
                code = gs_note_error(gs_error_VMerror);
73
0
                goto done;
74
0
            }
75
83.0k
            memcpy((char *)ctx->search_paths.genericresourcedir.data, i_ctx_p->system_params.GenericResourceDir, strlen(i_ctx_p->system_params.GenericResourceDir));
76
83.0k
            ctx->search_paths.genericresourcedir.size = strlen(i_ctx_p->system_params.GenericResourceDir);
77
83.0k
            ctx->search_paths.genericresourcedir.persistent = false;
78
83.0k
        }
79
80
83.0k
        ctx->search_paths.resource_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, (size_t)sizeof(gs_param_string) * r_size(&pfpath->list), "array of paths");
81
83.0k
        if (ctx->search_paths.resource_paths == NULL) {
82
0
            code = gs_note_error(gs_error_VMerror);
83
0
            goto done;
84
0
        }
85
83.0k
        memset(ctx->search_paths.resource_paths, 0x00, sizeof(gs_param_string) * r_size(&pfpath->list));
86
87
83.0k
        ctx->search_paths.num_resource_paths = r_size(&pfpath->list);
88
1.16M
        for (i = 0; i < r_size(&pfpath->list); i++) {
89
1.08M
            const ref *prdir = pfpath->list.value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
90
1.08M
            ctx->search_paths.resource_paths[i].data = gs_alloc_bytes(ctx->memory, r_size(prdir), "zpdfi_populate_search_paths");
91
1.08M
            if (ctx->search_paths.resource_paths[i].data == NULL) {
92
0
                code = gs_note_error(gs_error_VMerror);
93
0
                goto done;
94
0
            }
95
1.08M
            memcpy((char *)ctx->search_paths.resource_paths[i].data, prdir->value.const_bytes, r_size(prdir));
96
1.08M
            ctx->search_paths.resource_paths[i].size = r_size(prdir);
97
1.08M
            ctx->search_paths.resource_paths[i].persistent = false;
98
1.08M
        }
99
83.0k
        code = dict_find_string(systemdict, "FONTPATH", &fpathref);
100
83.0k
        if (code >= 0 && r_has_type(fpathref, t_array)) {
101
0
            ctx->search_paths.font_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, (size_t)sizeof(gs_param_string) * r_size(fpathref), "array of font paths");
102
0
            if (ctx->search_paths.font_paths == NULL) {
103
0
                code = gs_note_error(gs_error_VMerror);
104
0
                goto done;
105
0
            }
106
0
            memset(ctx->search_paths.font_paths, 0x00, sizeof(gs_param_string) * r_size(fpathref));
107
108
0
            ctx->search_paths.num_font_paths = r_size(fpathref);
109
0
            for (i = 0; i < r_size(fpathref); i++) {
110
0
                const ref *prdir = fpathref->value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
111
0
                ctx->search_paths.font_paths[i].data = gs_alloc_bytes(ctx->memory, r_size(prdir), "zpdfi_populate_search_paths");
112
0
                if (ctx->search_paths.font_paths[i].data == NULL) {
113
0
                    code = gs_note_error(gs_error_VMerror);
114
0
                    goto done;
115
0
                }
116
0
                memcpy((char *)ctx->search_paths.font_paths[i].data, prdir->value.const_bytes, r_size(prdir));
117
0
                ctx->search_paths.font_paths[i].size = r_size(prdir);
118
0
                ctx->search_paths.font_paths[i].persistent = false;
119
0
            }
120
0
        }
121
83.0k
        ctx->search_paths.search_here_first = minst->search_here_first;
122
83.0k
    }
123
83.0k
done:
124
83.0k
    return code >= 0 ? 0 : code;
125
83.0k
}
126
127
static int zpdfi_populate_fontmap_files(i_ctx_t *i_ctx_p, pdf_context *ctx)
128
83.0k
{
129
83.0k
    int code, i;
130
83.0k
    ref *fontmaps;
131
132
83.0k
    code = dict_find_string(systemdict, "FONTMAP", &fontmaps);
133
83.0k
    if (code >= 0 && r_has_type(fontmaps, t_array)) {
134
0
        ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, (size_t)sizeof(gs_string) * r_size(fontmaps), "array of fontmap files");
135
0
        if (ctx->fontmapfiles != 0) {
136
0
            memset(ctx->fontmapfiles, 0x00, sizeof(gs_string) * r_size(fontmaps));
137
0
            ctx->num_fontmapfiles = r_size(fontmaps);
138
0
            for (i = 0; i < r_size(fontmaps); i++) {
139
0
                const ref *fmapfile = fontmaps->value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
140
0
                ctx->fontmapfiles[i].data = gs_alloc_bytes(ctx->memory, r_size(fmapfile), "zpdfi_populate_fontmap_files");
141
0
                if (ctx->fontmapfiles[i].data == NULL) {
142
0
                    code = gs_note_error(gs_error_VMerror);
143
0
                    goto done;
144
0
                }
145
0
                memcpy((char *)ctx->fontmapfiles[i].data, fmapfile->value.const_bytes, r_size(fmapfile));
146
0
                ctx->fontmapfiles[i].size = r_size(fmapfile);
147
0
            }
148
0
        }
149
0
        else {
150
0
            code = gs_note_error(gs_error_VMerror);
151
0
            goto done;
152
0
        }
153
0
    }
154
83.0k
    else if (code >= 0 && r_has_type(fontmaps, t_string)) {
155
0
        ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_string), "array of fontmap files");
156
0
        if (ctx->fontmapfiles != 0) {
157
0
            ctx->num_fontmapfiles = 1;
158
0
            ctx->fontmapfiles[0].data = gs_alloc_bytes(ctx->memory, r_size(fontmaps), "zpdfi_populate_fontmap_files");
159
0
            if (ctx->fontmapfiles[0].data == NULL) {
160
0
                code = gs_note_error(gs_error_VMerror);
161
0
                goto done;
162
0
            }
163
0
            memcpy((char *)ctx->fontmapfiles[0].data, fontmaps->value.const_bytes, r_size(fontmaps));
164
0
            ctx->fontmapfiles[0].size = r_size(fontmaps);
165
0
        }
166
0
        else {
167
0
            code = gs_note_error(gs_error_VMerror);
168
0
            goto done;
169
0
        }
170
0
    }
171
83.0k
    else
172
83.0k
        code = 0;
173
83.0k
done:
174
83.0k
    return code;
175
83.0k
}
176
177
typedef struct stream_record_t {
178
    gs_memory_t *pdf_stream_memory; /* The memory allocator used to copy the PostScript stream to pdf_stream. Not exposed to garbager */
179
    stream *ps_stream;
180
} stream_record;
181
182
/*
183
 * Declare the structure we use to represent an instance of the PDF parser
184
 * as a t_struct.
185
 */
186
typedef struct pdfctx_s {
187
    pdf_context *ctx;               /* Not exposed to garbager */
188
    gs_memory_t *pdf_memory;        /* The 'wrapped' memory allocator used by the PDF interpreter. Not exposed to garbager */
189
    gs_memory_t *pdf_stream_memory; /* The memory allocator used to copy the PostScript stream to pdf_stream. Not exposed to garbager */
190
    stream_record *record;
191
    bool UsingPDFFile;
192
    gsicc_profile_cache_t *profile_cache;
193
    ref names_dict;
194
    gs_memory_t *cache_memory;      /* The memory allocator used to allocate the working (GC'ed) profile cache */
195
} pdfctx_t;
196
197
/* There is some unfortunately necessary complication in the structure above regarding the ICC profile cache.
198
 * Initially the problem was due to adding the colour space name to the 'interpreter data' part of the colour
199
 * space, in order to be able to identify the case where we switch to the current colour space.
200
 *
201
 * This caused problems with ICC spaces, because these maintain a reference to the colour space. If the profile
202
 * was stored in the PostScript profile cache (which it would be, because the profile cache is stored in the
203
 * grapchis state, which we inherit from the PostScript interpreter) then it would outlive the PDF interpreter,
204
 *  and when we came to free the cache it would try to free the colour space, which would try to free the PDF
205
 * name object, which had already been freed.
206
 *
207
 * To work around this we replaced the profile cache in the graphics state with the profile cache from the PDF
208
 * interpreter. Now when we free the PDF profile cache, it frees the colour spaces, and the PDF names, while they
209
 * are still valid.
210
 *
211
 * However, we then discovered that the garbage collector could reclaim the colour spaces. This happens because
212
 * no GC-visible object declares it has a reference to the colour space. It doesn't matter that the colour
213
 * space has been counted up, the GC frees it. Now the profile cache in pdfi is pointing to a colour space which
214
 * has gone away....
215
 *
216
 * To get round this, we create a brand-new profile cache, using GC'ed memory (well actually the interpreter
217
 * allocator, which is GC'ed for Ghostscript). When we switch to pdfi we replace the graphics state pdfi is
218
 * using with the one from the PostScript environment, and at the same time we swap out the profile cache
219
 * being used by that graphics state, so it uses our new one. On return to PostScript we swap them back.
220
 * This allows the lifetime of the profiles in the profile cache to be correct, because they are visible to the
221
 * garbage collector (the PDF context is a GC-visible object and enumerates it's member profile cache)
222
 * When we finalize the PDF context we count down the profile cache which dereferences all its entries. This
223
 * effectively frees the colour space (the memory may not be reclaimed yet) which calls the interpreter
224
 * specific cleanup, which frees the (still valid at this point) PDF name object and sets the pointer to NULL.
225
 *
226
 * The net result is that we have the profiles visible to the garbage collector during their lifetime, but
227
 * still have control over the cache, so we can empty it of the profiles created for pdfi when we close the
228
 * PDF interpreter.
229
 */
230
231
/* Structure descriptors */
232
static void pdfctx_finalize(const gs_memory_t *cmem, void *vptr);
233
234
static
235
CLEAR_MARKS_PROC(pdfctx_clear_marks)
236
608
{
237
608
  pdfctx_t *pdfctx = (pdfctx_t *)vptr;
238
608
  r_clear_attrs(&pdfctx->names_dict, l_mark);
239
608
}
240
241
static
242
3.00k
ENUM_PTRS_WITH(pdfctx_enum_ptrs, pdfctx_t *pdfctx) return 0;
243
600
case 0:
244
600
        ENUM_RETURN(pdfctx->record);
245
600
case 1:
246
600
    if (pdfctx->record != NULL)
247
565
        ENUM_RETURN(pdfctx->record->ps_stream);
248
35
    else
249
35
        ENUM_RETURN(NULL);
250
600
ENUM_PTR(2, pdfctx_t, profile_cache);
251
600
  case 3:
252
600
    ENUM_RETURN_REF(&((pdfctx_t *)vptr)->names_dict);
253
3.00k
ENUM_PTRS_END
254
255
600
static RELOC_PTRS_WITH(pdfctx_reloc_ptrs, pdfctx_t *pdfctx)
256
600
{
257
600
RELOC_REF_VAR(pdfctx->names_dict);
258
600
RELOC_VAR(pdfctx->profile_cache);
259
600
RELOC_VAR(pdfctx->record);
260
600
if (pdfctx->record)
261
600
    RELOC_VAR(pdfctx->record->ps_stream);
262
600
if (pdfctx->record && pdfctx->record->ps_stream) {
263
565
    pdfctx->ctx->main_stream->s = pdfctx->record->ps_stream;
264
565
}
265
600
}
266
600
RELOC_PTRS_END
267
268
gs_private_st_complex_only(st_pdfctx_t, pdfctx_t, "pdfctx_struct",\
269
    pdfctx_clear_marks, pdfctx_enum_ptrs, pdfctx_reloc_ptrs, pdfctx_finalize);
270
271
static int
272
notify_remove_stream(void *proc_data, void *event_data)
273
0
{
274
0
    stream_record *record = (stream_record *)proc_data;
275
276
0
    record->ps_stream = NULL;
277
0
    return 0;
278
0
}
279
280
static void
281
pdfctx_finalize(const gs_memory_t *cmem, void *vptr)
282
83.0k
{
283
83.0k
    pdfctx_t *pdfctx = vptr;
284
    /* Finalize methods have to cope with the possibility of being called multiple times
285
     *  on the same object - hence we null the entries.
286
     */
287
288
83.0k
    make_null(&pdfctx->names_dict);
289
83.0k
    if (pdfctx->profile_cache != NULL) {
290
317
        rc_decrement(pdfctx->profile_cache, "free the working profile cache");
291
317
        pdfctx->profile_cache = NULL;
292
317
    }
293
83.0k
    if (cmem != NULL) {
294
83.0k
        if (pdfctx->ctx != NULL) {
295
317
            if (pdfctx->record && pdfctx->record->ps_stream) {
296
                /* Detach the PostScript stream from the PDF context, otherwise the
297
                 * free_context code will close the main stream.
298
                 */
299
309
                gs_notify_unregister(&pdfctx->record->ps_stream->notify_list, notify_remove_stream, pdfctx->record);
300
309
                pdfctx->ctx->main_stream->s = NULL;
301
309
                gs_free_object(pdfctx->record->pdf_stream_memory, pdfctx->record, "free stream record");
302
309
                pdfctx->record = NULL;
303
309
            }
304
317
            (void)pdfi_free_context(pdfctx->ctx);
305
317
            pdfctx->ctx = NULL;
306
317
        }
307
83.0k
        if (pdfctx->pdf_memory != NULL) {
308
            /* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
309
83.0k
            (void)gs_memory_chunk_unwrap(pdfctx->pdf_memory);
310
83.0k
            pdfctx->pdf_memory = NULL;
311
83.0k
        }
312
83.0k
    }
313
83.0k
}
314
315
static int zPDFstream(i_ctx_t *i_ctx_p)
316
83.0k
{
317
83.0k
    os_ptr op = osp;
318
83.0k
    int code = 0;
319
83.0k
    stream *s;
320
83.0k
    pdfctx_t *pdfctx;
321
83.0k
    pdfi_switch_t i_switch;
322
323
83.0k
    check_op(2);
324
325
83.0k
    check_read_file(i_ctx_p, s, op - 1);
326
327
83.0k
    check_type(*op, t_pdfctx);
328
83.0k
    pdfctx = r_ptr(op, pdfctx_t);
329
330
    /* If the supplied context already has a file open, signal an error */
331
83.0k
    if (pdfctx->record != NULL || pdfctx->UsingPDFFile)
332
0
        return_error(gs_error_ioerror);
333
334
83.0k
    s->close_at_eod = false;
335
83.0k
    pdfctx->record = (stream_record *)gs_alloc_bytes_immovable(imemory->stable_memory, sizeof(stream_record), "");
336
83.0k
    if (pdfctx->record == NULL)
337
0
        return_error(gs_error_VMerror);
338
339
83.0k
    pdfctx->record->pdf_stream_memory = imemory->stable_memory;
340
83.0k
    pdfctx->record->ps_stream = s;
341
83.0k
    gs_notify_register(&s->notify_list, notify_remove_stream, pdfctx->record);
342
343
83.0k
    code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
344
345
83.0k
    if (code >= 0) {
346
83.0k
        code = pdfi_set_input_stream(pdfctx->ctx, pdfctx->record->ps_stream);
347
348
83.0k
        pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
349
83.0k
    }
350
351
83.0k
    if (code < 0) {
352
17.0k
        gs_notify_unregister(&pdfctx->record->ps_stream->notify_list, notify_remove_stream, pdfctx->record);
353
17.0k
        gs_free_object(pdfctx->record->pdf_stream_memory, pdfctx->record, "PDFstream record");
354
17.0k
        pdfctx->ctx->main_stream->s = NULL;
355
17.0k
        pdfctx->record = NULL;
356
17.0k
        return code;
357
17.0k
    }
358
359
66.0k
    pdfctx->ctx->finish_page = NULL;
360
66.0k
    make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx));
361
362
66.0k
    pop(2);
363
66.0k
    return 0;
364
83.0k
}
365
366
static int zPDFfile(i_ctx_t *i_ctx_p)
367
10
{
368
10
    os_ptr op = osp;
369
10
    pdfctx_t *pdfctx;
370
10
    char pdffilename[gp_file_name_sizeof];
371
10
    int code = 0;
372
10
    pdfi_switch_t i_switch;
373
374
10
    check_op(2);
375
376
4
    check_type(*op, t_pdfctx);
377
0
    pdfctx = r_ptr(op, pdfctx_t);
378
379
0
    check_read_type(*(op - 1), t_string);
380
0
    if (r_size(op - 1) > gp_file_name_sizeof - 2)
381
0
        return_error(gs_error_limitcheck);
382
383
    /* If the supplied context already has a file open, signal an error */
384
0
    if (pdfctx->record != NULL)
385
0
        return_error(gs_error_ioerror);
386
387
0
    memcpy(pdffilename, (op - 1)->value.bytes, r_size(op - 1));
388
0
    pdffilename[r_size(op - 1)] = 0;
389
390
0
    code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
391
392
0
    if (code >= 0) {
393
0
        code = pdfi_open_pdf_file(pdfctx->ctx, pdffilename);
394
395
0
        pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
396
0
    }
397
398
0
    if (code < 0)
399
0
        return code;
400
401
0
    pdfctx->UsingPDFFile = true;
402
0
    pdfctx->ctx->finish_page = NULL;
403
404
0
    pop(2);
405
0
    return 0;
406
0
}
407
408
static int zPDFclose(i_ctx_t *i_ctx_p)
409
82.7k
{
410
82.7k
    os_ptr op = osp;
411
82.7k
    int code = 0;
412
82.7k
    pdfctx_t *pdfctx;
413
414
82.7k
    check_type(*op, t_pdfctx);
415
82.7k
    pdfctx = r_ptr(op, pdfctx_t);
416
417
82.7k
    if (pdfctx->profile_cache != NULL) {
418
82.7k
        rc_decrement(pdfctx->profile_cache, "free the working profile cache");
419
82.7k
        pdfctx->profile_cache = NULL;
420
82.7k
    }
421
422
82.7k
    if (pdfctx->ctx != NULL) {
423
82.7k
        if (pdfctx->record != NULL) {
424
65.7k
            pdfi_switch_t i_switch;
425
426
65.7k
            code = gs_gsave(igs);
427
65.7k
            if (code < 0)
428
0
                return code;
429
430
65.7k
            code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
431
432
65.7k
            if (code >= 0) {
433
65.7k
                pdfi_finish_pdf_file(pdfctx->ctx);
434
65.7k
                pdfi_report_errors(pdfctx->ctx);
435
436
65.7k
                pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
437
65.7k
            }
438
65.7k
            code = gs_grestore(igs);
439
65.7k
            if (code < 0)
440
0
                return code;
441
            /* Detach the PostScript stream from the PDF context, otherwise the
442
             * close code will close the main stream
443
             */
444
65.7k
            if (pdfctx->ctx->main_stream)
445
65.7k
                pdfctx->ctx->main_stream->s = NULL;
446
65.7k
        }
447
82.7k
        code = pdfi_free_context(pdfctx->ctx);
448
82.7k
        pdfctx->ctx = NULL;
449
82.7k
    }
450
82.7k
    if (pdfctx->record) {
451
65.7k
        gs_notify_unregister(&pdfctx->record->ps_stream->notify_list, notify_remove_stream, pdfctx->record);
452
65.7k
        gs_free_object(pdfctx->record->pdf_stream_memory, pdfctx->record, "PDFstream record");
453
65.7k
        pdfctx->record = NULL;
454
65.7k
    }
455
82.7k
    pop(1);
456
82.7k
    return code;
457
82.7k
}
458
459
static int PDFobj_to_PSobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj, ref *PSobj);
460
461
#define DEBUG_INFO_DICT 0
462
463
static void debug_printmark(int type)
464
526k
{
465
#if DEBUG_INFO_DICT
466
    switch(type) {
467
        case 0:
468
            dbgprintf("<<\n");
469
            break;
470
        case 1:
471
            dbgprintf(">>\n");
472
            break;
473
        case 2:
474
            dbgprintf("[");
475
            break;
476
        case 3:
477
            dbgprintf("]\n");
478
            break;
479
    }
480
#endif
481
526k
}
482
483
static void debug_pdfobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj)
484
1.84M
{
485
#if DEBUG_INFO_DICT
486
    char *str = NULL;
487
    int code = 0, len = 0;
488
489
    switch(pdfi_type_of(PDFobj)) {
490
        case PDF_NAME:
491
            code = pdfi_string_from_name(pdfctx->ctx, (pdf_name *)PDFobj, &str, &len);
492
            if (code < 0)
493
                return;
494
            dbgprintf1("/%s ", str);
495
            (void)pdfi_free_string_from_name(pdfctx->ctx, str);
496
            break;
497
        case PDF_STRING:
498
            str = (char *)gs_alloc_bytes(pdfctx->ctx->memory, ((pdf_string *)PDFobj)->length + (size_t)1, "");
499
            if (str == NULL)
500
                return;
501
            memset(str, 0x00, ((pdf_string *)PDFobj)->length + 1);
502
            memcpy(str, ((pdf_string *)PDFobj)->data, ((pdf_string *)PDFobj)->length);
503
            dbgprintf1("/%s ", str);
504
            gs_free_object(pdfctx->ctx->memory, str, "");
505
            break;
506
        case PDF_INT:
507
            dbgprintf1("/%d ", ((pdf_num *)PDFobj)->value.i);
508
            break;
509
        case PDF_REAL:
510
            dbgprintf1("/%f ", ((pdf_num *)PDFobj)->value.d);
511
            break;
512
            break;
513
        case PDF_BOOL:
514
            if (PDFobj == PDF_TRUE_OBJ)
515
                dbgprintf("true ");
516
            else
517
                dbgprintf("false ");
518
            break;
519
        default:
520
            break;
521
    }
522
#endif
523
1.84M
}
524
525
static int PDFdict_to_PSdict(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_dict *PDFdict, ref *PSdict)
526
113k
{
527
113k
    int code = 0;
528
113k
    uint64_t index = 0;
529
113k
    pdf_name *Key = NULL;
530
113k
    pdf_obj *Value = NULL;
531
113k
    ref nameref, valueref;
532
113k
    char *str = NULL;
533
113k
    int len = 0;
534
535
113k
    code = dict_create(pdfi_dict_entries(PDFdict), PSdict);
536
113k
    if (code < 0)
537
0
        return code;
538
539
113k
    code = pdfi_loop_detector_mark(pdfctx->ctx);
540
113k
    if (code < 0)
541
0
        goto error;
542
543
113k
    code = pdfi_dict_first(pdfctx->ctx, PDFdict, (pdf_obj **)&Key, &Value, &index);
544
113k
    if (code == gs_error_undefined) {
545
676
        code = 0;
546
676
        goto error;
547
676
    }
548
549
560k
    while (code >= 0) {
550
560k
        code = pdfi_string_from_name(pdfctx->ctx, Key, &str, &len);
551
560k
        if (code < 0)
552
0
            goto error;
553
554
560k
        debug_pdfobj(i_ctx_p, pdfctx, (pdf_obj *)Key);
555
556
560k
        code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)str, len, &nameref, 1);
557
560k
        if (code < 0)
558
0
            goto error;
559
560
560k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, Value, &valueref);
561
560k
        if (code < 0)
562
263
            goto error;
563
564
560k
        code = dict_put(PSdict, &nameref, &valueref, &i_ctx_p->dict_stack);
565
560k
        if (code < 0)
566
0
            goto error;
567
568
560k
        pdfi_countdown(Key);
569
560k
        pdfi_countdown(Value);
570
560k
        Key = NULL;
571
560k
        Value = NULL;
572
573
560k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
574
560k
        if (code < 0)
575
0
            goto error;
576
577
560k
        code = pdfi_loop_detector_mark(pdfctx->ctx);
578
560k
        if (code < 0)
579
0
            goto error;
580
581
560k
        (void)pdfi_free_string_from_name(pdfctx->ctx, str);
582
560k
        str = NULL;
583
560k
        code = pdfi_dict_next(pdfctx->ctx, PDFdict, (pdf_obj **)&Key, &Value, &index);
584
560k
        if (code == gs_error_undefined) {
585
112k
            code = 0;
586
112k
            break;
587
112k
        }
588
560k
    }
589
113k
error:
590
113k
    (void)pdfi_free_string_from_name(pdfctx->ctx, str);
591
113k
    pdfi_countdown(Key);
592
113k
    pdfi_countdown(Value);
593
594
113k
    if (code < 0)
595
310
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
596
113k
    else
597
113k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
598
113k
    return code;
599
113k
}
600
601
static int PDFarray_to_PSarray(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_array *PDFarray, ref *PSarray)
602
149k
{
603
149k
    int code = 0, i = 0;
604
149k
    ref PS_ref;
605
149k
    pdf_obj *array_obj = NULL;
606
149k
    ref *eltp = NULL;
607
608
149k
    code = pdfi_loop_detector_mark(pdfctx->ctx);
609
149k
    if (code < 0)
610
0
        goto error;
611
612
149k
    code = ialloc_ref_array(PSarray, a_all, pdfi_array_size(PDFarray), "zPDFInfo");
613
149k
    if (code < 0)
614
0
        goto error;
615
616
757k
    for (i = 0;i < pdfi_array_size(PDFarray); i++) {
617
608k
        code = pdfi_array_fetch_recursing(pdfctx->ctx, PDFarray, i, &array_obj, true, true);
618
608k
        if (code < 0)
619
32
            goto error;
620
608k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, array_obj, &PS_ref);
621
608k
        if (code < 0) {
622
99
            pdfi_countdown(array_obj);
623
99
            goto error;
624
99
        }
625
626
608k
        eltp = PSarray->value.refs + i;
627
608k
        ref_assign_old((const ref *)PSarray, eltp, &PS_ref, "zPDFInfo");
628
629
608k
        pdfi_countdown(array_obj);
630
608k
        array_obj = NULL;
631
608k
    }
632
149k
error:
633
149k
    if (code < 0)
634
131
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
635
149k
    else
636
149k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
637
149k
    return code;
638
149k
}
639
640
static int PDFobj_to_PSobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj, ref *PSobj)
641
1.28M
{
642
1.28M
    int code = 0;
643
644
1.28M
    code = pdfi_loop_detector_mark(pdfctx->ctx);
645
1.28M
    if (code < 0)
646
0
        goto error;
647
648
1.28M
    debug_pdfobj(i_ctx_p, pdfctx, PDFobj);
649
650
1.28M
    switch(pdfi_type_of(PDFobj)) {
651
7.19k
        case PDF_NAME:
652
7.19k
            {
653
7.19k
                char *str = NULL;
654
7.19k
                int len;
655
656
7.19k
                code = pdfi_string_from_name(pdfctx->ctx, (pdf_name *)PDFobj, &str, &len);
657
7.19k
                if (code < 0)
658
0
                    goto error;
659
7.19k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)str, len, PSobj, 1);
660
7.19k
                (void)pdfi_free_string_from_name(pdfctx->ctx, str);
661
7.19k
            }
662
0
            break;
663
87.5k
        case PDF_STRING:
664
87.5k
            {
665
87.5k
                byte *sbody;
666
87.5k
                uint size = ((pdf_name *)PDFobj)->length;
667
668
87.5k
                sbody = ialloc_string(size, "string");
669
87.5k
                if (sbody == 0) {
670
0
                    code = gs_note_error(gs_error_VMerror);
671
87.5k
                } else {
672
87.5k
                    make_string(PSobj, a_all | icurrent_space, size, sbody);
673
87.5k
                    memcpy(sbody, ((pdf_name *)PDFobj)->data, size);
674
87.5k
                }
675
87.5k
            }
676
87.5k
            break;
677
497k
        case PDF_INT:
678
497k
            {
679
497k
                int64_t i;
680
681
497k
                code = pdfi_obj_to_int(pdfctx->ctx, PDFobj, &i);
682
497k
                if (code < 0)
683
0
                    goto error;
684
497k
                make_int(PSobj, i);
685
497k
            }
686
0
            break;
687
185k
        case PDF_BOOL:
688
185k
            if (PDFobj == PDF_TRUE_OBJ)
689
185k
                make_bool(PSobj, 1);
690
151k
            else
691
185k
                make_bool(PSobj, 0);
692
185k
            break;
693
239k
        case PDF_REAL:
694
239k
            {
695
239k
                double d;
696
697
239k
                code = pdfi_obj_to_real(pdfctx->ctx, PDFobj, &d);
698
239k
                if (code < 0)
699
0
                    goto error;
700
239k
                make_real(PSobj, d);
701
239k
            }
702
0
            break;
703
113k
        case PDF_DICT:
704
113k
            if (PDFobj->object_num != 0) {
705
20.3k
                code = pdfi_loop_detector_add_object(pdfctx->ctx, PDFobj->object_num);
706
20.3k
                if (code < 0)
707
0
                    goto error;
708
20.3k
            }
709
113k
            debug_printmark(0);
710
113k
            code = PDFdict_to_PSdict(i_ctx_p, pdfctx, (pdf_dict *)PDFobj, PSobj);
711
113k
            debug_printmark(1);
712
113k
            break;
713
149k
        case PDF_ARRAY:
714
149k
            if (PDFobj->object_num != 0) {
715
1.05k
                code = pdfi_loop_detector_add_object(pdfctx->ctx, PDFobj->object_num);
716
1.05k
                if (code < 0)
717
0
                    goto error;
718
1.05k
            }
719
149k
            debug_printmark(2);
720
149k
            code = PDFarray_to_PSarray(i_ctx_p, pdfctx, (pdf_array *)PDFobj, PSobj);
721
149k
            debug_printmark(3);
722
149k
            break;
723
855
        default:
724
855
            make_null(PSobj);
725
855
            break;
726
1.28M
    }
727
728
1.28M
error:
729
1.28M
    if (code < 0)
730
441
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
731
1.28M
    else
732
1.28M
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
733
1.28M
    return code;
734
1.28M
}
735
736
static int zPDFinfo(i_ctx_t *i_ctx_p)
737
66.0k
{
738
66.0k
    os_ptr op = osp;
739
66.0k
    pdfctx_t *pdfctx;
740
66.0k
    int code = 0;
741
66.0k
    ref intref, nameref;
742
66.0k
    uint64_t TotalFiles = 0, ix = 0;
743
66.0k
    char **names_array = NULL;
744
745
66.0k
    check_type(*(op), t_pdfctx);
746
66.0k
    pdfctx = r_ptr(op, pdfctx_t);
747
748
66.0k
    if ((pdfctx->record != NULL && pdfctx->record->ps_stream != NULL) || pdfctx->UsingPDFFile) {
749
66.0k
        code = dict_create(4, op);
750
66.0k
        if (code < 0)
751
0
            return code;
752
753
66.0k
        code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
754
66.0k
        if (code < 0)
755
0
            return code;
756
757
66.0k
        make_int(&intref, pdfctx->ctx->num_pages);
758
759
66.0k
        code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
760
66.0k
        if (code < 0)
761
0
            return code;
762
763
        /* Code to process Collections. The pdfi_prep_collection() function returns an
764
         * array of descriptions and filenames. Because the descriptions can contain
765
         * UTF16-BE encoded data we can't sue a NULL terminated string, so the description
766
         * strings are terminated with a triple-NULL sequence of bytes.
767
         * We copy the contents into a PostScript array, which we store in the info
768
         * dictionary using the /Collection key.
769
         */
770
66.0k
        if (pdfctx->ctx->Collection != NULL) {
771
0
            code = pdfi_prep_collection(pdfctx->ctx, &TotalFiles, &names_array);
772
0
            if (code >= 0 && TotalFiles > 0) {
773
0
                uint size;
774
0
                ref collection, stringref;
775
776
0
                code = ialloc_ref_array(&collection, a_all, TotalFiles * 2, "names array");
777
0
                if (code < 0)
778
0
                    goto error;
779
780
0
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"Collection", 10, &nameref, 1);
781
0
                if (code < 0)
782
0
                    goto error;
783
784
0
                code = dict_put(op, &nameref, &collection, &i_ctx_p->dict_stack);
785
0
                if (code < 0)
786
0
                    goto error;
787
788
0
                for (ix=0; ix < TotalFiles * 2; ix++) {
789
0
                    char *ptr;
790
0
                    byte *sbody;
791
0
                    ref *pelement;
792
793
0
                    if ((ptr = names_array[ix]) == NULL)
794
0
                        continue;
795
796
0
                    size = 0;
797
0
                    do {
798
0
                        if (ptr[0] == 0x00 && ptr[1] == 0x00 && ptr[2] == 0x00)
799
0
                            break;
800
0
                        ptr++;
801
0
                        size++;
802
0
                    } while (1);
803
0
                    sbody = ialloc_string(size, "string");
804
0
                    if (sbody == 0) {
805
0
                        code = gs_error_VMerror;
806
0
                        goto error;
807
0
                    }
808
0
                    make_string(&stringref, a_all | icurrent_space, size, sbody);
809
0
                    memset(sbody, 0x00, size);
810
0
                    memcpy(sbody, names_array[ix], size);
811
0
                    gs_free_object(pdfctx->ctx->memory, names_array[ix], "free collection temporary filenames");
812
0
                    names_array[ix] = NULL;
813
0
                    pelement = collection.value.refs + ix;
814
0
                    ref_assign_old(&collection, pelement, &stringref, "put names string");
815
0
                }
816
0
            }
817
0
            gs_free_object(pdfctx->ctx->memory, names_array, "free collection temporary filenames");
818
0
            code = 0;
819
66.0k
        } else {
820
66.0k
            if (pdfctx->ctx->Info != NULL) {
821
18.9k
                code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)pdfctx->ctx->Info, (ref *)op);
822
18.9k
                if (code < 0) {
823
79
                    if (pdfctx->ctx->args.pdfstoponerror)
824
0
                        return code;
825
79
                    code = dict_create(1, op);
826
79
                    if (code < 0)
827
0
                        return code;
828
79
                }
829
830
18.9k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
831
18.9k
                if (code < 0)
832
0
                    return code;
833
834
18.9k
                make_int(&intref, pdfctx->ctx->num_pages);
835
836
18.9k
                code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
837
18.9k
                if (code < 0)
838
0
                    return code;
839
47.0k
            } else {
840
47.0k
                code = dict_create(1, op);
841
47.0k
                if (code < 0)
842
0
                    return code;
843
844
47.0k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
845
47.0k
                if (code < 0)
846
0
                    return code;
847
848
47.0k
                make_int(&intref, pdfctx->ctx->num_pages);
849
850
47.0k
                code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
851
47.0k
                if (code < 0)
852
0
                    return code;
853
47.0k
            }
854
66.0k
        }
855
66.0k
    }
856
0
    else {
857
0
        return_error(gs_error_ioerror);
858
0
    }
859
66.0k
    return code;
860
861
0
error:
862
0
    for (ix=0; ix < TotalFiles * 2; ix++)
863
0
        gs_free_object(pdfctx->ctx->memory, names_array[ix], "free collection temporary filenames");
864
0
    gs_free_object(pdfctx->ctx->memory, names_array, "free collection temporary filenames");
865
0
    return code;
866
66.0k
}
867
868
static int zPDFpageinfo(i_ctx_t *i_ctx_p)
869
125k
{
870
125k
    os_ptr op = osp;
871
125k
    int page = 0, code = 0;
872
125k
    pdfctx_t *pdfctx;
873
125k
    pdf_dict *InfoDict = NULL;
874
125k
    pdfi_switch_t i_switch;
875
876
125k
    check_op(2);
877
878
125k
    check_type(*op, t_integer);
879
125k
    page = op->value.intval;
880
881
125k
    check_type(*(op - 1), t_pdfctx);
882
125k
    pdfctx = r_ptr(op - 1, pdfctx_t);
883
884
125k
    if ((pdfctx->record != NULL && pdfctx->record->ps_stream != NULL) || pdfctx->UsingPDFFile) {
885
125k
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
886
887
125k
        if (code >= 0) {
888
125k
            code = pdfi_page_info(pdfctx->ctx, (uint64_t)page, &InfoDict, false);
889
890
125k
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
891
125k
        }
892
893
125k
        if (code < 0)
894
32.5k
            return code;
895
896
92.5k
        pop(1);
897
92.5k
        op = osp;
898
899
92.5k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)InfoDict, op);
900
92.5k
        pdfi_countdown(InfoDict);
901
92.5k
        if (code < 0)
902
0
            return code;
903
92.5k
    }
904
0
    else {
905
0
        return_error(gs_error_ioerror);
906
0
    }
907
92.5k
    return 0;
908
125k
}
909
910
static int zPDFpageinfoExt(i_ctx_t *i_ctx_p)
911
0
{
912
0
    os_ptr op = osp;
913
0
    int page = 0, code = 0;
914
0
    pdfctx_t *pdfctx;
915
0
    pdf_dict *InfoDict = NULL;
916
0
    pdfi_switch_t i_switch;
917
918
0
    check_op(2);
919
920
0
    check_type(*op, t_integer);
921
0
    page = op->value.intval;
922
923
0
    check_type(*(op - 1), t_pdfctx);
924
0
    pdfctx = r_ptr(op - 1, pdfctx_t);
925
926
0
    if ((pdfctx->record != NULL && pdfctx->record->ps_stream != NULL) || pdfctx->UsingPDFFile) {
927
0
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
928
929
0
        if (code >= 0) {
930
0
            code = pdfi_page_info(pdfctx->ctx, (uint64_t)page, &InfoDict, true);
931
932
0
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
933
0
        }
934
935
0
        if (code < 0)
936
0
            return code;
937
938
0
        pop(1);
939
0
        op = osp;
940
941
0
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)InfoDict, op);
942
0
        pdfi_countdown(InfoDict);
943
0
        if (code < 0)
944
0
            return code;
945
0
    }
946
0
    else {
947
0
        return_error(gs_error_ioerror);
948
0
    }
949
0
    return 0;
950
0
}
951
952
static int zPDFmetadata(i_ctx_t *i_ctx_p)
953
0
{
954
#if 0
955
    os_ptr op = osp;
956
    pdfctx_t *pdfctx;
957
958
    check_type(*op, t_pdfctx);
959
    pdfctx = r_ptr(op, pdfctx_t);
960
#endif
961
962
0
    return_error(gs_error_undefined);
963
0
}
964
965
static int zPDFdrawpage(i_ctx_t *i_ctx_p)
966
92.3k
{
967
92.3k
    os_ptr op = osp;
968
92.3k
    int code = 0;
969
92.3k
    uint64_t page = 0;
970
92.3k
    pdfctx_t *pdfctx;
971
92.3k
    pdfi_switch_t i_switch;
972
973
92.3k
    check_op(2);
974
975
92.2k
    check_type(*op, t_integer);
976
92.2k
    page = op->value.intval;
977
978
92.2k
    check_type(*(op - 1), t_pdfctx);
979
92.2k
    pdfctx = r_ptr(op - 1, pdfctx_t);
980
981
92.2k
    if ((pdfctx->record != NULL && pdfctx->record->ps_stream != NULL) || pdfctx->UsingPDFFile) {
982
92.2k
        code = gs_gsave(igs);
983
92.2k
        if (code < 0)
984
0
            return code;
985
986
92.2k
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
987
988
92.2k
        if (code >= 0) {
989
92.2k
            if (pdfctx->ctx->args.pdfinfo)
990
0
                code = pdfi_output_page_info(pdfctx->ctx, page);
991
92.2k
            else
992
92.2k
                code = pdfi_page_render(pdfctx->ctx, page, false);
993
92.2k
            if (code >= 0)
994
84.6k
                pop(2);
995
996
92.2k
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
997
92.2k
        }
998
92.2k
        if (code == 0)
999
84.6k
            code = gs_grestore(igs);
1000
7.63k
        else
1001
7.63k
            (void)gs_grestore(igs);
1002
92.2k
    }
1003
0
    else {
1004
0
        return_error(gs_error_ioerror);
1005
0
    }
1006
92.2k
    return code;
1007
92.2k
}
1008
1009
static int zPDFdrawannots(i_ctx_t *i_ctx_p)
1010
0
{
1011
#if 0
1012
    os_ptr op = osp;
1013
    pdfctx_t *pdfctx;
1014
1015
    check_type(*op, t_pdfctx);
1016
    pdfctx = r_ptr(op, pdfctx_t);
1017
#endif
1018
1019
0
    return_error(gs_error_undefined);
1020
0
}
1021
1022
static int zpdfi_glyph_index(gs_font *pfont, byte *str, uint size, uint *glyph)
1023
151M
{
1024
151M
    int code = 0;
1025
151M
    ref nref;
1026
151M
    i_ctx_t *i_ctx_p = get_minst_from_memory(pfont->memory)->i_ctx_p;
1027
151M
    os_ptr op = osp;
1028
151M
    pdfctx_t *pdfctx;
1029
1030
151M
    check_type(*op - 1, t_pdfctx);
1031
151M
    pdfctx = r_ptr(op - 1, pdfctx_t);
1032
1033
151M
    code = name_ref(pfont->memory, str, size, &nref, true);
1034
151M
    if (code < 0)
1035
0
        return code;
1036
1037
151M
    code = dict_put(&pdfctx->names_dict, &nref, &nref, &i_ctx_p->dict_stack);
1038
151M
    if (code < 0)
1039
0
        return code;
1040
1041
151M
    *glyph = name_index(pfont->memory, &nref);
1042
151M
    return 0;
1043
151M
}
1044
1045
static int param_value_get_namelist(gs_memory_t *ps_mem, pdf_context *ctx, ref *pvalueref, char ***pstrlist)
1046
0
{
1047
0
    uint count;
1048
0
    char **strlist = NULL;
1049
0
    ref lval, sref;
1050
0
    int code;
1051
1052
0
    check_read_type(*pvalueref, t_array);
1053
1054
0
    strlist = (char **)gs_alloc_bytes(ctx->memory, (size_t)(r_size(pvalueref)+1)*sizeof(char *), "param_value_get_namelist");
1055
0
    if (strlist == NULL)
1056
0
        return_error(gs_error_VMerror);
1057
0
    memset(strlist, 0x00, (r_size(pvalueref)+1)*sizeof(char *));
1058
1059
0
    for (count = 0;count < r_size(pvalueref); count++) {
1060
0
        code = array_get(ps_mem, pvalueref, count, &lval);
1061
0
        if (code < 0)
1062
0
            return code;
1063
1064
0
        if (!r_has_type(&lval, t_string) && !r_has_type(&lval, t_name))
1065
0
            return_error(gs_error_typecheck);
1066
1067
0
        if (r_has_type(&lval, t_name))
1068
0
            name_string_ref(ps_mem, (const ref *)&lval, &sref);
1069
0
        else
1070
0
            sref = lval;
1071
1072
0
        strlist[count] = (char *)gs_alloc_bytes(ctx->memory, (size_t)sref.tas.rsize + 1, "param_value_get_namelist");
1073
0
        if (strlist[count] == NULL)
1074
0
            return_error(gs_error_VMerror);
1075
0
        memset(strlist[count], 0x00, sref.tas.rsize + 1);
1076
0
        memcpy(strlist[count], sref.value.bytes, sref.tas.rsize);
1077
0
    }
1078
0
    *pstrlist = strlist;
1079
0
    return 0;
1080
0
}
1081
1082
static int apply_interpreter_params(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, ref *pdictref)
1083
83.0k
{
1084
83.0k
    int code = gs_error_typecheck;
1085
83.0k
    ref *pvalueref;
1086
1087
83.0k
    if (dict_find_string(pdictref, "PDFCACHE", &pvalueref) > 0) {
1088
0
        if (!r_has_type(pvalueref, t_integer))
1089
0
            goto error;
1090
0
        pdfctx->ctx->args.PDFCacheSize = pvalueref->value.intval;
1091
0
    }
1092
1093
83.0k
    if (dict_find_string(pdictref, "PDFDEBUG", &pvalueref) > 0) {
1094
83.0k
        if (!r_has_type(pvalueref, t_boolean))
1095
0
            goto error;
1096
83.0k
        pdfctx->ctx->args.pdfdebug = pvalueref->value.boolval;
1097
83.0k
    }
1098
1099
83.0k
    if (dict_find_string(pdictref, "PDFSTOPONERROR", &pvalueref) > 0) {
1100
83.0k
        if (!r_has_type(pvalueref, t_boolean))
1101
0
            goto error;
1102
83.0k
        pdfctx->ctx->args.pdfstoponerror = pvalueref->value.boolval;
1103
83.0k
    }
1104
1105
83.0k
    if (dict_find_string(pdictref, "PDFSTOPONWARNING", &pvalueref) > 0) {
1106
83.0k
        if (!r_has_type(pvalueref, t_boolean))
1107
0
            goto error;
1108
83.0k
        pdfctx->ctx->args.pdfstoponwarning = pvalueref->value.boolval;
1109
83.0k
        if (pvalueref->value.boolval)
1110
0
            pdfctx->ctx->args.pdfstoponerror = pvalueref->value.boolval;
1111
83.0k
    }
1112
1113
83.0k
    if (dict_find_string(pdictref, "NOTRANSPARENCY", &pvalueref) > 0) {
1114
83.0k
        if (!r_has_type(pvalueref, t_boolean))
1115
0
            goto error;
1116
83.0k
        pdfctx->ctx->args.notransparency = pvalueref->value.boolval;
1117
83.0k
    }
1118
1119
83.0k
    if (dict_find_string(pdictref, "QUIET", &pvalueref) > 0) {
1120
83.0k
        if (!r_has_type(pvalueref, t_boolean))
1121
0
            goto error;
1122
83.0k
        pdfctx->ctx->args.QUIET = pvalueref->value.boolval;
1123
83.0k
    }
1124
1125
83.0k
    if (dict_find_string(pdictref, "VerboseErrors", &pvalueref) > 0) {
1126
0
        if (!r_has_type(pvalueref, t_boolean))
1127
0
            goto error;
1128
0
        pdfctx->ctx->args.verbose_errors = pvalueref->value.boolval;
1129
0
    }
1130
1131
83.0k
    if (dict_find_string(pdictref, "VerboseWarnings", &pvalueref) > 0) {
1132
0
        if (!r_has_type(pvalueref, t_boolean))
1133
0
            goto error;
1134
0
        pdfctx->ctx->args.verbose_warnings = pvalueref->value.boolval;
1135
0
    }
1136
1137
83.0k
    if (dict_find_string(pdictref, "PDFPassword", &pvalueref) > 0) {
1138
0
        if (!r_has_type(pvalueref, t_string))
1139
0
            goto error;
1140
0
        pdfctx->ctx->encryption.Password = (char *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF Password from zpdfops");
1141
0
        if (pdfctx->ctx->encryption.Password == NULL) {
1142
0
            code = gs_note_error(gs_error_VMerror);
1143
0
            goto error;
1144
0
        }
1145
0
        memset(pdfctx->ctx->encryption.Password, 0x00, r_size(pvalueref) + 1);
1146
0
        memcpy(pdfctx->ctx->encryption.Password, pvalueref->value.const_bytes, r_size(pvalueref));
1147
0
        pdfctx->ctx->encryption.PasswordLen = r_size(pvalueref);
1148
0
    }
1149
1150
83.0k
    if (dict_find_string(pdictref, "FirstPage", &pvalueref) > 0) {
1151
0
        if (!r_has_type(pvalueref, t_integer))
1152
0
            goto error;
1153
0
        pdfctx->ctx->args.first_page = pvalueref->value.intval;
1154
0
    }
1155
1156
83.0k
    if (dict_find_string(pdictref, "LastPage", &pvalueref) > 0) {
1157
0
        if (!r_has_type(pvalueref, t_integer))
1158
0
            goto error;
1159
0
        pdfctx->ctx->args.last_page = pvalueref->value.intval;
1160
0
    }
1161
1162
83.0k
    if (dict_find_string(pdictref, "PDFNOCIDFALLBACK", &pvalueref) > 0) {
1163
83.0k
        if (!r_has_type(pvalueref, t_boolean))
1164
0
            goto error;
1165
83.0k
        pdfctx->ctx->args.nocidfallback = pvalueref->value.boolval;
1166
83.0k
    }
1167
1168
83.0k
    if (dict_find_string(pdictref, "NO_PDFMARK_OUTLINES", &pvalueref) > 0) {
1169
0
        if (!r_has_type(pvalueref, t_boolean))
1170
0
            goto error;
1171
0
        pdfctx->ctx->args.no_pdfmark_outlines = pvalueref->value.boolval;
1172
0
    }
1173
1174
83.0k
    if (dict_find_string(pdictref, "PDFA", &pvalueref) > 0) {
1175
0
        if (!r_has_type(pvalueref, t_integer))
1176
0
            goto error;
1177
0
        pdfctx->ctx->args.PDFA = pvalueref->value.intval;
1178
0
    }
1179
1180
83.0k
    if (dict_find_string(pdictref, "PDFX", &pvalueref) > 0) {
1181
0
        if (!r_has_type(pvalueref, t_integer))
1182
0
            goto error;
1183
0
        pdfctx->ctx->args.PDFX = pvalueref->value.intval;
1184
0
    }
1185
1186
83.0k
    if (dict_find_string(pdictref, "PDFACompatibilityPolicy", &pvalueref) > 0) {
1187
0
        if (!r_has_type(pvalueref, t_integer))
1188
0
            goto error;
1189
0
        pdfctx->ctx->args.PDFA = pvalueref->value.intval;
1190
0
    }
1191
1192
    /* This one can be a boolean OR an integer */
1193
83.0k
    if (dict_find_string(pdictref, "UsePDFX3Profile", &pvalueref) > 0) {
1194
0
        if (!r_has_type(pvalueref, t_boolean)) {
1195
0
            if (!r_has_type(pvalueref, t_integer))
1196
0
                goto error;
1197
0
            else {
1198
0
                pdfctx->ctx->args.UsePDFX3Profile = true;
1199
0
                pdfctx->ctx->args.PDFX3Profile_num = pvalueref->value.intval;
1200
0
            }
1201
0
        } else {
1202
0
            pdfctx->ctx->args.UsePDFX3Profile = pvalueref->value.boolval;
1203
0
            pdfctx->ctx->args.PDFX3Profile_num = 0;
1204
0
        }
1205
0
    }
1206
1207
83.0k
    if (dict_find_string(pdictref, "NO_PDFMARK_DESTS", &pvalueref) > 0) {
1208
0
        if (!r_has_type(pvalueref, t_boolean))
1209
0
            goto error;
1210
0
        pdfctx->ctx->args.no_pdfmark_dests = pvalueref->value.boolval;
1211
0
    }
1212
1213
83.0k
    if (dict_find_string(pdictref, "PDFFitPage", &pvalueref) > 0) {
1214
0
        if (!r_has_type(pvalueref, t_boolean))
1215
0
            goto error;
1216
0
        pdfctx->ctx->args.pdffitpage = pvalueref->value.boolval;
1217
0
    }
1218
1219
83.0k
    if (dict_find_string(pdictref, "OutputFile", &pvalueref) > 0)
1220
83.0k
        pdfctx->ctx->args.printed = true;
1221
0
    else
1222
0
        pdfctx->ctx->args.printed = false;
1223
1224
83.0k
    if (dict_find_string(pdictref, "Printed", &pvalueref) > 0) {
1225
0
        if (!r_has_type(pvalueref, t_boolean))
1226
0
            goto error;
1227
0
        pdfctx->ctx->args.printed = pvalueref->value.boolval;
1228
0
    }
1229
1230
83.0k
    if (dict_find_string(pdictref, "UseBleedBox", &pvalueref) > 0) {
1231
0
        if (!r_has_type(pvalueref, t_boolean))
1232
0
            goto error;
1233
0
        pdfctx->ctx->args.usebleedbox = pvalueref->value.boolval;
1234
0
    }
1235
1236
83.0k
    if (dict_find_string(pdictref, "UseCropBox", &pvalueref) > 0) {
1237
0
        if (!r_has_type(pvalueref, t_boolean))
1238
0
            goto error;
1239
0
        pdfctx->ctx->args.usecropbox = pvalueref->value.boolval;
1240
0
    }
1241
1242
83.0k
    if (dict_find_string(pdictref, "UseArtBox", &pvalueref) > 0) {
1243
0
        if (!r_has_type(pvalueref, t_boolean))
1244
0
            goto error;
1245
0
        pdfctx->ctx->args.useartbox = pvalueref->value.boolval;
1246
0
    }
1247
1248
83.0k
    if (dict_find_string(pdictref, "UseTrimBox", &pvalueref) > 0) {
1249
0
        if (!r_has_type(pvalueref, t_boolean))
1250
0
            goto error;
1251
0
        pdfctx->ctx->args.usetrimbox = pvalueref->value.boolval;
1252
0
    }
1253
1254
83.0k
    if (dict_find_string(pdictref, "ShowAcroForm", &pvalueref) > 0) {
1255
0
        if (!r_has_type(pvalueref, t_boolean))
1256
0
            goto error;
1257
0
        pdfctx->ctx->args.showacroform = pvalueref->value.boolval;
1258
0
    }
1259
1260
83.0k
    if (dict_find_string(pdictref, "ShowAnnots", &pvalueref) > 0) {
1261
0
        if (!r_has_type(pvalueref, t_boolean))
1262
0
            goto error;
1263
0
        pdfctx->ctx->args.showannots = pvalueref->value.boolval;
1264
0
    }
1265
1266
83.0k
    if (dict_find_string(pdictref, "PreserveAnnots", &pvalueref) > 0) {
1267
0
        if (!r_has_type(pvalueref, t_boolean))
1268
0
            goto error;
1269
0
        pdfctx->ctx->args.preserveannots = pvalueref->value.boolval;
1270
0
    }
1271
1272
83.0k
    if (dict_find_string(pdictref, "PreserveMarkedContent", &pvalueref) > 0) {
1273
0
        if (!r_has_type(pvalueref, t_boolean))
1274
0
            goto error;
1275
0
        pdfctx->ctx->args.preservemarkedcontent = pvalueref->value.boolval;
1276
0
    }
1277
1278
83.0k
    if (dict_find_string(pdictref, "PreserveEmbeddedFiles", &pvalueref) > 0) {
1279
0
        if (!r_has_type(pvalueref, t_boolean))
1280
0
            goto error;
1281
0
        pdfctx->ctx->args.preserveembeddedfiles = pvalueref->value.boolval;
1282
0
    }
1283
1284
83.0k
    if (dict_find_string(pdictref, "PreserveDocView", &pvalueref) > 0) {
1285
0
        if (!r_has_type(pvalueref, t_boolean))
1286
0
            goto error;
1287
0
        pdfctx->ctx->args.preservedocview = pvalueref->value.boolval;
1288
0
    }
1289
1290
83.0k
    if (dict_find_string(pdictref, "NoUserUnit", &pvalueref) > 0) {
1291
0
        if (!r_has_type(pvalueref, t_boolean))
1292
0
            goto error;
1293
0
        pdfctx->ctx->args.nouserunit = pvalueref->value.boolval;
1294
0
    }
1295
1296
83.0k
    if (dict_find_string(pdictref, "RENDERTTNOTDEF", &pvalueref) > 0) {
1297
83.0k
        if (!r_has_type(pvalueref, t_boolean))
1298
0
            goto error;
1299
83.0k
        pdfctx->ctx->args.renderttnotdef = pvalueref->value.boolval;
1300
83.0k
    }
1301
1302
83.0k
    if (dict_find_string(pdictref, "DOPDFMARKS", &pvalueref) > 0) {
1303
0
        if (!r_has_type(pvalueref, t_boolean))
1304
0
            goto error;
1305
0
        pdfctx->ctx->args.dopdfmarks = pvalueref->value.boolval;
1306
0
    }
1307
1308
83.0k
    if (dict_find_string(pdictref, "PDFINFO", &pvalueref) > 0) {
1309
0
        if (!r_has_type(pvalueref, t_boolean))
1310
0
            goto error;
1311
0
        pdfctx->ctx->args.pdfinfo = pvalueref->value.boolval;
1312
0
    }
1313
83.0k
    if (dict_find_string(pdictref, "ShowAnnotTypes", &pvalueref) > 0) {
1314
0
        code = param_value_get_namelist(imemory, pdfctx->ctx, pvalueref,
1315
0
                                        &pdfctx->ctx->args.showannottypes);
1316
0
        if (code < 0)
1317
0
            goto error;
1318
0
    }
1319
83.0k
    if (dict_find_string(pdictref, "PreserveAnnotTypes", &pvalueref) > 0) {
1320
0
        code = param_value_get_namelist(imemory, pdfctx->ctx, pvalueref,
1321
0
                                        &pdfctx->ctx->args.preserveannottypes);
1322
0
        if (code < 0)
1323
0
            goto error;
1324
0
    }
1325
83.0k
    if (dict_find_string(pdictref, "CIDFSubstPath", &pvalueref) > 0) {
1326
0
        if (!r_has_type(pvalueref, t_string))
1327
0
            goto error;
1328
0
        pdfctx->ctx->args.cidfsubstpath.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF cidfsubstpath from zpdfops");
1329
0
        if (pdfctx->ctx->args.cidfsubstpath.data == NULL) {
1330
0
            code = gs_note_error(gs_error_VMerror);
1331
0
            goto error;
1332
0
        }
1333
0
        memcpy(pdfctx->ctx->args.cidfsubstpath.data, pvalueref->value.const_bytes, r_size(pvalueref));
1334
0
        pdfctx->ctx->args.cidfsubstpath.size = r_size(pvalueref);
1335
0
    }
1336
83.0k
    if (dict_find_string(pdictref, "CIDFSubstFont", &pvalueref) > 0) {
1337
0
        if (!r_has_type(pvalueref, t_string))
1338
0
            goto error;
1339
0
        pdfctx->ctx->args.cidfsubstfont.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF cidfsubstfont from zpdfops");
1340
0
        if (pdfctx->ctx->args.cidfsubstfont.data == NULL) {
1341
0
            code = gs_note_error(gs_error_VMerror);
1342
0
            goto error;
1343
0
        }
1344
0
        memcpy(pdfctx->ctx->args.cidfsubstfont.data, pvalueref->value.const_bytes, r_size(pvalueref));
1345
0
        pdfctx->ctx->args.cidfsubstfont.size = r_size(pvalueref);
1346
0
    }
1347
83.0k
    if (dict_find_string(pdictref, "SUBSTFONT", &pvalueref) > 0) {
1348
0
        ref nmstr, *namstrp;
1349
0
        if (r_has_type(pvalueref, t_string)) {
1350
0
            namstrp = pvalueref;
1351
0
            pdfctx->ctx->args.defaultfont_is_name = false;
1352
0
        } else if (r_has_type(pvalueref, t_name)) {
1353
0
            name_string_ref(imemory, pvalueref, &nmstr);
1354
0
            namstrp = &nmstr;
1355
0
            pdfctx->ctx->args.defaultfont_is_name = true;
1356
0
        }
1357
0
        else {
1358
0
            code = gs_note_error(gs_error_typecheck);
1359
0
            goto error;
1360
0
        }
1361
0
        pdfctx->ctx->args.defaultfont.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(namstrp) + 1, "PDF defaultfontname from zpdfops");
1362
0
        if (pdfctx->ctx->args.defaultfont.data == NULL) {
1363
0
            code = gs_note_error(gs_error_VMerror);
1364
0
            goto error;
1365
0
        }
1366
0
        memcpy(pdfctx->ctx->args.defaultfont.data, namstrp->value.const_bytes, r_size(namstrp));
1367
0
        pdfctx->ctx->args.defaultfont.size = r_size(namstrp);
1368
0
    }
1369
83.0k
    if (dict_find_string(pdictref, "IgnoreToUnicode", &pvalueref) > 0) {
1370
0
        if (!r_has_type(pvalueref, t_boolean))
1371
0
            goto error;
1372
0
        pdfctx->ctx->args.ignoretounicode = pvalueref->value.boolval;
1373
0
    }
1374
83.0k
    if (dict_find_string(pdictref, "NONATIVEFONTMAP", &pvalueref) > 0) {
1375
0
        if (!r_has_type(pvalueref, t_boolean))
1376
0
            goto error;
1377
0
        pdfctx->ctx->args.nonativefontmap = pvalueref->value.boolval;
1378
0
    }
1379
83.0k
    if (dict_find_string(pdictref, "PageCount", &pvalueref) > 0) {
1380
83.0k
        if (!r_has_type(pvalueref, t_integer))
1381
0
            goto error;
1382
83.0k
        pdfctx->ctx->Pdfmark_InitialPage = pvalueref->value.intval;
1383
83.0k
    }
1384
83.0k
    code = 0;
1385
1386
83.0k
error:
1387
83.0k
    return code;
1388
83.0k
}
1389
1390
static int zPDFSetParams(i_ctx_t *i_ctx_p)
1391
0
{
1392
0
    os_ptr op = osp;
1393
0
    int code = 0;
1394
0
    pdfctx_t *pdfctx = NULL;
1395
1396
0
    check_op(2);
1397
1398
0
    check_type(*(op - 1), t_pdfctx);
1399
0
    pdfctx = r_ptr(op - 1, pdfctx_t);
1400
1401
0
    check_type(*op, t_dictionary);
1402
1403
0
    code = apply_interpreter_params(i_ctx_p, pdfctx, op);
1404
1405
0
    pop(2);
1406
0
    return code;
1407
0
}
1408
1409
static int zPDFInit(i_ctx_t *i_ctx_p)
1410
83.0k
{
1411
83.0k
    os_ptr op = osp;
1412
83.0k
    pdfctx_t *pdfctx = NULL;
1413
83.0k
    pdf_context *ctx = NULL;
1414
83.0k
    int code = 0;
1415
83.0k
    gs_memory_t *cmem;
1416
1417
83.0k
    code = gs_memory_chunk_wrap(&cmem, imemory->non_gc_memory);
1418
83.0k
    if (code < 0)
1419
0
        return_error(gs_error_VMerror);
1420
1421
83.0k
    pdfctx = gs_alloc_struct(imemory, pdfctx_t, &st_pdfctx_t, "PDFcontext");
1422
83.0k
    if (!pdfctx) {
1423
0
        code = gs_note_error(gs_error_VMerror);
1424
0
        goto error;
1425
0
    }
1426
83.0k
    pdfctx->pdf_memory = cmem;
1427
83.0k
    pdfctx->ctx = NULL;
1428
83.0k
    pdfctx->record = NULL;
1429
83.0k
    pdfctx->UsingPDFFile = false;
1430
83.0k
    pdfctx->pdf_stream_memory = NULL;
1431
83.0k
    pdfctx->profile_cache = gsicc_profilecache_new(imemory);
1432
83.0k
    if (pdfctx->profile_cache == NULL) {
1433
0
        code = gs_note_error(gs_error_VMerror);
1434
0
        goto error;
1435
0
    }
1436
83.0k
    pdfctx->cache_memory = imemory;
1437
    /* The size is arbitrary */
1438
83.0k
    code = dict_alloc((gs_ref_memory_t *)imemory->stable_memory, 1, &pdfctx->names_dict);
1439
83.0k
    if (code < 0)
1440
0
        goto error;
1441
1442
83.0k
    ctx = pdfi_create_context(cmem);
1443
83.0k
    if (ctx == NULL) {
1444
0
        code = gs_note_error(gs_error_VMerror);
1445
0
        goto error;
1446
0
    }
1447
1448
83.0k
    pdfctx->ctx = ctx;
1449
83.0k
    get_zfont_glyph_name(&pdfctx->ctx->get_glyph_name);
1450
83.0k
    pdfctx->ctx->get_glyph_index = zpdfi_glyph_index;
1451
1452
83.0k
    if (ref_stack_count(&o_stack) > 0) {
1453
83.0k
        if (r_has_type(op, t_dictionary))
1454
83.0k
            code = apply_interpreter_params(i_ctx_p, pdfctx, op);
1455
83.0k
        pop(1);
1456
83.0k
        if (code < 0)
1457
0
            goto error;
1458
83.0k
    }
1459
83.0k
    code = zpdfi_populate_search_paths(i_ctx_p, ctx);
1460
83.0k
    if (code < 0)
1461
0
        goto error;
1462
1463
83.0k
    code = zpdfi_populate_fontmap_files(i_ctx_p, ctx);
1464
83.0k
    if (code < 0)
1465
0
        goto error;
1466
1467
83.0k
    op = osp;
1468
83.0k
    push(1);
1469
83.0k
    make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx));
1470
83.0k
    return 0;
1471
1472
0
error:
1473
0
    if (ctx != NULL)
1474
0
        pdfi_free_context(ctx);
1475
    /* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
1476
0
    (void)gs_memory_chunk_unwrap(cmem);
1477
0
    if (pdfctx != NULL) {
1478
0
        pdfctx->ctx = NULL; /* Freed already above! */
1479
0
        if (pdfctx->profile_cache != NULL) {
1480
0
            gs_free_object(imemory, pdfctx->profile_cache, "discard temporary profile cache");
1481
0
            pdfctx->profile_cache = NULL;
1482
0
        }
1483
0
        pdfctx->pdf_memory = NULL;
1484
0
        gs_free_object(imemory, pdfctx, "PDFcontext");
1485
0
    }
1486
0
    return code;
1487
83.0k
}
1488
1489
/*   <Pagelist_string> num_pages .PDFparsePageList even/odd, start, end ... range_count */
1490
/*   PostScript will create an array of 3 integers per range      */
1491
static int zPDFparsePageList(i_ctx_t *i_ctx_p)
1492
6
{
1493
6
    int code = 0, size = 0, i;
1494
6
    os_ptr op = osp;
1495
6
    int *page_range_array;
1496
6
    int num_pages;
1497
6
    ref *o;
1498
6
    char *PageString = NULL;
1499
1500
6
    check_op(2);
1501
1502
1
    code = int_param(op, max_int, &num_pages);
1503
1
    if (code < 0)
1504
1
        return code;
1505
1506
1
    check_type_only(*(op - 1), t_string);
1507
1508
0
    PageString = (char *)gs_alloc_bytes(imemory, (size_t)r_size(op - 1) + 1, "zPDFparsePageList");
1509
0
    if (PageString == NULL)
1510
0
        return_error(gs_error_VMerror);
1511
0
    memcpy(PageString, (op - 1)->value.const_bytes, r_size(op - 1));
1512
0
    PageString[r_size(op - 1)] = 0x00;
1513
0
    code = pagelist_parse_to_array(PageString, imemory, num_pages, &page_range_array);
1514
0
    gs_free_object(imemory, PageString, "zPDFparsePageList");
1515
1516
0
    make_int(op, 0);        /* default return 0 */
1517
0
    if (code < 0) {
1518
0
        return code;
1519
0
    }
1520
    /* code returned is the number of ranges */
1521
0
    size = 3 * (code - 1);    /* runpdfpagerange doesn't use 0, 0, 0 marker at end */
1522
0
    code = ref_stack_push(&o_stack, size - 1);
1523
0
    if (code < 0) {
1524
0
        return code;
1525
0
    }
1526
    /* push the even/odd, start, end triples on the stack */
1527
0
    for (i=0; i < size;  i++) {
1528
0
        o = ref_stack_index(&o_stack, size - i);
1529
0
        if (o == NULL)
1530
0
            return_error(gs_error_stackunderflow);
1531
        /* skip the initial "ordered" flag */
1532
0
        make_int(o, page_range_array[i+1]);
1533
0
    }
1534
0
    o = ref_stack_index(&o_stack, 0);
1535
0
    if (o == NULL)
1536
0
        return_error(gs_error_stackunderflow);
1537
0
    make_int(o, size);
1538
0
    pagelist_free_range_array(imemory, page_range_array);    /* all done with C array */
1539
0
    return 0;
1540
0
}
1541
#else
1542
1543
static int zPDFfile(i_ctx_t *i_ctx_p)
1544
{
1545
    return_error(gs_error_undefined);
1546
}
1547
1548
static int zPDFstream(i_ctx_t *i_ctx_p)
1549
{
1550
    return_error(gs_error_undefined);
1551
}
1552
1553
static int zPDFclose(i_ctx_t *i_ctx_p)
1554
{
1555
    return_error(gs_error_undefined);
1556
}
1557
1558
static int zPDFinfo(i_ctx_t *i_ctx_p)
1559
{
1560
    return_error(gs_error_undefined);
1561
}
1562
1563
static int zPDFpageinfo(i_ctx_t *i_ctx_p)
1564
{
1565
    return_error(gs_error_undefined);
1566
}
1567
1568
static int zPDFpageinfoExt(i_ctx_t *i_ctx_p)
1569
{
1570
    return_error(gs_error_undefined);
1571
}
1572
1573
static int zPDFmetadata(i_ctx_t *i_ctx_p)
1574
{
1575
    return_error(gs_error_undefined);
1576
}
1577
1578
static int zPDFdrawpage(i_ctx_t *i_ctx_p)
1579
{
1580
    return_error(gs_error_undefined);
1581
}
1582
1583
static int zPDFdrawannots(i_ctx_t *i_ctx_p)
1584
{
1585
    return_error(gs_error_undefined);
1586
}
1587
1588
static int zPDFSetParams(i_ctx_t *i_ctx_p)
1589
{
1590
    return_error(gs_error_undefined);
1591
}
1592
1593
static int zPDFInit(i_ctx_t *i_ctx_p)
1594
{
1595
    return_error(gs_error_undefined);
1596
}
1597
1598
static int zPDFparsePageList(i_ctx_t *i_ctx_p)
1599
{
1600
    return_error(gs_error_undefined);
1601
}
1602
#endif
1603
1604
static int zPDFAvailable(i_ctx_t *i_ctx_p)
1605
83.0k
{
1606
83.0k
    os_ptr op = osp;
1607
1608
83.0k
    push(1);
1609
83.0k
#if defined(BUILD_PDF) && BUILD_PDF == 1
1610
83.0k
    make_bool(op, true);
1611
#else
1612
    make_bool(op, false);
1613
#endif
1614
83.0k
    return 0;
1615
83.0k
}
1616
1617
/* ------ Initialization procedure ------ */
1618
1619
const op_def zpdfops_op_defs[] =
1620
{
1621
    {"0.PDFFile", zPDFfile},
1622
    {"1.PDFStream", zPDFstream},
1623
    {"1.PDFClose", zPDFclose},
1624
    {"1.PDFInfo", zPDFinfo},
1625
    {"1.PDFPageInfo", zPDFpageinfo},
1626
    {"1.PDFPageInfoExt", zPDFpageinfoExt},
1627
    {"1.PDFMetadata", zPDFmetadata},
1628
    {"1.PDFDrawPage", zPDFdrawpage},
1629
    {"1.PDFDrawAnnots", zPDFdrawannots},
1630
    {"1.PDFInit", zPDFInit},
1631
    {"1.PDFparsePageList", zPDFparsePageList},
1632
    {"0.PDFAvailable", zPDFAvailable},
1633
    {"2.PDFSetParams", zPDFSetParams},
1634
    op_def_end(0)
1635
};