Coverage Report

Created: 2025-06-10 07:06

/src/ghostpdl/base/spprint.c
Line
Count
Source (jump to first uncovered line)
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
/* Print values in ASCII form on a stream */
18
#include "math_.h"    /* for fabs */
19
#include "stdio_.h"   /* for stream.h */
20
#include "string_.h"    /* for strchr */
21
#include "stream.h"
22
#include "spprint.h"
23
24
/* ------ Output ------ */
25
26
/* Put a byte array on a stream. */
27
int
28
stream_write(stream * s, const void *ptr, uint count)
29
0
{
30
0
    uint used;
31
32
0
    sputs(s, (const byte *)ptr, count, &used);
33
0
    return (int)used;
34
0
}
35
36
/* Put a string on a stream. */
37
int
38
stream_puts(stream * s, const char *str)
39
0
{
40
0
    uint len = strlen(str);
41
0
    uint used;
42
0
    int status = sputs(s, (const byte *)str, len, &used);
43
44
0
    return (status >= 0 && used == len ? 0 : EOF);
45
0
}
46
47
/* Print a format string up to the first variable substitution. */
48
/* Return a pointer to the %, or to the terminating 0 if no % found. */
49
static const char *
50
pprintf_scan(stream * s, const char *format)
51
0
{
52
0
    const char *fp = format;
53
54
0
    for (; *fp != 0; ++fp) {
55
0
        if (*fp == '%') {
56
0
            if (fp[1] != '%')
57
0
                break;
58
0
            ++fp;
59
0
        }
60
0
        sputc(s, *fp);
61
0
    }
62
0
    return fp;
63
0
}
64
65
/* Print a short string on a stream. */
66
static void
67
pputs_short(stream *s, const char *str)
68
0
{
69
0
    const char *p = str;
70
71
0
    for (; *p; ++p)
72
0
        sputc(s, *p);
73
0
}
74
75
/* Print (an) int value(s) using a format. */
76
const char *
77
pprintd1(stream * s, const char *format, int v)
78
0
{
79
0
    const char *fp = pprintf_scan(s, format);
80
0
    char str[25];
81
82
#ifdef DEBUG
83
    if (*fp == 0 || fp[1] != 'd') /* shouldn't happen! */
84
        lprintf1("Bad format in pprintd1: %s\n", format);
85
#endif
86
0
    gs_snprintf(str, sizeof(str), "%d", v);
87
0
    pputs_short(s, str);
88
0
    return pprintf_scan(s, fp + 2);
89
0
}
90
const char *
91
pprintd2(stream * s, const char *format, int v1, int v2)
92
0
{
93
0
    return pprintd1(s, pprintd1(s, format, v1), v2);
94
0
}
95
const char *
96
pprintd3(stream * s, const char *format, int v1, int v2, int v3)
97
0
{
98
0
    return pprintd2(s, pprintd1(s, format, v1), v2, v3);
99
0
}
100
const char *
101
pprintd4(stream * s, const char *format, int v1, int v2, int v3, int v4)
102
0
{
103
0
    return pprintd2(s, pprintd2(s, format, v1, v2), v3, v4);
104
0
}
105
106
/* Print (a) floating point number(s) using a format. */
107
/* See gdevpdfx.h for why this is needed. */
108
const char *
109
pprintg1(stream * s, const char *format, double v)
110
0
{
111
0
    const char *fp = pprintf_scan(s, format);
112
0
    char dot, str[150];
113
114
#ifdef DEBUG
115
    if (*fp == 0 || fp[1] != 'g') /* shouldn't happen! */
116
        lprintf1("Bad format in pprintg: %s\n", format);
117
#endif
118
0
    gs_snprintf(str, sizeof(str), "%f", 1.5);
119
0
    dot = str[1]; /* locale-dependent */
120
0
    gs_snprintf(str, sizeof(str), "%g", v);
121
0
    if (strchr(str, 'e')) {
122
        /* Bad news.  Try again using f-format. */
123
0
        gs_snprintf(str, sizeof(str), (fabs(v) > 1 ? "%1.1f" : "%1.8f"), v);
124
0
    }
125
    /* Juggling locales isn't thread-safe. Posix me harder. */
126
0
    if (dot != '.') {
127
0
        char *pdot = strchr(str, dot);
128
0
        if (pdot)
129
0
            *pdot = '.';
130
0
    }
131
0
    pputs_short(s, str);
132
0
    return pprintf_scan(s, fp + 2);
133
0
}
134
const char *
135
pprintg2(stream * s, const char *format, double v1, double v2)
136
0
{
137
0
    return pprintg1(s, pprintg1(s, format, v1), v2);
138
0
}
139
const char *
140
pprintg3(stream * s, const char *format, double v1, double v2, double v3)
141
0
{
142
0
    return pprintg2(s, pprintg1(s, format, v1), v2, v3);
143
0
}
144
const char *
145
pprintg4(stream * s, const char *format, double v1, double v2, double v3,
146
         double v4)
147
0
{
148
0
    return pprintg2(s, pprintg2(s, format, v1, v2), v3, v4);
149
0
}
150
const char *
151
pprintg6(stream * s, const char *format, double v1, double v2, double v3,
152
         double v4, double v5, double v6)
153
0
{
154
0
    return pprintg3(s, pprintg3(s, format, v1, v2, v3), v4, v5, v6);
155
0
}
156
157
/* Print a long value using a format. */
158
const char *
159
pprintld1(stream *s, const char *format, long v)
160
0
{
161
0
    const char *fp = pprintf_scan(s, format);
162
0
    char str[25];
163
164
#ifdef DEBUG
165
    if (*fp == 0 || fp[1] != 'l' || fp[2] != 'd') /* shouldn't happen! */
166
        lprintf1("Bad format in pprintld: %s\n", format);
167
#endif
168
0
    gs_snprintf(str, sizeof(str), "%ld", v);
169
0
    pputs_short(s, str);
170
0
    return pprintf_scan(s, fp + 3);
171
0
}
172
const char *
173
pprintld2(stream *s, const char *format, long v1, long v2)
174
0
{
175
0
    return pprintld1(s, pprintld1(s, format, v1), v2);
176
0
}
177
const char *
178
pprintld3(stream *s, const char *format, long v1, long v2, long v3)
179
0
{
180
0
    return pprintld2(s, pprintld1(s, format, v1), v2, v3);
181
0
}
182
183
/* Print a size_t value using a format. */
184
const char *
185
pprintzd1(stream *s, const char *format, size_t v)
186
0
{
187
0
    const char *fp = pprintf_scan(s, format);
188
0
    char str[25];
189
0
    const size_t z = strlen("%"PRIdSIZE);
190
191
#ifdef DEBUG
192
    size_t i;
193
194
    for (i = 0; i < z; i++)
195
        if (fp[i] != ("%"PRIdSIZE)[i])
196
            break;
197
    if (i != z)
198
        lprintf1("Bad format in pprintzd: %s\n", format);
199
#endif
200
0
    gs_snprintf(str, sizeof(str), "%"PRIdSIZE, v);
201
0
    pputs_short(s, str);
202
0
    return pprintf_scan(s, fp + z);
203
0
}
204
const char *
205
pprintzd2(stream *s, const char *format, size_t v1, size_t v2)
206
0
{
207
0
    return pprintzd1(s, pprintzd1(s, format, v1), v2);
208
0
}
209
const char *
210
pprintzd3(stream *s, const char *format, size_t v1, size_t v2, size_t v3)
211
0
{
212
0
    return pprintzd2(s, pprintzd1(s, format, v1), v2, v3);
213
0
}
214
215
/* Print an int64_t value using a format. */
216
const char *
217
pprinti64d1(stream *s, const char *format, int64_t v)
218
0
{
219
0
    const char *fp = pprintf_scan(s, format);
220
0
    char str[25];
221
0
    const size_t z = strlen("%"PRId64);
222
223
#ifdef DEBUG
224
    size_t i;
225
226
    for (i = 0; i < z; i++)
227
        if (fp[i] != ("%"PRId64)[i])
228
            break;
229
    if (i != z)
230
        lprintf1("Bad format in pprinti64d: %s\n", format);
231
#endif
232
0
    gs_snprintf(str, sizeof(str), "%"PRId64, v);
233
0
    pputs_short(s, str);
234
0
    return pprintf_scan(s, fp + z);
235
0
}
236
const char *
237
pprinti64d2(stream *s, const char *format, int64_t v1, int64_t v2)
238
0
{
239
0
    return pprinti64d1(s, pprinti64d1(s, format, v1), v2);
240
0
}
241
const char *
242
pprinti64d3(stream *s, const char *format, int64_t v1, int64_t v2, int64_t v3)
243
0
{
244
0
    return pprinti64d2(s, pprinti64d1(s, format, v1), v2, v3);
245
0
}
246
247
/* Print (a) string(s) using a format. */
248
const char *
249
pprints1(stream * s, const char *format, const char *str)
250
0
{
251
0
    const char *fp = pprintf_scan(s, format);
252
253
#ifdef DEBUG
254
    if (*fp == 0 || fp[1] != 's') /* shouldn't happen! */
255
        lprintf1("Bad format in pprints: %s\n", format);
256
#endif
257
0
    pputs_short(s, str);
258
0
    return pprintf_scan(s, fp + 2);
259
0
}
260
const char *
261
pprints2(stream * s, const char *format, const char *str1, const char *str2)
262
0
{
263
0
    return pprints1(s, pprints1(s, format, str1), str2);
264
0
}
265
const char *
266
pprints3(stream * s, const char *format, const char *str1, const char *str2,
267
         const char *str3)
268
0
{
269
0
    return pprints2(s, pprints1(s, format, str1), str2, str3);
270
0
}