source: mainline/boot/generic/src/printf_core.c@ 28a5ebd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 28a5ebd was 28a5ebd, checked in by Martin Decky <martin@…>, 5 years ago

Use char32_t instead of wchat_t to represent UTF-32 strings

The intention of the native HelenOS string API has been always to
support Unicode in the UTF-8 and UTF-32 encodings as the sole character
representations and ignore the obsolete mess of older single-byte and
multibyte character encodings. Before C11, the wchar_t type has been
slightly misused for the purpose of the UTF-32 strings. The newer
char32_t type is obviously a much more suitable option. The standard
defines char32_t as uint_least32_t, thus we can take the liberty to fix
it to uint32_t.

To maintain compatilibity with the C Standard, the putwchar(wchar_t)
functions has been replaced by our custom putuchar(char32_t) functions
where appropriate.

  • Property mode set to 100644
File size: 19.3 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Jakub Jermar
3 * Copyright (c) 2006 Josef Cejka
4 * Copyright (c) 2009 Martin Decky
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * - The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/**
32 * @file
33 * @brief Printing functions.
34 */
35
36#include <printf_core.h>
37#include <printf.h>
38#include <stdarg.h>
39#include <stdbool.h>
40#include <stddef.h>
41#include <stdint.h>
42#include <macros.h>
43#include <str.h>
44
45/** show prefixes 0x or 0 */
46#define __PRINTF_FLAG_PREFIX 0x00000001
47
48/** signed / unsigned number */
49#define __PRINTF_FLAG_SIGNED 0x00000002
50
51/** print leading zeroes */
52#define __PRINTF_FLAG_ZEROPADDED 0x00000004
53
54/** align to left */
55#define __PRINTF_FLAG_LEFTALIGNED 0x00000010
56
57/** always show + sign */
58#define __PRINTF_FLAG_SHOWPLUS 0x00000020
59
60/** print space instead of plus */
61#define __PRINTF_FLAG_SPACESIGN 0x00000040
62
63/** show big characters */
64#define __PRINTF_FLAG_BIGCHARS 0x00000080
65
66/** number has - sign */
67#define __PRINTF_FLAG_NEGATIVE 0x00000100
68
69/**
70 * Buffer big enough for 64-bit number printed in base 2, sign, prefix and 0
71 * to terminate string... (last one is only for better testing end of buffer by
72 * zero-filling subroutine)
73 */
74#define PRINT_NUMBER_BUFFER_SIZE (64 + 5)
75
76/** Get signed or unsigned integer argument */
77#define PRINTF_GET_INT_ARGUMENT(type, ap, flags) \
78 ({ \
79 unsigned type res; \
80 \
81 if ((flags) & __PRINTF_FLAG_SIGNED) { \
82 signed type arg = va_arg((ap), signed type); \
83 \
84 if (arg < 0) { \
85 res = -arg; \
86 (flags) |= __PRINTF_FLAG_NEGATIVE; \
87 } else \
88 res = arg; \
89 } else \
90 res = va_arg((ap), unsigned type); \
91 \
92 res; \
93 })
94
95/** Enumeration of possible arguments types.
96 */
97typedef enum {
98 PrintfQualifierByte = 0,
99 PrintfQualifierShort,
100 PrintfQualifierInt,
101 PrintfQualifierLong,
102 PrintfQualifierLongLong,
103 PrintfQualifierPointer,
104 PrintfQualifierSize,
105 PrintfQualifierMax
106} qualifier_t;
107
108static const char *nullstr = "(NULL)";
109static const char *digits_small = "0123456789abcdef";
110static const char *digits_big = "0123456789ABCDEF";
111static const char invalch = U_SPECIAL;
112
113/** Print one or more characters without adding newline.
114 *
115 * @param buf Buffer holding characters with size of
116 * at least size bytes. NULL is not allowed!
117 * @param size Size of the buffer in bytes.
118 * @param ps Output method and its data.
119 *
120 * @return Number of characters printed.
121 *
122 */
123static int printf_putnchars(const char *buf, size_t size,
124 printf_spec_t *ps)
125{
126 return ps->str_write((void *) buf, size, ps->data);
127}
128
129/** Print string without adding a newline.
130 *
131 * @param str String to print.
132 * @param ps Write function specification and support data.
133 *
134 * @return Number of characters printed.
135 *
136 */
137static int printf_putstr(const char *str, printf_spec_t *ps)
138{
139 if (str == NULL)
140 return printf_putnchars(nullstr, str_size(nullstr), ps);
141
142 return ps->str_write((void *) str, str_size(str), ps->data);
143}
144
145/** Print one ASCII character.
146 *
147 * @param c ASCII character to be printed.
148 * @param ps Output method.
149 *
150 * @return Number of characters printed.
151 *
152 */
153static int printf_putchar(const char ch, printf_spec_t *ps)
154{
155 if (!ascii_check(ch))
156 return ps->str_write((void *) &invalch, 1, ps->data);
157
158 return ps->str_write(&ch, 1, ps->data);
159}
160
161/** Print one formatted ASCII character.
162 *
163 * @param ch Character to print.
164 * @param width Width modifier.
165 * @param flags Flags that change the way the character is printed.
166 *
167 * @return Number of characters printed, negative value on failure.
168 *
169 */
170static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
171{
172 size_t counter = 0;
173 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
174 while (--width > 0) {
175 /*
176 * One space is consumed by the character itself, hence
177 * the predecrement.
178 */
179 if (printf_putchar(' ', ps) > 0)
180 counter++;
181 }
182 }
183
184 if (printf_putchar(ch, ps) > 0)
185 counter++;
186
187 while (--width > 0) {
188 /*
189 * One space is consumed by the character itself, hence
190 * the predecrement.
191 */
192 if (printf_putchar(' ', ps) > 0)
193 counter++;
194 }
195
196 return (int) (counter);
197}
198
199/** Print string.
200 *
201 * @param str String to be printed.
202 * @param width Width modifier.
203 * @param precision Precision modifier.
204 * @param flags Flags that modify the way the string is printed.
205 *
206 * @return Number of characters printed, negative value on failure.
207 */
208static int print_str(char *str, int width, unsigned int precision,
209 uint32_t flags, printf_spec_t *ps)
210{
211 if (str == NULL)
212 return printf_putstr(nullstr, ps);
213
214 /* Print leading spaces. */
215 size_t strw = str_length(str);
216 if ((precision == 0) || (precision > strw))
217 precision = strw;
218
219 /* Left padding */
220 size_t counter = 0;
221 width -= precision;
222 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
223 while (width-- > 0) {
224 if (printf_putchar(' ', ps) == 1)
225 counter++;
226 }
227 }
228
229 /* Part of @a str fitting into the alloted space. */
230 int retval;
231 size_t size = str_lsize(str, precision);
232 if ((retval = printf_putnchars(str, size, ps)) < 0)
233 return -counter;
234
235 counter += retval;
236
237 /* Right padding */
238 while (width-- > 0) {
239 if (printf_putchar(' ', ps) == 1)
240 counter++;
241 }
242
243 return ((int) counter);
244}
245
246/** Print a number in a given base.
247 *
248 * Print significant digits of a number in given base.
249 *
250 * @param num Number to print.
251 * @param width Width modifier.
252 * @param precision Precision modifier.
253 * @param base Base to print the number in (must be between 2 and 16).
254 * @param flags Flags that modify the way the number is printed.
255 *
256 * @return Number of characters printed.
257 *
258 */
259static int print_number(uint64_t num, int width, int precision, int base,
260 uint32_t flags, printf_spec_t *ps)
261{
262 const char *digits;
263 if (flags & __PRINTF_FLAG_BIGCHARS)
264 digits = digits_big;
265 else
266 digits = digits_small;
267
268 char data[PRINT_NUMBER_BUFFER_SIZE];
269 char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1];
270
271 /* Size of number with all prefixes and signs */
272 int size = 0;
273
274 /* Put zero at end of string */
275 *ptr-- = 0;
276
277 if (num == 0) {
278 *ptr-- = '0';
279 size++;
280 } else {
281 do {
282 *ptr-- = digits[num % base];
283 size++;
284 } while (num /= base);
285 }
286
287 /* Size of plain number */
288 int number_size = size;
289
290 /*
291 * Collect the sum of all prefixes/signs/etc. to calculate padding and
292 * leading zeroes.
293 */
294 if (flags & __PRINTF_FLAG_PREFIX) {
295 switch (base) {
296 case 2:
297 /* Binary formating is not standard, but usefull */
298 size += 2;
299 break;
300 case 8:
301 size++;
302 break;
303 case 16:
304 size += 2;
305 break;
306 }
307 }
308
309 char sgn = 0;
310 if (flags & __PRINTF_FLAG_SIGNED) {
311 if (flags & __PRINTF_FLAG_NEGATIVE) {
312 sgn = '-';
313 size++;
314 } else if (flags & __PRINTF_FLAG_SHOWPLUS) {
315 sgn = '+';
316 size++;
317 } else if (flags & __PRINTF_FLAG_SPACESIGN) {
318 sgn = ' ';
319 size++;
320 }
321 }
322
323 if (flags & __PRINTF_FLAG_LEFTALIGNED)
324 flags &= ~__PRINTF_FLAG_ZEROPADDED;
325
326 /*
327 * If the number is left-aligned or precision is specified then
328 * padding with zeros is ignored.
329 */
330 if (flags & __PRINTF_FLAG_ZEROPADDED) {
331 if ((precision == 0) && (width > size))
332 precision = width - size + number_size;
333 }
334
335 /* Print leading spaces */
336 if (number_size > precision) {
337 /* Print the whole number, not only a part */
338 precision = number_size;
339 }
340
341 width -= precision + size - number_size;
342 size_t counter = 0;
343
344 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
345 while (width-- > 0) {
346 if (printf_putchar(' ', ps) == 1)
347 counter++;
348 }
349 }
350
351 /* Print sign */
352 if (sgn) {
353 if (printf_putchar(sgn, ps) == 1)
354 counter++;
355 }
356
357 /* Print prefix */
358 if (flags & __PRINTF_FLAG_PREFIX) {
359 switch (base) {
360 case 2:
361 /* Binary formating is not standard, but usefull */
362 if (printf_putchar('0', ps) == 1)
363 counter++;
364 if (flags & __PRINTF_FLAG_BIGCHARS) {
365 if (printf_putchar('B', ps) == 1)
366 counter++;
367 } else {
368 if (printf_putchar('b', ps) == 1)
369 counter++;
370 }
371 break;
372 case 8:
373 if (printf_putchar('o', ps) == 1)
374 counter++;
375 break;
376 case 16:
377 if (printf_putchar('0', ps) == 1)
378 counter++;
379 if (flags & __PRINTF_FLAG_BIGCHARS) {
380 if (printf_putchar('X', ps) == 1)
381 counter++;
382 } else {
383 if (printf_putchar('x', ps) == 1)
384 counter++;
385 }
386 break;
387 }
388 }
389
390 /* Print leading zeroes */
391 precision -= number_size;
392 while (precision-- > 0) {
393 if (printf_putchar('0', ps) == 1)
394 counter++;
395 }
396
397 /* Print the number itself */
398 int retval;
399 if ((retval = printf_putstr(++ptr, ps)) > 0)
400 counter += retval;
401
402 /* Print trailing spaces */
403
404 while (width-- > 0) {
405 if (printf_putchar(' ', ps) == 1)
406 counter++;
407 }
408
409 return ((int) counter);
410}
411
412/** Print formatted string.
413 *
414 * Print string formatted according to the fmt parameter and variadic arguments.
415 * Each formatting directive must have the following form:
416 *
417 * \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
418 *
419 * FLAGS:@n
420 * - "#" Force to print prefix. For \%o conversion, the prefix is 0, for
421 * \%x and \%X prefixes are 0x and 0X and for conversion \%b the
422 * prefix is 0b.
423 *
424 * - "-" Align to left.
425 *
426 * - "+" Print positive sign just as negative.
427 *
428 * - " " If the printed number is positive and "+" flag is not set,
429 * print space in place of sign.
430 *
431 * - "0" Print 0 as padding instead of spaces. Zeroes are placed between
432 * sign and the rest of the number. This flag is ignored if "-"
433 * flag is specified.
434 *
435 * WIDTH:@n
436 * - Specify the minimal width of a printed argument. If it is bigger,
437 * width is ignored. If width is specified with a "*" character instead of
438 * number, width is taken from parameter list. And integer parameter is
439 * expected before parameter for processed conversion specification. If
440 * this value is negative its absolute value is taken and the "-" flag is
441 * set.
442 *
443 * PRECISION:@n
444 * - Value precision. For numbers it specifies minimum valid numbers.
445 * Smaller numbers are printed with leading zeroes. Bigger numbers are not
446 * affected. Strings with more than precision characters are cut off. Just
447 * as with width, an "*" can be used used instead of a number. An integer
448 * value is then expected in parameters. When both width and precision are
449 * specified using "*", the first parameter is used for width and the
450 * second one for precision.
451 *
452 * TYPE:@n
453 * - "hh" Signed or unsigned char.@n
454 * - "h" Signed or unsigned short.@n
455 * - "" Signed or unsigned int (default value).@n
456 * - "l" Signed or unsigned long int.@n
457 * - "ll" Signed or unsigned long long int.@n
458 *
459 * CONVERSION:@n
460 * - % Print percentile character itself.
461 *
462 * - c Print single character. The character is expected to be plain
463 * ASCII (e.g. only values 0 .. 127 are valid).@n
464 *
465 * - s Print zero terminated string. If a NULL value is passed as
466 * value, "(NULL)" is printed instead.@n
467 *
468 * - P, p Print value of a pointer. Void * value is expected and it is
469 * printed in hexadecimal notation with prefix (as with
470 * \%#0.8X / \%#0.8x for 32-bit or \%#0.16lX / \%#0.16lx for 64-bit
471 * long pointers).
472 *
473 * - b Print value as unsigned binary number. Prefix is not printed by
474 * default. (Nonstandard extension.)
475 *
476 * - o Print value as unsigned octal number. Prefix is not printed by
477 * default.
478 *
479 * - d, i Print signed decimal number. There is no difference between d
480 * and i conversion.
481 *
482 * - u Print unsigned decimal number.
483 *
484 * - X, x Print hexadecimal number with upper- or lower-case. Prefix is
485 * not printed by default.
486 *
487 * All other characters from fmt except the formatting directives are printed
488 * verbatim.
489 *
490 * @param fmt Format NULL-terminated string.
491 *
492 * @return Number of characters printed, negative value on failure.
493 *
494 */
495int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
496{
497 size_t i; /* Index of the currently processed character from fmt */
498 size_t nxt = 0; /* Index of the next character from fmt */
499 size_t j = 0; /* Index to the first not printed nonformating character */
500
501 size_t counter = 0; /* Number of characters printed */
502 int retval; /* Return values from nested functions */
503
504 while (true) {
505 i = nxt;
506 char32_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
507
508 if (uc == 0)
509 break;
510
511 /* Control character */
512 if (uc == '%') {
513 /* Print common characters if any processed */
514 if (i > j) {
515 if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
516 /* Error */
517 counter = -counter;
518 goto out;
519 }
520 counter += retval;
521 }
522
523 j = i;
524
525 /* Parse modifiers */
526 uint32_t flags = 0;
527 bool end = false;
528
529 do {
530 i = nxt;
531 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
532 switch (uc) {
533 case '#':
534 flags |= __PRINTF_FLAG_PREFIX;
535 break;
536 case '-':
537 flags |= __PRINTF_FLAG_LEFTALIGNED;
538 break;
539 case '+':
540 flags |= __PRINTF_FLAG_SHOWPLUS;
541 break;
542 case ' ':
543 flags |= __PRINTF_FLAG_SPACESIGN;
544 break;
545 case '0':
546 flags |= __PRINTF_FLAG_ZEROPADDED;
547 break;
548 default:
549 end = true;
550 }
551 } while (!end);
552
553 /* Width & '*' operator */
554 int width = 0;
555 if (isdigit(uc)) {
556 while (true) {
557 width *= 10;
558 width += uc - '0';
559
560 i = nxt;
561 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
562 if (uc == 0)
563 break;
564 if (!isdigit(uc))
565 break;
566 }
567 } else if (uc == '*') {
568 /* Get width value from argument list */
569 i = nxt;
570 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
571 width = (int) va_arg(ap, int);
572 if (width < 0) {
573 /* Negative width sets '-' flag */
574 width *= -1;
575 flags |= __PRINTF_FLAG_LEFTALIGNED;
576 }
577 }
578
579 /* Precision and '*' operator */
580 int precision = 0;
581 if (uc == '.') {
582 i = nxt;
583 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
584 if (isdigit(uc)) {
585 while (true) {
586 precision *= 10;
587 precision += uc - '0';
588
589 i = nxt;
590 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
591 if (uc == 0)
592 break;
593 if (!isdigit(uc))
594 break;
595 }
596 } else if (uc == '*') {
597 /* Get precision value from the argument list */
598 i = nxt;
599 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
600 precision = (int) va_arg(ap, int);
601 if (precision < 0) {
602 /* Ignore negative precision */
603 precision = 0;
604 }
605 }
606 }
607
608 qualifier_t qualifier;
609
610 switch (uc) {
611 case 't':
612 /* ptrdiff_t */
613 if (sizeof(ptrdiff_t) == sizeof(int32_t))
614 qualifier = PrintfQualifierInt;
615 else
616 qualifier = PrintfQualifierLongLong;
617 i = nxt;
618 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
619 break;
620 case 'h':
621 /* Char or short */
622 qualifier = PrintfQualifierShort;
623 i = nxt;
624 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
625 if (uc == 'h') {
626 i = nxt;
627 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
628 qualifier = PrintfQualifierByte;
629 }
630 break;
631 case 'l':
632 /* Long or long long */
633 qualifier = PrintfQualifierLong;
634 i = nxt;
635 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
636 if (uc == 'l') {
637 i = nxt;
638 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
639 qualifier = PrintfQualifierLongLong;
640 }
641 break;
642 case 'z':
643 qualifier = PrintfQualifierSize;
644 i = nxt;
645 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
646 break;
647 case 'j':
648 qualifier = PrintfQualifierMax;
649 i = nxt;
650 uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
651 break;
652 default:
653 /* Default type */
654 qualifier = PrintfQualifierInt;
655 }
656
657 unsigned int base = 10;
658
659 switch (uc) {
660 /*
661 * String and character conversions.
662 */
663 case 's':
664 retval = print_str(va_arg(ap, char *), width, precision, flags, ps);
665
666 if (retval < 0) {
667 counter = -counter;
668 goto out;
669 }
670
671 counter += retval;
672 j = nxt;
673 continue;
674 case 'c':
675 retval = print_char(va_arg(ap, unsigned int), width, flags, ps);
676
677 if (retval < 0) {
678 counter = -counter;
679 goto out;
680 }
681
682 counter += retval;
683 j = nxt;
684 continue;
685
686 /*
687 * Integer values
688 */
689 case 'P':
690 /* Pointer */
691 flags |= __PRINTF_FLAG_BIGCHARS;
692 /* Fallthrough */
693 case 'p':
694 flags |= __PRINTF_FLAG_PREFIX;
695 flags |= __PRINTF_FLAG_ZEROPADDED;
696 base = 16;
697 qualifier = PrintfQualifierPointer;
698 break;
699 case 'b':
700 base = 2;
701 break;
702 case 'o':
703 base = 8;
704 break;
705 case 'd':
706 case 'i':
707 flags |= __PRINTF_FLAG_SIGNED;
708 /* Fallthrough */
709 case 'u':
710 break;
711 case 'X':
712 flags |= __PRINTF_FLAG_BIGCHARS;
713 /* Fallthrough */
714 case 'x':
715 base = 16;
716 break;
717
718 /* Percentile itself */
719 case '%':
720 j = i;
721 continue;
722
723 /*
724 * Bad formatting.
725 */
726 default:
727 /*
728 * Unknown format. Now, j is the index of '%'
729 * so we will print whole bad format sequence.
730 */
731 continue;
732 }
733
734 /* Print integers */
735 size_t size;
736 uint64_t number;
737
738 switch (qualifier) {
739 case PrintfQualifierByte:
740 size = sizeof(unsigned char);
741 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
742 break;
743 case PrintfQualifierShort:
744 size = sizeof(unsigned short);
745 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
746 break;
747 case PrintfQualifierInt:
748 size = sizeof(unsigned int);
749 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
750 break;
751 case PrintfQualifierLong:
752 size = sizeof(unsigned long);
753 number = PRINTF_GET_INT_ARGUMENT(long, ap, flags);
754 break;
755 case PrintfQualifierLongLong:
756 size = sizeof(unsigned long long);
757 number = PRINTF_GET_INT_ARGUMENT(long long, ap, flags);
758 break;
759 case PrintfQualifierPointer:
760 size = sizeof(void *);
761 precision = size << 1;
762 number = (uint64_t) (uintptr_t) va_arg(ap, void *);
763 break;
764 case PrintfQualifierSize:
765 size = sizeof(size_t);
766 number = (uint64_t) va_arg(ap, size_t);
767 break;
768 case PrintfQualifierMax:
769 size = sizeof(uintmax_t);
770 number = (uint64_t) va_arg(ap, uintmax_t);
771 break;
772 default:
773 /* Unknown qualifier */
774 counter = -counter;
775 goto out;
776 }
777
778 if ((retval = print_number(number, width, precision,
779 base, flags, ps)) < 0) {
780 counter = -counter;
781 goto out;
782 }
783
784 counter += retval;
785 j = nxt;
786 }
787 }
788
789 if (i > j) {
790 if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
791 /* Error */
792 counter = -counter;
793 goto out;
794 }
795 counter += retval;
796 }
797
798out:
799 return ((int) counter);
800}
801
802/** @}
803 */
Note: See TracBrowser for help on using the repository browser.