Changes in / [c7c6afd:240b2e4] in mainline
- Files:
-
- 8 added
- 2 deleted
- 20 edited
-
boot/arch/arm32/meson.build (modified) (1 diff)
-
boot/arch/arm64/meson.build (modified) (2 diffs)
-
boot/arch/ia64/meson.build (modified) (1 diff)
-
boot/arch/mips32/meson.build (modified) (1 diff)
-
boot/arch/ppc32/meson.build (modified) (1 diff)
-
boot/arch/riscv64/meson.build (modified) (1 diff)
-
boot/arch/sparc64/meson.build (modified) (1 diff)
-
boot/generic/include/macros.h (modified) (1 diff)
-
boot/generic/include/printf_core.h (added)
-
boot/generic/include/uchar.h (added)
-
boot/generic/src/printf_core.c (added)
-
boot/generic/src/vprintf.c (modified) (2 diffs)
-
common/include/printf_core.h (modified) (1 diff)
-
common/printf/printf_core.c (modified) (38 diffs)
-
common/stdc/snprintf.c (deleted)
-
common/stdc/vsnprintf.c (deleted)
-
kernel/generic/include/printf/printf_core.h (added)
-
kernel/generic/meson.build (modified) (2 diffs)
-
kernel/generic/src/log/log.c (modified) (3 diffs)
-
kernel/generic/src/printf/snprintf.c (added)
-
kernel/generic/src/printf/vprintf.c (modified) (3 diffs)
-
kernel/generic/src/printf/vsnprintf.c (added)
-
uspace/lib/c/generic/io/asprintf.c (modified) (2 diffs)
-
uspace/lib/c/generic/io/kio.c (modified) (2 diffs)
-
uspace/lib/c/generic/io/snprintf.c (added)
-
uspace/lib/c/generic/io/vprintf.c (modified) (2 diffs)
-
uspace/lib/c/generic/io/vsnprintf.c (added)
-
uspace/lib/c/include/stdio.h (modified) (1 diff)
-
uspace/lib/c/meson.build (modified) (2 diffs)
-
uspace/lib/posix/src/stdio.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
boot/arch/arm32/meson.build
rc7c6afd r240b2e4 66 66 'src/putchar.c', 67 67 '../../../common/stdc/mem.c', 68 '../../../common/printf/printf_core.c',69 68 '../../genarch/src/division.c', 69 '../../generic/src/printf_core.c', 70 70 '../../generic/src/vprintf.c', 71 71 '../../generic/src/printf.c', -
boot/arch/arm64/meson.build
rc7c6afd r240b2e4 49 49 'src/relocate.c', 50 50 '../../../common/stdc/mem.c', 51 '../../../common/printf/printf_core.c',52 51 '../../genarch/src/efi.c', 53 52 '../../generic/src/gzip.c', … … 56 55 '../../generic/src/payload.c', 57 56 '../../generic/src/printf.c', 57 '../../generic/src/printf_core.c', 58 58 '../../../common/str.c', 59 59 '../../generic/src/tar.c', -
boot/arch/ia64/meson.build
rc7c6afd r240b2e4 45 45 '../../genarch/src/division.c', 46 46 '../../generic/src/balloc.c', 47 '../../ ../common/printf/printf_core.c',47 '../../generic/src/printf_core.c', 48 48 '../../generic/src/vprintf.c', 49 49 '../../generic/src/printf.c', -
boot/arch/mips32/meson.build
rc7c6afd r240b2e4 45 45 '../../genarch/src/division.c', 46 46 '../../genarch/src/multiplication.c', 47 '../../ ../common/printf/printf_core.c',47 '../../generic/src/printf_core.c', 48 48 '../../generic/src/vprintf.c', 49 49 '../../generic/src/printf.c', -
boot/arch/ppc32/meson.build
rc7c6afd r240b2e4 43 43 '../../genarch/src/multiplication.c', 44 44 '../../generic/src/balloc.c', 45 '../../ ../common/printf/printf_core.c',45 '../../generic/src/printf_core.c', 46 46 '../../generic/src/vprintf.c', 47 47 '../../generic/src/printf.c', -
boot/arch/riscv64/meson.build
rc7c6afd r240b2e4 39 39 40 40 '../../../common/stdc/mem.c', 41 '../../ ../common/printf/printf_core.c',41 '../../generic/src/printf_core.c', 42 42 '../../generic/src/vprintf.c', 43 43 '../../generic/src/printf.c', -
boot/arch/sparc64/meson.build
rc7c6afd r240b2e4 41 41 '../../genarch/src/ofw_tree.c', 42 42 '../../generic/src/balloc.c', 43 '../../ ../common/printf/printf_core.c',43 '../../generic/src/printf_core.c', 44 44 '../../generic/src/vprintf.c', 45 45 '../../generic/src/printf.c', -
boot/generic/include/macros.h
rc7c6afd r240b2e4 34 34 35 35 #define min(a, b) ((a) < (b) ? (a) : (b)) 36 #define max(a, b) ((a) > (b) ? (a) : (b))37 36 38 37 #define isdigit(d) (((d) >= '0') && ((d) <= '9')) -
boot/generic/src/vprintf.c
rc7c6afd r240b2e4 36 36 #include <str.h> 37 37 38 static errno_t vprintf_str_write(const char *str, size_t size, void *data)38 static int vprintf_str_write(const char *str, size_t size, void *data) 39 39 { 40 40 size_t offset = 0; 41 size_t chars = 0; 41 42 42 while (offset < size) 43 while (offset < size) { 43 44 putuchar(str_decode(str, &offset, size)); 45 chars++; 46 } 44 47 45 return EOK;48 return chars; 46 49 } 47 50 … … 68 71 }; 69 72 70 return printf_core(fmt, &ps, ap); 73 int ret = printf_core(fmt, &ps, ap); 74 75 return ret; 71 76 } 72 77 -
common/include/printf_core.h
rc7c6afd r240b2e4 36 36 #define _LIBC_PRINTF_CORE_H_ 37 37 38 #include < errno.h>38 #include <stddef.h> 39 39 #include <stdarg.h> 40 #include <stddef.h>41 40 #include <uchar.h> 42 41 43 42 /** Structure for specifying output methods for different printf clones. */ 44 43 typedef struct { 45 /* 46 * String output function, returns EOK on success. 47 * Only returns an error when an irrecoverable failure occurs and 48 * the string cannot be fully output. 49 */ 50 errno_t (*write)(const char *, size_t, void *); 44 /* String output function, returns number of printed characters or EOF */ 45 int (*str_write)(const char *, size_t, void *); 46 47 /* Wide string output function, returns number of printed characters or EOF */ 48 int (*wstr_write)(const char32_t *, size_t, void *); 51 49 52 50 /* User data - output stream specification, state, locks, etc. */ -
common/printf/printf_core.c
rc7c6afd r240b2e4 3 3 * Copyright (c) 2006 Josef Cejka 4 4 * Copyright (c) 2009 Martin Decky 5 * Copyright (c) 2025 Jiří Zárevúcky6 5 * All rights reserved. 7 6 * … … 38 37 */ 39 38 40 #include <_bits/uchar.h> 41 #include <_bits/wint_t.h> 39 #include <stdio.h> 40 #include <stddef.h> 41 #include <stdlib.h> 42 #include <printf_core.h> 43 #include <ctype.h> 44 #include <str.h> 42 45 #include <assert.h> 43 #include <ctype.h>44 #include <errno.h>45 #include <limits.h>46 46 #include <macros.h> 47 #include <printf_core.h> 48 #include <stddef.h> 49 #include <stdint.h> 50 #include <stdlib.h> 51 #include <str.h> 47 #include <uchar.h> 52 48 53 49 /* Disable float support in kernel, because we usually disable floating operations there. */ … … 92 88 93 89 /** 94 * Buffer big enough for 64-bit number printed in base 2. 95 */ 96 #define PRINT_NUMBER_BUFFER_SIZE 64 90 * Buffer big enough for 64-bit number printed in base 2, sign, prefix and 0 91 * to terminate string... (last one is only for better testing end of buffer by 92 * zero-filling subroutine) 93 */ 94 #define PRINT_NUMBER_BUFFER_SIZE (64 + 5) 97 95 98 96 /** Get signed or unsigned integer argument */ … … 124 122 PrintfQualifierLongLong, 125 123 PrintfQualifierPointer, 124 PrintfQualifierSize, 125 PrintfQualifierMax 126 126 } qualifier_t; 127 127 128 static const char _digits_small[] = "0123456789abcdef"; 129 static const char _digits_big[] = "0123456789ABCDEF"; 130 131 static const char _nullstr[] = "(NULL)"; 132 static const char _replacement[] = u8"�"; 133 static const char _spaces[] = " "; 134 static const char _zeros[] = "000000000000000000000000000000000000000000000000"; 135 136 static void _set_errno(errno_t rc) 137 { 138 #ifdef errno 139 errno = rc; 140 #endif 141 } 142 143 static size_t _utf8_bytes(char32_t c) 144 { 145 if (c < 0x80) 146 return 1; 147 148 if (c < 0x800) 149 return 2; 150 151 if (c < 0xD800) 152 return 3; 153 154 /* Surrogate code points, invalid in UTF-32. */ 155 if (c < 0xE000) 156 return sizeof(_replacement) - 1; 157 158 if (c < 0x10000) 159 return 3; 160 161 if (c < 0x110000) 162 return 4; 163 164 /* Invalid character. */ 165 return sizeof(_replacement) - 1; 166 } 167 168 /** Counts characters and utf8 bytes in a wide string up to a byte limit. 169 * @param max_bytes Byte length limit for string's utf8 conversion. 170 * @param[out] len The number of wide characters 171 * @return Number of utf8 bytes that the first *len characters in the string 172 * will convert to. Will always be less than max_bytes. 173 */ 174 static size_t _utf8_wstr_bytes_len(char32_t *s, size_t max_bytes, size_t *len) 175 { 176 size_t bytes = 0; 177 size_t i; 178 179 for (i = 0; bytes < max_bytes && s[i]; i++) { 180 size_t next = _utf8_bytes(s[i]); 181 if (max_bytes - bytes < next) 182 break; 183 184 bytes += next; 185 } 186 187 *len = i; 188 return bytes; 189 } 190 191 #define TRY(expr) ({ errno_t rc = (expr); if (rc != EOK) return rc; }) 192 193 static inline void _saturating_add(size_t *a, size_t b) 194 { 195 size_t s = *a + b; 196 /* Only works because size_t is unsigned. */ 197 *a = (s < b) ? SIZE_MAX : s; 198 } 199 200 static errno_t _write_bytes(const char *buf, size_t n, printf_spec_t *ps, 201 size_t *written_bytes) 202 { 203 errno_t rc = ps->write(buf, n, ps->data); 204 if (rc != EOK) 205 return rc; 206 207 _saturating_add(written_bytes, n); 208 return EOK; 209 } 210 211 /** Write one UTF-32 character. */ 212 static errno_t _write_uchar(char32_t ch, printf_spec_t *ps, 213 size_t *written_bytes) 214 { 215 char utf8[4]; 216 size_t offset = 0; 217 218 if (chr_encode(ch, utf8, &offset, sizeof(utf8)) == EOK) 219 return _write_bytes(utf8, offset, ps, written_bytes); 220 221 /* Invalid character. */ 222 return _write_bytes(_replacement, sizeof(_replacement) - 1, ps, written_bytes); 223 } 224 225 /** Write n UTF-32 characters. */ 226 static errno_t _write_chars(const char32_t *buf, size_t n, printf_spec_t *ps, 227 size_t *written_bytes) 228 { 229 for (size_t i = 0; i < n; i++) 230 TRY(_write_uchar(buf[i], ps, written_bytes)); 231 232 return EOK; 233 } 234 235 static errno_t _write_char(char c, printf_spec_t *ps, size_t *written_bytes) 236 { 237 return _write_bytes(&c, 1, ps, written_bytes); 238 } 239 240 static errno_t _write_spaces(size_t n, printf_spec_t *ps, size_t *written_bytes) 241 { 242 size_t max_spaces = sizeof(_spaces) - 1; 243 244 while (n > max_spaces) { 245 TRY(_write_bytes(_spaces, max_spaces, ps, written_bytes)); 246 n -= max_spaces; 247 } 248 249 return _write_bytes(_spaces, n, ps, written_bytes); 250 } 251 252 static errno_t _write_zeros(size_t n, printf_spec_t *ps, size_t *written_bytes) 253 { 254 size_t max_zeros = sizeof(_zeros) - 1; 255 256 while (n > max_zeros) { 257 TRY(_write_bytes(_zeros, max_zeros, ps, written_bytes)); 258 n -= max_zeros; 259 } 260 261 return _write_bytes(_zeros, n, ps, written_bytes); 128 static const char *nullstr = "(NULL)"; 129 static const char *digits_small = "0123456789abcdef"; 130 static const char *digits_big = "0123456789ABCDEF"; 131 static const char invalch = U_SPECIAL; 132 133 /** Print one or more characters without adding newline. 134 * 135 * @param buf Buffer holding characters with size of 136 * at least size bytes. NULL is not allowed! 137 * @param size Size of the buffer in bytes. 138 * @param ps Output method and its data. 139 * 140 * @return Number of characters printed. 141 * 142 */ 143 static int printf_putnchars(const char *buf, size_t size, 144 printf_spec_t *ps) 145 { 146 return ps->str_write((void *) buf, size, ps->data); 147 } 148 149 /** Print one or more wide characters without adding newline. 150 * 151 * @param buf Buffer holding wide characters with size of 152 * at least size bytes. NULL is not allowed! 153 * @param size Size of the buffer in bytes. 154 * @param ps Output method and its data. 155 * 156 * @return Number of wide characters printed. 157 * 158 */ 159 static int printf_wputnchars(const char32_t *buf, size_t size, 160 printf_spec_t *ps) 161 { 162 return ps->wstr_write((void *) buf, size, ps->data); 163 } 164 165 /** Print string without adding a newline. 166 * 167 * @param str String to print. 168 * @param ps Write function specification and support data. 169 * 170 * @return Number of characters printed. 171 * 172 */ 173 static int printf_putstr(const char *str, printf_spec_t *ps) 174 { 175 if (str == NULL) 176 return printf_putnchars(nullstr, str_size(nullstr), ps); 177 178 return ps->str_write((void *) str, str_size(str), ps->data); 179 } 180 181 /** Print one ASCII character. 182 * 183 * @param c ASCII character to be printed. 184 * @param ps Output method. 185 * 186 * @return Number of characters printed. 187 * 188 */ 189 static int printf_putchar(const char ch, printf_spec_t *ps) 190 { 191 if (!ascii_check(ch)) 192 return ps->str_write((void *) &invalch, 1, ps->data); 193 194 return ps->str_write(&ch, 1, ps->data); 195 } 196 197 /** Print one wide character. 198 * 199 * @param c Wide character to be printed. 200 * @param ps Output method. 201 * 202 * @return Number of characters printed. 203 * 204 */ 205 static int printf_putuchar(const char32_t ch, printf_spec_t *ps) 206 { 207 if (!chr_check(ch)) 208 return ps->str_write((void *) &invalch, 1, ps->data); 209 210 return ps->wstr_write(&ch, sizeof(char32_t), ps->data); 262 211 } 263 212 … … 267 216 * @param width Width modifier. 268 217 * @param flags Flags that change the way the character is printed. 269 */ 270 static errno_t _format_char(const char c, size_t width, uint32_t flags, 271 printf_spec_t *ps, size_t *written_bytes) 272 { 273 size_t bytes = 1; 274 275 if (width <= bytes) 276 return _write_char(c, ps, written_bytes); 277 278 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 279 TRY(_write_char(c, ps, written_bytes)); 280 TRY(_write_spaces(width - bytes, ps, written_bytes)); 281 } else { 282 TRY(_write_spaces(width - bytes, ps, written_bytes)); 283 TRY(_write_char(c, ps, written_bytes)); 284 } 285 286 return EOK; 218 * 219 * @return Number of characters printed, negative value on failure. 220 * 221 */ 222 static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps) 223 { 224 size_t counter = 0; 225 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 226 while (--width > 0) { 227 /* 228 * One space is consumed by the character itself, hence 229 * the predecrement. 230 */ 231 if (printf_putchar(' ', ps) > 0) 232 counter++; 233 } 234 } 235 236 if (printf_putchar(ch, ps) > 0) 237 counter++; 238 239 while (--width > 0) { 240 /* 241 * One space is consumed by the character itself, hence 242 * the predecrement. 243 */ 244 if (printf_putchar(' ', ps) > 0) 245 counter++; 246 } 247 248 return (int) (counter); 287 249 } 288 250 … … 292 254 * @param width Width modifier. 293 255 * @param flags Flags that change the way the character is printed. 294 */ 295 static errno_t _format_uchar(const char32_t ch, size_t width, uint32_t flags, 296 printf_spec_t *ps, size_t *written_bytes) 297 { 298 /* 299 * All widths in printf() are specified in bytes. It might seem nonsensical 300 * with unicode text, but that's the way the function is defined. The width 301 * is barely useful if you want column alignment in terminal, but keep in 302 * mind that counting code points is only marginally better for that. 303 * Characters can span more than one unicode code point, even in languages 304 * based on latin alphabet, and a single unicode code point can occupy two 305 * spaces in east asian scripts. 306 * 307 * What the width can actually be useful for is padding, when you need the 308 * output to fill an exact number of bytes in a file. That use would break 309 * if we did our own thing here. 310 */ 311 312 size_t bytes = _utf8_bytes(ch); 313 314 if (width <= bytes) 315 return _write_uchar(ch, ps, written_bytes); 316 317 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 318 TRY(_write_uchar(ch, ps, written_bytes)); 319 TRY(_write_spaces(width - bytes, ps, written_bytes)); 320 } else { 321 TRY(_write_spaces(width - bytes, ps, written_bytes)); 322 TRY(_write_uchar(ch, ps, written_bytes)); 323 } 324 325 return EOK; 256 * 257 * @return Number of characters printed, negative value on failure. 258 * 259 */ 260 static int print_wchar(const char32_t ch, int width, uint32_t flags, printf_spec_t *ps) 261 { 262 size_t counter = 0; 263 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 264 while (--width > 0) { 265 /* 266 * One space is consumed by the character itself, hence 267 * the predecrement. 268 */ 269 if (printf_putchar(' ', ps) > 0) 270 counter++; 271 } 272 } 273 274 if (printf_putuchar(ch, ps) > 0) 275 counter++; 276 277 while (--width > 0) { 278 /* 279 * One space is consumed by the character itself, hence 280 * the predecrement. 281 */ 282 if (printf_putchar(' ', ps) > 0) 283 counter++; 284 } 285 286 return (int) (counter); 326 287 } 327 288 … … 332 293 * @param precision Precision modifier. 333 294 * @param flags Flags that modify the way the string is printed. 334 */ 335 static errno_t _format_cstr(const char *str, size_t width, int precision, 336 uint32_t flags, printf_spec_t *ps, size_t *written_bytes) 295 * 296 * @return Number of characters printed, negative value on failure. 297 */ 298 static int print_str(char *str, int width, unsigned int precision, 299 uint32_t flags, printf_spec_t *ps) 337 300 { 338 301 if (str == NULL) 339 str = _nullstr; 340 341 /* Negative precision == unspecified. */ 342 size_t max_bytes = (precision < 0) ? SIZE_MAX : (size_t) precision; 343 size_t bytes = str_nsize(str, max_bytes); 344 345 if (width <= bytes) 346 return _write_bytes(str, bytes, ps, written_bytes); 347 348 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 349 TRY(_write_bytes(str, bytes, ps, written_bytes)); 350 TRY(_write_spaces(width - bytes, ps, written_bytes)); 351 } else { 352 TRY(_write_spaces(width - bytes, ps, written_bytes)); 353 TRY(_write_bytes(str, bytes, ps, written_bytes)); 354 } 355 356 return EOK; 302 return printf_putstr(nullstr, ps); 303 304 size_t strw = str_length(str); 305 306 /* Precision unspecified - print everything. */ 307 if ((precision == 0) || (precision > strw)) 308 precision = strw; 309 310 /* Left padding */ 311 size_t counter = 0; 312 width -= precision; 313 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 314 while (width-- > 0) { 315 if (printf_putchar(' ', ps) == 1) 316 counter++; 317 } 318 } 319 320 /* Part of @a str fitting into the alloted space. */ 321 int retval; 322 size_t size = str_lsize(str, precision); 323 if ((retval = printf_putnchars(str, size, ps)) < 0) 324 return -counter; 325 326 counter += retval; 327 328 /* Right padding */ 329 while (width-- > 0) { 330 if (printf_putchar(' ', ps) == 1) 331 counter++; 332 } 333 334 return ((int) counter); 335 357 336 } 358 337 … … 363 342 * @param precision Precision modifier. 364 343 * @param flags Flags that modify the way the string is printed. 365 */ 366 static errno_t _format_wstr(char32_t *str, size_t width, int precision, 367 uint32_t flags, printf_spec_t *ps, size_t *written_bytes) 368 { 369 if (!str) 370 return _format_cstr(_nullstr, width, precision, flags, ps, written_bytes); 371 372 /* Width and precision are always byte-based. See _format_uchar() */ 373 /* Negative precision == unspecified. */ 374 size_t max_bytes = (precision < 0) ? SIZE_MAX : (size_t) precision; 375 376 size_t len; 377 size_t bytes = _utf8_wstr_bytes_len(str, max_bytes, &len); 378 379 if (width <= bytes) 380 return _write_chars(str, len, ps, written_bytes); 381 382 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 383 TRY(_write_chars(str, len, ps, written_bytes)); 384 TRY(_write_spaces(width - bytes, ps, written_bytes)); 385 } else { 386 TRY(_write_spaces(width - bytes, ps, written_bytes)); 387 TRY(_write_chars(str, len, ps, written_bytes)); 388 } 389 390 return EOK; 391 } 392 393 static char _sign(uint32_t flags) 394 { 395 if (!(flags & __PRINTF_FLAG_SIGNED)) 396 return 0; 397 398 if (flags & __PRINTF_FLAG_NEGATIVE) 399 return '-'; 400 401 if (flags & __PRINTF_FLAG_SHOWPLUS) 402 return '+'; 403 404 if (flags & __PRINTF_FLAG_SPACESIGN) 405 return ' '; 406 407 return 0; 344 * 345 * @return Number of wide characters printed, negative value on failure. 346 */ 347 static int print_wstr(char32_t *str, int width, unsigned int precision, 348 uint32_t flags, printf_spec_t *ps) 349 { 350 if (str == NULL) 351 return printf_putstr(nullstr, ps); 352 353 size_t strw = wstr_length(str); 354 355 /* Precision not specified - print everything. */ 356 if ((precision == 0) || (precision > strw)) 357 precision = strw; 358 359 /* Left padding */ 360 size_t counter = 0; 361 width -= precision; 362 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 363 while (width-- > 0) { 364 if (printf_putchar(' ', ps) == 1) 365 counter++; 366 } 367 } 368 369 /* Part of @a wstr fitting into the alloted space. */ 370 int retval; 371 size_t size = wstr_lsize(str, precision); 372 if ((retval = printf_wputnchars(str, size, ps)) < 0) 373 return -counter; 374 375 counter += retval; 376 377 /* Right padding */ 378 while (width-- > 0) { 379 if (printf_putchar(' ', ps) == 1) 380 counter++; 381 } 382 383 return ((int) counter); 408 384 } 409 385 … … 417 393 * @param base Base to print the number in (must be between 2 and 16). 418 394 * @param flags Flags that modify the way the number is printed. 419 */ 420 static errno_t _format_number(uint64_t num, size_t width, int precision, int base, 421 uint32_t flags, printf_spec_t *ps, size_t *written_bytes) 422 { 423 assert(base >= 2 && base <= 16); 424 425 /* Default precision for numeric output is 1. */ 426 size_t min_digits = (precision < 0) ? 1 : precision; 427 428 bool bigchars = flags & __PRINTF_FLAG_BIGCHARS; 429 bool prefix = flags & __PRINTF_FLAG_PREFIX; 430 bool left_aligned = flags & __PRINTF_FLAG_LEFTALIGNED; 431 bool zero_padded = flags & __PRINTF_FLAG_ZEROPADDED; 432 433 const char *digits = bigchars ? _digits_big : _digits_small; 434 435 char buffer[PRINT_NUMBER_BUFFER_SIZE]; 436 char *end = &buffer[PRINT_NUMBER_BUFFER_SIZE]; 437 438 /* Write number to the buffer. */ 439 int offset = 0; 440 while (num > 0) { 441 end[--offset] = digits[num % base]; 442 num /= base; 443 } 444 445 char *number = &end[offset]; 446 size_t number_len = end - number; 447 char sign = _sign(flags); 448 449 if (left_aligned) { 450 /* Space padded right-aligned. */ 451 size_t real_size = max(number_len, min_digits); 452 453 if (sign) { 454 TRY(_write_char(sign, ps, written_bytes)); 455 real_size++; 456 } 457 458 if (prefix && base == 2 && number_len > 0) { 459 TRY(_write_bytes(bigchars ? "0B" : "0b", 2, ps, written_bytes)); 460 real_size += 2; 461 } 462 463 if (prefix && base == 16 && number_len > 0) { 464 TRY(_write_bytes(bigchars ? "0X" : "0x", 2, ps, written_bytes)); 465 real_size += 2; 466 } 467 468 if (min_digits > number_len) { 469 TRY(_write_zeros(min_digits - number_len, ps, written_bytes)); 470 } else if (prefix && base == 8) { 471 TRY(_write_zeros(1, ps, written_bytes)); 472 real_size++; 473 } 474 475 TRY(_write_bytes(number, number_len, ps, written_bytes)); 476 477 if (width > real_size) 478 TRY(_write_spaces(width - real_size, ps, written_bytes)); 479 480 return EOK; 481 } 482 483 /* Zero padded number (ignored when left aligned or if precision is specified). */ 484 if (precision < 0 && zero_padded) { 485 size_t real_size = number_len; 486 487 if (sign) { 488 TRY(_write_char(sign, ps, written_bytes)); 489 real_size++; 490 } 491 492 if (prefix && base == 2 && number_len > 0) { 493 TRY(_write_bytes(bigchars ? "0B" : "0b", 2, ps, written_bytes)); 494 real_size += 2; 495 } 496 497 if (prefix && base == 16 && number_len > 0) { 498 TRY(_write_bytes(bigchars ? "0X" : "0x", 2, ps, written_bytes)); 499 real_size += 2; 500 } 501 502 if (width > real_size) 503 TRY(_write_zeros(width - real_size, ps, written_bytes)); 504 else if (number_len == 0 || (prefix && base == 8)) 505 TRY(_write_char('0', ps, written_bytes)); 506 507 return _write_bytes(number, number_len, ps, written_bytes); 508 } 509 510 /* Space padded right-aligned. */ 511 size_t real_size = max(number_len, min_digits); 512 if (sign) 513 real_size++; 514 515 if (prefix && (base == 2 || base == 16) && number_len > 0) 516 real_size += 2; 517 518 if (prefix && base == 8 && number_len >= min_digits) 519 real_size += 1; 520 521 if (width > real_size) 522 TRY(_write_spaces(width - real_size, ps, written_bytes)); 523 524 if (sign) 525 TRY(_write_char(sign, ps, written_bytes)); 526 527 if (prefix && base == 2 && number_len > 0) 528 TRY(_write_bytes(bigchars ? "0B" : "0b", 2, ps, written_bytes)); 529 530 if (prefix && base == 16 && number_len > 0) 531 TRY(_write_bytes(bigchars ? "0X" : "0x", 2, ps, written_bytes)); 532 533 if (min_digits > number_len) 534 TRY(_write_zeros(min_digits - number_len, ps, written_bytes)); 535 else if (prefix && base == 8) 536 TRY(_write_char('0', ps, written_bytes)); 537 538 return _write_bytes(number, number_len, ps, written_bytes); 395 * 396 * @return Number of characters printed. 397 * 398 */ 399 static int print_number(uint64_t num, int width, int precision, int base, 400 uint32_t flags, printf_spec_t *ps) 401 { 402 /* Precision not specified. */ 403 if (precision < 0) { 404 precision = 0; 405 } 406 407 const char *digits; 408 if (flags & __PRINTF_FLAG_BIGCHARS) 409 digits = digits_big; 410 else 411 digits = digits_small; 412 413 char data[PRINT_NUMBER_BUFFER_SIZE]; 414 char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1]; 415 416 /* Size of number with all prefixes and signs */ 417 int size = 0; 418 419 /* Put zero at end of string */ 420 *ptr-- = 0; 421 422 if (num == 0) { 423 *ptr-- = '0'; 424 size++; 425 } else { 426 do { 427 *ptr-- = digits[num % base]; 428 size++; 429 } while (num /= base); 430 } 431 432 /* Size of plain number */ 433 int number_size = size; 434 435 /* 436 * Collect the sum of all prefixes/signs/etc. to calculate padding and 437 * leading zeroes. 438 */ 439 if (flags & __PRINTF_FLAG_PREFIX) { 440 switch (base) { 441 case 2: 442 /* Binary formating is not standard, but usefull */ 443 size += 2; 444 break; 445 case 8: 446 size++; 447 break; 448 case 16: 449 size += 2; 450 break; 451 } 452 } 453 454 char sgn = 0; 455 if (flags & __PRINTF_FLAG_SIGNED) { 456 if (flags & __PRINTF_FLAG_NEGATIVE) { 457 sgn = '-'; 458 size++; 459 } else if (flags & __PRINTF_FLAG_SHOWPLUS) { 460 sgn = '+'; 461 size++; 462 } else if (flags & __PRINTF_FLAG_SPACESIGN) { 463 sgn = ' '; 464 size++; 465 } 466 } 467 468 if (flags & __PRINTF_FLAG_LEFTALIGNED) 469 flags &= ~__PRINTF_FLAG_ZEROPADDED; 470 471 /* 472 * If the number is left-aligned or precision is specified then 473 * padding with zeros is ignored. 474 */ 475 if (flags & __PRINTF_FLAG_ZEROPADDED) { 476 if ((precision == 0) && (width > size)) 477 precision = width - size + number_size; 478 } 479 480 /* Print leading spaces */ 481 if (number_size > precision) { 482 /* Print the whole number, not only a part */ 483 precision = number_size; 484 } 485 486 width -= precision + size - number_size; 487 size_t counter = 0; 488 489 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 490 while (width-- > 0) { 491 if (printf_putchar(' ', ps) == 1) 492 counter++; 493 } 494 } 495 496 /* Print sign */ 497 if (sgn) { 498 if (printf_putchar(sgn, ps) == 1) 499 counter++; 500 } 501 502 /* Print prefix */ 503 if (flags & __PRINTF_FLAG_PREFIX) { 504 switch (base) { 505 case 2: 506 /* Binary formating is not standard, but useful */ 507 if (printf_putchar('0', ps) == 1) 508 counter++; 509 if (flags & __PRINTF_FLAG_BIGCHARS) { 510 if (printf_putchar('B', ps) == 1) 511 counter++; 512 } else { 513 if (printf_putchar('b', ps) == 1) 514 counter++; 515 } 516 break; 517 case 8: 518 if (printf_putchar('o', ps) == 1) 519 counter++; 520 break; 521 case 16: 522 if (printf_putchar('0', ps) == 1) 523 counter++; 524 if (flags & __PRINTF_FLAG_BIGCHARS) { 525 if (printf_putchar('X', ps) == 1) 526 counter++; 527 } else { 528 if (printf_putchar('x', ps) == 1) 529 counter++; 530 } 531 break; 532 } 533 } 534 535 /* Print leading zeroes */ 536 precision -= number_size; 537 while (precision-- > 0) { 538 if (printf_putchar('0', ps) == 1) 539 counter++; 540 } 541 542 /* Print the number itself */ 543 int retval; 544 if ((retval = printf_putstr(++ptr, ps)) > 0) 545 counter += retval; 546 547 /* Print trailing spaces */ 548 549 while (width-- > 0) { 550 if (printf_putchar(' ', ps) == 1) 551 counter++; 552 } 553 554 return ((int) counter); 539 555 } 540 556 … … 554 570 555 571 /** Returns the sign character or 0 if no sign should be printed. */ 556 static char _get_sign_char(bool negative, uint32_t flags)572 static int get_sign_char(bool negative, uint32_t flags) 557 573 { 558 574 if (negative) { … … 567 583 } 568 584 585 /** Prints count times character ch. */ 586 static int print_padding(char ch, int count, printf_spec_t *ps) 587 { 588 for (int i = 0; i < count; ++i) { 589 if (ps->str_write(&ch, 1, ps->data) < 0) { 590 return -1; 591 } 592 } 593 594 return count; 595 } 596 569 597 /** Prints a special double (ie NaN, infinity) padded to width characters. */ 570 static errno_t _format_special(ieee_double_t val, int width, uint32_t flags,571 printf_spec_t *ps , size_t *written_bytes)598 static int print_special(ieee_double_t val, int width, uint32_t flags, 599 printf_spec_t *ps) 572 600 { 573 601 assert(val.is_special); 574 602 575 char sign = _get_sign_char(val.is_negative, flags);603 char sign = get_sign_char(val.is_negative, flags); 576 604 577 605 const int str_len = 3; … … 586 614 int padding_len = max(0, width - ((sign ? 1 : 0) + str_len)); 587 615 616 int counter = 0; 617 int ret; 618 588 619 /* Leading padding. */ 589 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) 590 TRY(_write_spaces(padding_len, ps, written_bytes)); 591 592 if (sign) 593 TRY(_write_char(sign, ps, written_bytes)); 594 595 TRY(_write_bytes(str, str_len, ps, written_bytes)); 620 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 621 if ((ret = print_padding(' ', padding_len, ps)) < 0) 622 return -1; 623 624 counter += ret; 625 } 626 627 if (sign) { 628 if ((ret = ps->str_write(&sign, 1, ps->data)) < 0) 629 return -1; 630 631 counter += ret; 632 } 633 634 if ((ret = ps->str_write(str, str_len, ps->data)) < 0) 635 return -1; 636 637 counter += ret; 596 638 597 639 /* Trailing padding. */ 598 if (flags & __PRINTF_FLAG_LEFTALIGNED) 599 TRY(_write_spaces(padding_len, ps, written_bytes)); 600 601 return EOK; 640 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 641 if ((ret = print_padding(' ', padding_len, ps)) < 0) 642 return -1; 643 644 counter += ret; 645 } 646 647 return counter; 602 648 } 603 649 604 650 /** Trims trailing zeros but leaves a single "0" intact. */ 605 static void _fp_trim_trailing_zeros(char *buf, int *len, int *dec_exp)651 static void fp_trim_trailing_zeros(char *buf, int *len, int *dec_exp) 606 652 { 607 653 /* Cut the zero off by adjusting the exponent. */ … … 613 659 614 660 /** Textually round up the last digit thereby eliminating it. */ 615 static void _fp_round_up(char *buf, int *len, int *dec_exp)661 static void fp_round_up(char *buf, int *len, int *dec_exp) 616 662 { 617 663 assert(1 <= *len); … … 657 703 * to the %f specifier. 658 704 */ 659 static errno_t _format_double_str_fixed(double_str_t *val_str, int precision, int width,660 uint32_t flags, printf_spec_t *ps , size_t *written_bytes)705 static int print_double_str_fixed(double_str_t *val_str, int precision, int width, 706 uint32_t flags, printf_spec_t *ps) 661 707 { 662 708 int len = val_str->len; … … 671 717 int int_len = max(1, len + dec_exp); 672 718 673 char sign = _get_sign_char(val_str->neg, flags);719 char sign = get_sign_char(val_str->neg, flags); 674 720 675 721 /* Fractional portion lengths. */ … … 680 726 char *buf_frac = buf + len - signif_frac_figs; 681 727 682 if (flags & __PRINTF_FLAG_NOFRACZEROS) 728 if (flags & __PRINTF_FLAG_NOFRACZEROS) { 683 729 trailing_frac_zeros = 0; 730 } 684 731 685 732 int frac_len = leading_frac_zeros + signif_frac_figs + trailing_frac_zeros; … … 691 738 692 739 int padding_len = max(0, width - num_len); 740 int ret = 0; 741 int counter = 0; 693 742 694 743 /* Leading padding and sign. */ 695 744 696 if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) 697 TRY(_write_spaces(padding_len, ps, written_bytes)); 698 699 if (sign) 700 TRY(_write_char(sign, ps, written_bytes)); 701 702 if (flags & __PRINTF_FLAG_ZEROPADDED) 703 TRY(_write_zeros(padding_len, ps, written_bytes)); 745 if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) { 746 if ((ret = print_padding(' ', padding_len, ps)) < 0) 747 return -1; 748 749 counter += ret; 750 } 751 752 if (sign) { 753 if ((ret = ps->str_write(&sign, 1, ps->data)) < 0) 754 return -1; 755 756 counter += ret; 757 } 758 759 if (flags & __PRINTF_FLAG_ZEROPADDED) { 760 if ((ret = print_padding('0', padding_len, ps)) < 0) 761 return -1; 762 763 counter += ret; 764 } 704 765 705 766 /* Print the intergral part of the buffer. */ … … 708 769 709 770 if (0 < buf_int_len) { 710 TRY(_write_bytes(buf, buf_int_len, ps, written_bytes)); 771 if ((ret = ps->str_write(buf, buf_int_len, ps->data)) < 0) 772 return -1; 773 774 counter += ret; 711 775 712 776 /* Print trailing zeros of the integral part of the number. */ 713 TRY(_write_zeros(int_len - buf_int_len, ps, written_bytes)); 777 if ((ret = print_padding('0', int_len - buf_int_len, ps)) < 0) 778 return -1; 714 779 } else { 715 780 /* Single leading integer 0. */ 716 TRY(_write_char('0', ps, written_bytes)); 717 } 781 char ch = '0'; 782 if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 783 return -1; 784 } 785 786 counter += ret; 718 787 719 788 /* Print the decimal point and the fractional part. */ 720 789 if (has_decimal_pt) { 721 TRY(_write_char('.', ps, written_bytes)); 790 char ch = '.'; 791 792 if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 793 return -1; 794 795 counter += ret; 722 796 723 797 /* Print leading zeros of the fractional part of the number. */ 724 TRY(_write_zeros(leading_frac_zeros, ps, written_bytes)); 798 if ((ret = print_padding('0', leading_frac_zeros, ps)) < 0) 799 return -1; 800 801 counter += ret; 725 802 726 803 /* Print significant digits of the fractional part of the number. */ 727 if (0 < signif_frac_figs) 728 TRY(_write_bytes(buf_frac, signif_frac_figs, ps, written_bytes)); 804 if (0 < signif_frac_figs) { 805 if ((ret = ps->str_write(buf_frac, signif_frac_figs, ps->data)) < 0) 806 return -1; 807 808 counter += ret; 809 } 729 810 730 811 /* Print trailing zeros of the fractional part of the number. */ 731 TRY(_write_zeros(trailing_frac_zeros, ps, written_bytes)); 812 if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0) 813 return -1; 814 815 counter += ret; 732 816 } 733 817 734 818 /* Trailing padding. */ 735 if (flags & __PRINTF_FLAG_LEFTALIGNED) 736 TRY(_write_spaces(padding_len, ps, written_bytes)); 737 738 return EOK; 819 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 820 if ((ret = print_padding(' ', padding_len, ps)) < 0) 821 return -1; 822 823 counter += ret; 824 } 825 826 return counter; 739 827 } 740 828 … … 749 837 * @param flags Printf flags. 750 838 * @param ps Printing functions. 751 */ 752 static errno_t _format_double_fixed(double g, int precision, int width, 753 uint32_t flags, printf_spec_t *ps, size_t *written_bytes) 839 * 840 * @return The number of characters printed; negative on failure. 841 */ 842 static int print_double_fixed(double g, int precision, int width, uint32_t flags, 843 printf_spec_t *ps) 754 844 { 755 845 if (flags & __PRINTF_FLAG_LEFTALIGNED) { … … 764 854 765 855 if (val.is_special) { 766 return _format_special(val, width, flags, ps, written_bytes);856 return print_special(val, width, flags, ps); 767 857 } 768 858 … … 787 877 * digit is definitely inaccurate so also round to get rid of it. 788 878 */ 789 _fp_round_up(buf, &val_str.len, &val_str.dec_exp);879 fp_round_up(buf, &val_str.len, &val_str.dec_exp); 790 880 791 881 /* Rounding could have introduced trailing zeros. */ 792 882 if (flags & __PRINTF_FLAG_NOFRACZEROS) { 793 _fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);883 fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp); 794 884 } 795 885 } else { … … 801 891 } 802 892 803 return _format_double_str_fixed(&val_str, precision, width, flags, ps, written_bytes);893 return print_double_str_fixed(&val_str, precision, width, flags, ps); 804 894 } 805 895 806 896 /** Prints the decimal exponent part of a %e specifier formatted number. */ 807 static errno_t _format_exponent(int exp_val, uint32_t flags, printf_spec_t *ps, 808 size_t *written_bytes) 809 { 897 static int print_exponent(int exp_val, uint32_t flags, printf_spec_t *ps) 898 { 899 int counter = 0; 900 int ret; 901 810 902 char exp_ch = (flags & __PRINTF_FLAG_BIGCHARS) ? 'E' : 'e'; 811 TRY(_write_char(exp_ch, ps, written_bytes)); 903 904 if ((ret = ps->str_write(&exp_ch, 1, ps->data)) < 0) 905 return -1; 906 907 counter += ret; 812 908 813 909 char exp_sign = (exp_val < 0) ? '-' : '+'; 814 TRY(_write_char(exp_sign, ps, written_bytes)); 910 911 if ((ret = ps->str_write(&exp_sign, 1, ps->data)) < 0) 912 return -1; 913 914 counter += ret; 815 915 816 916 /* Print the exponent. */ … … 826 926 const char *exp_str_start = &exp_str[3] - exp_len; 827 927 828 return _write_bytes(exp_str_start, exp_len, ps, written_bytes); 928 if ((ret = ps->str_write(exp_str_start, exp_len, ps->data)) < 0) 929 return -1; 930 931 counter += ret; 932 933 return counter; 829 934 } 830 935 … … 832 937 * to the %e specifier. 833 938 */ 834 static errno_t _format_double_str_scient(double_str_t *val_str, int precision,835 int width, uint32_t flags, printf_spec_t *ps , size_t *written_bytes)939 static int print_double_str_scient(double_str_t *val_str, int precision, 940 int width, uint32_t flags, printf_spec_t *ps) 836 941 { 837 942 int len = val_str->len; … … 841 946 assert(0 < len); 842 947 843 char sign = _get_sign_char(val_str->neg, flags);948 char sign = get_sign_char(val_str->neg, flags); 844 949 bool has_decimal_pt = (0 < precision) || (flags & __PRINTF_FLAG_DECIMALPT); 845 950 int dec_pt_len = has_decimal_pt ? 1 : 0; … … 863 968 864 969 int padding_len = max(0, width - num_len); 865 866 if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) 867 TRY(_write_spaces(padding_len, ps, written_bytes)); 868 869 if (sign) 870 TRY(_write_char(sign, ps, written_bytes)); 871 872 if (flags & __PRINTF_FLAG_ZEROPADDED) 873 TRY(_write_zeros(padding_len, ps, written_bytes)); 970 int ret = 0; 971 int counter = 0; 972 973 if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) { 974 if ((ret = print_padding(' ', padding_len, ps)) < 0) 975 return -1; 976 977 counter += ret; 978 } 979 980 if (sign) { 981 if ((ret = ps->str_write(&sign, 1, ps->data)) < 0) 982 return -1; 983 984 counter += ret; 985 } 986 987 if (flags & __PRINTF_FLAG_ZEROPADDED) { 988 if ((ret = print_padding('0', padding_len, ps)) < 0) 989 return -1; 990 991 counter += ret; 992 } 874 993 875 994 /* Single leading integer. */ 876 TRY(_write_char(buf[0], ps, written_bytes)); 995 if ((ret = ps->str_write(buf, 1, ps->data)) < 0) 996 return -1; 997 998 counter += ret; 877 999 878 1000 /* Print the decimal point and the fractional part. */ 879 1001 if (has_decimal_pt) { 880 TRY(_write_char('.', ps, written_bytes)); 1002 char ch = '.'; 1003 1004 if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 1005 return -1; 1006 1007 counter += ret; 881 1008 882 1009 /* Print significant digits of the fractional part of the number. */ 883 if (0 < signif_frac_figs) 884 TRY(_write_bytes(buf + 1, signif_frac_figs, ps, written_bytes)); 1010 if (0 < signif_frac_figs) { 1011 if ((ret = ps->str_write(buf + 1, signif_frac_figs, ps->data)) < 0) 1012 return -1; 1013 1014 counter += ret; 1015 } 885 1016 886 1017 /* Print trailing zeros of the fractional part of the number. */ 887 TRY(_write_zeros(trailing_frac_zeros, ps, written_bytes)); 1018 if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0) 1019 return -1; 1020 1021 counter += ret; 888 1022 } 889 1023 890 1024 /* Print the exponent. */ 891 TRY(_format_exponent(exp_val, flags, ps, written_bytes)); 892 893 if (flags & __PRINTF_FLAG_LEFTALIGNED) 894 TRY(_write_spaces(padding_len, ps, written_bytes)); 895 896 return EOK; 1025 if ((ret = print_exponent(exp_val, flags, ps)) < 0) 1026 return -1; 1027 1028 counter += ret; 1029 1030 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 1031 if ((ret = print_padding(' ', padding_len, ps)) < 0) 1032 return -1; 1033 1034 counter += ret; 1035 } 1036 1037 return counter; 897 1038 } 898 1039 … … 916 1057 * @param flags Printf flags. 917 1058 * @param ps Printing functions. 918 */ 919 static errno_t _format_double_scientific(double g, int precision, int width, 920 uint32_t flags, printf_spec_t *ps, size_t *written_bytes) 921 { 922 if (flags & __PRINTF_FLAG_LEFTALIGNED) 1059 * 1060 * @return The number of characters printed; negative on failure. 1061 */ 1062 static int print_double_scientific(double g, int precision, int width, 1063 uint32_t flags, printf_spec_t *ps) 1064 { 1065 if (flags & __PRINTF_FLAG_LEFTALIGNED) { 923 1066 flags &= ~__PRINTF_FLAG_ZEROPADDED; 1067 } 924 1068 925 1069 ieee_double_t val = extract_ieee_double(g); 926 1070 927 if (val.is_special) 928 return _format_special(val, width, flags, ps, written_bytes); 1071 if (val.is_special) { 1072 return print_special(val, width, flags, ps); 1073 } 929 1074 930 1075 char buf[MAX_DOUBLE_STR_BUF_SIZE]; … … 949 1094 * digit is definitely inaccurate so also round to get rid of it. 950 1095 */ 951 _fp_round_up(buf, &val_str.len, &val_str.dec_exp);1096 fp_round_up(buf, &val_str.len, &val_str.dec_exp); 952 1097 953 1098 /* Rounding could have introduced trailing zeros. */ 954 1099 if (flags & __PRINTF_FLAG_NOFRACZEROS) { 955 _fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);1100 fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp); 956 1101 } 957 1102 } else { … … 963 1108 } 964 1109 965 return _format_double_str_scient(&val_str, precision, width, flags, ps, written_bytes);1110 return print_double_str_scient(&val_str, precision, width, flags, ps); 966 1111 } 967 1112 … … 981 1126 * @return The number of characters printed; negative on failure. 982 1127 */ 983 static errno_t _format_double_generic(double g, int precision, int width,984 uint32_t flags, printf_spec_t *ps , size_t *written_bytes)1128 static int print_double_generic(double g, int precision, int width, 1129 uint32_t flags, printf_spec_t *ps) 985 1130 { 986 1131 ieee_double_t val = extract_ieee_double(g); 987 1132 988 if (val.is_special) 989 return _format_special(val, width, flags, ps, written_bytes); 1133 if (val.is_special) { 1134 return print_special(val, width, flags, ps); 1135 } 990 1136 991 1137 char buf[MAX_DOUBLE_STR_BUF_SIZE]; … … 1007 1153 if (-4 <= dec_exp && dec_exp < precision) { 1008 1154 precision = precision - (dec_exp + 1); 1009 return _format_double_fixed(g, precision, width,1010 flags | __PRINTF_FLAG_NOFRACZEROS, ps , written_bytes);1155 return print_double_fixed(g, precision, width, 1156 flags | __PRINTF_FLAG_NOFRACZEROS, ps); 1011 1157 } else { 1012 1158 --precision; 1013 return _format_double_scientific(g, precision, width,1014 flags | __PRINTF_FLAG_NOFRACZEROS, ps , written_bytes);1159 return print_double_scientific(g, precision, width, 1160 flags | __PRINTF_FLAG_NOFRACZEROS, ps); 1015 1161 } 1016 1162 } else { … … 1036 1182 /* Precision needed for the last significant digit. */ 1037 1183 precision = max(0, -val_str.dec_exp); 1038 return _format_double_str_fixed(&val_str, precision, width, flags, ps, written_bytes);1184 return print_double_str_fixed(&val_str, precision, width, flags, ps); 1039 1185 } else { 1040 1186 /* Use all produced digits. */ 1041 1187 precision = val_str.len - 1; 1042 return _format_double_str_scient(&val_str, precision, width, flags, ps, written_bytes);1188 return print_double_str_scient(&val_str, precision, width, flags, ps); 1043 1189 } 1044 1190 } … … 1061 1207 * @param flags Printf flags. 1062 1208 * @param ps Printing functions. 1063 */ 1064 static errno_t _format_double(double g, char spec, int precision, int width, 1065 uint32_t flags, printf_spec_t *ps, size_t *written_chars) 1209 * 1210 * @return The number of characters printed; negative on failure. 1211 */ 1212 static int print_double(double g, char spec, int precision, int width, 1213 uint32_t flags, printf_spec_t *ps) 1066 1214 { 1067 1215 switch (spec) { … … 1071 1219 case 'f': 1072 1220 precision = (precision < 0) ? 6 : precision; 1073 return _format_double_fixed(g, precision, width, flags, ps, written_chars);1221 return print_double_fixed(g, precision, width, flags, ps); 1074 1222 1075 1223 case 'E': … … 1078 1226 case 'e': 1079 1227 precision = (precision < 0) ? 6 : precision; 1080 return _format_double_scientific(g, precision, width, flags, ps, written_chars);1228 return print_double_scientific(g, precision, width, flags, ps); 1081 1229 1082 1230 case 'G': … … 1084 1232 /* Fallthrough */ 1085 1233 case 'g': 1086 return _format_double_generic(g, precision, width, flags, ps, written_chars);1234 return print_double_generic(g, precision, width, flags, ps); 1087 1235 1088 1236 default: … … 1093 1241 1094 1242 #endif 1095 1096 static const char *_strchrnul(const char *s, int c)1097 {1098 while (*s != c && *s != 0)1099 s++;1100 return s;1101 }1102 1103 /** Read a sequence of digits from the format string as a number.1104 * If the number has too many digits to fit in int, returns INT_MAX.1105 */1106 static int _read_num(const char *fmt, size_t *i)1107 {1108 const char *s;1109 unsigned n = 0;1110 1111 for (s = &fmt[*i]; isdigit(*s); s++) {1112 unsigned digit = (*s - '0');1113 1114 /* Check for overflow */1115 if (n > INT_MAX / 10 || n * 10 > INT_MAX - digit) {1116 n = INT_MAX;1117 while (isdigit(*s))1118 s++;1119 break;1120 }1121 1122 n = n * 10 + digit;1123 }1124 1125 *i = s - fmt;1126 return n;1127 }1128 1129 static uint32_t _parse_flags(const char *fmt, size_t *i)1130 {1131 uint32_t flags = 0;1132 1133 while (true) {1134 switch (fmt[(*i)++]) {1135 case '#':1136 flags |= __PRINTF_FLAG_PREFIX;1137 flags |= __PRINTF_FLAG_DECIMALPT;1138 continue;1139 case '-':1140 flags |= __PRINTF_FLAG_LEFTALIGNED;1141 continue;1142 case '+':1143 flags |= __PRINTF_FLAG_SHOWPLUS;1144 continue;1145 case ' ':1146 flags |= __PRINTF_FLAG_SPACESIGN;1147 continue;1148 case '0':1149 flags |= __PRINTF_FLAG_ZEROPADDED;1150 continue;1151 }1152 1153 --*i;1154 break;1155 }1156 1157 return flags;1158 }1159 1160 static bool _eat_char(const char *s, size_t *idx, int c)1161 {1162 if (s[*idx] != c)1163 return false;1164 1165 (*idx)++;1166 return true;1167 }1168 1169 static qualifier_t _read_qualifier(const char *s, size_t *idx)1170 {1171 switch (s[(*idx)++]) {1172 case 't': /* ptrdiff_t */1173 case 'z': /* size_t */1174 if (sizeof(ptrdiff_t) == sizeof(int))1175 return PrintfQualifierInt;1176 else1177 return PrintfQualifierLong;1178 1179 case 'h':1180 if (_eat_char(s, idx, 'h'))1181 return PrintfQualifierByte;1182 else1183 return PrintfQualifierShort;1184 1185 case 'l':1186 if (_eat_char(s, idx, 'l'))1187 return PrintfQualifierLongLong;1188 else1189 return PrintfQualifierLong;1190 1191 case 'j':1192 return PrintfQualifierLongLong;1193 1194 default:1195 --*idx;1196 1197 /* Unspecified */1198 return PrintfQualifierInt;1199 }1200 }1201 1243 1202 1244 /** Print formatted string. … … 1291 1333 int printf_core(const char *fmt, printf_spec_t *ps, va_list ap) 1292 1334 { 1293 errno_t rc = EOK;1335 size_t i; /* Index of the currently processed character from fmt */ 1294 1336 size_t nxt = 0; /* Index of the next character from fmt */ 1337 size_t j = 0; /* Index to the first not printed nonformating character */ 1295 1338 1296 1339 size_t counter = 0; /* Number of characters printed */ 1297 1298 while (rc == EOK) { 1299 /* Find the next specifier and write all the bytes before it. */1300 const char *s = _strchrnul(&fmt[nxt], '%');1301 size_t bytes = s - &fmt[nxt];1302 rc = _write_bytes(&fmt[nxt], bytes, ps, &counter); 1303 if ( rc != EOK)1340 int retval; /* Return values from nested functions */ 1341 1342 while (true) { 1343 i = nxt; 1344 char32_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1345 1346 if (uc == 0) 1304 1347 break; 1305 1348 1306 nxt += bytes; 1307 1308 /* Check for end of string. */ 1309 if (_eat_char(fmt, &nxt, 0)) 1310 break; 1311 1312 /* We must be at the start of a specifier. */ 1313 bool spec = _eat_char(fmt, &nxt, '%'); 1314 assert(spec); 1315 1316 /* Parse modifiers */ 1317 uint32_t flags = _parse_flags(fmt, &nxt); 1318 1319 /* Width & '*' operator */ 1320 int width = -1; 1321 if (_eat_char(fmt, &nxt, '*')) { 1322 /* Get width value from argument list */ 1323 width = va_arg(ap, int); 1324 1325 if (width < 0) { 1326 /* Negative width sets '-' flag */ 1327 width = (width == INT_MIN) ? INT_MAX : -width; 1328 flags |= __PRINTF_FLAG_LEFTALIGNED; 1349 /* Control character */ 1350 if (uc == '%') { 1351 /* Print common characters if any processed */ 1352 if (i > j) { 1353 if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) { 1354 /* Error */ 1355 counter = -counter; 1356 goto out; 1357 } 1358 counter += retval; 1329 1359 } 1330 } else { 1331 width = _read_num(fmt, &nxt); 1332 } 1333 1334 /* Precision and '*' operator */ 1335 int precision = -1; 1336 if (_eat_char(fmt, &nxt, '.')) { 1337 if (_eat_char(fmt, &nxt, '*')) { 1338 /* Get precision value from the argument list */ 1339 precision = va_arg(ap, int); 1340 1341 /* Negative is treated as omitted. */ 1342 if (precision < 0) 1343 precision = -1; 1344 } else { 1345 precision = _read_num(fmt, &nxt); 1360 1361 j = i; 1362 1363 /* Parse modifiers */ 1364 uint32_t flags = 0; 1365 bool end = false; 1366 1367 do { 1368 i = nxt; 1369 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1370 switch (uc) { 1371 case '#': 1372 flags |= __PRINTF_FLAG_PREFIX; 1373 flags |= __PRINTF_FLAG_DECIMALPT; 1374 break; 1375 case '-': 1376 flags |= __PRINTF_FLAG_LEFTALIGNED; 1377 break; 1378 case '+': 1379 flags |= __PRINTF_FLAG_SHOWPLUS; 1380 break; 1381 case ' ': 1382 flags |= __PRINTF_FLAG_SPACESIGN; 1383 break; 1384 case '0': 1385 flags |= __PRINTF_FLAG_ZEROPADDED; 1386 break; 1387 default: 1388 end = true; 1389 } 1390 } while (!end); 1391 1392 /* Width & '*' operator */ 1393 int width = 0; 1394 if (isdigit(uc)) { 1395 while (true) { 1396 width *= 10; 1397 width += uc - '0'; 1398 1399 i = nxt; 1400 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1401 if (uc == 0) 1402 break; 1403 if (!isdigit(uc)) 1404 break; 1405 } 1406 } else if (uc == '*') { 1407 /* Get width value from argument list */ 1408 i = nxt; 1409 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1410 width = (int) va_arg(ap, int); 1411 if (width < 0) { 1412 /* Negative width sets '-' flag */ 1413 width *= -1; 1414 flags |= __PRINTF_FLAG_LEFTALIGNED; 1415 } 1346 1416 } 1347 } 1348 1349 qualifier_t qualifier = _read_qualifier(fmt, &nxt); 1350 unsigned int base = 10; 1351 char specifier = fmt[nxt++]; 1352 1353 switch (specifier) { 1354 /* 1355 * String and character conversions. 1356 */ 1357 case 's': 1358 if (qualifier == PrintfQualifierLong) 1359 rc = _format_wstr(va_arg(ap, char32_t *), width, precision, flags, ps, &counter); 1360 else 1361 rc = _format_cstr(va_arg(ap, char *), width, precision, flags, ps, &counter); 1362 continue; 1363 1364 case 'c': 1365 if (qualifier == PrintfQualifierLong) 1366 rc = _format_uchar(va_arg(ap, wint_t), width, flags, ps, &counter); 1367 else 1368 rc = _format_char(va_arg(ap, int), width, flags, ps, &counter); 1369 continue; 1370 1371 /* 1372 * Floating point values 1373 */ 1374 case 'G': 1375 case 'g': 1376 case 'F': 1377 case 'f': 1378 case 'E': 1379 case 'e':; 1417 1418 /* Precision and '*' operator */ 1419 int precision = -1; 1420 if (uc == '.') { 1421 i = nxt; 1422 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1423 if (isdigit(uc)) { 1424 precision = 0; 1425 while (true) { 1426 precision *= 10; 1427 precision += uc - '0'; 1428 1429 i = nxt; 1430 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1431 if (uc == 0) 1432 break; 1433 if (!isdigit(uc)) 1434 break; 1435 } 1436 } else if (uc == '*') { 1437 /* Get precision value from the argument list */ 1438 i = nxt; 1439 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1440 precision = (int) va_arg(ap, int); 1441 if (precision < 0) { 1442 /* Ignore negative precision - use default instead */ 1443 precision = -1; 1444 } 1445 } 1446 } 1447 1448 qualifier_t qualifier; 1449 1450 switch (uc) { 1451 case 't': 1452 /* ptrdiff_t */ 1453 if (sizeof(ptrdiff_t) == sizeof(int32_t)) 1454 qualifier = PrintfQualifierInt; 1455 else 1456 qualifier = PrintfQualifierLongLong; 1457 i = nxt; 1458 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1459 break; 1460 case 'h': 1461 /* Char or short */ 1462 qualifier = PrintfQualifierShort; 1463 i = nxt; 1464 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1465 if (uc == 'h') { 1466 i = nxt; 1467 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1468 qualifier = PrintfQualifierByte; 1469 } 1470 break; 1471 case 'l': 1472 /* Long or long long */ 1473 qualifier = PrintfQualifierLong; 1474 i = nxt; 1475 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1476 if (uc == 'l') { 1477 i = nxt; 1478 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1479 qualifier = PrintfQualifierLongLong; 1480 } 1481 break; 1482 case 'z': 1483 qualifier = PrintfQualifierSize; 1484 i = nxt; 1485 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1486 break; 1487 case 'j': 1488 qualifier = PrintfQualifierMax; 1489 i = nxt; 1490 uc = str_decode(fmt, &nxt, STR_NO_LIMIT); 1491 break; 1492 default: 1493 /* Default type */ 1494 qualifier = PrintfQualifierInt; 1495 } 1496 1497 unsigned int base = 10; 1498 1499 switch (uc) { 1500 /* 1501 * String and character conversions. 1502 */ 1503 case 's': 1504 precision = max(0, precision); 1505 1506 if (qualifier == PrintfQualifierLong) 1507 retval = print_wstr(va_arg(ap, char32_t *), width, precision, flags, ps); 1508 else 1509 retval = print_str(va_arg(ap, char *), width, precision, flags, ps); 1510 1511 if (retval < 0) { 1512 counter = -counter; 1513 goto out; 1514 } 1515 1516 counter += retval; 1517 j = nxt; 1518 continue; 1519 case 'c': 1520 if (qualifier == PrintfQualifierLong) 1521 retval = print_wchar(va_arg(ap, wint_t), width, flags, ps); 1522 else 1523 retval = print_char(va_arg(ap, unsigned int), width, flags, ps); 1524 1525 if (retval < 0) { 1526 counter = -counter; 1527 goto out; 1528 } 1529 1530 counter += retval; 1531 j = nxt; 1532 continue; 1533 1380 1534 #ifdef HAS_FLOAT 1381 rc = _format_double(va_arg(ap, double), specifier, precision, 1382 width, flags, ps, &counter); 1383 #else 1384 rc = _format_cstr("<float unsupported>", width, -1, 0, ps, &counter); 1535 /* 1536 * Floating point values 1537 */ 1538 case 'G': 1539 case 'g': 1540 case 'F': 1541 case 'f': 1542 case 'E': 1543 case 'e': 1544 retval = print_double(va_arg(ap, double), uc, precision, 1545 width, flags, ps); 1546 1547 if (retval < 0) { 1548 counter = -counter; 1549 goto out; 1550 } 1551 1552 counter += retval; 1553 j = nxt; 1554 continue; 1385 1555 #endif 1386 continue; 1387 1388 /* 1389 * Integer values 1390 */ 1391 case 'P': 1392 /* Pointer */ 1393 flags |= __PRINTF_FLAG_BIGCHARS; 1394 /* Fallthrough */ 1395 case 'p': 1396 flags |= __PRINTF_FLAG_PREFIX; 1397 flags |= __PRINTF_FLAG_ZEROPADDED; 1398 base = 16; 1399 qualifier = PrintfQualifierPointer; 1400 break; 1401 case 'b': 1402 base = 2; 1403 break; 1404 case 'o': 1405 base = 8; 1406 break; 1407 case 'd': 1408 case 'i': 1409 flags |= __PRINTF_FLAG_SIGNED; 1410 break; 1411 case 'u': 1412 break; 1413 case 'X': 1414 flags |= __PRINTF_FLAG_BIGCHARS; 1415 /* Fallthrough */ 1416 case 'x': 1417 base = 16; 1418 break; 1419 1420 case '%': 1421 /* Percentile itself */ 1422 rc = _write_char('%', ps, &counter); 1423 continue; 1424 1425 /* 1426 * Bad formatting. 1427 */ 1428 default: 1429 rc = EINVAL; 1430 continue; 1431 } 1432 1433 /* Print integers */ 1434 uint64_t number; 1435 1436 switch (qualifier) { 1437 case PrintfQualifierByte: 1438 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 1439 break; 1440 case PrintfQualifierShort: 1441 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 1442 break; 1443 case PrintfQualifierInt: 1444 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 1445 break; 1446 case PrintfQualifierLong: 1447 number = PRINTF_GET_INT_ARGUMENT(long, ap, flags); 1448 break; 1449 case PrintfQualifierLongLong: 1450 number = PRINTF_GET_INT_ARGUMENT(long long, ap, flags); 1451 break; 1452 case PrintfQualifierPointer: 1453 precision = sizeof(void *) << 1; 1454 number = (uint64_t) (uintptr_t) va_arg(ap, void *); 1455 break; 1456 default: 1457 /* Unknown qualifier */ 1458 rc = EINVAL; 1459 continue; 1460 } 1461 1462 rc = _format_number(number, width, precision, base, flags, ps, &counter); 1463 } 1464 1465 if (rc != EOK) { 1466 _set_errno(rc); 1467 return -1; 1468 } 1469 1470 if (counter > INT_MAX) { 1471 _set_errno(EOVERFLOW); 1472 return -1; 1473 } 1474 1475 return (int) counter; 1556 1557 /* 1558 * Integer values 1559 */ 1560 case 'P': 1561 /* Pointer */ 1562 flags |= __PRINTF_FLAG_BIGCHARS; 1563 /* Fallthrough */ 1564 case 'p': 1565 flags |= __PRINTF_FLAG_PREFIX; 1566 flags |= __PRINTF_FLAG_ZEROPADDED; 1567 base = 16; 1568 qualifier = PrintfQualifierPointer; 1569 break; 1570 case 'b': 1571 base = 2; 1572 break; 1573 case 'o': 1574 base = 8; 1575 break; 1576 case 'd': 1577 case 'i': 1578 flags |= __PRINTF_FLAG_SIGNED; 1579 /* Fallthrough */ 1580 case 'u': 1581 break; 1582 case 'X': 1583 flags |= __PRINTF_FLAG_BIGCHARS; 1584 /* Fallthrough */ 1585 case 'x': 1586 base = 16; 1587 break; 1588 1589 case '%': 1590 /* Percentile itself */ 1591 j = i; 1592 continue; 1593 1594 /* 1595 * Bad formatting. 1596 */ 1597 default: 1598 /* 1599 * Unknown format. Now, j is the index of '%' 1600 * so we will print whole bad format sequence. 1601 */ 1602 continue; 1603 } 1604 1605 /* Print integers */ 1606 size_t size; 1607 uint64_t number; 1608 1609 switch (qualifier) { 1610 case PrintfQualifierByte: 1611 size = sizeof(unsigned char); 1612 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 1613 break; 1614 case PrintfQualifierShort: 1615 size = sizeof(unsigned short); 1616 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 1617 break; 1618 case PrintfQualifierInt: 1619 size = sizeof(unsigned int); 1620 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 1621 break; 1622 case PrintfQualifierLong: 1623 size = sizeof(unsigned long); 1624 number = PRINTF_GET_INT_ARGUMENT(long, ap, flags); 1625 break; 1626 case PrintfQualifierLongLong: 1627 size = sizeof(unsigned long long); 1628 number = PRINTF_GET_INT_ARGUMENT(long long, ap, flags); 1629 break; 1630 case PrintfQualifierPointer: 1631 size = sizeof(void *); 1632 precision = size << 1; 1633 number = (uint64_t) (uintptr_t) va_arg(ap, void *); 1634 break; 1635 case PrintfQualifierSize: 1636 size = sizeof(size_t); 1637 number = (uint64_t) va_arg(ap, size_t); 1638 break; 1639 case PrintfQualifierMax: 1640 size = sizeof(uintmax_t); 1641 number = (uint64_t) va_arg(ap, uintmax_t); 1642 break; 1643 default: 1644 /* Unknown qualifier */ 1645 counter = -counter; 1646 goto out; 1647 } 1648 1649 if ((retval = print_number(number, width, precision, 1650 base, flags, ps)) < 0) { 1651 counter = -counter; 1652 goto out; 1653 } 1654 1655 counter += retval; 1656 j = nxt; 1657 } 1658 } 1659 1660 if (i > j) { 1661 if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) { 1662 /* Error */ 1663 counter = -counter; 1664 goto out; 1665 } 1666 counter += retval; 1667 } 1668 1669 out: 1670 return ((int) counter); 1476 1671 } 1477 1672 -
kernel/generic/meson.build
rc7c6afd r240b2e4 40 40 'common/adt/list.c', 41 41 'common/adt/odict.c', 42 'common/gsort.c',43 42 'common/printf/printf_core.c', 44 43 'common/stdc/calloc.c', 45 44 'common/stdc/ctype.c', 46 45 'common/stdc/mem.c', 47 'common/stdc/snprintf.c', 48 'common/stdc/vsnprintf.c', 46 'common/gsort.c', 49 47 'common/str.c', 50 48 'common/str_error.c', … … 98 96 'src/mm/reserve.c', 99 97 'src/printf/printf.c', 98 'src/printf/snprintf.c', 100 99 'src/printf/vprintf.c', 100 'src/printf/vsnprintf.c', 101 101 'src/proc/program.c', 102 102 'src/proc/scheduler.c', -
kernel/generic/src/log/log.c
rc7c6afd r240b2e4 33 33 */ 34 34 35 #include < abi/log.h>36 #include < arch.h>37 #include < atomic.h>38 #include < console/console.h>35 #include <sysinfo/sysinfo.h> 36 #include <synch/spinlock.h> 37 #include <typedefs.h> 38 #include <ddi/irq.h> 39 39 #include <ddi/ddi.h> 40 #include <ddi/irq.h>41 #include <errno.h>42 40 #include <ipc/event.h> 43 41 #include <ipc/irq.h> 42 #include <arch.h> 43 #include <panic.h> 44 #include <putchar.h> 45 #include <atomic.h> 46 #include <syscall/copy.h> 47 #include <errno.h> 48 #include <str.h> 49 #include <print.h> 50 #include <printf/printf_core.h> 51 #include <stdarg.h> 44 52 #include <log.h> 45 #include <panic.h> 46 #include <print.h> 47 #include <printf_core.h> 48 #include <putchar.h> 49 #include <stdarg.h> 53 #include <console/console.h> 54 #include <abi/log.h> 50 55 #include <stdlib.h> 51 #include <str.h>52 #include <synch/spinlock.h>53 #include <syscall/copy.h>54 #include <sysinfo/sysinfo.h>55 #include <typedefs.h>56 56 57 57 #define LOG_PAGES 8 … … 204 204 { 205 205 size_t offset = 0; 206 207 while (offset < size) 206 size_t chars = 0; 207 208 while (offset < size) { 208 209 kio_push_char(str_decode(str, &offset, size)); 210 chars++; 211 } 209 212 210 213 log_append((const uint8_t *)str, size); 211 214 212 return EOK; 215 return chars; 216 } 217 218 static int log_printf_wstr_write(const char32_t *wstr, size_t size, void *data) 219 { 220 char buffer[16]; 221 size_t offset = 0; 222 size_t chars = 0; 223 224 for (offset = 0; offset < size; offset += sizeof(char32_t), chars++) { 225 kio_push_char(wstr[chars]); 226 227 size_t buffer_offset = 0; 228 errno_t rc = chr_encode(wstr[chars], buffer, &buffer_offset, 16); 229 if (rc != EOK) { 230 return EOF; 231 } 232 233 log_append((const uint8_t *)buffer, buffer_offset); 234 } 235 236 return chars; 213 237 } 214 238 … … 219 243 int log_vprintf(const char *fmt, va_list args) 220 244 { 245 int ret; 246 221 247 printf_spec_t ps = { 222 248 log_printf_str_write, 249 log_printf_wstr_write, 223 250 NULL 224 251 }; 225 252 226 return printf_core(fmt, &ps, args); 253 ret = printf_core(fmt, &ps, args); 254 255 return ret; 227 256 } 228 257 -
kernel/generic/src/printf/vprintf.c
rc7c6afd r240b2e4 36 36 #include <console/console.h> 37 37 #include <print.h> 38 #include <printf _core.h>38 #include <printf/printf_core.h> 39 39 #include <putchar.h> 40 40 #include <str.h> … … 42 42 #include <typedefs.h> 43 43 44 static errno_t vprintf_str_write(const char *str, size_t size, void *data)44 static int vprintf_str_write(const char *str, size_t size, void *data) 45 45 { 46 46 size_t offset = 0; 47 size_t chars = 0; 47 48 48 while (offset < size) 49 while (offset < size) { 49 50 putuchar(str_decode(str, &offset, size)); 51 chars++; 52 } 50 53 51 return EOK; 54 return chars; 55 } 56 57 static int vprintf_wstr_write(const char32_t *str, size_t size, void *data) 58 { 59 size_t offset = 0; 60 size_t chars = 0; 61 62 while (offset < size) { 63 putuchar(str[chars]); 64 chars++; 65 offset += sizeof(char32_t); 66 } 67 68 return chars; 52 69 } 53 70 … … 75 92 printf_spec_t ps = { 76 93 vprintf_str_write, 94 vprintf_wstr_write, 77 95 NULL 78 96 }; -
uspace/lib/c/generic/io/asprintf.c
rc7c6afd r240b2e4 40 40 #include <str.h> 41 41 #include <printf_core.h> 42 43 static int asprintf_str_write(const char *str, size_t count, void *unused) 44 { 45 return str_nlength(str, count); 46 } 47 48 static int asprintf_wstr_write(const char32_t *str, size_t count, void *unused) 49 { 50 return wstr_nlength(str, count); 51 } 52 53 int vprintf_length(const char *fmt, va_list args) 54 { 55 printf_spec_t ps = { 56 asprintf_str_write, 57 asprintf_wstr_write, 58 NULL 59 }; 60 61 return printf_core(fmt, &ps, args); 62 } 63 64 int printf_length(const char *fmt, ...) 65 { 66 va_list args; 67 va_start(args, fmt); 68 int ret = vprintf_length(fmt, args); 69 va_end(args); 70 71 return ret; 72 } 42 73 43 74 /** Allocate and print to string. … … 84 115 int ret = vasprintf(strp, fmt, args); 85 116 va_end(args); 117 86 118 return ret; 87 119 } -
uspace/lib/c/generic/io/kio.c
rc7c6afd r240b2e4 131 131 } 132 132 133 static errno_t kio_vprintf_str_write(const char *str, size_t size, void *data)133 static int kio_vprintf_str_write(const char *str, size_t size, void *data) 134 134 { 135 size_t wr = 0; 136 return kio_write(str, size, &wr); 135 size_t wr; 136 137 wr = 0; 138 (void) kio_write(str, size, &wr); 139 return str_nlength(str, wr); 140 } 141 142 static int kio_vprintf_wstr_write(const char32_t *str, size_t size, void *data) 143 { 144 size_t offset = 0; 145 size_t chars = 0; 146 size_t wr; 147 148 while (offset < size) { 149 char buf[STR_BOUNDS(1)]; 150 size_t sz = 0; 151 152 if (chr_encode(str[chars], buf, &sz, STR_BOUNDS(1)) == EOK) 153 kio_write(buf, sz, &wr); 154 155 chars++; 156 offset += sizeof(char32_t); 157 } 158 159 return chars; 137 160 } 138 161 … … 149 172 printf_spec_t ps = { 150 173 kio_vprintf_str_write, 174 kio_vprintf_wstr_write, 151 175 NULL 152 176 }; -
uspace/lib/c/generic/io/vprintf.c
rc7c6afd r240b2e4 42 42 static FIBRIL_MUTEX_INITIALIZE(printf_mutex); 43 43 44 static errno_t vprintf_str_write(const char *str, size_t size, void *stream)44 static int vprintf_str_write(const char *str, size_t size, void *stream) 45 45 { 46 errno_t old_errno = errno; 46 size_t wr = fwrite(str, 1, size, (FILE *) stream); 47 return str_nlength(str, wr); 48 } 47 49 48 errno = EOK; 49 size_t written = fwrite(str, 1, size, (FILE *) stream); 50 static int vprintf_wstr_write(const char32_t *str, size_t size, void *stream) 51 { 52 size_t offset = 0; 53 size_t chars = 0; 50 54 51 if (errno == EOK && written != size) 52 errno = EIO; 55 while (offset < size) { 56 if (fputuc(str[chars], (FILE *) stream) <= 0) 57 break; 53 58 54 if (errno != EOK) 55 return errno; 59 chars++; 60 offset += sizeof(char32_t); 61 } 56 62 57 errno = old_errno; 58 return EOK; 63 return chars; 59 64 } 60 65 … … 72 77 printf_spec_t ps = { 73 78 vprintf_str_write, 79 vprintf_wstr_write, 74 80 stream 75 81 }; -
uspace/lib/c/include/stdio.h
rc7c6afd r240b2e4 209 209 }; 210 210 211 extern int vprintf_length(const char *, va_list); 212 extern int printf_length(const char *, ...) 213 _HELENOS_PRINTF_ATTRIBUTE(1, 2); 211 214 extern FILE *fdopen(int, const char *); 212 215 extern int fileno(FILE *); -
uspace/lib/c/meson.build
rc7c6afd r240b2e4 72 72 'common/stdc/mem.c', 73 73 'common/stdc/qsort.c', 74 'common/stdc/snprintf.c',75 74 'common/stdc/uchar.c', 76 'common/stdc/vsnprintf.c',77 75 'common/stdc/wchar.c', 78 76 'common/str.c', … … 115 113 'generic/io/logctl.c', 116 114 'generic/io/printf.c', 115 'generic/io/snprintf.c', 117 116 'generic/io/table.c', 118 117 'generic/io/vprintf.c', 118 'generic/io/vsnprintf.c', 119 119 'generic/ipc.c', 120 120 'generic/irq.c', -
uspace/lib/posix/src/stdio.c
rc7c6afd r240b2e4 232 232 * @return The number of written characters. 233 233 */ 234 static errno_t _dprintf_str_write(const char *str, size_t size, void *fd)234 static int _dprintf_str_write(const char *str, size_t size, void *fd) 235 235 { 236 236 const int fildes = *(int *) fd; 237 237 size_t wr; 238 return vfs_write(fildes, &posix_pos[fildes], str, size, &wr); 238 if (failed(vfs_write(fildes, &posix_pos[fildes], str, size, &wr))) 239 return -1; 240 return str_nlength(str, wr); 241 } 242 243 /** 244 * Write wide string to the opened file. 245 * 246 * @param str String to be written. 247 * @param size Size of the string (in bytes). 248 * @param fd File descriptor of the opened file. 249 * @return The number of written characters. 250 */ 251 static int _dprintf_wstr_write(const char32_t *str, size_t size, void *fd) 252 { 253 size_t offset = 0; 254 size_t chars = 0; 255 size_t sz; 256 char buf[4]; 257 258 while (offset < size) { 259 sz = 0; 260 if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != EOK) { 261 break; 262 } 263 264 const int fildes = *(int *) fd; 265 size_t nwr; 266 if (vfs_write(fildes, &posix_pos[fildes], buf, sz, &nwr) != EOK) 267 break; 268 269 chars++; 270 offset += sizeof(char32_t); 271 } 272 273 return chars; 239 274 } 240 275 … … 250 285 { 251 286 printf_spec_t spec = { 252 .write = _dprintf_str_write, 287 .str_write = _dprintf_str_write, 288 .wstr_write = _dprintf_wstr_write, 253 289 .data = &fildes 254 290 };
Note:
See TracChangeset
for help on using the changeset viewer.
