[Krafton Jungle] PintOS 2.0.0
크래프톤 정글 PintOS
 
Loading...
Searching...
No Matches
stdio.c File Reference
#include <stdio.h>
#include <ctype.h>
#include <inttypes.h>
#include <round.h>
#include <stdint.h>
#include <string.h>
Include dependency graph for stdio.c:

Classes

struct  vsnprintf_aux
 
struct  printf_conversion
 
struct  integer_base
 

Functions

static void vsnprintf_helper (char, void *)
 
int vsnprintf (char *buffer, size_t buf_size, const char *format, va_list args)
 
int snprintf (char *buffer, size_t buf_size, const char *format,...)
 
int printf (const char *format,...)
 
static const char * parse_conversion (const char *format, struct printf_conversion *, va_list *)
 
static void format_integer (uintmax_t value, bool is_signed, bool negative, const struct integer_base *, const struct printf_conversion *, void(*output)(char, void *), void *aux)
 
static void output_dup (char ch, size_t cnt, void(*output)(char, void *), void *aux)
 
static void format_string (const char *string, int length, struct printf_conversion *, void(*output)(char, void *), void *aux)
 
void __vprintf (const char *format, va_list args, void(*output)(char, void *), void *aux)
 
void __printf (const char *format, void(*output)(char, void *), void *aux,...)
 
void hex_dump (uintptr_t ofs, const void *buf_, size_t size, bool ascii)
 

Variables

static const struct integer_base base_d = {10, "0123456789", 0, 3}
 
static const struct integer_base base_o = {8, "01234567", 0, 3}
 
static const struct integer_base base_x = {16, "0123456789abcdef", 'x', 4}
 
static const struct integer_base base_X = {16, "0123456789ABCDEF", 'X', 4}
 

Function Documentation

◆ __printf()

void __printf ( const char *  format,
void(*)(char, void *)  output,
void *  aux,
  ... 
)
539 {
540 va_list args;
541
542 va_start (args, aux);
543 __vprintf (format, args, output, aux);
544 va_end (args);
545}
#define va_end(LIST)
Definition: stdarg.h:10
#define va_start(LIST, ARG)
Definition: stdarg.h:9
__builtin_va_list va_list
Definition: stdarg.h:7
void __vprintf(const char *format, va_list args, void(*output)(char, void *), void *aux)
Definition: stdio.c:146
Here is the call graph for this function:
Here is the caller graph for this function:

◆ __vprintf()

void __vprintf ( const char *  format,
va_list  args,
void(*)(char, void *)  output,
void *  aux 
)
147 {
148 for (; *format != '\0'; format++) {
149 struct printf_conversion c;
150
151 /* Literally copy non-conversions to output. */
152 if (*format != '%') {
153 output (*format, aux);
154 continue;
155 }
156 format++;
157
158 /* %% => %. */
159 if (*format == '%') {
160 output ('%', aux);
161 continue;
162 }
163
164 /* Parse conversion specifiers. */
165 format = parse_conversion (format, &c, &args);
166
167 /* Do conversion. */
168 switch (*format) {
169 case 'd':
170 case 'i':
171 {
172 /* Signed integer conversions. */
173 intmax_t value;
174
175 switch (c.type) {
176 case CHAR:
177 value = (signed char) va_arg (args, int);
178 break;
179 case SHORT:
180 value = (short) va_arg (args, int);
181 break;
182 case INT:
183 value = va_arg (args, int);
184 break;
185 case INTMAX:
186 value = va_arg (args, intmax_t);
187 break;
188 case LONG:
189 value = va_arg (args, long);
190 break;
191 case LONGLONG:
192 value = va_arg (args, long long);
193 break;
194 case PTRDIFFT:
195 value = va_arg (args, ptrdiff_t);
196 break;
197 case SIZET:
198 value = va_arg (args, size_t);
199 if (value > SIZE_MAX / 2)
200 value = value - SIZE_MAX - 1;
201 break;
202 default:
203 NOT_REACHED ();
204 }
205
206 format_integer (value < 0 ? -value : value,
207 true, value < 0, &base_d, &c, output, aux);
208 }
209 break;
210
211 case 'o':
212 case 'u':
213 case 'x':
214 case 'X':
215 {
216 /* Unsigned integer conversions. */
217 uintmax_t value;
218 const struct integer_base *b;
219
220 switch (c.type) {
221 case CHAR:
222 value = (unsigned char) va_arg (args, unsigned);
223 break;
224 case SHORT:
225 value = (unsigned short) va_arg (args, unsigned);
226 break;
227 case INT:
228 value = va_arg (args, unsigned);
229 break;
230 case INTMAX:
231 value = va_arg (args, uintmax_t);
232 break;
233 case LONG:
234 value = va_arg (args, unsigned long);
235 break;
236 case LONGLONG:
237 value = va_arg (args, unsigned long long);
238 break;
239 case PTRDIFFT:
240 value = va_arg (args, ptrdiff_t);
241#if UINTMAX_MAX != PTRDIFF_MAX
242 value &= ((uintmax_t) PTRDIFF_MAX << 1) | 1;
243#endif
244 break;
245 case SIZET:
246 value = va_arg (args, size_t);
247 break;
248 default:
249 NOT_REACHED ();
250 }
251
252 switch (*format) {
253 case 'o': b = &base_o; break;
254 case 'u': b = &base_d; break;
255 case 'x': b = &base_x; break;
256 case 'X': b = &base_X; break;
257 default: NOT_REACHED ();
258 }
259
260 format_integer (value, false, false, b, &c, output, aux);
261 }
262 break;
263
264 case 'c':
265 {
266 /* Treat character as single-character string. */
267 char ch = va_arg (args, int);
268 format_string (&ch, 1, &c, output, aux);
269 }
270 break;
271
272 case 's':
273 {
274 /* String conversion. */
275 const char *s = va_arg (args, char *);
276 if (s == NULL)
277 s = "(null)";
278
279 /* Limit string length according to precision.
280Note: if c.precision == -1 then strnlen() will get
281SIZE_MAX for MAXLEN, which is just what we want. */
282 format_string (s, strnlen (s, c.precision), &c, output, aux);
283 }
284 break;
285
286 case 'p':
287 {
288 /* Pointer conversion.
289 Format pointers as %#x. */
290 void *p = va_arg (args, void *);
291
292 c.flags = POUND;
293 format_integer ((uintptr_t) p, false, false,
294 &base_x, &c, output, aux);
295 }
296 break;
297
298 case 'f':
299 case 'e':
300 case 'E':
301 case 'g':
302 case 'G':
303 case 'n':
304 /* We don't support floating-point arithmetic,
305 and %n can be part of a security hole. */
306 __printf ("<<no %%%c in kernel>>", output, aux, *format);
307 break;
308
309 default:
310 __printf ("<<no %%%c conversion>>", output, aux, *format);
311 break;
312 }
313 }
314}
#define NOT_REACHED()
Definition: debug.h:34
static uint8_t s[256]
Definition: random.c:17
#define va_arg(LIST, TYPE)
Definition: stdarg.h:11
#define NULL
Definition: stddef.h:4
__PTRDIFF_TYPE__ ptrdiff_t
Definition: stddef.h:9
int64_t intmax_t
Definition: stdint.h:39
uint64_t uintmax_t
Definition: stdint.h:43
#define SIZE_MAX
Definition: stdint.h:49
uint64_t uintptr_t
Definition: stdint.h:36
#define PTRDIFF_MAX
Definition: stdint.h:47
static const struct integer_base base_x
Definition: stdio.c:129
void __printf(const char *format, void(*output)(char, void *), void *aux,...)
Definition: stdio.c:538
static const struct integer_base base_o
Definition: stdio.c:128
static void format_integer(uintmax_t value, bool is_signed, bool negative, const struct integer_base *, const struct printf_conversion *, void(*output)(char, void *), void *aux)
Definition: stdio.c:437
static const char * parse_conversion(const char *format, struct printf_conversion *, va_list *)
Definition: stdio.c:321
static void format_string(const char *string, int length, struct printf_conversion *, void(*output)(char, void *), void *aux)
Definition: stdio.c:523
static const struct integer_base base_X
Definition: stdio.c:130
static const struct integer_base base_d
Definition: stdio.c:127
size_t strnlen(const char *, size_t)
Definition: string.c:284
Definition: stdio.c:120
Definition: stdio.c:89
@ INTMAX
Definition: stdio.c:112
@ LONGLONG
Definition: stdio.c:114
@ CHAR
Definition: stdio.c:109
@ SIZET
Definition: stdio.c:116
@ LONG
Definition: stdio.c:113
@ SHORT
Definition: stdio.c:110
@ INT
Definition: stdio.c:111
@ PTRDIFFT
Definition: stdio.c:115
Here is the call graph for this function:
Here is the caller graph for this function:

◆ format_integer()

static void format_integer ( uintmax_t  value,
bool  is_signed,
bool  negative,
const struct integer_base b,
const struct printf_conversion c,
void(*)(char, void *)  output,
void *  aux 
)
static
440 {
441 char buf[64], *cp; /* Buffer and current position. */
442 int x; /* `x' character to use or 0 if none. */
443 int sign; /* Sign character or 0 if none. */
444 int precision; /* Rendered precision. */
445 int pad_cnt; /* # of pad characters to fill field width. */
446 int digit_cnt; /* # of digits output so far. */
447
448 /* Determine sign character, if any.
449 An unsigned conversion will never have a sign character,
450 even if one of the flags requests one. */
451 sign = 0;
452 if (is_signed) {
453 if (c->flags & PLUS)
454 sign = negative ? '-' : '+';
455 else if (c->flags & SPACE)
456 sign = negative ? '-' : ' ';
457 else if (negative)
458 sign = '-';
459 }
460
461 /* Determine whether to include `0x' or `0X'.
462 It will only be included with a hexadecimal conversion of a
463 nonzero value with the # flag. */
464 x = (c->flags & POUND) && value ? b->x : 0;
465
466 /* Accumulate digits into buffer.
467 This algorithm produces digits in reverse order, so later we
468 will output the buffer's content in reverse. */
469 cp = buf;
470 digit_cnt = 0;
471 while (value > 0) {
472 if ((c->flags & GROUP) && digit_cnt > 0 && digit_cnt % b->group == 0)
473 *cp++ = ',';
474 *cp++ = b->digits[value % b->base];
475 value /= b->base;
476 digit_cnt++;
477 }
478
479 /* Append enough zeros to match precision.
480 If requested precision is 0, then a value of zero is
481 rendered as a null string, otherwise as "0".
482 If the # flag is used with base 8, the result must always
483 begin with a zero. */
484 precision = c->precision < 0 ? 1 : c->precision;
485 while (cp - buf < precision && cp < buf + sizeof buf - 1)
486 *cp++ = '0';
487 if ((c->flags & POUND) && b->base == 8 && (cp == buf || cp[-1] != '0'))
488 *cp++ = '0';
489
490 /* Calculate number of pad characters to fill field width. */
491 pad_cnt = c->width - (cp - buf) - (x ? 2 : 0) - (sign != 0);
492 if (pad_cnt < 0)
493 pad_cnt = 0;
494
495 /* Do output. */
496 if ((c->flags & (MINUS | ZERO)) == 0)
497 output_dup (' ', pad_cnt, output, aux);
498 if (sign)
499 output (sign, aux);
500 if (x) {
501 output ('0', aux);
502 output (x, aux);
503 }
504 if (c->flags & ZERO)
505 output_dup ('0', pad_cnt, output, aux);
506 while (cp > buf)
507 output (*--cp, aux);
508 if (c->flags & MINUS)
509 output_dup (' ', pad_cnt, output, aux);
510}
static void output_dup(char ch, size_t cnt, void(*output)(char, void *), void *aux)
Definition: stdio.c:514
int x
Definition: stdio.c:123
int base
Definition: stdio.c:121
int group
Definition: stdio.c:124
const char * digits
Definition: stdio.c:122
int width
Definition: stdio.c:101
enum printf_conversion::@4 flags
int precision
Definition: stdio.c:105
Here is the call graph for this function:
Here is the caller graph for this function:

◆ format_string()

static void format_string ( const char *  string,
int  length,
struct printf_conversion c,
void(*)(char, void *)  output,
void *  aux 
)
static
525 {
526 int i;
527 if (c->width > length && (c->flags & MINUS) == 0)
528 output_dup (' ', c->width - length, output, aux);
529 for (i = 0; i < length; i++)
530 output (string[i], aux);
531 if (c->width > length && (c->flags & MINUS) != 0)
532 output_dup (' ', c->width - length, output, aux);
533}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hex_dump()

void hex_dump ( uintptr_t  ofs,
const void *  buf_,
size_t  size,
bool  ascii 
)
553 {
554 const uint8_t *buf = buf_;
555 const size_t per_line = 16; /* Maximum bytes per line. */
556
557 while (size > 0) {
558 size_t start, end, n;
559 size_t i;
560
561 /* Number of bytes on this line. */
562 start = ofs % per_line;
563 end = per_line;
564 if (end - start > size)
565 end = start + size;
566 n = end - start;
567
568 /* Print line. */
569 printf ("%016llx ", (uintmax_t) ROUND_DOWN (ofs, per_line));
570 for (i = 0; i < start; i++)
571 printf (" ");
572 for (; i < end; i++)
573 printf ("%02hhx%c",
574 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
575 if (ascii) {
576 for (; i < per_line; i++)
577 printf (" ");
578 printf ("|");
579 for (i = 0; i < start; i++)
580 printf (" ");
581 for (; i < end; i++)
582 printf ("%c",
583 isprint (buf[i - start]) ? buf[i - start] : '.');
584 for (; i < per_line; i++)
585 printf (" ");
586 printf ("|");
587 }
588 printf ("\n");
589
590 ofs += n;
591 buf += n;
592 size -= n;
593 }
594}
static int isprint(int c)
Definition: ctype.h:18
uint16_t size
Definition: mmu.h:0
#define ROUND_DOWN(X, STEP)
Definition: round.h:14
unsigned char uint8_t
Definition: stdint.h:20
int printf(const char *format,...)
Definition: stdio.c:75
Here is the call graph for this function:
Here is the caller graph for this function:

◆ output_dup()

static void output_dup ( char  ch,
size_t  cnt,
void(*)(char, void *)  output,
void *  aux 
)
static
514 {
515 while (cnt-- > 0)
516 output (ch, aux);
517}
Here is the caller graph for this function:

◆ parse_conversion()

static const char * parse_conversion ( const char *  format,
struct printf_conversion c,
va_list args 
)
static
322 {
323 /* Parse flag characters. */
324 c->flags = 0;
325 for (;;) {
326 switch (*format++) {
327 case '-':
328 c->flags |= MINUS;
329 break;
330 case '+':
331 c->flags |= PLUS;
332 break;
333 case ' ':
334 c->flags |= SPACE;
335 break;
336 case '#':
337 c->flags |= POUND;
338 break;
339 case '0':
340 c->flags |= ZERO;
341 break;
342 case '\'':
343 c->flags |= GROUP;
344 break;
345 default:
346 format--;
347 goto not_a_flag;
348 }
349 }
350not_a_flag:
351 if (c->flags & MINUS)
352 c->flags &= ~ZERO;
353 if (c->flags & PLUS)
354 c->flags &= ~SPACE;
355
356 /* Parse field width. */
357 c->width = 0;
358 if (*format == '*') {
359 format++;
360 c->width = va_arg (*args, int);
361 } else {
362 for (; isdigit (*format); format++)
363 c->width = c->width * 10 + *format - '0';
364 }
365 if (c->width < 0) {
366 c->width = -c->width;
367 c->flags |= MINUS;
368 }
369
370 /* Parse precision. */
371 c->precision = -1;
372 if (*format == '.') {
373 format++;
374 if (*format == '*') {
375 format++;
376 c->precision = va_arg (*args, int);
377 } else {
378 c->precision = 0;
379 for (; isdigit (*format); format++)
380 c->precision = c->precision * 10 + *format - '0';
381 }
382 if (c->precision < 0)
383 c->precision = -1;
384 }
385 if (c->precision >= 0)
386 c->flags &= ~ZERO;
387
388 /* Parse type. */
389 c->type = INT;
390 switch (*format++) {
391 case 'h':
392 if (*format == 'h') {
393 format++;
394 c->type = CHAR;
395 }
396 else
397 c->type = SHORT;
398 break;
399
400 case 'j':
401 c->type = INTMAX;
402 break;
403
404 case 'l':
405 if (*format == 'l') {
406 format++;
407 c->type = LONGLONG;
408 }
409 else
410 c->type = LONG;
411 break;
412
413 case 't':
414 c->type = PTRDIFFT;
415 break;
416
417 case 'z':
418 c->type = SIZET;
419 break;
420
421 default:
422 format--;
423 break;
424 }
425
426 return format;
427}
static int isdigit(int c)
Definition: ctype.h:7
enum printf_conversion::@5 type
Here is the call graph for this function:
Here is the caller graph for this function:

◆ printf()

int printf ( const char *  format,
  ... 
)
75 {
76 va_list args;
77 int retval;
78
79 va_start (args, format);
80 retval = vprintf (format, args);
81 va_end (args);
82
83 return retval;
84}
int int int vprintf(const char *, va_list) PRINTF_FORMAT(1
Here is the call graph for this function:
Here is the caller graph for this function:

◆ snprintf()

int snprintf ( char *  buffer,
size_t  buf_size,
const char *  format,
  ... 
)
59 {
60 va_list args;
61 int retval;
62
63 va_start (args, format);
64 retval = vsnprintf (buffer, buf_size, format, args);
65 va_end (args);
66
67 return retval;
68}
static struct intq buffer
Definition: input.c:7
int vsnprintf(char *buffer, size_t buf_size, const char *format, va_list args)
Definition: stdio.c:25
Here is the call graph for this function:

◆ vsnprintf()

int vsnprintf ( char *  buffer,
size_t  buf_size,
const char *  format,
va_list  args 
)
25 {
26 /* Set up aux data for vsnprintf_helper(). */
27 struct vsnprintf_aux aux;
28 aux.p = buffer;
29 aux.length = 0;
30 aux.max_length = buf_size > 0 ? buf_size - 1 : 0;
31
32 /* Do most of the work. */
33 __vprintf (format, args, vsnprintf_helper, &aux);
34
35 /* Add null terminator. */
36 if (buf_size > 0)
37 *aux.p = '\0';
38
39 return aux.length;
40}
static void vsnprintf_helper(char, void *)
Definition: stdio.c:44
Definition: stdio.c:9
char * p
Definition: stdio.c:10
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vsnprintf_helper()

static void vsnprintf_helper ( char  ch,
void *  aux_ 
)
static
44 {
45 struct vsnprintf_aux *aux = aux_;
46
47 if (aux->length++ < aux->max_length)
48 *aux->p++ = ch;
49}
int max_length
Definition: stdio.c:12
int length
Definition: stdio.c:11
Here is the caller graph for this function:

Variable Documentation

◆ base_d

const struct integer_base base_d = {10, "0123456789", 0, 3}
static

◆ base_o

const struct integer_base base_o = {8, "01234567", 0, 3}
static

◆ base_x

const struct integer_base base_x = {16, "0123456789abcdef", 'x', 4}
static

◆ base_X

const struct integer_base base_X = {16, "0123456789ABCDEF", 'X', 4}
static