Changeset c7c6afd in mainline
- Timestamp:
- 2025-04-13T23:27:44Z (4 days ago)
- Children:
- b6061f8c
- Parents:
- 240b2e4 (diff), f5e1692 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Wayne Thornton <wmthornton-dev@…> (2025-04-13 23:27:44)
- git-committer:
- GitHub <noreply@…> (2025-04-13 23:27:44)
- Files:
-
- 6 deleted
- 20 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
boot/arch/arm32/meson.build
r240b2e4 rc7c6afd 66 66 'src/putchar.c', 67 67 '../../../common/stdc/mem.c', 68 '../../../common/printf/printf_core.c', 68 69 '../../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
r240b2e4 rc7c6afd 49 49 'src/relocate.c', 50 50 '../../../common/stdc/mem.c', 51 '../../../common/printf/printf_core.c', 51 52 '../../genarch/src/efi.c', 52 53 '../../generic/src/gzip.c', … … 55 56 '../../generic/src/payload.c', 56 57 '../../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
r240b2e4 rc7c6afd 45 45 '../../genarch/src/division.c', 46 46 '../../generic/src/balloc.c', 47 '../../ generic/src/printf_core.c',47 '../../../common/printf/printf_core.c', 48 48 '../../generic/src/vprintf.c', 49 49 '../../generic/src/printf.c', -
boot/arch/mips32/meson.build
r240b2e4 rc7c6afd 45 45 '../../genarch/src/division.c', 46 46 '../../genarch/src/multiplication.c', 47 '../../ generic/src/printf_core.c',47 '../../../common/printf/printf_core.c', 48 48 '../../generic/src/vprintf.c', 49 49 '../../generic/src/printf.c', -
boot/arch/ppc32/meson.build
r240b2e4 rc7c6afd 43 43 '../../genarch/src/multiplication.c', 44 44 '../../generic/src/balloc.c', 45 '../../ generic/src/printf_core.c',45 '../../../common/printf/printf_core.c', 46 46 '../../generic/src/vprintf.c', 47 47 '../../generic/src/printf.c', -
boot/arch/riscv64/meson.build
r240b2e4 rc7c6afd 39 39 40 40 '../../../common/stdc/mem.c', 41 '../../ generic/src/printf_core.c',41 '../../../common/printf/printf_core.c', 42 42 '../../generic/src/vprintf.c', 43 43 '../../generic/src/printf.c', -
boot/arch/sparc64/meson.build
r240b2e4 rc7c6afd 41 41 '../../genarch/src/ofw_tree.c', 42 42 '../../generic/src/balloc.c', 43 '../../ generic/src/printf_core.c',43 '../../../common/printf/printf_core.c', 44 44 '../../generic/src/vprintf.c', 45 45 '../../generic/src/printf.c', -
boot/generic/include/macros.h
r240b2e4 rc7c6afd 34 34 35 35 #define min(a, b) ((a) < (b) ? (a) : (b)) 36 #define max(a, b) ((a) > (b) ? (a) : (b)) 36 37 37 38 #define isdigit(d) (((d) >= '0') && ((d) <= '9')) -
boot/generic/src/vprintf.c
r240b2e4 rc7c6afd 36 36 #include <str.h> 37 37 38 static int vprintf_str_write(const char *str, size_t size, void *data)38 static errno_t vprintf_str_write(const char *str, size_t size, void *data) 39 39 { 40 40 size_t offset = 0; 41 size_t chars = 0;42 41 43 while (offset < size) {42 while (offset < size) 44 43 putuchar(str_decode(str, &offset, size)); 45 chars++;46 }47 44 48 return chars;45 return EOK; 49 46 } 50 47 … … 71 68 }; 72 69 73 int ret = printf_core(fmt, &ps, ap); 74 75 return ret; 70 return printf_core(fmt, &ps, ap); 76 71 } 77 72 -
common/include/printf_core.h
r240b2e4 rc7c6afd 36 36 #define _LIBC_PRINTF_CORE_H_ 37 37 38 #include <errno.h> 39 #include <stdarg.h> 38 40 #include <stddef.h> 39 #include <stdarg.h>40 41 #include <uchar.h> 41 42 42 43 /** Structure for specifying output methods for different printf clones. */ 43 44 typedef struct { 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 *); 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 *); 49 51 50 52 /* User data - output stream specification, state, locks, etc. */ -
common/printf/printf_core.c
r240b2e4 rc7c6afd 3 3 * Copyright (c) 2006 Josef Cejka 4 4 * Copyright (c) 2009 Martin Decky 5 * Copyright (c) 2025 Jiří Zárevúcky 5 6 * All rights reserved. 6 7 * … … 37 38 */ 38 39 39 #include <stdio.h> 40 #include <_bits/uchar.h> 41 #include <_bits/wint_t.h> 42 #include <assert.h> 43 #include <ctype.h> 44 #include <errno.h> 45 #include <limits.h> 46 #include <macros.h> 47 #include <printf_core.h> 40 48 #include <stddef.h> 49 #include <stdint.h> 41 50 #include <stdlib.h> 42 #include <printf_core.h>43 #include <ctype.h>44 51 #include <str.h> 45 #include <assert.h>46 #include <macros.h>47 #include <uchar.h>48 52 49 53 /* Disable float support in kernel, because we usually disable floating operations there. */ … … 88 92 89 93 /** 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) 94 * Buffer big enough for 64-bit number printed in base 2. 95 */ 96 #define PRINT_NUMBER_BUFFER_SIZE 64 95 97 96 98 /** Get signed or unsigned integer argument */ … … 122 124 PrintfQualifierLongLong, 123 125 PrintfQualifierPointer, 124 PrintfQualifierSize,125 PrintfQualifierMax126 126 } qualifier_t; 127 127 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); 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); 211 262 } 212 263 … … 216 267 * @param width Width modifier. 217 268 * @param flags Flags that change the way the character is printed. 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); 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; 249 287 } 250 288 … … 254 292 * @param width Width modifier. 255 293 * @param flags Flags that change the way the character is printed. 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); 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; 287 326 } 288 327 … … 293 332 * @param precision Precision modifier. 294 333 * @param flags Flags that modify the way the string is printed. 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) 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) 300 337 { 301 338 if (str == NULL) 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 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; 336 357 } 337 358 … … 342 363 * @param precision Precision modifier. 343 364 * @param flags Flags that modify the way the string is printed. 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); 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; 384 408 } 385 409 … … 393 417 * @param base Base to print the number in (must be between 2 and 16). 394 418 * @param flags Flags that modify the way the number is printed. 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); 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); 555 539 } 556 540 … … 570 554 571 555 /** Returns the sign character or 0 if no sign should be printed. */ 572 static intget_sign_char(bool negative, uint32_t flags)556 static char _get_sign_char(bool negative, uint32_t flags) 573 557 { 574 558 if (negative) { … … 583 567 } 584 568 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 597 569 /** Prints a special double (ie NaN, infinity) padded to width characters. */ 598 static int print_special(ieee_double_t val, int width, uint32_t flags,599 printf_spec_t *ps )570 static errno_t _format_special(ieee_double_t val, int width, uint32_t flags, 571 printf_spec_t *ps, size_t *written_bytes) 600 572 { 601 573 assert(val.is_special); 602 574 603 char sign = get_sign_char(val.is_negative, flags);575 char sign = _get_sign_char(val.is_negative, flags); 604 576 605 577 const int str_len = 3; … … 614 586 int padding_len = max(0, width - ((sign ? 1 : 0) + str_len)); 615 587 616 int counter = 0;617 int ret;618 619 588 /* Leading padding. */ 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; 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)); 638 596 639 597 /* Trailing padding. */ 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; 598 if (flags & __PRINTF_FLAG_LEFTALIGNED) 599 TRY(_write_spaces(padding_len, ps, written_bytes)); 600 601 return EOK; 648 602 } 649 603 650 604 /** Trims trailing zeros but leaves a single "0" intact. */ 651 static void fp_trim_trailing_zeros(char *buf, int *len, int *dec_exp)605 static void _fp_trim_trailing_zeros(char *buf, int *len, int *dec_exp) 652 606 { 653 607 /* Cut the zero off by adjusting the exponent. */ … … 659 613 660 614 /** Textually round up the last digit thereby eliminating it. */ 661 static void fp_round_up(char *buf, int *len, int *dec_exp)615 static void _fp_round_up(char *buf, int *len, int *dec_exp) 662 616 { 663 617 assert(1 <= *len); … … 703 657 * to the %f specifier. 704 658 */ 705 static int print_double_str_fixed(double_str_t *val_str, int precision, int width,706 uint32_t flags, printf_spec_t *ps )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) 707 661 { 708 662 int len = val_str->len; … … 717 671 int int_len = max(1, len + dec_exp); 718 672 719 char sign = get_sign_char(val_str->neg, flags);673 char sign = _get_sign_char(val_str->neg, flags); 720 674 721 675 /* Fractional portion lengths. */ … … 726 680 char *buf_frac = buf + len - signif_frac_figs; 727 681 728 if (flags & __PRINTF_FLAG_NOFRACZEROS) {682 if (flags & __PRINTF_FLAG_NOFRACZEROS) 729 683 trailing_frac_zeros = 0; 730 }731 684 732 685 int frac_len = leading_frac_zeros + signif_frac_figs + trailing_frac_zeros; … … 738 691 739 692 int padding_len = max(0, width - num_len); 740 int ret = 0;741 int counter = 0;742 693 743 694 /* Leading padding and sign. */ 744 695 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 } 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)); 765 704 766 705 /* Print the intergral part of the buffer. */ … … 769 708 770 709 if (0 < buf_int_len) { 771 if ((ret = ps->str_write(buf, buf_int_len, ps->data)) < 0) 772 return -1; 773 774 counter += ret; 710 TRY(_write_bytes(buf, buf_int_len, ps, written_bytes)); 775 711 776 712 /* Print trailing zeros of the integral part of the number. */ 777 if ((ret = print_padding('0', int_len - buf_int_len, ps)) < 0) 778 return -1; 713 TRY(_write_zeros(int_len - buf_int_len, ps, written_bytes)); 779 714 } else { 780 715 /* Single leading integer 0. */ 781 char ch = '0'; 782 if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 783 return -1; 784 } 785 786 counter += ret; 716 TRY(_write_char('0', ps, written_bytes)); 717 } 787 718 788 719 /* Print the decimal point and the fractional part. */ 789 720 if (has_decimal_pt) { 790 char ch = '.'; 791 792 if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 793 return -1; 794 795 counter += ret; 721 TRY(_write_char('.', ps, written_bytes)); 796 722 797 723 /* Print leading zeros of the fractional part of the number. */ 798 if ((ret = print_padding('0', leading_frac_zeros, ps)) < 0) 799 return -1; 800 801 counter += ret; 724 TRY(_write_zeros(leading_frac_zeros, ps, written_bytes)); 802 725 803 726 /* Print significant digits of the fractional part of the number. */ 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 } 727 if (0 < signif_frac_figs) 728 TRY(_write_bytes(buf_frac, signif_frac_figs, ps, written_bytes)); 810 729 811 730 /* Print trailing zeros of the fractional part of the number. */ 812 if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0) 813 return -1; 814 815 counter += ret; 731 TRY(_write_zeros(trailing_frac_zeros, ps, written_bytes)); 816 732 } 817 733 818 734 /* Trailing padding. */ 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; 735 if (flags & __PRINTF_FLAG_LEFTALIGNED) 736 TRY(_write_spaces(padding_len, ps, written_bytes)); 737 738 return EOK; 827 739 } 828 740 … … 837 749 * @param flags Printf flags. 838 750 * @param ps Printing functions. 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) 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) 844 754 { 845 755 if (flags & __PRINTF_FLAG_LEFTALIGNED) { … … 854 764 855 765 if (val.is_special) { 856 return print_special(val, width, flags, ps);766 return _format_special(val, width, flags, ps, written_bytes); 857 767 } 858 768 … … 877 787 * digit is definitely inaccurate so also round to get rid of it. 878 788 */ 879 fp_round_up(buf, &val_str.len, &val_str.dec_exp);789 _fp_round_up(buf, &val_str.len, &val_str.dec_exp); 880 790 881 791 /* Rounding could have introduced trailing zeros. */ 882 792 if (flags & __PRINTF_FLAG_NOFRACZEROS) { 883 fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);793 _fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp); 884 794 } 885 795 } else { … … 891 801 } 892 802 893 return print_double_str_fixed(&val_str, precision, width, flags, ps);803 return _format_double_str_fixed(&val_str, precision, width, flags, ps, written_bytes); 894 804 } 895 805 896 806 /** Prints the decimal exponent part of a %e specifier formatted number. */ 897 static int print_exponent(int exp_val, uint32_t flags, printf_spec_t *ps) 898 { 899 int counter = 0; 900 int ret; 901 807 static errno_t _format_exponent(int exp_val, uint32_t flags, printf_spec_t *ps, 808 size_t *written_bytes) 809 { 902 810 char exp_ch = (flags & __PRINTF_FLAG_BIGCHARS) ? 'E' : 'e'; 903 904 if ((ret = ps->str_write(&exp_ch, 1, ps->data)) < 0) 905 return -1; 906 907 counter += ret; 811 TRY(_write_char(exp_ch, ps, written_bytes)); 908 812 909 813 char exp_sign = (exp_val < 0) ? '-' : '+'; 910 911 if ((ret = ps->str_write(&exp_sign, 1, ps->data)) < 0) 912 return -1; 913 914 counter += ret; 814 TRY(_write_char(exp_sign, ps, written_bytes)); 915 815 916 816 /* Print the exponent. */ … … 926 826 const char *exp_str_start = &exp_str[3] - exp_len; 927 827 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; 828 return _write_bytes(exp_str_start, exp_len, ps, written_bytes); 934 829 } 935 830 … … 937 832 * to the %e specifier. 938 833 */ 939 static int print_double_str_scient(double_str_t *val_str, int precision,940 int width, uint32_t flags, printf_spec_t *ps )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) 941 836 { 942 837 int len = val_str->len; … … 946 841 assert(0 < len); 947 842 948 char sign = get_sign_char(val_str->neg, flags);843 char sign = _get_sign_char(val_str->neg, flags); 949 844 bool has_decimal_pt = (0 < precision) || (flags & __PRINTF_FLAG_DECIMALPT); 950 845 int dec_pt_len = has_decimal_pt ? 1 : 0; … … 968 863 969 864 int padding_len = max(0, width - num_len); 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 } 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)); 993 874 994 875 /* Single leading integer. */ 995 if ((ret = ps->str_write(buf, 1, ps->data)) < 0) 996 return -1; 997 998 counter += ret; 876 TRY(_write_char(buf[0], ps, written_bytes)); 999 877 1000 878 /* Print the decimal point and the fractional part. */ 1001 879 if (has_decimal_pt) { 1002 char ch = '.'; 1003 1004 if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 1005 return -1; 1006 1007 counter += ret; 880 TRY(_write_char('.', ps, written_bytes)); 1008 881 1009 882 /* Print significant digits of the fractional part of the number. */ 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 } 883 if (0 < signif_frac_figs) 884 TRY(_write_bytes(buf + 1, signif_frac_figs, ps, written_bytes)); 1016 885 1017 886 /* Print trailing zeros of the fractional part of the number. */ 1018 if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0) 1019 return -1; 1020 1021 counter += ret; 887 TRY(_write_zeros(trailing_frac_zeros, ps, written_bytes)); 1022 888 } 1023 889 1024 890 /* Print the exponent. */ 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; 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; 1038 897 } 1039 898 … … 1057 916 * @param flags Printf flags. 1058 917 * @param ps Printing functions. 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) { 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) 1066 923 flags &= ~__PRINTF_FLAG_ZEROPADDED; 1067 }1068 924 1069 925 ieee_double_t val = extract_ieee_double(g); 1070 926 1071 if (val.is_special) { 1072 return print_special(val, width, flags, ps); 1073 } 927 if (val.is_special) 928 return _format_special(val, width, flags, ps, written_bytes); 1074 929 1075 930 char buf[MAX_DOUBLE_STR_BUF_SIZE]; … … 1094 949 * digit is definitely inaccurate so also round to get rid of it. 1095 950 */ 1096 fp_round_up(buf, &val_str.len, &val_str.dec_exp);951 _fp_round_up(buf, &val_str.len, &val_str.dec_exp); 1097 952 1098 953 /* Rounding could have introduced trailing zeros. */ 1099 954 if (flags & __PRINTF_FLAG_NOFRACZEROS) { 1100 fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);955 _fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp); 1101 956 } 1102 957 } else { … … 1108 963 } 1109 964 1110 return print_double_str_scient(&val_str, precision, width, flags, ps);965 return _format_double_str_scient(&val_str, precision, width, flags, ps, written_bytes); 1111 966 } 1112 967 … … 1126 981 * @return The number of characters printed; negative on failure. 1127 982 */ 1128 static int print_double_generic(double g, int precision, int width,1129 uint32_t flags, printf_spec_t *ps )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) 1130 985 { 1131 986 ieee_double_t val = extract_ieee_double(g); 1132 987 1133 if (val.is_special) { 1134 return print_special(val, width, flags, ps); 1135 } 988 if (val.is_special) 989 return _format_special(val, width, flags, ps, written_bytes); 1136 990 1137 991 char buf[MAX_DOUBLE_STR_BUF_SIZE]; … … 1153 1007 if (-4 <= dec_exp && dec_exp < precision) { 1154 1008 precision = precision - (dec_exp + 1); 1155 return print_double_fixed(g, precision, width,1156 flags | __PRINTF_FLAG_NOFRACZEROS, ps );1009 return _format_double_fixed(g, precision, width, 1010 flags | __PRINTF_FLAG_NOFRACZEROS, ps, written_bytes); 1157 1011 } else { 1158 1012 --precision; 1159 return print_double_scientific(g, precision, width,1160 flags | __PRINTF_FLAG_NOFRACZEROS, ps );1013 return _format_double_scientific(g, precision, width, 1014 flags | __PRINTF_FLAG_NOFRACZEROS, ps, written_bytes); 1161 1015 } 1162 1016 } else { … … 1182 1036 /* Precision needed for the last significant digit. */ 1183 1037 precision = max(0, -val_str.dec_exp); 1184 return print_double_str_fixed(&val_str, precision, width, flags, ps);1038 return _format_double_str_fixed(&val_str, precision, width, flags, ps, written_bytes); 1185 1039 } else { 1186 1040 /* Use all produced digits. */ 1187 1041 precision = val_str.len - 1; 1188 return print_double_str_scient(&val_str, precision, width, flags, ps);1042 return _format_double_str_scient(&val_str, precision, width, flags, ps, written_bytes); 1189 1043 } 1190 1044 } … … 1207 1061 * @param flags Printf flags. 1208 1062 * @param ps Printing functions. 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) 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) 1214 1066 { 1215 1067 switch (spec) { … … 1219 1071 case 'f': 1220 1072 precision = (precision < 0) ? 6 : precision; 1221 return print_double_fixed(g, precision, width, flags, ps);1073 return _format_double_fixed(g, precision, width, flags, ps, written_chars); 1222 1074 1223 1075 case 'E': … … 1226 1078 case 'e': 1227 1079 precision = (precision < 0) ? 6 : precision; 1228 return print_double_scientific(g, precision, width, flags, ps);1080 return _format_double_scientific(g, precision, width, flags, ps, written_chars); 1229 1081 1230 1082 case 'G': … … 1232 1084 /* Fallthrough */ 1233 1085 case 'g': 1234 return print_double_generic(g, precision, width, flags, ps);1086 return _format_double_generic(g, precision, width, flags, ps, written_chars); 1235 1087 1236 1088 default: … … 1241 1093 1242 1094 #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 else 1177 return PrintfQualifierLong; 1178 1179 case 'h': 1180 if (_eat_char(s, idx, 'h')) 1181 return PrintfQualifierByte; 1182 else 1183 return PrintfQualifierShort; 1184 1185 case 'l': 1186 if (_eat_char(s, idx, 'l')) 1187 return PrintfQualifierLongLong; 1188 else 1189 return PrintfQualifierLong; 1190 1191 case 'j': 1192 return PrintfQualifierLongLong; 1193 1194 default: 1195 --*idx; 1196 1197 /* Unspecified */ 1198 return PrintfQualifierInt; 1199 } 1200 } 1243 1201 1244 1202 /** Print formatted string. … … 1333 1291 int printf_core(const char *fmt, printf_spec_t *ps, va_list ap) 1334 1292 { 1335 size_t i; /* Index of the currently processed character from fmt */1293 errno_t rc = EOK; 1336 1294 size_t nxt = 0; /* Index of the next character from fmt */ 1337 size_t j = 0; /* Index to the first not printed nonformating character */1338 1295 1339 1296 size_t counter = 0; /* Number of characters printed */ 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) 1347 break; 1348 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; 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) 1304 break; 1305 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; 1359 1329 } 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 } 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); 1416 1346 } 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 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':; 1534 1380 #ifdef HAS_FLOAT 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; 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); 1555 1385 #endif 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); 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; 1671 1476 } 1672 1477 -
common/stdc/vsnprintf.c
r240b2e4 rc7c6afd 1 1 /* 2 2 * Copyright (c) 2006 Josef Cejka 3 * Copyright (c) 2025 Jiří Zárevúcky 3 4 * All rights reserved. 4 5 * … … 27 28 */ 28 29 29 /** @addtogroup kernel_generic30 /** @addtogroup libc 30 31 * @{ 31 32 */ … … 33 34 */ 34 35 35 #ifndef KERN_PRINTF_CORE_H_ 36 #define KERN_PRINTF_CORE_H_ 36 #include <errno.h> 37 #include <macros.h> 38 #include <printf_core.h> 39 #include <stdarg.h> 40 #include <stdio.h> 41 #include <str.h> 37 42 38 #include <stdarg.h> 39 #include <stddef.h> 40 #include <uchar.h> 43 typedef struct { 44 char *dst; /* Destination */ 45 size_t left; 46 } vsnprintf_data_t; 41 47 42 /** Structure for specifying output methods for different printf clones. */ 43 typedef struct { 44 /* String output function, returns number of printed characters or EOF */ 45 int (*str_write)(const char *, size_t, void *); 48 static int vsnprintf_str_write(const char *str, size_t size, void *data) 49 { 50 vsnprintf_data_t *d = data; 51 size_t left = min(size, d->left); 52 if (left > 0) { 53 memcpy(d->dst, str, left); 54 d->dst += left; 55 d->left -= left; 56 } 57 return EOK; 58 } 46 59 47 /* Wide string output function, returns number of printed characters or EOF */ 48 int (*wstr_write)(const char32_t *, size_t, void *); 60 int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) 61 { 62 vsnprintf_data_t data = { 63 .dst = str, 64 .left = size ? size - 1 : 0, 65 }; 49 66 50 /* User data - output stream specification, state, locks, etc. */ 51 void *data; 52 } printf_spec_t; 67 printf_spec_t ps = { 68 vsnprintf_str_write, 69 &data 70 }; 53 71 54 extern int printf_core(const char *fmt, printf_spec_t *ps, va_list ap); 72 int written = printf_core(fmt, &ps, ap); 73 if (written < 0) 74 return written; 55 75 56 #endif 76 /* Write the terminating NUL character. */ 77 if (size > 0) 78 data.dst[0] = 0; 79 80 return written; 81 } 57 82 58 83 /** @} -
kernel/generic/meson.build
r240b2e4 rc7c6afd 40 40 'common/adt/list.c', 41 41 'common/adt/odict.c', 42 'common/gsort.c', 42 43 'common/printf/printf_core.c', 43 44 'common/stdc/calloc.c', 44 45 'common/stdc/ctype.c', 45 46 'common/stdc/mem.c', 46 'common/gsort.c', 47 'common/stdc/snprintf.c', 48 'common/stdc/vsnprintf.c', 47 49 'common/str.c', 48 50 'common/str_error.c', … … 96 98 'src/mm/reserve.c', 97 99 'src/printf/printf.c', 98 'src/printf/snprintf.c',99 100 '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
r240b2e4 rc7c6afd 33 33 */ 34 34 35 #include <sysinfo/sysinfo.h> 36 #include <synch/spinlock.h> 37 #include <typedefs.h> 35 #include <abi/log.h> 36 #include <arch.h> 37 #include <atomic.h> 38 #include <console/console.h> 39 #include <ddi/ddi.h> 38 40 #include <ddi/irq.h> 39 #include < ddi/ddi.h>41 #include <errno.h> 40 42 #include <ipc/event.h> 41 43 #include <ipc/irq.h> 42 #include < arch.h>44 #include <log.h> 43 45 #include <panic.h> 46 #include <print.h> 47 #include <printf_core.h> 44 48 #include <putchar.h> 45 #include <atomic.h> 49 #include <stdarg.h> 50 #include <stdlib.h> 51 #include <str.h> 52 #include <synch/spinlock.h> 46 53 #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> 52 #include <log.h> 53 #include <console/console.h> 54 #include <abi/log.h> 55 #include <stdlib.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 size_t chars = 0; 207 208 while (offset < size) { 206 207 while (offset < size) 209 208 kio_push_char(str_decode(str, &offset, size)); 210 chars++;211 }212 209 213 210 log_append((const uint8_t *)str, size); 214 211 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; 212 return EOK; 237 213 } 238 214 … … 243 219 int log_vprintf(const char *fmt, va_list args) 244 220 { 245 int ret;246 247 221 printf_spec_t ps = { 248 222 log_printf_str_write, 249 log_printf_wstr_write,250 223 NULL 251 224 }; 252 225 253 ret = printf_core(fmt, &ps, args); 254 255 return ret; 226 return printf_core(fmt, &ps, args); 256 227 } 257 228 -
kernel/generic/src/printf/vprintf.c
r240b2e4 rc7c6afd 36 36 #include <console/console.h> 37 37 #include <print.h> 38 #include <printf /printf_core.h>38 #include <printf_core.h> 39 39 #include <putchar.h> 40 40 #include <str.h> … … 42 42 #include <typedefs.h> 43 43 44 static int vprintf_str_write(const char *str, size_t size, void *data)44 static errno_t vprintf_str_write(const char *str, size_t size, void *data) 45 45 { 46 46 size_t offset = 0; 47 size_t chars = 0;48 47 49 while (offset < size) {48 while (offset < size) 50 49 putuchar(str_decode(str, &offset, size)); 51 chars++;52 }53 50 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; 51 return EOK; 69 52 } 70 53 … … 92 75 printf_spec_t ps = { 93 76 vprintf_str_write, 94 vprintf_wstr_write,95 77 NULL 96 78 }; -
uspace/lib/c/generic/io/asprintf.c
r240b2e4 rc7c6afd 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 NULL59 };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 }73 42 74 43 /** Allocate and print to string. … … 115 84 int ret = vasprintf(strp, fmt, args); 116 85 va_end(args); 117 118 86 return ret; 119 87 } -
uspace/lib/c/generic/io/kio.c
r240b2e4 rc7c6afd 131 131 } 132 132 133 static int kio_vprintf_str_write(const char *str, size_t size, void *data)133 static errno_t kio_vprintf_str_write(const char *str, size_t size, void *data) 134 134 { 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; 135 size_t wr = 0; 136 return kio_write(str, size, &wr); 160 137 } 161 138 … … 172 149 printf_spec_t ps = { 173 150 kio_vprintf_str_write, 174 kio_vprintf_wstr_write,175 151 NULL 176 152 }; -
uspace/lib/c/generic/io/vprintf.c
r240b2e4 rc7c6afd 42 42 static FIBRIL_MUTEX_INITIALIZE(printf_mutex); 43 43 44 static int vprintf_str_write(const char *str, size_t size, void *stream)44 static errno_t vprintf_str_write(const char *str, size_t size, void *stream) 45 45 { 46 size_t wr = fwrite(str, 1, size, (FILE *) stream); 47 return str_nlength(str, wr); 48 } 46 errno_t old_errno = errno; 49 47 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; 48 errno = EOK; 49 size_t written = fwrite(str, 1, size, (FILE *) stream); 54 50 55 while (offset < size) { 56 if (fputuc(str[chars], (FILE *) stream) <= 0) 57 break; 51 if (errno == EOK && written != size) 52 errno = EIO; 58 53 59 chars++; 60 offset += sizeof(char32_t); 61 } 54 if (errno != EOK) 55 return errno; 62 56 63 return chars; 57 errno = old_errno; 58 return EOK; 64 59 } 65 60 … … 77 72 printf_spec_t ps = { 78 73 vprintf_str_write, 79 vprintf_wstr_write,80 74 stream 81 75 }; -
uspace/lib/c/include/stdio.h
r240b2e4 rc7c6afd 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);214 211 extern FILE *fdopen(int, const char *); 215 212 extern int fileno(FILE *); -
uspace/lib/c/meson.build
r240b2e4 rc7c6afd 72 72 'common/stdc/mem.c', 73 73 'common/stdc/qsort.c', 74 'common/stdc/snprintf.c', 74 75 'common/stdc/uchar.c', 76 'common/stdc/vsnprintf.c', 75 77 'common/stdc/wchar.c', 76 78 'common/str.c', … … 113 115 'generic/io/logctl.c', 114 116 'generic/io/printf.c', 115 'generic/io/snprintf.c',116 117 'generic/io/table.c', 117 118 '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
r240b2e4 rc7c6afd 232 232 * @return The number of written characters. 233 233 */ 234 static int _dprintf_str_write(const char *str, size_t size, void *fd)234 static errno_t _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 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; 238 return vfs_write(fildes, &posix_pos[fildes], str, size, &wr); 274 239 } 275 240 … … 285 250 { 286 251 printf_spec_t spec = { 287 .str_write = _dprintf_str_write, 288 .wstr_write = _dprintf_wstr_write, 252 .write = _dprintf_str_write, 289 253 .data = &fildes 290 254 };
Note:
See TracChangeset
for help on using the changeset viewer.