Subversion Repositories HelenOS

Compare Revisions

Regard whitespace Rev 4179 → Rev 4180

/trunk/kernel/generic/src/printf/printf.c
33,7 → 33,6
*/
 
#include <print.h>
int printf(const char *fmt, ...);
 
int printf(const char *fmt, ...)
{
/trunk/kernel/generic/src/printf/vprintf.c
39,28 → 39,58
#include <arch/asm.h>
#include <arch/types.h>
#include <typedefs.h>
#include <string.h>
 
SPINLOCK_INITIALIZE(printf_lock); /**< vprintf spinlock */
 
static int vprintf_write(const char *str, size_t count, void *unused)
static int vprintf_write_utf8(const char *str, size_t size, void *data)
{
size_t i;
for (i = 0; i < count; i++)
putchar(str[i]);
return i;
index_t index = 0;
index_t chars = 0;
while (index < size) {
putchar(utf8_decode(str, &index, size - 1));
index++;
chars++;
}
 
int puts(const char *s)
return chars;
}
 
static int vprintf_write_utf32(const wchar_t *str, size_t size, void *data)
{
size_t i;
for (i = 0; s[i] != 0; i++)
putchar(s[i]);
return i;
index_t index = 0;
while (index < (size / sizeof(wchar_t))) {
putchar(str[index]);
index++;
}
 
return index;
}
 
int puts(const char *str)
{
index_t index = 0;
index_t chars = 0;
wchar_t uc;
while ((uc = utf8_decode(str, &index, UTF8_NO_LIMIT)) != 0) {
putchar(uc);
index++;
chars++;
}
return chars;
}
 
int vprintf(const char *fmt, va_list ap)
{
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vprintf_write, NULL};
printf_spec_t ps = {
vprintf_write_utf8,
vprintf_write_utf32,
NULL
};
ipl_t ipl = interrupts_disable();
spinlock_lock(&printf_lock);
/trunk/kernel/generic/src/printf/vsnprintf.c
34,61 → 34,148
 
#include <print.h>
#include <printf/printf_core.h>
#include <string.h>
#include <memstr.h>
 
struct vsnprintf_data {
size_t size; /* total space for string */
size_t len; /* count of currently used characters */
char *string; /* destination string */
};
typedef struct {
size_t size; /* Total size of the buffer (in bytes) */
size_t len; /* Number of already used bytes */
char *dst; /* Destination */
} vsnprintf_data_t;
 
/** Write string to given buffer.
* Write at most data->size characters including trailing zero. According to C99, snprintf() has to return number
* of characters that would have been written if enough space had been available. Hence the return value is not
* number of really printed characters but size of the input string. Number of really used characters
* is stored in data->len.
* @param str source string to print
* @param count size of source string
* @param data structure with destination string, counter of used space and total string size.
* @return number of characters to print (not characters really printed!)
/** Write UTF-8 string to given buffer.
*
* Write at most data->size plain characters including trailing zero.
* According to C99, snprintf() has to return number of characters that
* would have been written if enough space had been available. Hence
* the return value is not the number of actually printed characters
* but size of the input string.
*
* @param str Source UTF-8 string to print.
* @param size Number of plain characters in str.
* @param data Structure describing destination string, counter
* of used space and total string size.
*
* @return Number of UTF-8 characters to print (not characters actually
* printed).
*
*/
static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
static int vsnprintf_write_utf8(const char *str, size_t size, vsnprintf_data_t *data)
{
size_t i;
i = data->size - data->len;
size_t left = data->size - data->len;
 
if (i == 0) {
return count;
}
if (left == 0)
return ((int) size);
if (i == 1) {
/* We have only one free byte left in buffer => write there trailing zero */
data->string[data->size - 1] = 0;
if (left == 1) {
/* We have only one free byte left in buffer
* -> store trailing zero
*/
data->dst[data->size - 1] = 0;
data->len = data->size;
return count;
return ((int) size);
}
if (i <= count) {
/* We have not enought space for whole string with the trailing zero => print only a part of string */
memcpy((void *)(data->string + data->len), (void *)str, i - 1);
data->string[data->size - 1] = 0;
if (left <= size) {
/* We have not enought space for whole string
* with the trailing zero => print only a part
* of string
*/
index_t index = 0;
while (index < size) {
wchar_t uc = utf8_decode(str, &index, size - 1);
if (!utf8_encode(uc, data->dst, &data->len, data->size - 1))
break;
data->len++;
index++;
}
/* Put trailing zero at end, but not count it
* into data->len so it could be rewritten next time
*/
data->dst[data->len] = 0;
return ((int) size);
}
/* Buffer is big enought to print the whole string */
memcpy((void *)(data->dst + data->len), (void *) str, size);
data->len += size;
/* Put trailing zero at end, but not count it
* into data->len so it could be rewritten next time
*/
data->dst[data->len] = 0;
return ((int) size);
}
 
/** Write UTF-32 string to given buffer.
*
* Write at most data->size plain characters including trailing zero.
* According to C99, snprintf() has to return number of characters that
* would have been written if enough space had been available. Hence
* the return value is not the number of actually printed characters
* but size of the input string.
*
* @param str Source UTF-32 string to print.
* @param size Number of bytes in str.
* @param data Structure describing destination string, counter
* of used space and total string size.
*
* @return Number of UTF-8 characters to print (not characters actually
* printed).
*
*/
static int vsnprintf_write_utf32(const wchar_t *str, size_t size, vsnprintf_data_t *data)
{
index_t index = 0;
while (index < (size / sizeof(wchar_t))) {
size_t left = data->size - data->len;
if (left == 0)
return ((int) size);
if (left == 1) {
/* We have only one free byte left in buffer
* -> store trailing zero
*/
data->dst[data->size - 1] = 0;
data->len = data->size;
return count;
return ((int) size);
}
/* Buffer is big enought to print whole string */
memcpy((void *)(data->string + data->len), (void *)str, count);
data->len += count;
/* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */
data->string[data->len] = 0;
if (!utf8_encode(str[index], data->dst, &data->len, data->size - 1))
break;
 
return count;
data->len++;
index++;
}
 
/* Put trailing zero at end, but not count it
* into data->len so it could be rewritten next time
*/
data->dst[data->len] = 0;
return ((int) size);
}
 
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
{
struct vsnprintf_data data = {size, 0, str};
struct printf_spec ps = {(int(*)(void *, size_t, void *))vsnprintf_write, &data};
vsnprintf_data_t data = {
size,
0,
str
};
printf_spec_t ps = {
(int(*) (const char *, size_t, void *)) vsnprintf_write_utf8,
(int(*) (const wchar_t *, size_t, void *)) vsnprintf_write_utf32,
&data
};
 
/* Print 0 at end of string - fix the case that nothing will be printed */
if (size > 0)
/trunk/kernel/generic/src/printf/printf_core.c
1,6 → 1,7
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
36,7 → 37,6
*/
 
#include <printf/printf_core.h>
#include <putchar.h>
#include <print.h>
#include <arch/arg.h>
#include <macros.h>
78,69 → 78,140
PrintfQualifierPointer
} qualifier_t;
 
static char nullstr[] = "(NULL)";
static char digits_small[] = "0123456789abcdef";
static char digits_big[] = "0123456789ABCDEF";
 
/** Print one or more characters without adding newline.
/** Print one or more UTF-8 characters without adding newline.
*
* @param buf Buffer with size at least count bytes. NULL pointer is
* not allowed!
* @param count Number of characters to print.
* @param buf Buffer holding UTF-8 characters with size of
* at least size bytes. NULL is not allowed!
* @param size Size of the buffer in bytes.
* @param ps Output method and its data.
* @return Number of characters printed.
*
* @return Number of UTF-8 characters printed.
*
*/
static int printf_putnchars(const char * buf, size_t count,
struct printf_spec *ps)
static int printf_putnchars_utf8(const char *buf, size_t size,
printf_spec_t *ps)
{
return ps->write((void *) buf, count, ps->data);
return ps->write_utf8((void *) buf, size, ps->data);
}
 
/** Print a string without adding a newline.
/** Print one or more UTF-32 characters without adding newline.
*
* @param str String to print.
* @param buf Buffer holding UTF-32 characters with size of
* at least size bytes. NULL is not allowed!
* @param size Size of the buffer in bytes.
* @param ps Output method and its data.
*
* @return Number of UTF-32 characters printed.
*
*/
static int printf_putnchars_utf32(const wchar_t *buf, size_t size,
printf_spec_t *ps)
{
return ps->write_utf32((void *) buf, size, ps->data);
}
 
/** Print UTF-8 string without adding a newline.
*
* @param str UTF-8 string to print.
* @param ps Write function specification and support data.
* @return Number of characters printed.
*
* @return Number of UTF-8 characters printed.
*
*/
static int printf_putstr(const char * str, struct printf_spec *ps)
static int printf_putstr(const char *str, printf_spec_t *ps)
{
size_t count;
if (str == NULL)
return printf_putnchars_utf8(nullstr, strlen(nullstr), ps);
if (str == NULL) {
char *nullstr = "(NULL)";
return printf_putnchars(nullstr, strlen(nullstr), ps);
return ps->write_utf8((void *) str, strlen(str), ps->data);
}
 
count = strlen(str);
/** Print one ASCII character.
*
* @param c ASCII character to be printed.
* @param ps Output method.
*
* @return Number of characters printed.
*
*/
static int printf_putchar(const char ch, printf_spec_t *ps)
{
if (!ascii_check(ch))
return ps->write_utf8((void *) &invalch, 1, ps->data);
 
return ps->write((void *) str, count, ps->data);
return ps->write_utf8(&ch, 1, ps->data);
}
 
/** Print one character.
/** Print one UTF-32 character.
*
* @param c Character to be printed.
* @param c UTF-32 character to be printed.
* @param ps Output method.
*
* @return Number of characters printed.
*
*/
static int printf_putchar(int c, struct printf_spec *ps)
static int printf_putwchar(const wchar_t ch, printf_spec_t *ps)
{
unsigned char ch = c;
if (!unicode_check(ch))
return ps->write_utf8((void *) &invalch, 1, ps->data);
return ps->write((void *) &ch, 1, ps->data);
return ps->write_utf32(&ch, 1, ps->data);
}
 
/** Print one formatted character.
/** Print one formatted ASCII character.
*
* @param c Character to print.
* @param ch Character to print.
* @param width Width modifier.
* @param flags Flags that change the way the character is printed.
*
* @return Number of characters printed, negative value on failure.
*
*/
static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps)
static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
{
int counter = 0;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
* One space is consumed by the character itself, hence
* the predecrement.
*/
if (printf_putchar(' ', ps) > 0)
counter++;
}
}
if (printf_putchar(ch, ps) > 0)
counter++;
while (--width > 0) {
/*
* One space is consumed by the character itself, hence
* the predecrement.
*/
if (printf_putchar(' ', ps) > 0)
counter++;
}
return (int) (counter + 1);
}
 
/** Print one formatted UTF-32 character.
*
* @param ch Character to print.
* @param width Width modifier.
* @param flags Flags that change the way the character is printed.
*
* @return Number of characters printed, negative value on failure.
*
*/
static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
{
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (--width > 0) {
/*
148,11 → 219,11
* the predecrement.
*/
if (printf_putchar(' ', ps) > 0)
++counter;
counter++;
}
}
if (printf_putchar(c, ps) > 0)
if (printf_putwchar(ch, ps) > 0)
counter++;
 
while (--width > 0) {
161,41 → 232,78
* the predecrement.
*/
if (printf_putchar(' ', ps) > 0)
++counter;
counter++;
}
return ++counter;
return (int) (counter + 1);
}
 
/** Print string.
/** Print UTF-8 string.
*
* @param s String to be printed.
* @param str UTF-8 string to be printed.
* @param width Width modifier.
* @param precision Precision modifier.
* @param flags Flags that modify the way the string is printed.
*
* @return Number of characters printed, negative value on failure.
* @return Number of UTF-8 characters printed, negative value on failure.
*/
static int print_string(char *s, int width, unsigned int precision,
uint64_t flags, struct printf_spec *ps)
static int print_utf8(char *str, int width, unsigned int precision,
uint32_t flags, printf_spec_t *ps)
{
int counter = 0;
size_t size;
if (str == NULL)
return printf_putstr(nullstr, ps);
/* Print leading spaces */
size_t size = strlen_utf8(str);
if (precision == 0)
precision = size;
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
}
}
int retval;
size_t bytes = utf8_count_bytes(str, min(size, precision));
if ((retval = printf_putnchars_utf8(str, bytes, ps)) < 0)
return -counter;
 
if (s == NULL) {
return printf_putstr("(NULL)", ps);
counter += retval;
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
}
size = strlen(s);
return ((int) counter);
}
 
/* print leading spaces */
/** Print UTF-32 string.
*
* @param str UTF-32 string to be printed.
* @param width Width modifier.
* @param precision Precision modifier.
* @param flags Flags that modify the way the string is printed.
*
* @return Number of UTF-32 characters printed, negative value on failure.
*/
static int print_utf32(wchar_t *str, int width, unsigned int precision,
uint32_t flags, printf_spec_t *ps)
{
if (str == NULL)
return printf_putstr(nullstr, ps);
 
/* Print leading spaces */
size_t size = strlen_utf32(str);
if (precision == 0)
precision = size;
 
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
203,26 → 311,27
}
}
 
if ((retval = printf_putnchars(s, min(size, precision), ps)) < 0) {
int retval;
size_t bytes = min(size, precision) * sizeof(wchar_t);
if ((retval = printf_putnchars_utf32(str, bytes, ps)) < 0)
return -counter;
}
counter += retval;
 
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
++counter;
counter++;
}
return counter;
return ((int) counter);
}
 
 
/** Print a number in a given base.
*
* Print significant digits of a number in given base.
*
* @param num Number to print.
* @param widt Width modifier.h
* @param width Width modifier.
* @param precision Precision modifier.
* @param base Base to print the number in (must be between 2 and 16).
* @param flags Flags that modify the way the number is printed.
231,22 → 340,23
*
*/
static int print_number(uint64_t num, int width, int precision, int base,
uint64_t flags, struct printf_spec *ps)
uint32_t flags, printf_spec_t *ps)
{
char *digits = digits_small;
char d[PRINT_NUMBER_BUFFER_SIZE];
char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
int size = 0; /* size of number with all prefixes and signs */
int number_size; /* size of plain number */
char sgn;
int retval;
int counter = 0;
char *digits;
if (flags & __PRINTF_FLAG_BIGCHARS)
digits = digits_big;
else
digits = digits_small;
*ptr-- = 0; /* Put zero at end of string */
char data[PRINT_NUMBER_BUFFER_SIZE];
char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1];
 
/* Size of number with all prefixes and signs */
int size = 0;
/* Put zero at end of string */
*ptr-- = 0;
if (num == 0) {
*ptr-- = '0';
size++;
257,15 → 367,17
} while (num /= base);
}
number_size = size;
/* Size of plain number */
int number_size = size;
 
/*
* Collect the sum of all prefixes/signs/... to calculate padding and
* Collect the sum of all prefixes/signs/etc. to calculate padding and
* leading zeroes.
*/
if (flags & __PRINTF_FLAG_PREFIX) {
switch(base) {
case 2: /* Binary formating is not standard, but usefull */
case 2:
/* Binary formating is not standard, but usefull */
size += 2;
break;
case 8:
277,7 → 389,7
}
}
 
sgn = 0;
char sgn = 0;
if (flags & __PRINTF_FLAG_SIGNED) {
if (flags & __PRINTF_FLAG_NEGATIVE) {
sgn = '-';
291,27 → 403,26
}
}
 
if (flags & __PRINTF_FLAG_LEFTALIGNED) {
if (flags & __PRINTF_FLAG_LEFTALIGNED)
flags &= ~__PRINTF_FLAG_ZEROPADDED;
}
 
/*
* If the number is leftaligned or precision is specified then
* zeropadding is ignored.
* If the number is left-aligned or precision is specified then
* padding with zeros is ignored.
*/
if (flags & __PRINTF_FLAG_ZEROPADDED) {
if ((precision == 0) && (width > size)) {
if ((precision == 0) && (width > size))
precision = width - size + number_size;
}
}
 
/* print leading spaces */
/* Print leading spaces */
if (number_size > precision) {
/* print the whole number not only a part */
/* Print the whole number, not only a part */
precision = number_size;
}
 
width -= precision + size - number_size;
count_t counter = 0;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
while (width-- > 0) {
320,18 → 431,17
}
}
/* print sign */
/* Print sign */
if (sgn) {
if (printf_putchar(sgn, ps) == 1)
counter++;
}
/* print prefix */
/* Print prefix */
if (flags & __PRINTF_FLAG_PREFIX) {
switch(base) {
case 2: /* Binary formating is not standard, but usefull */
case 2:
/* Binary formating is not standard, but usefull */
if (printf_putchar('0', ps) == 1)
counter++;
if (flags & __PRINTF_FLAG_BIGCHARS) {
360,7 → 470,7
}
}
 
/* print leading zeroes */
/* Print leading zeroes */
precision -= number_size;
while (precision-- > 0) {
if (printf_putchar('0', ps) == 1)
367,14 → 477,12
counter++;
}
 
/* print number itself */
 
if ((retval = printf_putstr(++ptr, ps)) > 0) {
/* Print the number itself */
int retval;
if ((retval = printf_putstr(++ptr, ps)) > 0)
counter += retval;
}
/* print ending spaces */
/* Print tailing spaces */
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
381,10 → 489,9
counter++;
}
 
return counter;
return ((int) counter);
}
 
 
/** Print formatted string.
*
* Print string formatted according to the fmt parameter and variadic arguments.
430,16 → 537,24
* - "h" Signed or unsigned short.@n
* - "" Signed or unsigned int (default value).@n
* - "l" Signed or unsigned long int.@n
* If conversion is "c", the character is wchar_t (UTF-32).@n
* If conversion is "s", the string is wchar_t * (UTF-32).@n
* - "ll" Signed or unsigned long long int.@n
*
*
* CONVERSION:@n
* - % Print percentile character itself.
*
* - c Print single character.
* - c Print single character. The character is expected to be plain
* ASCII (e.g. only values 0 .. 127 are valid).@n
* If type is "l", then the character is expected to be UTF-32
* (e.g. values 0 .. 0x10ffff are valid).
*
* - s Print zero terminated string. If a NULL value is passed as
* value, "(NULL)" is printed instead.
* value, "(NULL)" is printed instead.@n
* The string is expected to be correctly encoded UTF-8 (or plain
* ASCII, which is a subset of UTF-8).@n
* If type is "l", then the string is expected to be correctly
* encoded UTF-32.
*
* - P, p Print value of a pointer. Void * value is expected and it is
* printed in hexadecimal notation with prefix (as with \%#X / \%#x
462,33 → 577,27
* All other characters from fmt except the formatting directives are printed in
* verbatim.
*
* @param fmt Formatting NULL terminated string.
* @return Number of characters printed, negative value on failure.
* @param fmt Formatting NULL terminated string (UTF-8 or plain ASCII).
*
* @return Number of UTF-8 characters printed, negative value on failure.
*
*/
int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
{
int i = 0; /* index of the currently processed char from fmt */
int j = 0; /* index to the first not printed nonformating character */
int end;
int counter; /* counter of printed characters */
int retval; /* used to store return values from called functions */
char c;
qualifier_t qualifier; /* type of argument */
int base; /* base in which a numeric parameter will be printed */
uint64_t number; /* argument value */
size_t size; /* byte size of integer parameter */
int width, precision;
uint64_t flags;
index_t i = 0; /* Index of the currently processed character from fmt */
index_t j = 0; /* Index to the first not printed nonformating character */
counter = 0;
wchar_t uc; /* Current UTF-32 character decoded from fmt */
count_t counter = 0; /* Number of UTF-8 characters printed */
int retval; /* Return values from nested functions */
while ((c = fmt[i])) {
/* control character */
if (c == '%') {
/* print common characters if any processed */
while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) {
/* Control character */
if (uc == '%') {
/* Print common characters if any processed */
if (i > j) {
if ((retval = printf_putnchars(&fmt[j],
(size_t)(i - j), ps)) < 0) { /* error */
if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) {
/* Error */
counter = -counter;
goto out;
}
496,13 → 605,14
}
j = i;
/* parse modifiers */
flags = 0;
end = 0;
/* Parse modifiers */
uint32_t flags = 0;
bool end = false;
do {
++i;
switch (c = fmt[i]) {
i++;
switch ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) {
case '#':
flags |= __PRINTF_FLAG_PREFIX;
break;
519,96 → 629,118
flags |= __PRINTF_FLAG_ZEROPADDED;
break;
default:
end = 1;
end = true;
};
} while (!end);
} while (end == 0);
/* Width & '*' operator */
int width = 0;
if (isdigit(uc)) {
while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) {
if (!isdigit(uc))
break;
/* width & '*' operator */
width = 0;
if (isdigit(fmt[i])) {
while (isdigit(fmt[i])) {
width *= 10;
width += fmt[i++] - '0';
width += uc - '0';
i++;
}
} else if (fmt[i] == '*') {
/* get width value from argument list */
} else if (uc == '*') {
/* Get width value from argument list */
i++;
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
width = (int) va_arg(ap, int);
if (width < 0) {
/* negative width sets '-' flag */
/* Negative width sets '-' flag */
width *= -1;
flags |= __PRINTF_FLAG_LEFTALIGNED;
}
}
/* precision and '*' operator */
precision = 0;
if (fmt[i] == '.') {
++i;
if (isdigit(fmt[i])) {
while (isdigit(fmt[i])) {
/* Precision and '*' operator */
int precision = 0;
if (uc == '.') {
i++;
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
if (isdigit(uc)) {
while ((uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT)) != 0) {
if (!isdigit(uc))
break;
precision *= 10;
precision += fmt[i++] - '0';
precision += uc - '0';
i++;
}
} else if (fmt[i] == '*') {
/*
* Get precision value from the argument
* list.
*/
/* Get precision value from the argument list */
i++;
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
precision = (int) va_arg(ap, int);
if (precision < 0) {
/* ignore negative precision */
/* Ignore negative precision */
precision = 0;
}
}
}
 
switch (fmt[i++]) {
/** @todo unimplemented qualifiers:
qualifier_t qualifier;
switch (uc) {
/** @todo Unimplemented qualifiers:
* t ptrdiff_t - ISO C 99
*/
case 'h': /* char or short */
case 'h':
/* Char or short */
qualifier = PrintfQualifierShort;
if (fmt[i] == 'h') {
i++;
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
if (uc == 'h') {
i++;
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
qualifier = PrintfQualifierByte;
}
break;
case 'l': /* long or long long*/
case 'l':
/* Long or long long */
qualifier = PrintfQualifierLong;
if (fmt[i] == 'l') {
i++;
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
if (uc == 'l') {
i++;
uc = utf8_decode(fmt, &i, UTF8_NO_LIMIT);
qualifier = PrintfQualifierLongLong;
}
break;
default:
/* default type */
/* Default type */
qualifier = PrintfQualifierInt;
--i;
}
base = 10;
unsigned int base = 10;
 
switch (c = fmt[i]) {
 
switch (uc) {
/*
* String and character conversions.
*/
case 's':
if ((retval = print_string(va_arg(ap, char *),
width, precision, flags, ps)) < 0) {
if (qualifier == PrintfQualifierLong)
retval = print_utf32(va_arg(ap, wchar_t *), width, precision, flags, ps);
else
retval = print_utf8(va_arg(ap, char *), width, precision, flags, ps);
if (retval < 0) {
counter = -counter;
goto out;
};
}
 
counter += retval;
j = i + 1;
goto next_char;
case 'c':
c = va_arg(ap, unsigned int);
retval = print_char(c, width, flags, ps);
if (qualifier == PrintfQualifierLong)
retval = print_wchar(va_arg(ap, wchar_t), width, flags, ps);
else
retval = print_char(va_arg(ap, unsigned int), width, flags, ps);
if (retval < 0) {
counter = -counter;
goto out;
621,7 → 753,8
/*
* Integer values
*/
case 'P': /* pointer */
case 'P':
/* Pointer */
flags |= __PRINTF_FLAG_BIGCHARS;
case 'p':
flags |= __PRINTF_FLAG_PREFIX;
644,10 → 777,12
case 'x':
base = 16;
break;
/* percentile itself */
/* Percentile itself */
case '%':
j = i;
goto next_char;
/*
* Bad formatting.
*/
659,9 → 794,9
goto next_char;
}
/* Print integers */
/* print number */
size_t size;
uint64_t number;
switch (qualifier) {
case PrintfQualifierByte:
size = sizeof(unsigned char);
687,7 → 822,8
size = sizeof(void *);
number = (uint64_t) (unsigned long) va_arg(ap, void *);
break;
default: /* Unknown qualifier */
default:
/* Unknown qualifier */
counter = -counter;
goto out;
}
719,21 → 855,20
}
next_char:
++i;
i++;
}
if (i > j) {
if ((retval = printf_putnchars(&fmt[j], (unative_t) (i - j),
ps)) < 0) { /* error */
if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) {
/* Error */
counter = -counter;
goto out;
}
counter += retval;
}
 
out:
return counter;
return ((int) counter);
}
 
/** @}