Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/zusparam.c
Line
Count
Source
1
/* Copyright (C) 2001-2023 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
0
{
127
0
    os_ptr op = osp;
128
0
    ref params[2];
129
0
    array_param_list list;
130
0
    gs_param_list *const plist = (gs_param_list *)&list;
131
0
    int result = 0;
132
0
    int code = name_ref(imemory, (const byte *)"Password", 8, &params[0], 0);
133
0
    password pass;
134
135
0
    if (code < 0)
136
0
        return code;
137
0
    check_op(1);
138
0
    params[1] = *op;
139
0
    array_param_list_read(&list, params, 2, NULL, false, iimemory);
140
0
    if (dict_read_password(&pass, systemdict, "StartJobPassword") >= 0 &&
141
0
        param_check_password(plist, &pass) == 0
142
0
        )
143
0
        result = 1;
144
0
    if (dict_read_password(&pass, systemdict, "SystemParamsPassword") >= 0 &&
145
0
        param_check_password(plist, &pass) == 0
146
0
        )
147
0
        result = 2;
148
0
    iparam_list_release(&list);
149
0
    make_int(op, result);
150
0
    return 0;
151
0
}
152
153
/* ------ System parameters ------ */
154
155
/* Integer values */
156
static long
157
current_BuildTime(i_ctx_t *i_ctx_p)
158
963k
{
159
963k
    return gs_buildtime;
160
963k
}
161
162
/* we duplicate this definition here instead of including bfont.h and
163
   all its dependencies */
164
165
8.80M
#define ifont_dir (gs_lib_ctx_get_interp_instance(imemory)->font_dir)
166
167
static long
168
current_MaxFontCache(i_ctx_t *i_ctx_p)
169
963k
{
170
963k
    return gs_currentcachesize(ifont_dir);
171
963k
}
172
static int
173
set_MaxFontCache(i_ctx_t *i_ctx_p, long val)
174
0
{
175
    /* Changing the cache params clears the "pairs" cache, which
176
       causes a crash if the in use font/matrix pair disappears
177
       during a text operation. So don't allow that to happen.
178
     */
179
0
    if (op_show_find(i_ctx_p) != NULL)
180
0
        return_error(gs_error_invalidaccess);
181
0
    return gs_setcachesize(igs, ifont_dir,
182
0
                           (uint)(val < 0 ? 0 : val > max_uint ? max_uint :
183
0
                                   val));
184
0
}
185
static long
186
current_CurFontCache(i_ctx_t *i_ctx_p)
187
963k
{
188
963k
    uint cstat[7];
189
190
963k
    gs_cachestatus(ifont_dir, cstat);
191
963k
    return cstat[0];
192
963k
}
193
194
/* Even though size_t is unsigned, PostScript limits this to signed range */
195
static size_t
196
current_MaxGlobalVM(i_ctx_t *i_ctx_p)
197
963k
{
198
963k
    gs_memory_gc_status_t stat;
199
963k
    size_t val;
200
201
963k
    gs_memory_gc_status(iimemory_global, &stat);
202
    /* RJW: This seems very supicious to me. I get that in CPSI
203
     * mode the max_vm figure needs to be kept to 32bit mode, but
204
     * surely clipping it should be correct, rather than truncating
205
     * it? i.e. min(stat.max_vm, 0x7fffffff) */
206
963k
    if (gs_currentcpsimode(imemory))
207
0
        return stat.max_vm & 0x7fffffff;
208
    /* else clamp at the maximum positive value for the size_t size signed integer */
209
963k
    val = min(stat.max_vm, MAX_VM_THRESHOLD);
210
963k
    return val;
211
963k
}
212
213
/* Even though size_t is unsigned, PostScript limits this to signed range */
214
static int
215
set_MaxGlobalVM(i_ctx_t *i_ctx_p, size_t val)
216
0
{
217
0
    gs_memory_gc_status_t stat;
218
219
0
    gs_memory_gc_status(iimemory_global, &stat);
220
0
    stat.max_vm = val;
221
0
    gs_memory_set_gc_status(iimemory_global, &stat);
222
0
    return 0;
223
0
}
224
static long
225
current_Revision(i_ctx_t *i_ctx_p)
226
963k
{
227
963k
    return gs_revision;
228
963k
}
229
230
static long
231
current_PageCount(i_ctx_t *i_ctx_p)
232
963k
{
233
963k
    gx_device *dev = gs_currentdevice(igs);
234
235
963k
    if ((*dev_proc(dev, get_page_device))(dev) != 0)
236
385k
        if (dev->ShowpageCount > i_ctx_p->nv_page_count)
237
0
          i_ctx_p->nv_page_count = dev->ShowpageCount;
238
963k
    return 1000 + i_ctx_p->nv_page_count; /* Add 1000 to imitate NV memory */
239
963k
}
240
241
static const size_t_param_def_t system_size_t_params[] =
242
{
243
    /* Extensions */
244
    {"MaxGlobalVM", MIN_VM_THRESHOLD, MAX_VM_THRESHOLD, current_MaxGlobalVM, set_MaxGlobalVM}
245
};
246
247
static const long_param_def_t system_long_params[] =
248
{
249
    {"BuildTime", min_long, max_long, current_BuildTime, NULL},
250
    {"MaxFontCache", 0, MAX_UINT_PARAM, current_MaxFontCache, set_MaxFontCache},
251
    {"CurFontCache", 0, MAX_UINT_PARAM, current_CurFontCache, NULL},
252
    {"Revision", min_long, max_long, current_Revision, NULL},
253
    {"PageCount", min_long, max_long, current_PageCount, NULL}
254
};
255
256
/* Boolean values */
257
static bool
258
current_ByteOrder(i_ctx_t *i_ctx_p)
259
1.15M
{
260
1.15M
    return !ARCH_IS_BIG_ENDIAN;
261
1.15M
}
262
static const bool_param_def_t system_bool_params[] =
263
{
264
    {"ByteOrder", current_ByteOrder, NULL}
265
};
266
267
/* String values */
268
static void
269
current_RealFormat(i_ctx_t *i_ctx_p, gs_param_string * pval)
270
1.15M
{
271
1.15M
#if ARCH_FLOATS_ARE_IEEE
272
1.15M
    static const char *const rfs = "IEEE";
273
#else
274
    static const char *const rfs = "not IEEE";
275
#endif
276
277
1.15M
    pval->data = (const byte *)rfs;
278
1.15M
    pval->size = strlen(rfs);
279
1.15M
    pval->persistent = true;
280
1.15M
}
281
282
static const string_param_def_t system_string_params[] =
283
{
284
    {"RealFormat", current_RealFormat, NULL},
285
};
286
287
/* The system parameter set */
288
static const param_set system_param_set =
289
{
290
    system_size_t_params, countof(system_size_t_params),
291
    NULL, 0,  /* No i64 params for systemparams (yet) */
292
    system_long_params, countof(system_long_params),
293
    system_bool_params, countof(system_bool_params),
294
    system_string_params, countof(system_string_params)
295
};
296
297
/* <dict> .setsystemparams - */
298
static int
299
zsetsystemparams(i_ctx_t *i_ctx_p)
300
0
{
301
0
    os_ptr op = osp;
302
0
    int code;
303
0
    dict_param_list list;
304
0
    gs_param_list *const plist = (gs_param_list *)&list;
305
0
    password pass;
306
307
0
    check_op(1);
308
0
    check_type(*op, t_dictionary);
309
0
    code = dict_param_list_read(&list, op, NULL, false, iimemory);
310
0
    if (code < 0)
311
0
        return code;
312
0
    code = dict_read_password(&pass, systemdict, "SystemParamsPassword");
313
0
    if (code < 0)
314
0
        return code;
315
0
    code = param_check_password(plist, &pass);
316
0
    if (code != 0) {
317
0
        if (code > 0)
318
0
            code = gs_note_error(gs_error_invalidaccess);
319
0
        goto out;
320
0
    }
321
0
    code = param_read_password(plist, "StartJobPassword", &pass);
322
0
    switch (code) {
323
0
        default:    /* invalid */
324
0
            goto out;
325
0
        case 1:   /* missing */
326
0
            break;
327
0
        case 0:
328
0
            code = dict_write_password(&pass, systemdict,
329
0
                                       "StartJobPassword",
330
0
                                       ! i_ctx_p->LockFilePermissions);
331
0
            if (code < 0)
332
0
                goto out;
333
0
    }
334
0
    code = param_read_password(plist, "SystemParamsPassword", &pass);
335
0
    switch (code) {
336
0
        default:    /* invalid */
337
0
            goto out;
338
0
        case 1:   /* missing */
339
0
            break;
340
0
        case 0:
341
0
            code = dict_write_password(&pass, systemdict,
342
0
                                       "SystemParamsPassword",
343
0
                                       ! i_ctx_p->LockFilePermissions);
344
0
            if (code < 0)
345
0
                goto out;
346
0
    }
347
348
0
    code = setparams(i_ctx_p, plist, &system_param_set);
349
0
  out:
350
0
    iparam_list_release(&list);
351
0
    if (code < 0)
352
0
        return code;
353
0
    pop(1);
354
0
    return 0;
355
0
}
356
357
/* - .currentsystemparams <name1> <value1> ... */
358
static int
359
zcurrentsystemparams(i_ctx_t *i_ctx_p)
360
963k
{
361
963k
    return currentparams(i_ctx_p, &system_param_set);
362
963k
}
363
364
/* <name> .getsystemparam <value> */
365
static int
366
zgetsystemparam(i_ctx_t *i_ctx_p)
367
385k
{
368
385k
    return currentparam1(i_ctx_p, &system_param_set);
369
385k
}
370
371
/* ------ User parameters ------ */
372
373
/* Integer values */
374
static long
375
current_JobTimeout(i_ctx_t *i_ctx_p)
376
770k
{
377
770k
    return 0;
378
770k
}
379
static int
380
set_JobTimeout(i_ctx_t *i_ctx_p, long val)
381
658k
{
382
658k
    return 0;
383
658k
}
384
static long
385
current_MaxFontItem(i_ctx_t *i_ctx_p)
386
963k
{
387
963k
    return gs_currentcacheupper(ifont_dir);
388
963k
}
389
static int
390
set_MaxFontItem(i_ctx_t *i_ctx_p, long val)
391
1.04M
{
392
1.04M
    return gs_setcacheupper(ifont_dir, val);
393
1.04M
}
394
static long
395
current_MinFontCompress(i_ctx_t *i_ctx_p)
396
963k
{
397
963k
    return gs_currentcachelower(ifont_dir);
398
963k
}
399
static int
400
set_MinFontCompress(i_ctx_t *i_ctx_p, long val)
401
1.04M
{
402
1.04M
    return gs_setcachelower(ifont_dir, val);
403
1.04M
}
404
static long
405
current_MaxOpStack(i_ctx_t *i_ctx_p)
406
770k
{
407
770k
    return ref_stack_max_count(&o_stack);
408
770k
}
409
static int
410
set_MaxOpStack(i_ctx_t *i_ctx_p, long val)
411
851k
{
412
851k
    return ref_stack_set_max_count(&o_stack, val);
413
851k
}
414
static long
415
current_MaxDictStack(i_ctx_t *i_ctx_p)
416
770k
{
417
770k
    return ref_stack_max_count(&d_stack);
418
770k
}
419
static int
420
set_MaxDictStack(i_ctx_t *i_ctx_p, long val)
421
851k
{
422
851k
    return ref_stack_set_max_count(&d_stack, val);
423
851k
}
424
static long
425
current_MaxExecStack(i_ctx_t *i_ctx_p)
426
770k
{
427
770k
    return ref_stack_max_count(&e_stack);
428
770k
}
429
static int
430
set_MaxExecStack(i_ctx_t *i_ctx_p, long val)
431
851k
{
432
851k
    return ref_stack_set_max_count(&e_stack, val);
433
851k
}
434
static size_t
435
current_MaxLocalVM(i_ctx_t *i_ctx_p)
436
770k
{
437
770k
    gs_memory_gc_status_t stat;
438
770k
    size_t val;
439
440
770k
    gs_memory_gc_status(iimemory_local, &stat);
441
    /* RJW: This seems very supicious to me. I get that in CPSI
442
     * mode the max_vm figure needs to be kept to 32bit mode, but
443
     * surely clipping it should be correct, rather than truncating
444
     * it? i.e. min(stat.max_vm, 0x7fffffff) */
445
770k
    if (gs_currentcpsimode(imemory))
446
0
        return stat.max_vm & 0x7fffffff;
447
    /* else clamp at the maximun positive value for the size_t size signed integer */
448
770k
    val = min(stat.max_vm, MAX_VM_THRESHOLD);
449
770k
    return val;
450
770k
}
451
/* Even though size_t is unsigned, PostScript limits this to signed range */
452
static int
453
set_MaxLocalVM(i_ctx_t *i_ctx_p, size_t val)
454
658k
{
455
658k
    gs_memory_gc_status_t stat;
456
457
658k
    gs_memory_gc_status(iimemory_local, &stat);
458
658k
    stat.max_vm = val;
459
658k
    gs_memory_set_gc_status(iimemory_local, &stat);
460
658k
    return 0;
461
658k
}
462
static long
463
current_VMReclaim(i_ctx_t *i_ctx_p)
464
963k
{
465
963k
    gs_memory_gc_status_t gstat, lstat;
466
467
963k
    gs_memory_gc_status(iimemory_global, &gstat);
468
963k
    gs_memory_gc_status(iimemory_local, &lstat);
469
963k
    return (!gstat.enabled ? -2 : !lstat.enabled ? -1 : 0);
470
963k
}
471
static int64_t
472
current_VMThreshold(i_ctx_t *i_ctx_p)
473
963k
{
474
963k
    gs_memory_gc_status_t stat;
475
476
963k
    gs_memory_gc_status(iimemory_local, &stat);
477
963k
    return stat.vm_threshold;
478
963k
}
479
static long
480
current_WaitTimeout(i_ctx_t *i_ctx_p)
481
770k
{
482
770k
    return 0;
483
770k
}
484
static int
485
set_WaitTimeout(i_ctx_t *i_ctx_p, long val)
486
658k
{
487
658k
    return 0;
488
658k
}
489
static long
490
current_MinScreenLevels(i_ctx_t *i_ctx_p)
491
770k
{
492
770k
    return gs_currentminscreenlevels(imemory);
493
770k
}
494
static int
495
set_MinScreenLevels(i_ctx_t *i_ctx_p, long val)
496
658k
{
497
658k
    gs_setminscreenlevels(imemory, (uint) val);
498
658k
    return 0;
499
658k
}
500
static long
501
current_AlignToPixels(i_ctx_t *i_ctx_p)
502
770k
{
503
770k
    return gs_currentaligntopixels(ifont_dir);
504
770k
}
505
static int
506
set_AlignToPixels(i_ctx_t *i_ctx_p, long val)
507
658k
{
508
658k
    gs_setaligntopixels(ifont_dir, (uint)val);
509
658k
    return 0;
510
658k
}
511
static long
512
current_GridFitTT(i_ctx_t *i_ctx_p)
513
770k
{
514
770k
    return gs_currentgridfittt(ifont_dir);
515
770k
}
516
static int
517
set_GridFitTT(i_ctx_t *i_ctx_p, long val)
518
658k
{
519
658k
    gs_setgridfittt(ifont_dir, (uint)val);
520
658k
    return 0;
521
658k
}
522
523
#undef ifont_dir
524
525
static void
526
current_devicen_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
527
770k
{
528
770k
    gs_currentdevicenicc(igs, pval);
529
770k
}
530
531
static int
532
set_devicen_profile_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
533
658k
{
534
658k
    return gs_setdevicenprofileicc(igs, pval);
535
658k
}
536
537
static void
538
current_default_gray_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
539
770k
{
540
770k
    gs_currentdefaultgrayicc(igs, pval);
541
770k
}
542
543
static int
544
set_default_gray_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
545
658k
{
546
658k
    return gs_setdefaultgrayicc(igs, pval);
547
658k
}
548
549
static void
550
current_icc_directory(i_ctx_t *i_ctx_p, gs_param_string * pval)
551
770k
{
552
770k
    gs_currenticcdirectory(igs, pval);
553
770k
}
554
555
static int
556
set_icc_directory(i_ctx_t *i_ctx_p, gs_param_string * pval)
557
658k
{
558
658k
    return gs_seticcdirectory(igs, pval);
559
658k
}
560
561
static void
562
current_srcgtag_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
563
770k
{
564
770k
    gs_currentsrcgtagicc(igs, pval);
565
770k
}
566
567
static int
568
set_srcgtag_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
569
658k
{
570
658k
    return gs_setsrcgtagicc(igs, pval);
571
658k
}
572
573
static void
574
current_default_rgb_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
575
770k
{
576
770k
    gs_currentdefaultrgbicc(igs, pval);
577
770k
}
578
579
static int
580
set_default_rgb_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
581
658k
{
582
658k
    return gs_setdefaultrgbicc(igs, pval);
583
658k
}
584
585
static void
586
current_named_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
587
770k
{
588
770k
    gs_currentnamedicc(igs, pval);
589
770k
}
590
591
static int
592
set_named_profile_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
593
658k
{
594
658k
    return gs_setnamedprofileicc(igs, pval);
595
658k
}
596
597
static void
598
current_default_cmyk_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
599
770k
{
600
770k
    gs_currentdefaultcmykicc(igs, pval);
601
770k
}
602
603
static int
604
set_default_cmyk_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
605
658k
{
606
658k
    return gs_setdefaultcmykicc(igs, pval);
607
658k
}
608
609
static void
610
current_lab_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
611
770k
{
612
770k
    gs_currentlabicc(igs, pval);
613
770k
}
614
615
static int
616
set_lab_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
617
658k
{
618
658k
    return gs_setlabicc(igs, pval);
619
658k
}
620
621
static const size_t_param_def_t user_size_t_params[] =
622
{
623
    {"MaxLocalVM", MIN_VM_THRESHOLD, MAX_VM_THRESHOLD, current_MaxLocalVM, set_MaxLocalVM}
624
};
625
626
static const i64_param_def_t user_i64_params[] =
627
{
628
    {"VMThreshold", -1, MAX_VM_THRESHOLD, current_VMThreshold, set_vm_threshold},
629
};
630
631
static const long_param_def_t user_long_params[] =
632
{
633
    {"JobTimeout", 0, MAX_UINT_PARAM,
634
     current_JobTimeout, set_JobTimeout},
635
    {"MaxFontItem", MIN_INT_PARAM, MAX_UINT_PARAM,
636
     current_MaxFontItem, set_MaxFontItem},
637
    {"MinFontCompress", MIN_INT_PARAM, MAX_UINT_PARAM,
638
     current_MinFontCompress, set_MinFontCompress},
639
    {"MaxOpStack", -1, max_long,
640
     current_MaxOpStack, set_MaxOpStack},
641
    {"MaxDictStack", -1, max_long,
642
     current_MaxDictStack, set_MaxDictStack},
643
    {"MaxExecStack", -1, max_long,
644
     current_MaxExecStack, set_MaxExecStack},
645
    {"VMReclaim", -2, 0,
646
     current_VMReclaim, set_vm_reclaim},
647
    {"WaitTimeout", 0, MAX_UINT_PARAM,
648
     current_WaitTimeout, set_WaitTimeout},
649
    /* Extensions */
650
    {"MinScreenLevels", 0, MAX_UINT_PARAM,
651
     current_MinScreenLevels, set_MinScreenLevels},
652
    {"AlignToPixels", 0, 1,
653
     current_AlignToPixels, set_AlignToPixels},
654
    {"GridFitTT", 0, 3,
655
     current_GridFitTT, set_GridFitTT}
656
};
657
658
/* Note that string objects that are maintained as user params must be
659
   either allocated in non-gc memory or be a constant in the executable.
660
   The problem stems from the way userparams are retained during garbage
661
   collection in a param_list (collected by currentuserparams).  For
662
   some reason this param_list does not get the pointers to strings relocated
663
   during the GC. Note that the param_dict itself is correctly updated by reloc,
664
   it is just the pointers to the strings in the param_list that are not traced
665
   and updated. An example of this includes the ICCProfilesDir, which sets a
666
   string in the icc_manager. When a reclaim occurs, the string is relocated
667
   (when in non-gc memory and when it is noted to the gc with the proper object
668
   descriptor).  Then if a set_icc_directory occurs, the user params pointer has
669
   NOT been updated and validation problems will occur. */
670
static const string_param_def_t user_string_params[] =
671
{
672
    {"DefaultGrayProfile", current_default_gray_icc, set_default_gray_icc},
673
    {"DefaultRGBProfile", current_default_rgb_icc, set_default_rgb_icc},
674
    {"DefaultCMYKProfile", current_default_cmyk_icc, set_default_cmyk_icc},
675
    {"NamedProfile", current_named_icc, set_named_profile_icc},
676
    {"ICCProfilesDir", current_icc_directory, set_icc_directory},
677
    {"LabProfile", current_lab_icc, set_lab_icc},
678
    {"DeviceNProfile", current_devicen_icc, set_devicen_profile_icc},
679
    {"SourceObjectICC", current_srcgtag_icc, set_srcgtag_icc}
680
};
681
682
/* Boolean values */
683
static bool
684
current_AccurateScreens(i_ctx_t *i_ctx_p)
685
770k
{
686
770k
    return gs_currentaccuratescreens(imemory);
687
770k
}
688
static int
689
set_AccurateScreens(i_ctx_t *i_ctx_p, bool val)
690
658k
{
691
658k
    gs_setaccuratescreens(imemory, val);
692
658k
    return 0;
693
658k
}
694
/* Boolean values */
695
static bool
696
current_OverrideICC(i_ctx_t *i_ctx_p)
697
770k
{
698
770k
    return gs_currentoverrideicc(igs);
699
770k
}
700
static int
701
set_OverrideICC(i_ctx_t *i_ctx_p, bool val)
702
658k
{
703
658k
    gs_setoverrideicc(igs, val);
704
658k
    return 0;
705
658k
}
706
static bool
707
current_LockFilePermissions(i_ctx_t *i_ctx_p)
708
770k
{
709
770k
    return i_ctx_p->LockFilePermissions;
710
770k
}
711
static int
712
set_LockFilePermissions(i_ctx_t *i_ctx_p, bool val)
713
658k
{
714
    /* allow locking even if already locked */
715
658k
    if (i_ctx_p->LockFilePermissions && !val)
716
0
        return_error(gs_error_invalidaccess);
717
658k
    i_ctx_p->LockFilePermissions = val;
718
658k
    return 0;
719
658k
}
720
static bool
721
current_RenderTTNotdef(i_ctx_t *i_ctx_p)
722
770k
{
723
770k
    return i_ctx_p->RenderTTNotdef;
724
770k
}
725
static int
726
set_RenderTTNotdef(i_ctx_t *i_ctx_p, bool val)
727
658k
{
728
658k
    i_ctx_p->RenderTTNotdef = val;
729
658k
    return 0;
730
658k
}
731
static const bool_param_def_t user_bool_params[] =
732
{
733
    {"AccurateScreens", current_AccurateScreens, set_AccurateScreens},
734
    {"LockFilePermissions", current_LockFilePermissions, set_LockFilePermissions},
735
    {"RenderTTNotdef", current_RenderTTNotdef, set_RenderTTNotdef},
736
    {"OverrideICC", current_OverrideICC, set_OverrideICC}
737
};
738
739
/* The user parameter set */
740
static const param_set user_param_set =
741
{
742
    user_size_t_params, countof(user_size_t_params),
743
    user_i64_params, countof(user_i64_params),
744
    user_long_params, countof(user_long_params),
745
    user_bool_params, countof(user_bool_params),
746
    user_string_params, countof(user_string_params)
747
};
748
749
/* <dict> .setuserparams - */
750
/* We break this out for use when switching contexts. */
751
int
752
set_user_params(i_ctx_t *i_ctx_p, const ref *paramdict)
753
5.28M
{
754
5.28M
    dict_param_list list;
755
5.28M
    int code;
756
757
5.28M
    check_type(*paramdict, t_dictionary);
758
5.28M
    code = dict_param_list_read(&list, paramdict, NULL, false, iimemory);
759
5.28M
    if (code < 0)
760
1
        return code;
761
5.28M
    code = setparams(i_ctx_p, (gs_param_list *)&list, &user_param_set);
762
5.28M
    iparam_list_release(&list);
763
5.28M
    return code;
764
5.28M
}
765
static int
766
zsetuserparams(i_ctx_t *i_ctx_p)
767
4.68M
{
768
4.68M
    os_ptr op = osp;
769
4.68M
    int code;
770
771
4.68M
    check_op(1);
772
4.68M
    code = set_user_params(i_ctx_p, op);
773
4.68M
    if (code >= 0) {
774
        /* Update cached scanner options. */
775
4.68M
        i_ctx_p->scanner_options =
776
4.68M
            ztoken_scanner_options(op, i_ctx_p->scanner_options);
777
4.68M
        pop(1);
778
4.68M
    }
779
4.68M
    return code;
780
4.68M
}
781
782
/* - .currentuserparams <name1> <value1> ... */
783
static int
784
zcurrentuserparams(i_ctx_t *i_ctx_p)
785
770k
{
786
770k
    return currentparams(i_ctx_p, &user_param_set);
787
770k
}
788
789
/* <name> .getuserparam <value> */
790
static int
791
zgetuserparam(i_ctx_t *i_ctx_p)
792
770k
{
793
770k
    return currentparam1(i_ctx_p, &user_param_set);
794
770k
}
795
796
/* ------ Initialization procedure ------ */
797
798
const op_def zusparam_op_defs[] =
799
{
800
        /* User and system parameters are accessible even in Level 1 */
801
        /* (if this is a Level 2 system). */
802
    {"0.currentsystemparams", zcurrentsystemparams},
803
    {"0.currentuserparams", zcurrentuserparams},
804
    {"1.getsystemparam", zgetsystemparam},
805
    {"1.getuserparam", zgetuserparam},
806
    {"1.setsystemparams", zsetsystemparams},
807
    {"1.setuserparams", zsetuserparams},
808
        /* The rest of the operators are defined only in Level 2. */
809
    op_def_begin_level2(),
810
    {"1.checkpassword", zcheckpassword},
811
    op_def_end(0)
812
};
813
814
/* ------ Internal procedures ------ */
815
816
/* Set the values of a parameter set from a parameter list. */
817
/* We don't attempt to back out if anything fails. */
818
static int
819
setparams(i_ctx_t *i_ctx_p, gs_param_list * plist, const param_set * pset)
820
5.28M
{
821
5.28M
    int code;
822
5.28M
    unsigned int i;
823
824
10.5M
    for (i = 0; i < pset->size_t_count; i++) {
825
5.28M
        const size_t_param_def_t *pdef = &pset->size_t_defs[i];
826
5.28M
        size_t val;
827
828
5.28M
        if (pdef->set == NULL)
829
0
            continue;
830
5.28M
        code = param_read_size_t(plist, pdef->pname, &val);
831
5.28M
        switch (code) {
832
0
            default:    /* invalid */
833
0
                return code;
834
4.62M
            case 1:   /* missing */
835
4.62M
                break;
836
658k
            case 0:
837
658k
                if (val < pdef->min_value || val > pdef->max_value)
838
0
                    return_error(gs_error_rangecheck);
839
658k
                code = (*pdef->set)(i_ctx_p, val);
840
658k
                if (code < 0)
841
0
                    return code;
842
5.28M
        }
843
5.28M
    }
844
845
10.5M
    for (i = 0; i < pset->i64_count; i++) {
846
5.28M
        const i64_param_def_t *pdef = &pset->i64_defs[i];
847
5.28M
        int64_t val;
848
849
5.28M
        if (pdef->set == NULL)
850
0
            continue;
851
5.28M
        code = param_read_i64(plist, pdef->pname, &val);
852
5.28M
        switch (code) {
853
0
            default:    /* invalid */
854
0
                return code;
855
4.23M
            case 1:   /* missing */
856
4.23M
                break;
857
1.04M
            case 0:
858
1.04M
                if (val < pdef->min_value || val > pdef->max_value)
859
0
                    return_error(gs_error_rangecheck);
860
1.04M
                code = (*pdef->set)(i_ctx_p, val);
861
1.04M
                if (code < 0)
862
0
                    return code;
863
5.28M
        }
864
5.28M
    }
865
866
63.3M
    for (i = 0; i < pset->long_count; i++) {
867
58.1M
        const long_param_def_t *pdef = &pset->long_defs[i];
868
58.1M
        long val;
869
870
58.1M
        if (pdef->set == NULL)
871
0
            continue;
872
58.1M
        code = param_read_long(plist, pdef->pname, &val);
873
58.1M
        switch (code) {
874
12
            default:    /* invalid */
875
12
                return code;
876
49.1M
            case 1:   /* missing */
877
49.1M
                break;
878
8.98M
            case 0:
879
8.98M
                if (val < pdef->min_value || val > pdef->max_value)
880
3
                    return_error(gs_error_rangecheck);
881
8.98M
                code = (*pdef->set)(i_ctx_p, val);
882
8.98M
                if (code < 0)
883
0
                    return code;
884
58.1M
        }
885
58.1M
    }
886
26.4M
    for (i = 0; i < pset->bool_count; i++) {
887
21.1M
        const bool_param_def_t *pdef = &pset->bool_defs[i];
888
21.1M
        bool val;
889
890
21.1M
        if (pdef->set == NULL)
891
0
            continue;
892
21.1M
        code = param_read_bool(plist, pdef->pname, &val);
893
21.1M
        if (code == 0)
894
2.63M
            code = (*pdef->set)(i_ctx_p, val);
895
21.1M
        if (code < 0)
896
0
            return code;
897
21.1M
    }
898
899
47.5M
    for (i = 0; i < pset->string_count; i++) {
900
42.2M
        const string_param_def_t *pdef = &pset->string_defs[i];
901
42.2M
        gs_param_string val;
902
903
42.2M
        if (pdef->set == NULL)
904
0
            continue;
905
42.2M
        code = param_read_string(plist, pdef->pname, &val);
906
42.2M
        switch (code) {
907
0
            default:    /* invalid */
908
0
                return code;
909
36.9M
            case 1:   /* missing */
910
36.9M
                break;
911
5.27M
            case 0:
912
5.27M
                code = (*pdef->set)(i_ctx_p, &val);
913
5.27M
                if (code < 0)
914
0
                    return code;
915
42.2M
        }
916
42.2M
    }
917
918
5.28M
    return 0;
919
5.28M
}
920
921
/* Get the current values of a parameter set to the stack. */
922
static bool
923
pname_matches(const char *pname, const ref * psref)
924
49.3M
{
925
49.3M
    return
926
49.3M
        (psref == 0 ||
927
22.3M
         !bytes_compare((const byte *)pname, strlen(pname),
928
22.3M
                        psref->value.const_bytes, r_size(psref)));
929
49.3M
}
930
static int
931
current_param_list(i_ctx_t *i_ctx_p, const param_set * pset,
932
                   const ref * psref /*t_string */ )
933
2.89M
{
934
2.89M
    stack_param_list list;
935
2.89M
    gs_param_list *const plist = (gs_param_list *)&list;
936
2.89M
    int code = 0;
937
2.89M
    unsigned int i;
938
939
2.89M
    stack_param_list_write(&list, &o_stack, NULL, iimemory);
940
941
5.78M
    for (i = 0; i < pset->size_t_count; i++) {
942
2.89M
        const char *pname = pset->size_t_defs[i].pname;
943
944
2.89M
        if (pname_matches(pname, psref)) {
945
1.73M
            size_t val = (*pset->size_t_defs[i].current)(i_ctx_p);
946
947
1.73M
            code = param_write_size_t(plist, pname, &val);
948
1.73M
            if (code < 0)
949
0
                return code;
950
1.73M
        }
951
2.89M
    }
952
4.43M
    for (i = 0; i < pset->i64_count; i++) {
953
1.54M
        const char *pname = pset->i64_defs[i].pname;
954
955
1.54M
        if (pname_matches(pname, psref)) {
956
963k
            int64_t val = (*pset->i64_defs[i].current)(i_ctx_p);
957
958
963k
            code = param_write_i64(plist, pname, &val);
959
963k
            if (code < 0)
960
0
                return code;
961
963k
        }
962
1.54M
    }
963
26.5M
    for (i = 0; i < pset->long_count; i++) {
964
23.6M
        const char *pname = pset->long_defs[i].pname;
965
966
23.6M
        if (pname_matches(pname, psref)) {
967
13.8M
            long val = (*pset->long_defs[i].current)(i_ctx_p);
968
969
13.8M
            code = param_write_long(plist, pname, &val);
970
13.8M
            if (code < 0)
971
0
                return code;
972
13.8M
        }
973
23.6M
    }
974
10.4M
    for (i = 0; i < pset->bool_count; i++) {
975
7.51M
        const char *pname = pset->bool_defs[i].pname;
976
977
7.51M
        if (pname_matches(pname, psref)) {
978
4.23M
            bool val = (*pset->bool_defs[i].current)(i_ctx_p);
979
980
4.23M
            code = param_write_bool(plist, pname, &val);
981
4.23M
            if (code < 0)
982
0
                return code;
983
4.23M
        }
984
7.51M
    }
985
16.5M
    for (i = 0; i < pset->string_count; i++) {
986
13.6M
        const char *pname = pset->string_defs[i].pname;
987
988
13.6M
        if (pname_matches(pname, psref)) {
989
7.32M
            gs_param_string val;
990
991
7.32M
            (*pset->string_defs[i].current)(i_ctx_p, &val);
992
7.32M
            code = param_write_string(plist, pname, &val);
993
7.32M
            if (code < 0)
994
0
                return code;
995
7.32M
        }
996
13.6M
    }
997
2.89M
    if (psref) {
998
        /*
999
         * Scanner options can be read, but only individually by .getuserparam.
1000
         * This avoids putting them into userparams, and being affected by save/restore.
1001
         */
1002
1.15M
        const char *pname;
1003
1.15M
        bool val;
1004
1.15M
        int code;
1005
1006
1.15M
        switch (ztoken_get_scanner_option(psref, i_ctx_p->scanner_options, &pname)) {
1007
0
            case 0:
1008
0
                code = param_write_null(plist, pname);
1009
0
                break;
1010
0
            case 1:
1011
0
                val = true;
1012
0
                code = param_write_bool(plist, pname, &val);
1013
0
                break;
1014
1.15M
            default:
1015
1.15M
                code = 0;
1016
1.15M
                break;
1017
1.15M
        }
1018
1.15M
        if (code < 0)
1019
0
            return code;
1020
1.15M
    }
1021
2.89M
    return code;
1022
2.89M
}
1023
1024
/* Get the current values of a parameter set to the stack. */
1025
static int
1026
currentparams(i_ctx_t *i_ctx_p, const param_set * pset)
1027
1.73M
{
1028
1.73M
    return current_param_list(i_ctx_p, pset, NULL);
1029
1.73M
}
1030
1031
/* Get the value of a single parameter to the stack, or signal an error. */
1032
static int
1033
currentparam1(i_ctx_t *i_ctx_p, const param_set * pset)
1034
1.15M
{
1035
1.15M
    os_ptr op = osp;
1036
1.15M
    ref sref;
1037
1.15M
    int code;
1038
1039
1.15M
    check_type(*op, t_name);
1040
1.15M
    check_ostack(2);
1041
1.15M
    name_string_ref(imemory, (const ref *)op, &sref);
1042
1.15M
    code = current_param_list(i_ctx_p, pset, &sref);
1043
1.15M
    if (code < 0)
1044
0
        return code;
1045
1.15M
    if (osp == op)
1046
0
        return_error(gs_error_undefined);
1047
    /* We know osp == op + 2. */
1048
1.15M
    ref_assign(op, op + 2);
1049
1.15M
    pop(2);
1050
1.15M
    return code;
1051
1.15M
}