Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/zusparam.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
/* User and system parameter operators */
18
#include "memory_.h"
19
#include "string_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "gscdefs.h"
23
#include "gsstruct.h"   /* for gxht.h */
24
#include "gsfont.h"   /* for user params */
25
#include "gxht.h"   /* for user params */
26
#include "gsutil.h"
27
#include "estack.h"
28
#include "ialloc.h"   /* for imemory for status */
29
#include "icontext.h"   /* for set_user_params prototype */
30
#include "idict.h"
31
#include "idparam.h"
32
#include "iparam.h"
33
#include "dstack.h"
34
#include "iname.h"
35
#include "itoken.h"
36
#include "iutil2.h"
37
#include "ivmem2.h"
38
#include "store.h"
39
#include "gsnamecl.h"
40
#include "igstate.h"
41
#include "gscms.h"
42
#include "gsicc_manage.h"
43
#include "gsparamx.h"
44
#include "gx.h"
45
#include "gxgstate.h"
46
#include "gslibctx.h"
47
#include "ichar.h"
48
49
/* The (global) font directory */
50
extern gs_font_dir *ifont_dir;  /* in zfont.c */
51
52
/* Define an individual user or system parameter. */
53
/* Eventually this will be made public. */
54
#define param_def_common\
55
    const char *pname
56
57
typedef struct param_def_s {
58
    param_def_common;
59
} param_def_t;
60
61
typedef struct size_t_param_def_s {
62
    param_def_common;
63
    size_t min_value, max_value;
64
    size_t (*current)(i_ctx_t *);
65
    int (*set)(i_ctx_t *, size_t);
66
} size_t_param_def_t;
67
68
typedef struct i64_param_def_s {
69
    param_def_common;
70
    int64_t min_value, max_value;
71
    int64_t (*current)(i_ctx_t *);
72
    int (*set)(i_ctx_t *, int64_t);
73
} i64_param_def_t;
74
75
typedef struct long_param_def_s {
76
    param_def_common;
77
    long min_value, max_value;
78
    long (*current)(i_ctx_t *);
79
    int (*set)(i_ctx_t *, long);
80
} long_param_def_t;
81
82
#if ARCH_SIZEOF_LONG > ARCH_SIZEOF_INT
83
#  define MAX_UINT_PARAM max_uint
84
#  define MIN_INT_PARAM min_int
85
#else
86
#  define MAX_UINT_PARAM max_long
87
#  define MIN_INT_PARAM min_long
88
#endif
89
90
typedef struct bool_param_def_s {
91
    param_def_common;
92
    bool (*current)(i_ctx_t *);
93
    int (*set)(i_ctx_t *, bool);
94
} bool_param_def_t;
95
96
typedef struct string_param_def_s {
97
    param_def_common;
98
    void (*current)(i_ctx_t *, gs_param_string *);
99
    int (*set)(i_ctx_t *, gs_param_string *);
100
} string_param_def_t;
101
102
/* Define a parameter set (user or system). */
103
typedef struct param_set_s {
104
    const size_t_param_def_t *size_t_defs;
105
    uint size_t_count;
106
    const i64_param_def_t *i64_defs;
107
    uint i64_count;
108
    const long_param_def_t *long_defs;
109
    uint long_count;
110
    const bool_param_def_t *bool_defs;
111
    uint bool_count;
112
    const string_param_def_t *string_defs;
113
    uint string_count;
114
} param_set;
115
116
/* Forward references */
117
static int setparams(i_ctx_t *, gs_param_list *, const param_set *);
118
static int currentparams(i_ctx_t *, const param_set *);
119
static int currentparam1(i_ctx_t *, const param_set *);
120
121
/* ------ Passwords ------ */
122
123
/* <string|int> .checkpassword <0|1|2> */
124
static int
125
zcheckpassword(i_ctx_t *i_ctx_p)
126
9.03k
{
127
9.03k
    os_ptr op = osp;
128
9.03k
    ref params[2];
129
9.03k
    array_param_list list;
130
9.03k
    gs_param_list *const plist = (gs_param_list *)&list;
131
9.03k
    int result = 0;
132
9.03k
    int code = name_ref(imemory, (const byte *)"Password", 8, &params[0], 0);
133
9.03k
    password pass;
134
135
9.03k
    if (code < 0)
136
0
        return code;
137
9.03k
    check_op(1);
138
9.03k
    params[1] = *op;
139
9.03k
    array_param_list_read(&list, params, 2, NULL, false, iimemory);
140
9.03k
    if (dict_read_password(&pass, systemdict, "StartJobPassword") >= 0 &&
141
0
        param_check_password(plist, &pass) == 0
142
9.03k
        )
143
0
        result = 1;
144
145
9.03k
    if (i_ctx_p->system_params.SystemParamsPassword != NULL && strlen(i_ctx_p->system_params.SystemParamsPassword) < 64) {
146
0
        memcpy(pass.data, i_ctx_p->system_params.SystemParamsPassword, strlen(i_ctx_p->system_params.SystemParamsPassword));;
147
0
        pass.size = strlen(i_ctx_p->system_params.SystemParamsPassword);
148
9.03k
    } else {
149
9.03k
        pass.data[0] = 0x00;
150
9.03k
        pass.size = 0;
151
9.03k
    }
152
9.03k
    if (param_check_password(plist, &pass) == 0)
153
9.03k
        result = 2;
154
155
9.03k
    iparam_list_release(&list);
156
9.03k
    make_int(op, result);
157
9.03k
    return 0;
158
9.03k
}
159
160
/* ------ System parameters ------ */
161
162
/* Integer values */
163
static long
164
current_BuildTime(i_ctx_t *i_ctx_p)
165
2.59M
{
166
2.59M
    return gs_buildtime;
167
2.59M
}
168
169
static long
170
current_CurDisplayList(i_ctx_t *i_ctx_p)
171
2.59M
{
172
2.59M
    return i_ctx_p->system_params.CurDisplayList;
173
2.59M
}
174
175
static long
176
current_CurFormCache(i_ctx_t *i_ctx_p)
177
2.59M
{
178
2.59M
    return i_ctx_p->system_params.CurFormCache;
179
2.59M
}
180
181
static long
182
current_CurOutlineCache(i_ctx_t *i_ctx_p)
183
2.59M
{
184
2.59M
    return i_ctx_p->system_params.CurOutlineCache;
185
2.59M
}
186
187
static long
188
current_CurPatternCache(i_ctx_t *i_ctx_p)
189
2.59M
{
190
2.59M
    return i_ctx_p->system_params.CurPatternCache;
191
2.59M
}
192
193
static long
194
current_CurScreenStorage(i_ctx_t *i_ctx_p)
195
2.59M
{
196
2.59M
    return i_ctx_p->system_params.CurScreenStorage;
197
2.59M
}
198
199
static long
200
current_CurSourceList(i_ctx_t *i_ctx_p)
201
2.59M
{
202
2.59M
    return i_ctx_p->system_params.CurSourceList;
203
2.59M
}
204
205
static long
206
current_CurStoredScreenCache(i_ctx_t *i_ctx_p)
207
2.59M
{
208
2.59M
    return i_ctx_p->system_params.CurStoredScreenCache;
209
2.59M
}
210
211
static long
212
current_CurUPathCache(i_ctx_t *i_ctx_p)
213
2.59M
{
214
2.59M
    return i_ctx_p->system_params.CurScreenStorage;
215
2.59M
}
216
217
static long
218
current_MaxDisplayAndSourceList(i_ctx_t *i_ctx_p)
219
2.59M
{
220
2.59M
    return i_ctx_p->system_params.MaxDisplayAndSourceList;
221
2.59M
}
222
223
static int
224
set_MaxDisplayAndSourceList(i_ctx_t *i_ctx_p, long val)
225
0
{
226
0
    i_ctx_p->system_params.MaxDisplayAndSourceList = val;
227
0
    return 0;
228
0
}
229
230
static long
231
current_MaxDisplayList(i_ctx_t *i_ctx_p)
232
2.59M
{
233
2.59M
    return i_ctx_p->system_params.MaxDisplayList;
234
2.59M
}
235
236
static int
237
set_MaxDisplayList(i_ctx_t *i_ctx_p, long val)
238
0
{
239
0
    i_ctx_p->system_params.MaxDisplayList = val;
240
0
    return 0;
241
0
}
242
243
static long
244
current_MaxFormCache(i_ctx_t *i_ctx_p)
245
2.59M
{
246
2.59M
    return i_ctx_p->system_params.MaxFormCache;
247
2.59M
}
248
249
static int
250
set_MaxFormCache(i_ctx_t *i_ctx_p, long val)
251
0
{
252
0
    i_ctx_p->system_params.MaxFormCache = val;
253
0
    return 0;
254
0
}
255
256
static long
257
current_MaxImageBuffer(i_ctx_t *i_ctx_p)
258
2.59M
{
259
2.59M
    return i_ctx_p->system_params.MaxImageBuffer;
260
2.59M
}
261
262
static int
263
set_MaxImageBuffer(i_ctx_t *i_ctx_p, long val)
264
0
{
265
0
    i_ctx_p->system_params.MaxImageBuffer = val;
266
0
    return 0;
267
0
}
268
269
static long
270
current_MaxOutlineCache(i_ctx_t *i_ctx_p)
271
2.59M
{
272
2.59M
    return i_ctx_p->system_params.MaxOutlineCache;
273
2.59M
}
274
275
static int
276
set_MaxOutlineCache(i_ctx_t *i_ctx_p, long val)
277
0
{
278
0
    i_ctx_p->system_params.MaxOutlineCache = val;
279
0
    return 0;
280
0
}
281
282
static long
283
current_MaxPatternCache(i_ctx_t *i_ctx_p)
284
2.59M
{
285
2.59M
    return i_ctx_p->system_params.MaxPatternCache;
286
2.59M
}
287
288
static int
289
set_MaxPatternCache(i_ctx_t *i_ctx_p, long val)
290
0
{
291
0
    i_ctx_p->system_params.MaxPatternCache = val;
292
0
    return 0;
293
0
}
294
295
static long
296
current_MaxUPathCache(i_ctx_t *i_ctx_p)
297
2.59M
{
298
2.59M
    return i_ctx_p->system_params.MaxUPathCache;
299
2.59M
}
300
301
static int
302
set_MaxUPathCache(i_ctx_t *i_ctx_p, long val)
303
0
{
304
0
    i_ctx_p->system_params.MaxUPathCache = val;
305
0
    return 0;
306
0
}
307
308
static long
309
current_MaxScreenStorage(i_ctx_t *i_ctx_p)
310
2.59M
{
311
2.59M
    return i_ctx_p->system_params.MaxScreenStorage;
312
2.59M
}
313
314
static int
315
set_MaxScreenStorage(i_ctx_t *i_ctx_p, long val)
316
0
{
317
0
    i_ctx_p->system_params.MaxScreenStorage = val;
318
0
    return 0;
319
0
}
320
321
static long
322
current_MaxSourceList(i_ctx_t *i_ctx_p)
323
2.59M
{
324
2.59M
    return i_ctx_p->system_params.MaxSourceList;
325
2.59M
}
326
327
static int
328
set_MaxSourceList(i_ctx_t *i_ctx_p, long val)
329
0
{
330
0
    i_ctx_p->system_params.MaxSourceList = val;
331
0
    return 0;
332
0
}
333
334
static long
335
current_RamSize(i_ctx_t *i_ctx_p)
336
2.59M
{
337
2.59M
    return i_ctx_p->system_params.RamSize;
338
2.59M
}
339
340
#if 0 /* compiled out (to quell warnings), pending complete removal */
341
static long
342
current_JobTimeout(i_ctx_t *i_ctx_p)
343
{
344
    return i_ctx_p->system_params.JobTimeout;
345
}
346
347
static int
348
set_JobTimeout(i_ctx_t *i_ctx_p, long val)
349
{
350
    i_ctx_p->system_params.JobTimeout = val;
351
    return 0;
352
}
353
354
static long
355
current_WaitTimeout(i_ctx_t *i_ctx_p)
356
{
357
    return i_ctx_p->system_params.WaitTimeout;
358
}
359
360
static int
361
set_WaitTimeout(i_ctx_t *i_ctx_p, long val)
362
{
363
    i_ctx_p->system_params.WaitTimeout = val;
364
    return 0;
365
}
366
#endif
367
368
/* we duplicate this definition here instead of including bfont.h and
369
   all its dependencies */
370
371
14.7M
#define ifont_dir (gs_lib_ctx_get_interp_instance(imemory)->font_dir)
372
373
static long
374
current_MaxFontCache(i_ctx_t *i_ctx_p)
375
7.78M
{
376
7.78M
    return gs_currentcachesize(ifont_dir);
377
7.78M
}
378
static int
379
set_MaxFontCache(i_ctx_t *i_ctx_p, long val)
380
0
{
381
    /* Changing the cache params clears the "pairs" cache, which
382
       causes a crash if the in use font/matrix pair disappears
383
       during a text operation. So don't allow that to happen.
384
     */
385
0
    if (op_show_find(i_ctx_p) != NULL)
386
0
        return_error(gs_error_invalidaccess);
387
0
    return gs_setcachesize(igs, ifont_dir,
388
0
                           (uint)(val < 0 ? 0 : val > max_uint ? max_uint :
389
0
                                   val));
390
0
}
391
static long
392
current_CurFontCache(i_ctx_t *i_ctx_p)
393
2.59M
{
394
2.59M
    uint cstat[7];
395
396
2.59M
    gs_cachestatus(ifont_dir, cstat);
397
2.59M
    return cstat[0];
398
2.59M
}
399
400
/* Even though size_t is unsigned, PostScript limits this to signed range */
401
static size_t
402
current_MaxGlobalVM(i_ctx_t *i_ctx_p)
403
2.59M
{
404
2.59M
    gs_memory_gc_status_t stat;
405
2.59M
    size_t val;
406
407
2.59M
    gs_memory_gc_status(iimemory_global, &stat);
408
    /* RJW: This seems very supicious to me. I get that in CPSI
409
     * mode the max_vm figure needs to be kept to 32bit mode, but
410
     * surely clipping it should be correct, rather than truncating
411
     * it? i.e. min(stat.max_vm, 0x7fffffff) */
412
2.59M
    if (gs_currentcpsimode(imemory))
413
0
        return stat.max_vm & 0x7fffffff;
414
    /* else clamp at the maximum positive value for the size_t size signed integer */
415
2.59M
    val = min(stat.max_vm, MAX_VM_THRESHOLD);
416
2.59M
    return val;
417
2.59M
}
418
419
/* Even though size_t is unsigned, PostScript limits this to signed range */
420
static int
421
set_MaxGlobalVM(i_ctx_t *i_ctx_p, size_t val)
422
0
{
423
0
    gs_memory_gc_status_t stat;
424
425
0
    gs_memory_gc_status(iimemory_global, &stat);
426
0
    stat.max_vm = val;
427
0
    gs_memory_set_gc_status(iimemory_global, &stat);
428
0
    return 0;
429
0
}
430
static long
431
current_Revision(i_ctx_t *i_ctx_p)
432
2.59M
{
433
2.59M
    return gs_revision;
434
2.59M
}
435
436
static long
437
current_PageCount(i_ctx_t *i_ctx_p)
438
2.59M
{
439
2.59M
    gx_device *dev = gs_currentdevice(igs);
440
441
2.59M
    if ((*dev_proc(dev, get_page_device))(dev) != 0)
442
810k
        if (dev->ShowpageCount > i_ctx_p->nv_page_count)
443
60.7k
          i_ctx_p->nv_page_count = dev->ShowpageCount;
444
2.59M
    return 1000 + i_ctx_p->nv_page_count; /* Add 1000 to imitate NV memory */
445
2.59M
}
446
447
static const size_t_param_def_t system_size_t_params[] =
448
{
449
    /* Extensions */
450
    {"MaxGlobalVM", MIN_VM_THRESHOLD, MAX_VM_THRESHOLD, current_MaxGlobalVM, set_MaxGlobalVM}
451
};
452
453
static const long_param_def_t system_long_params[] =
454
{
455
    {"BuildTime", min_long, max_long, current_BuildTime, NULL},
456
    {"CurDisplayList", 0, MAX_UINT_PARAM, current_CurDisplayList, NULL},
457
    {"CurFormCache", 0, MAX_UINT_PARAM, current_CurFormCache, NULL},
458
    {"CurOutlineCache", 0, MAX_UINT_PARAM, current_CurOutlineCache, NULL},
459
    {"CurPatternCache", 0, MAX_UINT_PARAM, current_CurPatternCache, NULL},
460
    {"CurScreenStorage", 0, MAX_UINT_PARAM, current_CurScreenStorage, NULL},
461
    {"CurSourceList", 0, MAX_UINT_PARAM, current_CurSourceList, NULL},
462
    {"CurStoredScreenCache", 0, MAX_UINT_PARAM, current_CurStoredScreenCache, NULL},
463
    {"CurUPathCache", 0, MAX_UINT_PARAM, current_CurUPathCache, NULL},
464
    {"MaxDisplayAndSourceList", 0, MAX_UINT_PARAM, current_MaxDisplayAndSourceList, set_MaxDisplayAndSourceList},
465
    {"MaxDisplayList", 0, MAX_UINT_PARAM, current_MaxDisplayList, set_MaxDisplayList},
466
    {"MaxImageBuffer", 0, MAX_UINT_PARAM, current_MaxImageBuffer, set_MaxImageBuffer},
467
    {"MaxFormCache", 0, MAX_UINT_PARAM, current_MaxFormCache, set_MaxFormCache},
468
    {"MaxOutlineCache", 0, MAX_UINT_PARAM, current_MaxOutlineCache, set_MaxOutlineCache},
469
    {"MaxPatternCache", 0, MAX_UINT_PARAM, current_MaxPatternCache, set_MaxPatternCache},
470
    {"MaxUPathCache", 0, MAX_UINT_PARAM, current_MaxUPathCache, set_MaxUPathCache},
471
    {"MaxScreenStorage", 0, MAX_UINT_PARAM, current_MaxScreenStorage, set_MaxScreenStorage},
472
    {"MaxSourceList", 0, MAX_UINT_PARAM, current_MaxSourceList, set_MaxSourceList},
473
    {"RamSize", 0, MAX_UINT_PARAM, current_RamSize, NULL},
474
    {"MaxFontCache", 0, MAX_UINT_PARAM, current_MaxFontCache, set_MaxFontCache},
475
    {"CurFontCache", 0, MAX_UINT_PARAM, current_CurFontCache, NULL},
476
    {"JobTimeout", 0, MAX_UINT_PARAM, current_MaxFontCache, set_MaxFontCache},
477
    {"WaitTimeout", 0, MAX_UINT_PARAM, current_MaxFontCache, set_MaxFontCache},
478
    {"Revision", min_long, max_long, current_Revision, NULL},
479
    {"PageCount", min_long, max_long, current_PageCount, NULL}
480
};
481
482
/* Boolean values */
483
static bool
484
current_ByteOrder(i_ctx_t *i_ctx_p)
485
2.75M
{
486
2.75M
    return !ARCH_IS_BIG_ENDIAN;
487
2.75M
}
488
static const bool_param_def_t system_bool_params[] =
489
{
490
    {"ByteOrder", current_ByteOrder, NULL}
491
};
492
493
/* String values */
494
static void
495
current_RealFormat(i_ctx_t *i_ctx_p, gs_param_string * pval)
496
2.75M
{
497
2.75M
#if ARCH_FLOATS_ARE_IEEE
498
2.75M
    static const char *const rfs = "IEEE";
499
#else
500
    static const char *const rfs = "not IEEE";
501
#endif
502
503
2.75M
    pval->data = (const byte *)rfs;
504
2.75M
    pval->size = strlen(rfs);
505
2.75M
    pval->persistent = true;
506
2.75M
}
507
508
static void
509
current_LicenseID(i_ctx_t *i_ctx_p, gs_param_string * pval)
510
2.59M
{
511
2.59M
    static const char *const rfs = "LN-001";
512
513
2.59M
    pval->data = (const byte *)rfs;
514
2.59M
    pval->size = strlen(rfs);
515
2.59M
    pval->persistent = true;
516
2.59M
}
517
518
extern const char *const gs_product;
519
520
static void
521
current_PrinterName(i_ctx_t *i_ctx_p, gs_param_string * pval)
522
2.59M
{
523
2.59M
    pval->data = (const byte *)gs_product;
524
2.59M
    pval->size = strlen(gs_product);
525
2.59M
    pval->persistent = true;
526
2.59M
}
527
528
static void
529
current_InputDevice(i_ctx_t *i_ctx_p, gs_param_string * pval)
530
2.59M
{
531
2.59M
    pval->data = (const byte *)NULL;
532
2.59M
    pval->size = 0;
533
2.59M
    pval->persistent = true;
534
2.59M
}
535
536
static void
537
current_OutputDevice(i_ctx_t *i_ctx_p, gs_param_string * pval)
538
2.59M
{
539
2.59M
    pval->data = (const byte *)NULL;
540
2.59M
    pval->size = 0;
541
2.59M
    pval->persistent = true;
542
2.59M
}
543
544
static void
545
current_GenericResourceDir(i_ctx_t *i_ctx_p, gs_param_string * pval)
546
2.59M
{
547
2.59M
    pval->data = (const byte *)i_ctx_p->system_params.GenericResourceDir;
548
2.59M
    if (i_ctx_p->system_params.GenericResourceDir != NULL)
549
2.43M
        pval->size = strlen(i_ctx_p->system_params.GenericResourceDir);
550
162k
    else
551
162k
        pval->size = 0;
552
2.59M
    pval->persistent = false;
553
2.59M
}
554
555
static int
556
set_GenericResourceDir(i_ctx_t *i_ctx_p, gs_param_string *pval)
557
162k
{
558
162k
    if (gs_is_path_control_active(imemory))
559
0
        return 0;
560
561
162k
    if (i_ctx_p->system_params.GenericResourceDir != NULL){
562
0
        gs_free_object(imemory->non_gc_memory, i_ctx_p->system_params.GenericResourceDir, "set_GenericResourceDir");
563
0
    }
564
162k
    i_ctx_p->system_params.GenericResourceDir = (char *)gs_alloc_bytes(imemory->non_gc_memory, pval->size + 1, "set_GenericResourceDir");
565
162k
    if (i_ctx_p->system_params.GenericResourceDir == NULL)
566
0
        return_error(gs_error_VMerror);
567
162k
    memcpy(i_ctx_p->system_params.GenericResourceDir, pval->data, pval->size);
568
162k
    i_ctx_p->system_params.GenericResourceDir[pval->size] = 0x00;
569
162k
    return 0;
570
162k
};
571
572
static void
573
current_FontResourceDir(i_ctx_t *i_ctx_p, gs_param_string * pval)
574
2.72M
{
575
2.72M
    pval->data = (const byte *)i_ctx_p->system_params.FontResourceDir;
576
2.72M
    if (i_ctx_p->system_params.FontResourceDir != NULL)
577
2.56M
        pval->size = strlen(i_ctx_p->system_params.FontResourceDir);
578
162k
    else
579
162k
        pval->size = 0;
580
2.72M
    pval->persistent = false;
581
2.72M
}
582
583
static int
584
set_FontResourceDir(i_ctx_t *i_ctx_p, gs_param_string *pval)
585
162k
{
586
162k
    if (gs_is_path_control_active(imemory))
587
0
        return 0;
588
589
162k
    if (i_ctx_p->system_params.FontResourceDir != NULL){
590
0
        gs_free_object(imemory->non_gc_memory, i_ctx_p->system_params.FontResourceDir, "set_FontResourceDir");
591
0
    }
592
162k
    i_ctx_p->system_params.FontResourceDir = (char *)gs_alloc_bytes(imemory->non_gc_memory, pval->size + 1, "set_FontResourceDir");
593
162k
    if (i_ctx_p->system_params.FontResourceDir == NULL)
594
0
        return_error(gs_error_VMerror);
595
162k
    memcpy(i_ctx_p->system_params.FontResourceDir, pval->data, pval->size);
596
162k
    i_ctx_p->system_params.FontResourceDir[pval->size] = 0x00;
597
162k
    return 0;
598
162k
};
599
600
static void
601
current_GenericResourcePathSep(i_ctx_t *i_ctx_p, gs_param_string * pval)
602
4.05M
{
603
4.05M
    pval->data = (const byte *)i_ctx_p->system_params.GenericResourcePathSep;
604
4.05M
    if (i_ctx_p->system_params.GenericResourcePathSep != NULL)
605
3.89M
        pval->size = strlen(i_ctx_p->system_params.GenericResourcePathSep);
606
162k
    else
607
162k
        pval->size = 0;
608
4.05M
    pval->persistent = false;
609
4.05M
}
610
611
static int
612
set_GenericResourcePathSep(i_ctx_t *i_ctx_p, gs_param_string *pval)
613
162k
{
614
162k
    if (gs_is_path_control_active(imemory))
615
0
        return 0;
616
617
162k
    if (i_ctx_p->system_params.GenericResourcePathSep != NULL){
618
0
        gs_free_object(imemory->non_gc_memory, i_ctx_p->system_params.GenericResourcePathSep, "set_GenericResourcePathSep");
619
0
    }
620
162k
    i_ctx_p->system_params.GenericResourcePathSep = (char *)gs_alloc_bytes(imemory->non_gc_memory, pval->size + 1, "set_GenericResourcePathSep");
621
162k
    if (i_ctx_p->system_params.GenericResourcePathSep == NULL)
622
0
        return_error(gs_error_VMerror);
623
162k
    memcpy(i_ctx_p->system_params.GenericResourcePathSep, pval->data, pval->size);
624
162k
    i_ctx_p->system_params.GenericResourcePathSep[pval->size] = 0x00;
625
162k
    return 0;
626
162k
};
627
628
static void
629
current_PercentDiskFontResourceDir(i_ctx_t *i_ctx_p, gs_param_string * pval)
630
2.59M
{
631
2.59M
    pval->data = (const byte *)i_ctx_p->system_params.PercentDiskFontResourceDir;
632
2.59M
    if (i_ctx_p->system_params.PercentDiskFontResourceDir != NULL)
633
2.43M
        pval->size = strlen(i_ctx_p->system_params.PercentDiskFontResourceDir);
634
162k
    else
635
162k
        pval->size = 0;
636
2.59M
    pval->persistent = false;
637
2.59M
}
638
639
static int
640
set_PercentDiskFontResourceDir(i_ctx_t *i_ctx_p, gs_param_string *pval)
641
162k
{
642
162k
    if (gs_is_path_control_active(imemory))
643
0
        return 0;
644
645
162k
    if (i_ctx_p->system_params.PercentDiskFontResourceDir != NULL){
646
0
        gs_free_object(imemory->non_gc_memory, i_ctx_p->system_params.PercentDiskFontResourceDir, "set_PercentDiskFontResourceDir");
647
0
    }
648
162k
    i_ctx_p->system_params.PercentDiskFontResourceDir = (char *)gs_alloc_bytes(imemory->non_gc_memory, pval->size + 1, "set_PercentDiskFontResourceDir");
649
162k
    if (i_ctx_p->system_params.PercentDiskFontResourceDir == NULL)
650
0
        return_error(gs_error_VMerror);
651
162k
    memcpy(i_ctx_p->system_params.PercentDiskFontResourceDir, pval->data, pval->size);
652
162k
    i_ctx_p->system_params.PercentDiskFontResourceDir[pval->size] = 0x00;
653
162k
    return 0;
654
162k
};
655
656
static void
657
current_PercentDiskGenericResourceDir(i_ctx_t *i_ctx_p, gs_param_string * pval)
658
2.59M
{
659
2.59M
    pval->data = (const byte *)i_ctx_p->system_params.PercentDiskGenericResourceDir;
660
2.59M
    if (i_ctx_p->system_params.PercentDiskGenericResourceDir != NULL)
661
2.43M
        pval->size = strlen(i_ctx_p->system_params.PercentDiskGenericResourceDir);
662
162k
    else
663
162k
        pval->size = 0;
664
2.59M
    pval->persistent = false;
665
2.59M
}
666
667
static int
668
set_PercentDiskGenericResourceDir(i_ctx_t *i_ctx_p, gs_param_string *pval)
669
162k
{
670
162k
    if (gs_is_path_control_active(imemory))
671
0
        return 0;
672
673
162k
    if (i_ctx_p->system_params.PercentDiskGenericResourceDir != NULL){
674
0
        gs_free_object(imemory->non_gc_memory, i_ctx_p->system_params.PercentDiskGenericResourceDir, "set_PercentDiskGenericResourceDir");
675
0
    }
676
162k
    i_ctx_p->system_params.PercentDiskGenericResourceDir = (char *)gs_alloc_bytes(imemory->non_gc_memory, pval->size + 1, "set_PercentDiskGenericResourceDir");
677
162k
    if (i_ctx_p->system_params.PercentDiskGenericResourceDir == NULL)
678
0
        return_error(gs_error_VMerror);
679
162k
    memcpy(i_ctx_p->system_params.PercentDiskGenericResourceDir, pval->data, pval->size);
680
162k
    i_ctx_p->system_params.PercentDiskGenericResourceDir[pval->size] = 0x00;
681
162k
    return 0;
682
162k
};
683
684
static int
685
set_StartJobPassword(i_ctx_t *i_ctx_p, gs_param_string *pval)
686
0
{
687
0
    if (i_ctx_p->system_params.StartJobPassword != NULL){
688
0
        gs_free_object(imemory->non_gc_memory, i_ctx_p->system_params.StartJobPassword, "set_StartJobPassword");
689
0
    }
690
0
    i_ctx_p->system_params.StartJobPassword = (char *)gs_alloc_bytes(imemory->non_gc_memory, pval->size + 1, "set_StartJobPassword");
691
0
    if (i_ctx_p->system_params.StartJobPassword == NULL)
692
0
        return_error(gs_error_VMerror);
693
0
    memcpy(i_ctx_p->system_params.StartJobPassword, pval->data, pval->size);
694
0
    i_ctx_p->system_params.StartJobPassword[pval->size] = 0x00;
695
0
    return 0;
696
0
};
697
698
static int
699
set_SystemParamsPassword(i_ctx_t *i_ctx_p, gs_param_string *pval)
700
0
{
701
0
    if (i_ctx_p->system_params.SystemParamsPassword != NULL){
702
0
        gs_free_object(imemory->non_gc_memory, i_ctx_p->system_params.PercentDiskGenericResourceDir, "set_SystemParamsPassword");
703
0
    }
704
0
    i_ctx_p->system_params.SystemParamsPassword = (char *)gs_alloc_bytes(imemory->non_gc_memory, pval->size + 1, "set_SystemParamsPassword");
705
0
    if (i_ctx_p->system_params.SystemParamsPassword == NULL)
706
0
        return_error(gs_error_VMerror);
707
0
    memcpy(i_ctx_p->system_params.SystemParamsPassword, pval->data, pval->size);
708
0
    i_ctx_p->system_params.SystemParamsPassword[pval->size] = 0x00;
709
0
    return 0;
710
0
};
711
712
static const string_param_def_t system_string_params[] =
713
{
714
    {"RealFormat", current_RealFormat, NULL},
715
    {"LicenseID", current_LicenseID, NULL},
716
    {"PrinterName", current_PrinterName, NULL},
717
    {"CurInputDevice", current_InputDevice, NULL},
718
    {"CurOutputDevice", current_OutputDevice, NULL},
719
    {"GenericResourceDir", current_GenericResourceDir, set_GenericResourceDir},
720
    {"FontResourceDir", current_FontResourceDir, set_FontResourceDir},
721
    {"GenericResourcePathSep", current_GenericResourcePathSep, set_GenericResourcePathSep},
722
    {"%diskFontResourceDir", current_PercentDiskFontResourceDir, set_PercentDiskFontResourceDir},
723
    {"%diskGenericResourceDir", current_PercentDiskGenericResourceDir, set_PercentDiskGenericResourceDir},
724
    {"StartJobPassword", NULL, set_StartJobPassword},
725
    {"SystemParamsPassword", NULL, set_SystemParamsPassword},
726
};
727
728
/* The system parameter set */
729
static const param_set system_param_set =
730
{
731
    system_size_t_params, countof(system_size_t_params),
732
    NULL, 0,  /* No i64 params for systemparams (yet) */
733
    system_long_params, countof(system_long_params),
734
    system_bool_params, countof(system_bool_params),
735
    system_string_params, countof(system_string_params)
736
};
737
738
/* <dict> .setsystemparams - */
739
static int
740
zsetsystemparams(i_ctx_t *i_ctx_p)
741
162k
{
742
162k
    os_ptr op = osp;
743
162k
    int code;
744
162k
    dict_param_list list;
745
162k
    gs_param_list *const plist = (gs_param_list *)&list;
746
162k
    password pass;
747
748
162k
    check_op(1);
749
162k
    check_type(*op, t_dictionary);
750
162k
    code = dict_param_list_read(&list, op, NULL, false, iimemory);
751
162k
    if (code < 0)
752
0
        return code;
753
162k
    if (i_ctx_p->system_params.SystemParamsPassword != NULL && strlen(i_ctx_p->system_params.SystemParamsPassword) < 64) {
754
0
        memcpy(pass.data, i_ctx_p->system_params.SystemParamsPassword, strlen(i_ctx_p->system_params.SystemParamsPassword));;
755
0
        pass.size = strlen(i_ctx_p->system_params.SystemParamsPassword);
756
162k
    } else {
757
162k
        pass.data[0] = 0x00;
758
162k
        pass.size = 0;
759
162k
    }
760
162k
    code = param_check_password(plist, &pass);
761
162k
    if (code != 0) {
762
0
        if (code > 0)
763
0
            code = gs_note_error(gs_error_invalidaccess);
764
0
        goto out;
765
0
    }
766
767
162k
    code = setparams(i_ctx_p, plist, &system_param_set);
768
162k
  out:
769
162k
    iparam_list_release(&list);
770
162k
    if (code < 0)
771
0
        return code;
772
162k
    pop(1);
773
162k
    return 0;
774
162k
}
775
776
/* - .currentsystemparams <name1> <value1> ... */
777
static int
778
zcurrentsystemparams(i_ctx_t *i_ctx_p)
779
2.59M
{
780
2.59M
    return currentparams(i_ctx_p, &system_param_set);
781
2.59M
}
782
783
/* <name> .getsystemparam <value> */
784
static int
785
zgetsystemparam(i_ctx_t *i_ctx_p)
786
1.91M
{
787
1.91M
    return currentparam1(i_ctx_p, &system_param_set);
788
1.91M
}
789
790
/* ------ User parameters ------ */
791
792
/* Integer values */
793
static long
794
current_user_JobTimeout(i_ctx_t *i_ctx_p)
795
324k
{
796
324k
    return 0;
797
324k
}
798
static int
799
set_user_JobTimeout(i_ctx_t *i_ctx_p, long val)
800
688k
{
801
688k
    return 0;
802
688k
}
803
static long
804
current_MaxFontItem(i_ctx_t *i_ctx_p)
805
324k
{
806
324k
    return gs_currentcacheupper(ifont_dir);
807
324k
}
808
static int
809
set_MaxFontItem(i_ctx_t *i_ctx_p, long val)
810
850k
{
811
850k
    return gs_setcacheupper(ifont_dir, val);
812
850k
}
813
static long
814
current_MinFontCompress(i_ctx_t *i_ctx_p)
815
324k
{
816
324k
    return gs_currentcachelower(ifont_dir);
817
324k
}
818
static int
819
set_MinFontCompress(i_ctx_t *i_ctx_p, long val)
820
850k
{
821
850k
    return gs_setcachelower(ifont_dir, val);
822
850k
}
823
static long
824
current_MaxOpStack(i_ctx_t *i_ctx_p)
825
324k
{
826
324k
    return ref_stack_max_count(&o_stack);
827
324k
}
828
static int
829
set_MaxOpStack(i_ctx_t *i_ctx_p, long val)
830
850k
{
831
850k
    return ref_stack_set_max_count(&o_stack, val);
832
850k
}
833
static long
834
current_MaxDictStack(i_ctx_t *i_ctx_p)
835
324k
{
836
324k
    return ref_stack_max_count(&d_stack);
837
324k
}
838
static int
839
set_MaxDictStack(i_ctx_t *i_ctx_p, long val)
840
850k
{
841
850k
    return ref_stack_set_max_count(&d_stack, val);
842
850k
}
843
static long
844
current_MaxExecStack(i_ctx_t *i_ctx_p)
845
324k
{
846
324k
    return ref_stack_max_count(&e_stack);
847
324k
}
848
static int
849
set_MaxExecStack(i_ctx_t *i_ctx_p, long val)
850
850k
{
851
850k
    return ref_stack_set_max_count(&e_stack, val);
852
850k
}
853
static size_t
854
current_MaxLocalVM(i_ctx_t *i_ctx_p)
855
324k
{
856
324k
    gs_memory_gc_status_t stat;
857
324k
    size_t val;
858
859
324k
    gs_memory_gc_status(iimemory_local, &stat);
860
    /* RJW: This seems very supicious to me. I get that in CPSI
861
     * mode the max_vm figure needs to be kept to 32bit mode, but
862
     * surely clipping it should be correct, rather than truncating
863
     * it? i.e. min(stat.max_vm, 0x7fffffff) */
864
324k
    if (gs_currentcpsimode(imemory))
865
0
        return stat.max_vm & 0x7fffffff;
866
    /* else clamp at the maximun positive value for the size_t size signed integer */
867
324k
    val = min(stat.max_vm, MAX_VM_THRESHOLD);
868
324k
    return val;
869
324k
}
870
/* Even though size_t is unsigned, PostScript limits this to signed range */
871
static int
872
set_MaxLocalVM(i_ctx_t *i_ctx_p, size_t val)
873
688k
{
874
688k
    gs_memory_gc_status_t stat;
875
876
688k
    gs_memory_gc_status(iimemory_local, &stat);
877
688k
    stat.max_vm = val;
878
688k
    gs_memory_set_gc_status(iimemory_local, &stat);
879
688k
    return 0;
880
688k
}
881
static long
882
current_VMReclaim(i_ctx_t *i_ctx_p)
883
324k
{
884
324k
    gs_memory_gc_status_t gstat, lstat;
885
886
324k
    gs_memory_gc_status(iimemory_global, &gstat);
887
324k
    gs_memory_gc_status(iimemory_local, &lstat);
888
324k
    return (!gstat.enabled ? -2 : !lstat.enabled ? -1 : 0);
889
324k
}
890
static int64_t
891
current_VMThreshold(i_ctx_t *i_ctx_p)
892
324k
{
893
324k
    gs_memory_gc_status_t stat;
894
895
324k
    gs_memory_gc_status(iimemory_local, &stat);
896
324k
    return stat.vm_threshold;
897
324k
}
898
static long
899
current_user_WaitTimeout(i_ctx_t *i_ctx_p)
900
324k
{
901
324k
    return 0;
902
324k
}
903
static int
904
set_user_WaitTimeout(i_ctx_t *i_ctx_p, long val)
905
688k
{
906
688k
    return 0;
907
688k
}
908
static long
909
current_MinScreenLevels(i_ctx_t *i_ctx_p)
910
324k
{
911
324k
    return gs_currentminscreenlevels(imemory);
912
324k
}
913
static int
914
set_MinScreenLevels(i_ctx_t *i_ctx_p, long val)
915
688k
{
916
688k
    gs_setminscreenlevels(imemory, (uint) val);
917
688k
    return 0;
918
688k
}
919
static long
920
current_AlignToPixels(i_ctx_t *i_ctx_p)
921
324k
{
922
324k
    return gs_currentaligntopixels(ifont_dir);
923
324k
}
924
static int
925
set_AlignToPixels(i_ctx_t *i_ctx_p, long val)
926
688k
{
927
688k
    gs_setaligntopixels(ifont_dir, (uint)val);
928
688k
    return 0;
929
688k
}
930
static long
931
current_GridFitTT(i_ctx_t *i_ctx_p)
932
324k
{
933
324k
    return gs_currentgridfittt(ifont_dir);
934
324k
}
935
static int
936
set_GridFitTT(i_ctx_t *i_ctx_p, long val)
937
688k
{
938
688k
    gs_setgridfittt(ifont_dir, (uint)val);
939
688k
    return 0;
940
688k
}
941
942
#undef ifont_dir
943
944
static long
945
current_MaxFormItem(i_ctx_t *i_ctx_p)
946
324k
{
947
324k
    return(i_ctx_p->user_params.MaxFormItem);
948
324k
}
949
static int
950
set_MaxFormItem(i_ctx_t *i_ctx_p, long val)
951
688k
{
952
688k
    i_ctx_p->user_params.MaxFormItem = val;
953
688k
    return 0;
954
688k
}
955
956
static long
957
current_MaxPatternItem(i_ctx_t *i_ctx_p)
958
324k
{
959
324k
    return(i_ctx_p->user_params.MaxPatternItem);
960
324k
}
961
static int
962
set_MaxPatternItem(i_ctx_t *i_ctx_p, long val)
963
688k
{
964
688k
    i_ctx_p->user_params.MaxPatternItem = val;
965
688k
    return 0;
966
688k
}
967
968
static long
969
current_MaxScreenItem(i_ctx_t *i_ctx_p)
970
324k
{
971
324k
    return(i_ctx_p->user_params.MaxScreenItem);
972
324k
}
973
static int
974
set_MaxScreenItem(i_ctx_t *i_ctx_p, long val)
975
688k
{
976
688k
    i_ctx_p->user_params.MaxScreenItem = val;
977
688k
    return 0;
978
688k
}
979
980
static long
981
current_MaxUPathItem(i_ctx_t *i_ctx_p)
982
324k
{
983
324k
    return(i_ctx_p->user_params.MaxUPathItem);
984
324k
}
985
static int
986
set_MaxUPathItem(i_ctx_t *i_ctx_p, long val)
987
688k
{
988
688k
    i_ctx_p->user_params.MaxUPathItem = val;
989
688k
    return 0;
990
688k
}
991
992
static long
993
current_MaxSuperScreen(i_ctx_t *i_ctx_p)
994
324k
{
995
324k
    return(i_ctx_p->user_params.MaxFormItem);
996
324k
}
997
static int
998
set_MaxSuperScreen(i_ctx_t *i_ctx_p, long val)
999
850k
{
1000
850k
    i_ctx_p->user_params.MaxFormItem = val;
1001
850k
    return 0;
1002
850k
}
1003
1004
static long
1005
current_HalftoneMode(i_ctx_t *i_ctx_p)
1006
324k
{
1007
324k
    return(i_ctx_p->user_params.HalftoneMode);
1008
324k
}
1009
static int
1010
set_HalftoneMode(i_ctx_t *i_ctx_p, long val)
1011
850k
{
1012
850k
    i_ctx_p->user_params.HalftoneMode = val;
1013
850k
    return 0;
1014
850k
}
1015
1016
static void
1017
current_devicen_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1018
324k
{
1019
324k
    gs_currentdevicenicc(igs, pval);
1020
324k
}
1021
1022
static int
1023
set_devicen_profile_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1024
688k
{
1025
688k
    return gs_setdevicenprofileicc(igs, pval);
1026
688k
}
1027
1028
static void
1029
current_default_gray_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1030
324k
{
1031
324k
    gs_currentdefaultgrayicc(igs, pval);
1032
324k
}
1033
1034
static int
1035
set_default_gray_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1036
688k
{
1037
688k
    return gs_setdefaultgrayicc(igs, pval);
1038
688k
}
1039
1040
static void
1041
current_icc_directory(i_ctx_t *i_ctx_p, gs_param_string * pval)
1042
324k
{
1043
324k
    gs_currenticcdirectory(igs, pval);
1044
324k
}
1045
1046
static int
1047
set_icc_directory(i_ctx_t *i_ctx_p, gs_param_string * pval)
1048
688k
{
1049
688k
    return gs_seticcdirectory(igs, pval);
1050
688k
}
1051
1052
static void
1053
current_srcgtag_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1054
324k
{
1055
324k
    gs_currentsrcgtagicc(igs, pval);
1056
324k
}
1057
1058
static int
1059
set_srcgtag_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1060
688k
{
1061
688k
    return gs_setsrcgtagicc(igs, pval);
1062
688k
}
1063
1064
static void
1065
current_default_rgb_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1066
324k
{
1067
324k
    gs_currentdefaultrgbicc(igs, pval);
1068
324k
}
1069
1070
static int
1071
set_default_rgb_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1072
689k
{
1073
689k
    return gs_setdefaultrgbicc(igs, pval);
1074
689k
}
1075
1076
static void
1077
current_named_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1078
324k
{
1079
324k
    gs_currentnamedicc(igs, pval);
1080
324k
}
1081
1082
static int
1083
set_named_profile_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1084
688k
{
1085
688k
    return gs_setnamedprofileicc(igs, pval);
1086
688k
}
1087
1088
static void
1089
current_default_cmyk_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1090
324k
{
1091
324k
    gs_currentdefaultcmykicc(igs, pval);
1092
324k
}
1093
1094
static int
1095
set_default_cmyk_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1096
688k
{
1097
688k
    return gs_setdefaultcmykicc(igs, pval);
1098
688k
}
1099
1100
static void
1101
current_lab_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1102
324k
{
1103
324k
    gs_currentlabicc(igs, pval);
1104
324k
}
1105
1106
static int
1107
set_lab_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
1108
688k
{
1109
688k
    return gs_setlabicc(igs, pval);
1110
688k
}
1111
1112
static void
1113
current_JobName(i_ctx_t *i_ctx_p, gs_param_string * pval)
1114
324k
{
1115
324k
    if (i_ctx_p->user_params.JobName == NULL) {
1116
162k
        pval->data = NULL;
1117
162k
        pval->size = 0;
1118
162k
        pval->persistent = false;
1119
162k
    } else {
1120
161k
        pval->data = (const byte *)i_ctx_p->user_params.JobName;
1121
161k
        pval->size = strlen(i_ctx_p->user_params.JobName);
1122
161k
        pval->persistent = false;
1123
161k
    }
1124
324k
}
1125
1126
static int
1127
set_JobName(i_ctx_t *i_ctx_p, gs_param_string * pval)
1128
850k
{
1129
850k
    if (i_ctx_p->user_params.JobName != NULL) {
1130
688k
        gs_free_object(imemory->non_gc_memory, i_ctx_p->user_params.JobName, "set_JobName");
1131
688k
    }
1132
850k
    i_ctx_p->user_params.JobName = (char *)gs_alloc_bytes(imemory->non_gc_memory, pval->size + 1, "set_JobName");
1133
850k
    if (i_ctx_p->user_params.JobName == NULL)
1134
0
        return_error(gs_error_VMerror);
1135
850k
    if (pval->size)
1136
0
        memcpy(i_ctx_p->user_params.JobName, pval->data, pval->size);
1137
850k
    i_ctx_p->user_params.JobName[pval->size] = 0x00;
1138
850k
    return 0;
1139
850k
}
1140
1141
static const size_t_param_def_t user_size_t_params[] =
1142
{
1143
    {"MaxLocalVM", MIN_VM_THRESHOLD, MAX_VM_THRESHOLD, current_MaxLocalVM, set_MaxLocalVM}
1144
};
1145
1146
static const i64_param_def_t user_i64_params[] =
1147
{
1148
    {"VMThreshold", -1, MAX_VM_THRESHOLD, current_VMThreshold, set_vm_threshold},
1149
};
1150
1151
static const long_param_def_t user_long_params[] =
1152
{
1153
    {"JobTimeout", 0, MAX_UINT_PARAM,
1154
     current_user_JobTimeout, set_user_JobTimeout},
1155
    {"MaxFontItem", MIN_INT_PARAM, MAX_UINT_PARAM,
1156
     current_MaxFontItem, set_MaxFontItem},
1157
    {"MinFontCompress", MIN_INT_PARAM, MAX_UINT_PARAM,
1158
     current_MinFontCompress, set_MinFontCompress},
1159
    {"MaxOpStack", -1, max_long,
1160
     current_MaxOpStack, set_MaxOpStack},
1161
    {"MaxDictStack", -1, max_long,
1162
     current_MaxDictStack, set_MaxDictStack},
1163
    {"MaxExecStack", -1, max_long,
1164
     current_MaxExecStack, set_MaxExecStack},
1165
    {"VMReclaim", -2, 0,
1166
     current_VMReclaim, set_vm_reclaim},
1167
    {"WaitTimeout", 0, MAX_UINT_PARAM,
1168
     current_user_WaitTimeout, set_user_WaitTimeout},
1169
    /* Extensions */
1170
    {"MinScreenLevels", 0, MAX_UINT_PARAM,
1171
     current_MinScreenLevels, set_MinScreenLevels},
1172
    {"AlignToPixels", 0, 1,
1173
     current_AlignToPixels, set_AlignToPixels},
1174
    {"GridFitTT", 0, 3,
1175
     current_GridFitTT, set_GridFitTT},
1176
    {"MaxFormItem", 0, MAX_UINT_PARAM,
1177
    current_MaxFormItem, set_MaxFormItem},
1178
    {"MaxPatternItem", 0, MAX_UINT_PARAM,
1179
    current_MaxPatternItem, set_MaxPatternItem},
1180
    {"MaxScreenItem", 0, MAX_UINT_PARAM,
1181
    current_MaxScreenItem, set_MaxScreenItem},
1182
    {"MaxUPathItem", 0, MAX_UINT_PARAM,
1183
    current_MaxUPathItem, set_MaxUPathItem},
1184
    {"HalftoneMode", 0, 2,
1185
    current_HalftoneMode, set_HalftoneMode},
1186
    {"MaxSuperScreen", 0, MAX_UINT_PARAM,
1187
    current_MaxSuperScreen, set_MaxSuperScreen},
1188
};
1189
1190
/* Note that string objects that are maintained as user params must be
1191
   either allocated in non-gc memory or be a constant in the executable.
1192
   The problem stems from the way userparams are retained during garbage
1193
   collection in a param_list (collected by currentuserparams).  For
1194
   some reason this param_list does not get the pointers to strings relocated
1195
   during the GC. Note that the param_dict itself is correctly updated by reloc,
1196
   it is just the pointers to the strings in the param_list that are not traced
1197
   and updated. An example of this includes the ICCProfilesDir, which sets a
1198
   string in the icc_manager. When a reclaim occurs, the string is relocated
1199
   (when in non-gc memory and when it is noted to the gc with the proper object
1200
   descriptor).  Then if a set_icc_directory occurs, the user params pointer has
1201
   NOT been updated and validation problems will occur. */
1202
static const string_param_def_t user_string_params[] =
1203
{
1204
    {"DefaultGrayProfile", current_default_gray_icc, set_default_gray_icc},
1205
    {"DefaultRGBProfile", current_default_rgb_icc, set_default_rgb_icc},
1206
    {"DefaultCMYKProfile", current_default_cmyk_icc, set_default_cmyk_icc},
1207
    {"NamedProfile", current_named_icc, set_named_profile_icc},
1208
    {"ICCProfilesDir", current_icc_directory, set_icc_directory},
1209
    {"LabProfile", current_lab_icc, set_lab_icc},
1210
    {"DeviceNProfile", current_devicen_icc, set_devicen_profile_icc},
1211
    {"SourceObjectICC", current_srcgtag_icc, set_srcgtag_icc},
1212
    {"JobName", current_JobName, set_JobName},
1213
};
1214
1215
/* Boolean values */
1216
static bool
1217
current_AccurateScreens(i_ctx_t *i_ctx_p)
1218
324k
{
1219
324k
    return gs_currentaccuratescreens(imemory);
1220
324k
}
1221
static int
1222
set_AccurateScreens(i_ctx_t *i_ctx_p, bool val)
1223
688k
{
1224
688k
    gs_setaccuratescreens(imemory, val);
1225
688k
    return 0;
1226
688k
}
1227
/* Boolean values */
1228
static bool
1229
current_OverrideICC(i_ctx_t *i_ctx_p)
1230
324k
{
1231
324k
    return gs_currentoverrideicc(igs);
1232
324k
}
1233
static int
1234
set_OverrideICC(i_ctx_t *i_ctx_p, bool val)
1235
688k
{
1236
688k
    gs_setoverrideicc(igs, val);
1237
688k
    return 0;
1238
688k
}
1239
static bool
1240
current_LockFilePermissions(i_ctx_t *i_ctx_p)
1241
324k
{
1242
324k
    return i_ctx_p->LockFilePermissions;
1243
324k
}
1244
static int
1245
set_LockFilePermissions(i_ctx_t *i_ctx_p, bool val)
1246
688k
{
1247
    /* allow locking even if already locked */
1248
688k
    if (i_ctx_p->LockFilePermissions && !val)
1249
0
        return_error(gs_error_invalidaccess);
1250
688k
    i_ctx_p->LockFilePermissions = val;
1251
688k
    return 0;
1252
688k
}
1253
static bool
1254
current_RenderTTNotdef(i_ctx_t *i_ctx_p)
1255
324k
{
1256
324k
    return i_ctx_p->RenderTTNotdef;
1257
324k
}
1258
static int
1259
set_RenderTTNotdef(i_ctx_t *i_ctx_p, bool val)
1260
688k
{
1261
688k
    i_ctx_p->RenderTTNotdef = val;
1262
688k
    return 0;
1263
688k
}
1264
1265
static const bool_param_def_t user_bool_params[] =
1266
{
1267
    {"AccurateScreens", current_AccurateScreens, set_AccurateScreens},
1268
    {"LockFilePermissions", current_LockFilePermissions, set_LockFilePermissions},
1269
    {"RenderTTNotdef", current_RenderTTNotdef, set_RenderTTNotdef},
1270
    {"OverrideICC", current_OverrideICC, set_OverrideICC},
1271
};
1272
1273
/* The user parameter set */
1274
static const param_set user_param_set =
1275
{
1276
    user_size_t_params, countof(user_size_t_params),
1277
    user_i64_params, countof(user_i64_params),
1278
    user_long_params, countof(user_long_params),
1279
    user_bool_params, countof(user_bool_params),
1280
    user_string_params, countof(user_string_params)
1281
};
1282
1283
/* <dict> .setuserparams - */
1284
/* We break this out for use when switching contexts. */
1285
int
1286
set_user_params(i_ctx_t *i_ctx_p, const ref *paramdict)
1287
3.93M
{
1288
3.93M
    dict_param_list list;
1289
3.93M
    int code, i;
1290
1291
3.93M
    check_type(*paramdict, t_dictionary);
1292
3.93M
    code = dict_param_list_read(&list, paramdict, NULL, false, iimemory);
1293
3.93M
    if (code < 0)
1294
0
        return code;
1295
3.93M
    code = setparams(i_ctx_p, (gs_param_list *)&list, &user_param_set);
1296
3.93M
    iparam_list_release(&list);
1297
3.93M
    if (code < 0)
1298
10
        return code;
1299
1300
3.93M
    {
1301
3.93M
        int index, code;
1302
3.93M
        ref elt[2], *userparams_dict;
1303
1304
3.93M
        if (dict_find_string(systemdict, "userparams", &userparams_dict) < 0)
1305
0
            return 0;
1306
1307
3.93M
        index = dict_first(paramdict);
1308
31.0M
        while ((index = dict_next(paramdict, index, elt)) >= 0)
1309
27.1M
        {
1310
27.1M
            if (r_has_type(&elt[0], t_name)) {
1311
27.1M
                ref sref;
1312
1313
27.1M
                name_string_ref(imemory, (const ref *)&elt[0], &sref);
1314
27.1M
                if (r_is_number(&elt[1])) {
1315
28.3M
                    for (i = 0;i < countof(user_size_t_params);i++) {
1316
14.5M
                        if (strlen(user_size_t_params[i].pname) == r_size(&sref) && strncmp((const char *)sref.value.bytes, user_size_t_params[i].pname, r_size(&sref)) == 0) {
1317
688k
                            code = dict_put(userparams_dict, &elt[0], &elt[1], &idict_stack);
1318
688k
                            if (code < 0)
1319
0
                                return code;
1320
688k
                            break;
1321
688k
                        }
1322
14.5M
                    }
1323
28.2M
                    for (i = 0;i < countof(user_i64_params);i++) {
1324
14.5M
                        if (strlen(user_i64_params[i].pname) == r_size(&sref) && strncmp((const char *)sref.value.bytes, user_i64_params[i].pname, r_size(&sref)) == 0) {
1325
                            /* We only have one i64 parameter 'VMThreshold', and it needs special cas treatment. If we ever have more we'll
1326
                             * need to isolate it. If VMThreshold is '-1' then it takes a default value, which is hadnled by set_vmthreshold.
1327
                             * What we need to do is set the value of the PostScript object to be the value actually in use.
1328
                             */
1329
850k
                            gs_memory_gc_status_t stat;
1330
1331
850k
                            gs_memory_gc_status(iimemory_local, &stat);
1332
850k
                            if (r_has_type(&elt[1], t_integer))
1333
850k
                                    elt[1].value.intval = (int)stat.vm_threshold;
1334
850k
                            if (r_has_type(&elt[1], t_real))
1335
0
                                    elt[1].value.realval = (float)stat.vm_threshold;
1336
850k
                            code = dict_put(userparams_dict, &elt[0], &elt[1], &idict_stack);
1337
850k
                            if (code < 0)
1338
0
                                return code;
1339
850k
                            break;
1340
850k
                        }
1341
14.5M
                    }
1342
142M
                    for (i = 0;i < countof(user_long_params);i++) {
1343
141M
                        if (strlen(user_long_params[i].pname) == r_size(&sref) && strncmp((const char *)sref.value.bytes, user_long_params[i].pname, r_size(&sref)) == 0) {
1344
12.9M
                            code = dict_put(userparams_dict, &elt[0], &elt[1], &idict_stack);
1345
12.9M
                            if (code < 0)
1346
0
                                return code;
1347
12.9M
                            break;
1348
12.9M
                        }
1349
141M
                    }
1350
14.5M
                }
1351
27.1M
                if (r_has_type(&elt[1], t_boolean)) {
1352
14.3M
                    for (i = 0;i < countof(user_bool_params);i++) {
1353
12.8M
                        if (strlen(user_bool_params[i].pname) == r_size(&sref) && strncmp((const char *)sref.value.bytes, user_bool_params[i].pname, r_size(&sref)) == 0) {
1354
2.75M
                            code = dict_put(userparams_dict, &elt[0], &elt[1], &idict_stack);
1355
2.75M
                            if (code < 0)
1356
0
                                return code;
1357
2.75M
                            break;
1358
2.75M
                        }
1359
12.8M
                    }
1360
4.25M
                }
1361
27.1M
                if (r_has_type(&elt[1], t_string)) {
1362
32.4M
                    for (i = 0;i < countof(user_string_params);i++) {
1363
32.4M
                        if (strlen(user_string_params[i].pname) == r_size(&sref) && strncmp((const char *)sref.value.bytes, user_string_params[i].pname, r_size(&sref)) == 0) {
1364
6.35M
                            code = dict_put(userparams_dict, &elt[0], &elt[1], &idict_stack);
1365
6.35M
                            if (code < 0)
1366
0
                                return code;
1367
6.35M
                            break;
1368
6.35M
                        }
1369
32.4M
                    }
1370
6.35M
                }
1371
27.1M
                if (r_size(&sref) == 17 && strncmp((const char *)sref.value.bytes, "ProcessDSCComment", r_size(&sref)) == 0) {
1372
1.17M
                    if (!r_has_type(&elt[1], t_null) && !r_is_array(&elt[1]))
1373
0
                        return_error(gs_error_typecheck);
1374
1.17M
                    code = dict_put(userparams_dict, &elt[0], &elt[1], &idict_stack);
1375
1.17M
                    if (code < 0)
1376
0
                        return code;
1377
1.17M
                }
1378
27.1M
                if (r_size(&sref) == 14 && strncmp((const char *)sref.value.bytes, "ProcessComment", r_size(&sref)) == 0) {
1379
688k
                    if (!r_has_type(&elt[1], t_null) && !r_is_array(&elt[1]))
1380
0
                        return_error(gs_error_typecheck);
1381
688k
                    code = dict_put(userparams_dict, &elt[0], &elt[1], &idict_stack);
1382
688k
                    if (code < 0)
1383
0
                        return code;
1384
688k
                }
1385
27.1M
                if (r_size(&sref) == 16 && strncmp((const char *)sref.value.bytes, "IdiomRecognition", r_size(&sref)) == 0) {
1386
1.66M
                    if (!r_has_type(&elt[1], t_null) && !r_is_array(&elt[1]) && !r_has_type(&elt[1], t_boolean))
1387
0
                        return_error(gs_error_typecheck);
1388
1.66M
                    code = dict_put(userparams_dict, &elt[0], &elt[1], &idict_stack);
1389
1.66M
                    if (code < 0)
1390
0
                        return code;
1391
1.66M
                }
1392
27.1M
            }
1393
27.1M
        }
1394
3.93M
    }
1395
3.93M
    return code;
1396
3.93M
}
1397
static int
1398
zsetuserparams(i_ctx_t *i_ctx_p)
1399
3.43M
{
1400
3.43M
    os_ptr op = osp;
1401
3.43M
    int code;
1402
1403
3.43M
    check_op(1);
1404
3.43M
    code = set_user_params(i_ctx_p, op);
1405
3.43M
    if (code >= 0) {
1406
        /* Update cached scanner options. */
1407
3.43M
        i_ctx_p->scanner_options =
1408
3.43M
            ztoken_scanner_options(op, i_ctx_p->scanner_options);
1409
3.43M
        pop(1);
1410
3.43M
    }
1411
3.43M
    return code;
1412
3.43M
}
1413
1414
/* - .currentuserparams <name1> <value1> ... */
1415
static int
1416
zcurrentuserparams(i_ctx_t *i_ctx_p)
1417
324k
{
1418
324k
    return currentparams(i_ctx_p, &user_param_set);
1419
324k
}
1420
1421
/* <name> .getuserparam <value> */
1422
static int
1423
zgetuserparam(i_ctx_t *i_ctx_p)
1424
0
{
1425
0
    return currentparam1(i_ctx_p, &user_param_set);
1426
0
}
1427
1428
/* ------ Initialization procedure ------ */
1429
1430
const op_def zusparam_op_defs[] =
1431
{
1432
        /* User and system parameters are accessible even in Level 1 */
1433
        /* (if this is a Level 2 system). */
1434
    {"0.currentsystemparams", zcurrentsystemparams},
1435
    {"0.currentuserparams", zcurrentuserparams},
1436
    {"1.getsystemparam", zgetsystemparam},
1437
    {"1.getuserparam", zgetuserparam},
1438
    {"1.setsystemparams", zsetsystemparams},
1439
    {"1.setuserparams", zsetuserparams},
1440
        /* The rest of the operators are defined only in Level 2. */
1441
    op_def_begin_level2(),
1442
    {"1.checkpassword", zcheckpassword},
1443
    op_def_end(0)
1444
};
1445
1446
/* ------ Internal procedures ------ */
1447
1448
/* Set the values of a parameter set from a parameter list. */
1449
/* We don't attempt to back out if anything fails. */
1450
static int
1451
setparams(i_ctx_t *i_ctx_p, gs_param_list * plist, const param_set * pset)
1452
4.09M
{
1453
4.09M
    int code;
1454
4.09M
    unsigned int i;
1455
1456
8.18M
    for (i = 0; i < pset->size_t_count; i++) {
1457
4.09M
        const size_t_param_def_t *pdef = &pset->size_t_defs[i];
1458
4.09M
        size_t val;
1459
1460
4.09M
        if (pdef->set == NULL)
1461
0
            continue;
1462
4.09M
        code = param_read_size_t(plist, pdef->pname, &val);
1463
4.09M
        switch (code) {
1464
0
            default:    /* invalid */
1465
0
                return code;
1466
3.40M
            case 1:   /* missing */
1467
3.40M
                break;
1468
688k
            case 0:
1469
688k
                if (val < pdef->min_value || val > pdef->max_value)
1470
0
                    return_error(gs_error_rangecheck);
1471
688k
                code = (*pdef->set)(i_ctx_p, val);
1472
688k
                if (code < 0)
1473
0
                    return code;
1474
4.09M
        }
1475
4.09M
    }
1476
1477
8.02M
    for (i = 0; i < pset->i64_count; i++) {
1478
3.93M
        const i64_param_def_t *pdef = &pset->i64_defs[i];
1479
3.93M
        int64_t val;
1480
1481
3.93M
        if (pdef->set == NULL)
1482
0
            continue;
1483
3.93M
        code = param_read_i64(plist, pdef->pname, &val);
1484
3.93M
        switch (code) {
1485
0
            default:    /* invalid */
1486
0
                return code;
1487
3.08M
            case 1:   /* missing */
1488
3.08M
                break;
1489
850k
            case 0:
1490
850k
                if (val < pdef->min_value || val > pdef->max_value)
1491
0
                    return_error(gs_error_rangecheck);
1492
850k
                code = (*pdef->set)(i_ctx_p, val);
1493
850k
                if (code < 0)
1494
0
                    return code;
1495
3.93M
        }
1496
3.93M
    }
1497
1498
74.9M
    for (i = 0; i < pset->long_count; i++) {
1499
70.8M
        const long_param_def_t *pdef = &pset->long_defs[i];
1500
70.8M
        long val;
1501
1502
70.8M
        if (pdef->set == NULL)
1503
2.10M
            continue;
1504
68.7M
        code = param_read_long(plist, pdef->pname, &val);
1505
68.7M
        switch (code) {
1506
7
            default:    /* invalid */
1507
7
                return code;
1508
55.7M
            case 1:   /* missing */
1509
55.7M
                break;
1510
12.9M
            case 0:
1511
12.9M
                if (val < pdef->min_value || val > pdef->max_value)
1512
3
                    return_error(gs_error_rangecheck);
1513
12.9M
                code = (*pdef->set)(i_ctx_p, val);
1514
12.9M
                if (code < 0)
1515
0
                    return code;
1516
68.7M
        }
1517
68.7M
    }
1518
19.9M
    for (i = 0; i < pset->bool_count; i++) {
1519
15.8M
        const bool_param_def_t *pdef = &pset->bool_defs[i];
1520
15.8M
        bool val;
1521
1522
15.8M
        if (pdef->set == NULL)
1523
162k
            continue;
1524
15.7M
        code = param_read_bool(plist, pdef->pname, &val);
1525
15.7M
        if (code == 0)
1526
2.75M
            code = (*pdef->set)(i_ctx_p, val);
1527
15.7M
        if (code < 0)
1528
0
            return code;
1529
15.7M
    }
1530
1531
41.4M
    for (i = 0; i < pset->string_count; i++) {
1532
37.3M
        const string_param_def_t *pdef = &pset->string_defs[i];
1533
37.3M
        gs_param_string val;
1534
1535
37.3M
        if (pdef->set == NULL)
1536
811k
            continue;
1537
36.5M
        code = param_read_string(plist, pdef->pname, &val);
1538
36.5M
        switch (code) {
1539
0
            default:    /* invalid */
1540
0
                return code;
1541
29.3M
            case 1:   /* missing */
1542
29.3M
                break;
1543
7.16M
            case 0:
1544
7.16M
                code = (*pdef->set)(i_ctx_p, &val);
1545
7.16M
                if (code < 0)
1546
0
                    return code;
1547
36.5M
        }
1548
36.5M
    }
1549
1550
4.09M
    return 0;
1551
4.09M
}
1552
1553
/* Get the current values of a parameter set to the stack. */
1554
static bool
1555
pname_matches(const char *pname, const ref * psref)
1556
186M
{
1557
186M
    return
1558
186M
        (psref == 0 ||
1559
74.8M
         !bytes_compare((const byte *)pname, strlen(pname),
1560
74.8M
                        psref->value.const_bytes, r_size(psref)));
1561
186M
}
1562
static int
1563
current_param_list(i_ctx_t *i_ctx_p, const param_set * pset,
1564
                   const ref * psref /*t_string */ )
1565
4.83M
{
1566
4.83M
    stack_param_list list;
1567
4.83M
    gs_param_list *const plist = (gs_param_list *)&list;
1568
4.83M
    int code = 0;
1569
4.83M
    unsigned int i;
1570
1571
4.83M
    stack_param_list_write(&list, &o_stack, NULL, iimemory);
1572
1573
9.67M
    for (i = 0; i < pset->size_t_count; i++) {
1574
4.83M
        const char *pname = pset->size_t_defs[i].pname;
1575
1576
4.83M
        if (pname_matches(pname, psref)) {
1577
2.91M
            if (pset->size_t_defs[i].current != NULL) {
1578
2.91M
                size_t val = (*pset->size_t_defs[i].current)(i_ctx_p);
1579
1580
2.91M
                code = param_write_size_t(plist, pname, &val);
1581
2.91M
                if (code < 0)
1582
0
                    return code;
1583
2.91M
            }
1584
2.91M
        }
1585
4.83M
    }
1586
5.16M
    for (i = 0; i < pset->i64_count; i++) {
1587
324k
        const char *pname = pset->i64_defs[i].pname;
1588
1589
324k
        if (pname_matches(pname, psref)) {
1590
324k
            if (pset->i64_defs[i].current != NULL) {
1591
324k
                int64_t val = (*pset->i64_defs[i].current)(i_ctx_p);
1592
1593
324k
                code = param_write_i64(plist, pname, &val);
1594
324k
                if (code < 0)
1595
0
                    return code;
1596
324k
            }
1597
324k
        }
1598
324k
    }
1599
123M
    for (i = 0; i < pset->long_count; i++) {
1600
118M
        const char *pname = pset->long_defs[i].pname;
1601
1602
118M
        if (pname_matches(pname, psref)) {
1603
70.3M
            if (pset->long_defs[i].current != NULL) {
1604
70.3M
                long val = (*pset->long_defs[i].current)(i_ctx_p);
1605
1606
70.3M
                code = param_write_long(plist, pname, &val);
1607
70.3M
                if (code < 0)
1608
0
                    return code;
1609
70.3M
            }
1610
70.3M
        }
1611
118M
    }
1612
10.6M
    for (i = 0; i < pset->bool_count; i++) {
1613
5.81M
        const char *pname = pset->bool_defs[i].pname;
1614
1615
5.81M
        if (pname_matches(pname, psref)) {
1616
4.05M
            if (pset->bool_defs[i].current != NULL) {
1617
4.05M
                bool val = (*pset->bool_defs[i].current)(i_ctx_p);
1618
1619
4.05M
                code = param_write_bool(plist, pname, &val);
1620
4.05M
                if (code < 0)
1621
0
                    return code;
1622
4.05M
            }
1623
4.05M
        }
1624
5.81M
    }
1625
61.9M
    for (i = 0; i < pset->string_count; i++) {
1626
57.0M
        const char *pname = pset->string_defs[i].pname;
1627
1628
57.0M
        if (pname_matches(pname, psref)) {
1629
35.8M
            gs_param_string val;
1630
1631
35.8M
            if (pset->string_defs[i].current != NULL) {
1632
30.6M
                (*pset->string_defs[i].current)(i_ctx_p, &val);
1633
30.6M
                code = param_write_string(plist, pname, &val);
1634
30.6M
                if (code < 0)
1635
0
                    return code;
1636
30.6M
            }
1637
35.8M
        }
1638
57.0M
    }
1639
4.83M
    if (psref) {
1640
        /*
1641
         * Scanner options can be read, but only individually by .getuserparam.
1642
         * This avoids putting them into userparams, and being affected by save/restore.
1643
         */
1644
1.91M
        const char *pname;
1645
1.91M
        bool val;
1646
1.91M
        int code;
1647
1648
1.91M
        switch (ztoken_get_scanner_option(psref, i_ctx_p->scanner_options, &pname)) {
1649
0
            case 0:
1650
0
                code = param_write_null(plist, pname);
1651
0
                break;
1652
0
            case 1:
1653
0
                val = true;
1654
0
                code = param_write_bool(plist, pname, &val);
1655
0
                break;
1656
1.91M
            default:
1657
1.91M
                code = 0;
1658
1.91M
                break;
1659
1.91M
        }
1660
1.91M
        if (code < 0)
1661
0
            return code;
1662
1.91M
    }
1663
4.83M
    return code;
1664
4.83M
}
1665
1666
/* Get the current values of a parameter set to the stack. */
1667
static int
1668
currentparams(i_ctx_t *i_ctx_p, const param_set * pset)
1669
2.91M
{
1670
2.91M
    return current_param_list(i_ctx_p, pset, NULL);
1671
2.91M
}
1672
1673
/* Get the value of a single parameter to the stack, or signal an error. */
1674
static int
1675
currentparam1(i_ctx_t *i_ctx_p, const param_set * pset)
1676
1.91M
{
1677
1.91M
    os_ptr op = osp;
1678
1.91M
    ref sref;
1679
1.91M
    int code;
1680
1681
1.91M
    check_type(*op, t_name);
1682
1.91M
    check_ostack(2);
1683
1.91M
    name_string_ref(imemory, (const ref *)op, &sref);
1684
1.91M
    code = current_param_list(i_ctx_p, pset, &sref);
1685
1.91M
    if (code < 0)
1686
0
        return code;
1687
1.91M
    if (osp == op)
1688
0
        return_error(gs_error_undefined);
1689
    /* We know osp == op + 2. */
1690
1.91M
    ref_assign(op, op + 2);
1691
1.91M
    pop(2);
1692
1.91M
    return code;
1693
1.91M
}