source: rtems/cpukit/score/src/iovprintf.c @ 21275b58

5
Last change on this file since 21275b58 was bda8f80, checked in by Sebastian Huber <sebastian.huber@…>, on 07/18/18 at 06:54:57

score: Add a FALLTHROUGH comment to kvprintf()

This change was added to the FreeBSD version of this function.

This was spotted by Coverity Scan.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1986, 1988, 1991, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *      @(#)subr_prf.c  8.3 (Berkeley) 1/21/94
37 */
38
39#include <rtems/score/io.h>
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 336417 2018-07-17 14:56:54Z markj $");
43
44#include <sys/param.h>
45#include <string.h>
46
47/* Max number conversion buffer length: a intmax_t in base 8, plus NUL byte. */
48#define MAXNBUF (howmany(sizeof(intmax_t) * NBBY, 3) + 1)
49
50static inline int imax(int a, int b) { return (a > b ? a : b); }
51
52static char const hex2ascii_data[2][16] = {
53    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
54      'a', 'b', 'c', 'd', 'e', 'f' },
55    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
56      'A', 'B', 'C', 'D', 'E', 'F' }
57};
58
59static inline char
60hex2ascii(int hex)
61{
62
63        return (hex2ascii_data[0][hex]);
64}
65
66/*
67 * Put a NUL-terminated ASCII number (base <= 16) in a buffer in reverse
68 * order; return an optional length and a pointer to the last character
69 * written in the buffer (i.e., the first character of the string).
70 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
71 */
72static char *
73ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
74{
75        char *p;
76
77        p = nbuf;
78        *p = '\0';
79        do {
80                *++p = hex2ascii_data[upper][num % base];
81        } while (num /= base);
82        if (lenp)
83                *lenp = p - nbuf;
84        return (p);
85}
86
87int
88_IO_Vprintf(IO_Put_char put_char, void *arg, char const *fmt, va_list ap)
89{
90#define PCHAR(c) {int cc=(c); (*put_char)(cc, arg); retval++; }
91        char nbuf[MAXNBUF];
92        const char *p, *percent, *q;
93        u_char *up;
94        int ch, n;
95        uintmax_t num;
96        int base, lflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
97        int cflag, hflag, jflag;
98        RTEMS_STATIC_ASSERT(sizeof(intmax_t) == sizeof(long long), _IO_Vprintf_j);
99#if __SIZEOF_PTRDIFF_T__ == __SIZEOF_LONG__
100#define tflag lflag
101#else
102        int tflag;
103#endif
104#if __SIZEOF_SIZE_T__ == __SIZEOF_LONG__
105#define zflag lflag
106#else
107        int zflag;
108#endif
109        int dwidth, upper;
110        char padc;
111        int stop = 0, retval = 0;
112
113        num = 0;
114
115        if (fmt == NULL)
116                fmt = "(fmt null)\n";
117
118        for (;;) {
119                padc = ' ';
120                width = 0;
121                while ((ch = (u_char)*fmt++) != '%' || stop) {
122                        if (ch == '\0')
123                                return (retval);
124                        PCHAR(ch);
125                }
126                percent = fmt - 1;
127                lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
128                sign = 0; dot = 0; dwidth = 0; upper = 0;
129                cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
130reswitch:       switch (ch = (u_char)*fmt++) {
131                case '.':
132                        dot = 1;
133                        goto reswitch;
134                case '#':
135                        sharpflag = 1;
136                        goto reswitch;
137                case '+':
138                        sign = 1;
139                        goto reswitch;
140                case '-':
141                        ladjust = 1;
142                        goto reswitch;
143                case '%':
144                        PCHAR(ch);
145                        break;
146                case '*':
147                        if (!dot) {
148                                width = va_arg(ap, int);
149                                if (width < 0) {
150                                        ladjust = !ladjust;
151                                        width = -width;
152                                }
153                        } else {
154                                dwidth = va_arg(ap, int);
155                        }
156                        goto reswitch;
157                case '0':
158                        if (!dot) {
159                                padc = '0';
160                                goto reswitch;
161                        }
162                        /* FALLTHROUGH */
163                case '1': case '2': case '3': case '4':
164                case '5': case '6': case '7': case '8': case '9':
165                                for (n = 0;; ++fmt) {
166                                        n = n * 10 + ch - '0';
167                                        ch = *fmt;
168                                        if (ch < '0' || ch > '9')
169                                                break;
170                                }
171                        if (dot)
172                                dwidth = n;
173                        else
174                                width = n;
175                        goto reswitch;
176                case 'c':
177                        width -= 1;
178
179                        if (!ladjust && width > 0)
180                                while (width--)
181                                        PCHAR(padc);
182                        PCHAR(va_arg(ap, int));
183                        if (ladjust && width > 0)
184                                while (width--)
185                                        PCHAR(padc);
186                        break;
187                case 'D':
188                        up = va_arg(ap, u_char *);
189                        p = va_arg(ap, char *);
190                        if (!width)
191                                width = 16;
192                        while(width--) {
193                                PCHAR(hex2ascii(*up >> 4));
194                                PCHAR(hex2ascii(*up & 0x0f));
195                                up++;
196                                if (width)
197                                        for (q=p;*q;q++)
198                                                PCHAR(*q);
199                        }
200                        break;
201                case 'd':
202                case 'i':
203                        base = 10;
204                        sign = 1;
205                        goto handle_sign;
206                case 'h':
207                        if (hflag) {
208                                hflag = 0;
209                                cflag = 1;
210                        } else
211                                hflag = 1;
212                        goto reswitch;
213                case 'j':
214                        jflag = 1;
215                        goto reswitch;
216                case 'l':
217                        if (lflag) {
218                                jflag = 1;
219                        } else
220                                lflag = 1;
221                        goto reswitch;
222                case 'o':
223                        base = 8;
224                        goto handle_nosign;
225                case 'p':
226                        base = 16;
227                        sharpflag = (width == 0);
228                        sign = 0;
229                        num = (uintptr_t)va_arg(ap, void *);
230                        goto number;
231                case 's':
232                        p = va_arg(ap, char *);
233                        if (p == NULL)
234                                p = "(null)";
235                        if (!dot)
236                                n = strlen (p);
237                        else
238                                for (n = 0; n < dwidth && p[n]; n++)
239                                        continue;
240
241                        width -= n;
242
243                        if (!ladjust && width > 0)
244                                while (width--)
245                                        PCHAR(padc);
246                        while (n--)
247                                PCHAR(*p++);
248                        if (ladjust && width > 0)
249                                while (width--)
250                                        PCHAR(padc);
251                        break;
252                case 't':
253                        tflag = 1;
254                        goto reswitch;
255                case 'u':
256                        base = 10;
257                        goto handle_nosign;
258                case 'X':
259                        upper = 1;
260                case 'x':
261                        base = 16;
262                        goto handle_nosign;
263                case 'y':
264                        base = 16;
265                        sign = 1;
266                        goto handle_sign;
267                case 'z':
268                        zflag = 1;
269                        goto reswitch;
270handle_nosign:
271                        sign = 0;
272                        if (jflag)
273                                num = va_arg(ap, uintmax_t);
274#if __SIZEOF_PTRDIFF_T__ != __SIZEOF_LONG__
275                        else if (tflag)
276                                num = va_arg(ap, ptrdiff_t);
277#endif
278                        else if (lflag)
279                                num = va_arg(ap, u_long);
280#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG__
281                        else if (zflag)
282                                num = va_arg(ap, size_t);
283#endif
284                        else if (hflag)
285                                num = (u_short)va_arg(ap, int);
286                        else if (cflag)
287                                num = (u_char)va_arg(ap, int);
288                        else
289                                num = va_arg(ap, u_int);
290                        goto number;
291handle_sign:
292                        if (jflag)
293                                num = va_arg(ap, intmax_t);
294#if __SIZEOF_PTRDIFF_T__ == __SIZEOF_LONG__
295                        else if (tflag)
296                                num = va_arg(ap, ptrdiff_t);
297#endif
298                        else if (lflag)
299                                num = va_arg(ap, long);
300#if __SIZEOF_SIZE_T__ == __SIZEOF_LONG__
301                        else if (zflag)
302                                num = va_arg(ap, ssize_t);
303#endif
304                        else if (hflag)
305                                num = (short)va_arg(ap, int);
306                        else if (cflag)
307                                num = (char)va_arg(ap, int);
308                        else
309                                num = va_arg(ap, int);
310number:
311                        if (sign && (intmax_t)num < 0) {
312                                neg = 1;
313                                num = -(intmax_t)num;
314                        }
315                        p = ksprintn(nbuf, num, base, &n, upper);
316                        tmp = 0;
317                        if (sharpflag && num != 0) {
318                                if (base == 8)
319                                        tmp++;
320                                else if (base == 16)
321                                        tmp += 2;
322                        }
323                        if (neg)
324                                tmp++;
325
326                        if (!ladjust && padc == '0')
327                                dwidth = width - tmp;
328                        width -= tmp + imax(dwidth, n);
329                        dwidth -= n;
330                        if (!ladjust)
331                                while (width-- > 0)
332                                        PCHAR(' ');
333                        if (neg)
334                                PCHAR('-');
335                        if (sharpflag && num != 0) {
336                                if (base == 8) {
337                                        PCHAR('0');
338                                } else if (base == 16) {
339                                        PCHAR('0');
340                                        PCHAR('x');
341                                }
342                        }
343                        while (dwidth-- > 0)
344                                PCHAR('0');
345
346                        while (*p)
347                                PCHAR(*p--);
348
349                        if (ladjust)
350                                while (width-- > 0)
351                                        PCHAR(' ');
352
353                        break;
354                default:
355                        while (percent < fmt)
356                                PCHAR(*percent++);
357                        /*
358                         * Since we ignore a formatting argument it is no
359                         * longer safe to obey the remaining formatting
360                         * arguments as the arguments will no longer match
361                         * the format specs.
362                         */
363                        stop = 1;
364                        break;
365                }
366        }
367#undef PCHAR
368}
Note: See TracBrowser for help on using the repository browser.