Coverage Report

Created: 2022-04-16 11:23

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