From 4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 27 Mar 2012 11:51:08 +0200 Subject: reorganize file structure to match the upstream requirements --- pintos-progos/lib/stdio.c | 655 ---------------------------------------------- 1 file changed, 655 deletions(-) delete mode 100644 pintos-progos/lib/stdio.c (limited to 'pintos-progos/lib/stdio.c') diff --git a/pintos-progos/lib/stdio.c b/pintos-progos/lib/stdio.c deleted file mode 100644 index 8927c50..0000000 --- a/pintos-progos/lib/stdio.c +++ /dev/null @@ -1,655 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* Auxiliary data for vsnprintf_helper(). */ -struct vsnprintf_aux - { - char *p; /* Current output position. */ - int length; /* Length of output string. */ - int max_length; /* Max length of output string. */ - }; - -static void vsnprintf_helper (char, void *); - -/* Like vprintf(), except that output is stored into BUFFER, - which must have space for BUF_SIZE characters. Writes at most - BUF_SIZE - 1 characters to BUFFER, followed by a null - terminator. BUFFER will always be null-terminated unless - BUF_SIZE is zero. Returns the number of characters that would - have been written to BUFFER, not including a null terminator, - had there been enough room. */ -int -vsnprintf (char *buffer, size_t buf_size, const char *format, va_list args) -{ - /* Set up aux data for vsnprintf_helper(). */ - struct vsnprintf_aux aux; - aux.p = buffer; - aux.length = 0; - aux.max_length = buf_size > 0 ? buf_size - 1 : 0; - - /* Do most of the work. */ - __vprintf (format, args, vsnprintf_helper, &aux); - - /* Add null terminator. */ - if (buf_size > 0) - *aux.p = '\0'; - - return aux.length; -} - -/* Helper function for vsnprintf(). */ -static void -vsnprintf_helper (char ch, void *aux_) -{ - struct vsnprintf_aux *aux = aux_; - - if (aux->length++ < aux->max_length) - *aux->p++ = ch; -} - -/* Like printf(), except that output is stored into BUFFER, - which must have space for BUF_SIZE characters. Writes at most - BUF_SIZE - 1 characters to BUFFER, followed by a null - terminator. BUFFER will always be null-terminated unless - BUF_SIZE is zero. Returns the number of characters that would - have been written to BUFFER, not including a null terminator, - had there been enough room. */ -int -snprintf (char *buffer, size_t buf_size, const char *format, ...) -{ - va_list args; - int retval; - - va_start (args, format); - retval = vsnprintf (buffer, buf_size, format, args); - va_end (args); - - return retval; -} - -/* Writes formatted output to the console. - In the kernel, the console is both the video display and first - serial port. - In userspace, the console is file descriptor 1. */ -int -printf (const char *format, ...) -{ - va_list args; - int retval; - - va_start (args, format); - retval = vprintf (format, args); - va_end (args); - - return retval; -} - -/* printf() formatting internals. */ - -/* A printf() conversion. */ -struct printf_conversion - { - /* Flags. */ - enum - { - MINUS = 1 << 0, /* '-' */ - PLUS = 1 << 1, /* '+' */ - SPACE = 1 << 2, /* ' ' */ - POUND = 1 << 3, /* '#' */ - ZERO = 1 << 4, /* '0' */ - GROUP = 1 << 5 /* '\'' */ - } - flags; - - /* Minimum field width. */ - int width; - - /* Numeric precision. - -1 indicates no precision was specified. */ - int precision; - - /* Type of argument to format. */ - enum - { - CHAR = 1, /* hh */ - SHORT = 2, /* h */ - INT = 3, /* (none) */ - INTMAX = 4, /* j */ - LONG = 5, /* l */ - LONGLONG = 6, /* ll */ - PTRDIFFT = 7, /* t */ - SIZET = 8 /* z */ - } - type; - }; - -struct integer_base - { - int base; /* Base. */ - const char *digits; /* Collection of digits. */ - int x; /* `x' character to use, for base 16 only. */ - int group; /* Number of digits to group with ' flag. */ - }; - -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}; - -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) -{ - for (; *format != '\0'; format++) - { - struct printf_conversion c; - - /* Literally copy non-conversions to output. */ - if (*format != '%') - { - output (*format, aux); - continue; - } - format++; - - /* %% => %. */ - if (*format == '%') - { - output ('%', aux); - continue; - } - - /* Parse conversion specifiers. */ - format = parse_conversion (format, &c, &args); - - /* Do conversion. */ - switch (*format) - { - case 'd': - case 'i': - { - /* Signed integer conversions. */ - intmax_t value; - - switch (c.type) - { - case CHAR: - value = (signed char) va_arg (args, int); - break; - case SHORT: - value = (short) va_arg (args, int); - break; - case INT: - value = va_arg (args, int); - break; - case INTMAX: - value = va_arg (args, intmax_t); - break; - case LONG: - value = va_arg (args, long); - break; - case LONGLONG: - value = va_arg (args, long long); - break; - case PTRDIFFT: - value = va_arg (args, ptrdiff_t); - break; - case SIZET: - value = va_arg (args, size_t); - if (value > SIZE_MAX / 2) - value = value - SIZE_MAX - 1; - break; - default: - NOT_REACHED (); - } - - format_integer (value < 0 ? -value : value, - true, value < 0, &base_d, &c, output, aux); - } - break; - - case 'o': - case 'u': - case 'x': - case 'X': - { - /* Unsigned integer conversions. */ - uintmax_t value; - const struct integer_base *b; - - switch (c.type) - { - case CHAR: - value = (unsigned char) va_arg (args, unsigned); - break; - case SHORT: - value = (unsigned short) va_arg (args, unsigned); - break; - case INT: - value = va_arg (args, unsigned); - break; - case INTMAX: - value = va_arg (args, uintmax_t); - break; - case LONG: - value = va_arg (args, unsigned long); - break; - case LONGLONG: - value = va_arg (args, unsigned long long); - break; - case PTRDIFFT: - value = va_arg (args, ptrdiff_t); -#if UINTMAX_MAX != PTRDIFF_MAX - value &= ((uintmax_t) PTRDIFF_MAX << 1) | 1; -#endif - break; - case SIZET: - value = va_arg (args, size_t); - break; - default: - NOT_REACHED (); - } - - switch (*format) - { - case 'o': b = &base_o; break; - case 'u': b = &base_d; break; - case 'x': b = &base_x; break; - case 'X': b = &base_X; break; - default: NOT_REACHED (); - } - - format_integer (value, false, false, b, &c, output, aux); - } - break; - - case 'c': - { - /* Treat character as single-character string. */ - char ch = va_arg (args, int); - format_string (&ch, 1, &c, output, aux); - } - break; - - case 's': - { - /* String conversion. */ - const char *s = va_arg (args, char *); - if (s == NULL) - s = "(null)"; - - /* Limit string length according to precision. - Note: if c.precision == -1 then strnlen() will get - SIZE_MAX for MAXLEN, which is just what we want. */ - format_string (s, strnlen (s, c.precision), &c, output, aux); - } - break; - - case 'p': - { - /* Pointer conversion. - Format pointers as %#x. */ - void *p = va_arg (args, void *); - - c.flags = POUND; - format_integer ((uintptr_t) p, false, false, - &base_x, &c, output, aux); - } - break; - - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - case 'n': - /* We don't support floating-point arithmetic, - and %n can be part of a security hole. */ - __printf ("<>", output, aux, *format); - break; - - default: - __printf ("<>", output, aux, *format); - break; - } - } -} - -/* Parses conversion option characters starting at FORMAT and - initializes C appropriately. Returns the character in FORMAT - that indicates the conversion (e.g. the `d' in `%d'). Uses - *ARGS for `*' field widths and precisions. */ -static const char * -parse_conversion (const char *format, struct printf_conversion *c, - va_list *args) -{ - /* Parse flag characters. */ - c->flags = 0; - for (;;) - { - switch (*format++) - { - case '-': - c->flags |= MINUS; - break; - case '+': - c->flags |= PLUS; - break; - case ' ': - c->flags |= SPACE; - break; - case '#': - c->flags |= POUND; - break; - case '0': - c->flags |= ZERO; - break; - case '\'': - c->flags |= GROUP; - break; - default: - format--; - goto not_a_flag; - } - } - not_a_flag: - if (c->flags & MINUS) - c->flags &= ~ZERO; - if (c->flags & PLUS) - c->flags &= ~SPACE; - - /* Parse field width. */ - c->width = 0; - if (*format == '*') - { - format++; - c->width = va_arg (*args, int); - } - else - { - for (; isdigit (*format); format++) - c->width = c->width * 10 + *format - '0'; - } - if (c->width < 0) - { - c->width = -c->width; - c->flags |= MINUS; - } - - /* Parse precision. */ - c->precision = -1; - if (*format == '.') - { - format++; - if (*format == '*') - { - format++; - c->precision = va_arg (*args, int); - } - else - { - c->precision = 0; - for (; isdigit (*format); format++) - c->precision = c->precision * 10 + *format - '0'; - } - if (c->precision < 0) - c->precision = -1; - } - if (c->precision >= 0) - c->flags &= ~ZERO; - - /* Parse type. */ - c->type = INT; - switch (*format++) - { - case 'h': - if (*format == 'h') - { - format++; - c->type = CHAR; - } - else - c->type = SHORT; - break; - - case 'j': - c->type = INTMAX; - break; - - case 'l': - if (*format == 'l') - { - format++; - c->type = LONGLONG; - } - else - c->type = LONG; - break; - - case 't': - c->type = PTRDIFFT; - break; - - case 'z': - c->type = SIZET; - break; - - default: - format--; - break; - } - - return format; -} - -/* Performs an integer conversion, writing output to OUTPUT with - auxiliary data AUX. The integer converted has absolute value - VALUE. If IS_SIGNED is true, does a signed conversion with - NEGATIVE indicating a negative value; otherwise does an - unsigned conversion and ignores NEGATIVE. The output is done - according to the provided base B. Details of the conversion - are in C. */ -static void -format_integer (uintmax_t value, bool is_signed, bool negative, - const struct integer_base *b, - const struct printf_conversion *c, - void (*output) (char, void *), void *aux) -{ - char buf[64], *cp; /* Buffer and current position. */ - int x; /* `x' character to use or 0 if none. */ - int sign; /* Sign character or 0 if none. */ - int precision; /* Rendered precision. */ - int pad_cnt; /* # of pad characters to fill field width. */ - int digit_cnt; /* # of digits output so far. */ - - /* Determine sign character, if any. - An unsigned conversion will never have a sign character, - even if one of the flags requests one. */ - sign = 0; - if (is_signed) - { - if (c->flags & PLUS) - sign = negative ? '-' : '+'; - else if (c->flags & SPACE) - sign = negative ? '-' : ' '; - else if (negative) - sign = '-'; - } - - /* Determine whether to include `0x' or `0X'. - It will only be included with a hexadecimal conversion of a - nonzero value with the # flag. */ - x = (c->flags & POUND) && value ? b->x : 0; - - /* Accumulate digits into buffer. - This algorithm produces digits in reverse order, so later we - will output the buffer's content in reverse. */ - cp = buf; - digit_cnt = 0; - while (value > 0) - { - if ((c->flags & GROUP) && digit_cnt > 0 && digit_cnt % b->group == 0) - *cp++ = ','; - *cp++ = b->digits[value % b->base]; - value /= b->base; - digit_cnt++; - } - - /* Append enough zeros to match precision. - If requested precision is 0, then a value of zero is - rendered as a null string, otherwise as "0". - If the # flag is used with base 8, the result must always - begin with a zero. */ - precision = c->precision < 0 ? 1 : c->precision; - while (cp - buf < precision && cp < buf + sizeof buf - 1) - *cp++ = '0'; - if ((c->flags & POUND) && b->base == 8 && (cp == buf || cp[-1] != '0')) - *cp++ = '0'; - - /* Calculate number of pad characters to fill field width. */ - pad_cnt = c->width - (cp - buf) - (x ? 2 : 0) - (sign != 0); - if (pad_cnt < 0) - pad_cnt = 0; - - /* Do output. */ - if ((c->flags & (MINUS | ZERO)) == 0) - output_dup (' ', pad_cnt, output, aux); - if (sign) - output (sign, aux); - if (x) - { - output ('0', aux); - output (x, aux); - } - if (c->flags & ZERO) - output_dup ('0', pad_cnt, output, aux); - while (cp > buf) - output (*--cp, aux); - if (c->flags & MINUS) - output_dup (' ', pad_cnt, output, aux); -} - -/* Writes CH to OUTPUT with auxiliary data AUX, CNT times. */ -static void -output_dup (char ch, size_t cnt, void (*output) (char, void *), void *aux) -{ - while (cnt-- > 0) - output (ch, aux); -} - -/* Formats the LENGTH characters starting at STRING according to - the conversion specified in C. Writes output to OUTPUT with - auxiliary data AUX. */ -static void -format_string (const char *string, int length, - struct printf_conversion *c, - void (*output) (char, void *), void *aux) -{ - int i; - if (c->width > length && (c->flags & MINUS) == 0) - output_dup (' ', c->width - length, output, aux); - for (i = 0; i < length; i++) - output (string[i], aux); - if (c->width > length && (c->flags & MINUS) != 0) - output_dup (' ', c->width - length, output, aux); -} - -/* Wrapper for __vprintf() that converts varargs into a - va_list. */ -void -__printf (const char *format, - void (*output) (char, void *), void *aux, ...) -{ - va_list args; - - va_start (args, aux); - __vprintf (format, args, output, aux); - va_end (args); -} - -/* Dumps the SIZE bytes in BUF to the console as hex bytes - arranged 16 per line. Numeric offsets are also included, - starting at OFS for the first byte in BUF. If ASCII is true - then the corresponding ASCII characters are also rendered - alongside. */ -void -hex_dump (uintptr_t ofs, const void *buf_, size_t size, bool ascii) -{ - const uint8_t *buf = buf_; - const size_t per_line = 16; /* Maximum bytes per line. */ - - while (size > 0) - { - size_t start, end, n; - size_t i; - - /* Number of bytes on this line. */ - start = ofs % per_line; - end = per_line; - if (end - start > size) - end = start + size; - n = end - start; - - /* Print line. */ - printf ("%08jx ", (uintmax_t) ROUND_DOWN (ofs, per_line)); - for (i = 0; i < start; i++) - printf (" "); - for (; i < end; i++) - printf ("%02hhx%c", - buf[i - start], i == per_line / 2 - 1? '-' : ' '); - if (ascii) - { - for (; i < per_line; i++) - printf (" "); - printf ("|"); - for (i = 0; i < start; i++) - printf (" "); - for (; i < end; i++) - printf ("%c", - isprint (buf[i - start]) ? buf[i - start] : '.'); - for (; i < per_line; i++) - printf (" "); - printf ("|"); - } - printf ("\n"); - - ofs += n; - buf += n; - size -= n; - } -} - -/* Prints SIZE, which represents a number of bytes, in a - human-readable format, e.g. "256 kB". */ -void -print_human_readable_size (uint64_t size) -{ - if (size == 1) - printf ("1 byte"); - else - { - static const char *factors[] = {"bytes", "kB", "MB", "GB", "TB", NULL}; - const char **fp; - - for (fp = factors; size >= 1024 && fp[1] != NULL; fp++) - size /= 1024; - printf ("%"PRIu64" %s", size, *fp); - } -} -- cgit v1.2.3