Coverage Report

Created: 2025-04-22 06:20

/src/libspectre/ghostscript/base/spsdf.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2020 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
/* Common utilities for PostScript and PDF format printing */
18
#include "stdio_.h"   /* for stream.h */
19
#include "string_.h"
20
#include "gstypes.h"
21
#include "gsmemory.h"
22
#include "gserrors.h"
23
#include "spprint.h"
24
#include "spsdf.h"
25
#include "stream.h"
26
#include "strimpl.h"
27
#include "sa85x.h"
28
#include "sstring.h"
29
#include "scanchar.h"
30
31
/*
32
 * Write a string in its shortest form ( () or <> ).  Note that
33
 * this form is different depending on whether binary data are allowed.
34
 * Currently we don't support ASCII85 strings ( <~ ~> ).
35
 */
36
void
37
s_write_ps_string(stream * s, const byte * str, uint size, int print_ok)
38
0
{
39
0
    uint added = 0;
40
0
    uint i;
41
0
    const stream_template *templat;
42
0
    stream_AXE_state state;
43
0
    stream_state *st = NULL;
44
45
0
    if (print_ok & PRINT_BINARY_OK) {
46
        /* Only need to escape (, ), \, CR, EOL. */
47
0
        stream_putc(s, '(');
48
0
        for (i = 0; i < size; ++i) {
49
0
            byte ch = str[i];
50
51
0
            switch (ch) {
52
0
                case char_CR:
53
0
                    stream_puts(s, "\\r");
54
0
                    continue;
55
0
                case char_EOL:
56
0
                    stream_puts(s, "\\n");
57
0
                    continue;
58
0
                case '(':
59
0
                case ')':
60
0
                case '\\':
61
0
                    stream_putc(s, '\\');
62
0
            }
63
0
            stream_putc(s, ch);
64
0
        }
65
0
        stream_putc(s, ')');
66
0
        return;
67
0
    }
68
0
    for (i = 0; i < size; ++i) {
69
0
        byte ch = str[i];
70
71
0
        if (ch == 0 || ch >= 127)
72
0
            added += 3;
73
0
        else if (strchr("()\\\n\r\t\b\f", ch) != 0)
74
0
            ++added;
75
0
        else if (ch < 32)
76
0
            added += 3;
77
0
    }
78
79
0
    if (added < size || (print_ok & PRINT_HEX_NOT_OK)) {
80
        /* More efficient, or mandatory, to represent as PostScript string. */
81
0
        templat = &s_PSSE_template;
82
0
        stream_putc(s, '(');
83
0
    } else {
84
        /* More efficient, and permitted, to represent as hex string. */
85
0
        templat = &s_AXE_template;
86
0
        st = (stream_state *) & state;
87
0
        s_AXE_init_inline(&state);
88
0
        stream_putc(s, '<');
89
0
    }
90
91
0
    {
92
0
        byte buf[100];    /* size is arbitrary */
93
0
        stream_cursor_read r;
94
0
        stream_cursor_write w;
95
0
        int status;
96
97
0
        r.ptr = str - 1;
98
0
        r.limit = r.ptr + size;
99
0
        w.limit = buf + sizeof(buf) - 1;
100
0
        do {
101
            /* One picky compiler complains if we initialize to buf - 1. */
102
0
            w.ptr = buf;  w.ptr--;
103
0
            status = (*templat->process) (st, &r, &w, true);
104
0
            stream_write(s, buf, (uint) (w.ptr + 1 - buf));
105
0
        }
106
0
        while (status == 1);
107
0
    }
108
0
}
109
110
/* Set up a write stream that just keeps track of the position. */
111
int
112
s_alloc_position_stream(stream ** ps, gs_memory_t * mem)
113
0
{
114
0
    stream *s = *ps = s_alloc(mem, "s_alloc_position_stream");
115
116
0
    if (s == 0)
117
0
        return_error(gs_error_VMerror);
118
0
    swrite_position_only(s);
119
0
    return 0;
120
0
}
121
122
/* ---------------- Parameter printing ---------------- */
123
124
private_st_printer_param_list();
125
const param_printer_params_t param_printer_params_default = {
126
    param_printer_params_default_values
127
};
128
129
/* We'll implement the other printers later if we have to. */
130
static param_proc_xmit_typed(param_print_typed);
131
/*static param_proc_begin_xmit_collection(param_print_begin_collection);*/
132
/*static param_proc_end_xmit_collection(param_print_end_collection);*/
133
static const gs_param_list_procs printer_param_list_procs = {
134
    param_print_typed,
135
    NULL /* begin_collection */ ,
136
    NULL /* end_collection */ ,
137
    NULL /* get_next_key */ ,
138
    gs_param_request_default,
139
    gs_param_requested_default
140
};
141
142
int
143
s_init_param_printer(printer_param_list_t *prlist,
144
                     const param_printer_params_t * ppp, stream * s)
145
0
{
146
0
    gs_param_list_init((gs_param_list *)prlist, &printer_param_list_procs,
147
0
                       NULL);
148
0
    prlist->strm = s;
149
0
    prlist->params = *ppp;
150
0
    prlist->any = false;
151
0
    return 0;
152
0
}
153
int
154
s_alloc_param_printer(gs_param_list ** pplist,
155
                      const param_printer_params_t * ppp, stream * s,
156
                      gs_memory_t * mem)
157
0
{
158
0
    printer_param_list_t *prlist =
159
0
        gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list,
160
0
                        "s_alloc_param_printer");
161
0
    int code;
162
163
0
    *pplist = (gs_param_list *)prlist;
164
0
    if (prlist == 0)
165
0
        return_error(gs_error_VMerror);
166
0
    code = s_init_param_printer(prlist, ppp, s);
167
0
    prlist->memory = mem;
168
0
    return code;
169
0
}
170
171
void
172
s_release_param_printer(printer_param_list_t *prlist)
173
0
{
174
0
    if (prlist) {
175
0
        if (prlist->any && prlist->params.suffix)
176
0
            stream_puts(prlist->strm, prlist->params.suffix);
177
0
    }
178
0
}
179
void
180
s_free_param_printer(gs_param_list * plist)
181
0
{
182
0
    if (plist) {
183
0
        printer_param_list_t *const prlist = (printer_param_list_t *) plist;
184
185
0
        s_release_param_printer(prlist);
186
0
        gs_free_object(prlist->memory, plist, "s_free_param_printer");
187
0
    }
188
0
}
189
190
static int
191
param_print_typed(gs_param_list * plist, gs_param_name pkey,
192
                  gs_param_typed_value * pvalue)
193
0
{
194
0
    printer_param_list_t *const prlist = (printer_param_list_t *)plist;
195
0
    stream *s = prlist->strm;
196
197
0
    if (!prlist->any) {
198
0
        if (prlist->params.prefix)
199
0
            stream_puts(s, prlist->params.prefix);
200
0
        prlist->any = true;
201
0
    }
202
0
    if (prlist->params.item_prefix)
203
0
        stream_puts(s, prlist->params.item_prefix);
204
0
    pprints1(s, "/%s", pkey);
205
0
    switch (pvalue->type) {
206
0
        case gs_param_type_null:
207
0
            stream_puts(s, " null");
208
0
            break;
209
0
        case gs_param_type_bool:
210
0
            stream_puts(s, (pvalue->value.b ? " true" : " false"));
211
0
            break;
212
0
        case gs_param_type_int:
213
0
            pprintd1(s, " %d", pvalue->value.i);
214
0
            break;
215
0
        case gs_param_type_long:
216
0
            pprintld1(s, " %ld", pvalue->value.l);
217
0
            break;
218
0
        case gs_param_type_size_t:
219
0
            pprintzd1(s, " %"PRIdSIZE, pvalue->value.z);
220
0
            break;
221
0
        case gs_param_type_i64:
222
0
            pprinti64d1(s, " %"PRId64, pvalue->value.i64);
223
0
            break;
224
0
        case gs_param_type_float:
225
0
            pprintg1(s, " %g", pvalue->value.f);
226
0
            break;
227
0
        case gs_param_type_string:
228
0
            s_write_ps_string(s, pvalue->value.s.data, pvalue->value.s.size,
229
0
                              prlist->params.print_ok);
230
0
            break;
231
0
        case gs_param_type_name:
232
            /****** SHOULD USE #-ESCAPES FOR PDF ******/
233
0
            stream_putc(s, '/');
234
0
            stream_write(s, pvalue->value.n.data, pvalue->value.n.size);
235
0
            break;
236
0
        case gs_param_type_int_array:
237
0
            {
238
0
                uint i;
239
0
                char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n');
240
241
0
                stream_putc(s, '[');
242
0
                for (i = 0; i < pvalue->value.ia.size; ++i) {
243
0
                    pprintd1(s, "%d", pvalue->value.ia.data[i]);
244
0
                    stream_putc(s, sepr);
245
0
                }
246
0
                stream_putc(s, ']');
247
0
            }
248
0
            break;
249
0
        case gs_param_type_float_array:
250
0
            {
251
0
                uint i;
252
0
                char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n');
253
254
0
                stream_putc(s, '[');
255
0
                for (i = 0; i < pvalue->value.fa.size; ++i) {
256
0
                    pprintg1(s, "%g", pvalue->value.fa.data[i]);
257
0
                    stream_putc(s, sepr);
258
0
                }
259
0
                stream_putc(s, ']');
260
0
            }
261
0
            break;
262
            /*case gs_param_type_string_array: */
263
            /*case gs_param_type_name_array: */
264
0
        default:
265
0
            return_error(gs_error_typecheck);
266
0
    }
267
0
    if (prlist->params.item_suffix)
268
0
        stream_puts(s, prlist->params.item_suffix);
269
0
    return 0;
270
0
}