mirror of
https://github.com/drasko/codezero.git
synced 2026-02-09 08:23:22 +01:00
Created libc under containers/posix which now all tasks use to build.
There is a problem in the new libc that test0 now misbehaves. Going to be fixed.
This commit is contained in:
446
containers/posix/libc/src/printf.c
Normal file
446
containers/posix/libc/src/printf.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/*********************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2004 Karlsruhe University
|
||||
*
|
||||
* File path: generic/printk.cc
|
||||
* Description: Implementation of printf
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
********************************************************************/
|
||||
#include <stdarg.h> /* for va_list, ... comes with gcc */
|
||||
#include <stdio.h>
|
||||
|
||||
/* FIXME: LICENSE LICENCE */
|
||||
typedef unsigned int word_t;
|
||||
|
||||
extern void putc(const char c);
|
||||
extern int print_tid (word_t val, word_t width, word_t precision, int adjleft);
|
||||
|
||||
|
||||
/* convert nibble to lowercase hex char */
|
||||
#define hexchars(x) (((x) < 10) ? ('0' + (x)) : ('a' + ((x) - 10)))
|
||||
|
||||
/**
|
||||
* Print hexadecimal value
|
||||
*
|
||||
* @param val value to print
|
||||
* @param width width in caracters
|
||||
* @param precision minimum number of digits to apprear
|
||||
* @param adjleft left adjust the value
|
||||
* @param nullpad pad with leading zeros (when right padding)
|
||||
*
|
||||
* Prints a hexadecimal value with leading zeroes of given width
|
||||
* using putc(), or if adjleft argument is given, print
|
||||
* hexadecimal value with space padding to the right.
|
||||
*
|
||||
* @returns the number of charaters printed (should be same as width).
|
||||
*/
|
||||
int print_hex64(unsigned long long val, int width, int precision, int adjleft, int nullpad)
|
||||
{
|
||||
int i, n = 0;
|
||||
int nwidth = 0;
|
||||
unsigned int high, low;
|
||||
|
||||
high = val >> 32;
|
||||
low = (unsigned int)val;
|
||||
|
||||
// Find width of hexnumber
|
||||
if (high) {
|
||||
while ((high >> (4 * nwidth)) && ((unsigned) nwidth < 2 * sizeof (unsigned int)))
|
||||
nwidth++;
|
||||
nwidth += 32;
|
||||
} else {
|
||||
while ((low >> (4 * nwidth)) && ((unsigned) nwidth < 2 * sizeof (unsigned int)))
|
||||
nwidth++;
|
||||
}
|
||||
|
||||
if (nwidth == 0)
|
||||
nwidth = 1;
|
||||
|
||||
// May need to increase number of printed digits
|
||||
if (precision > nwidth)
|
||||
nwidth = precision;
|
||||
|
||||
// May need to increase number of printed characters
|
||||
if (width == 0 && width < nwidth)
|
||||
width = nwidth;
|
||||
|
||||
// Print number with padding
|
||||
if (high)
|
||||
{
|
||||
if (!adjleft)
|
||||
for (i = width - nwidth; i > 0; i--, n++)
|
||||
putc (nullpad ? '0' : ' ');
|
||||
for (i = 4 * (nwidth - 33); i >= 0; i -= 4, n++)
|
||||
putc (hexchars ((high >> i) & 0xF));
|
||||
if (adjleft)
|
||||
for (i = width - nwidth; i > 0; i--, n++)
|
||||
putc (' ');
|
||||
width -= 32;
|
||||
nwidth -= 32;
|
||||
nullpad = 1;
|
||||
}
|
||||
if (! adjleft)
|
||||
for (i = width - nwidth; i > 0; i--, n++)
|
||||
putc (nullpad ? '0' : ' ');
|
||||
for (i = 4 * (nwidth - 1); i >= 0; i -= 4, n++)
|
||||
putc (hexchars ((low >> i) & 0xF));
|
||||
if (adjleft)
|
||||
for (i = width - nwidth; i > 0; i--, n++)
|
||||
putc (' ');
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int print_hex_3arg(const word_t val, int width, int precision)
|
||||
{
|
||||
long i, n = 0;
|
||||
long nwidth = 0;
|
||||
int adjleft = 0;
|
||||
int nullpad = 0;
|
||||
|
||||
// Find width of hexnumber
|
||||
while ((val >> (4 * nwidth)) && (word_t) nwidth < 2 * sizeof (word_t))
|
||||
nwidth++;
|
||||
|
||||
if (nwidth == 0)
|
||||
nwidth = 1;
|
||||
|
||||
// May need to increase number of printed digits
|
||||
if (precision > nwidth)
|
||||
nwidth = precision;
|
||||
|
||||
// May need to increase number of printed characters
|
||||
if (width == 0 && width < nwidth)
|
||||
width = nwidth;
|
||||
|
||||
// Print number with padding
|
||||
if (! adjleft)
|
||||
for (i = width - nwidth; i > 0; i--, n++)
|
||||
putc (nullpad ? '0' : ' ');
|
||||
for (i = 4 * (nwidth - 1); i >= 0; i -= 4, n++)
|
||||
putc (hexchars ((val >> i) & 0xF));
|
||||
if (adjleft)
|
||||
for (i = width - nwidth; i > 0; i--, n++)
|
||||
putc (' ');
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int print_hex_5arg(const word_t val, int width,
|
||||
int precision, int adjleft, int nullpad)
|
||||
{
|
||||
long i, n = 0;
|
||||
long nwidth = 0;
|
||||
|
||||
// Find width of hexnumber
|
||||
while ((val >> (4 * nwidth)) && (word_t) nwidth < 2 * sizeof (word_t))
|
||||
nwidth++;
|
||||
|
||||
if (nwidth == 0)
|
||||
nwidth = 1;
|
||||
|
||||
// May need to increase number of printed digits
|
||||
if (precision > nwidth)
|
||||
nwidth = precision;
|
||||
|
||||
// May need to increase number of printed characters
|
||||
if (width == 0 && width < nwidth)
|
||||
width = nwidth;
|
||||
|
||||
// Print number with padding
|
||||
if (! adjleft)
|
||||
for (i = width - nwidth; i > 0; i--, n++)
|
||||
putc (nullpad ? '0' : ' ');
|
||||
for (i = 4 * (nwidth - 1); i >= 0; i -= 4, n++)
|
||||
putc (hexchars ((val >> i) & 0xF));
|
||||
if (adjleft)
|
||||
for (i = width - nwidth; i > 0; i--, n++)
|
||||
putc (' ');
|
||||
|
||||
return n;
|
||||
}
|
||||
/**
|
||||
* Print a string
|
||||
*
|
||||
* @param s zero-terminated string to print
|
||||
* @param width minimum width of printed string
|
||||
*
|
||||
* Prints the zero-terminated string using putc(). The printed
|
||||
* string will be right padded with space to so that it will be
|
||||
* at least WIDTH characters wide.
|
||||
*
|
||||
* @returns the number of charaters printed.
|
||||
*/
|
||||
int print_string_3arg(const char * s, const int width, const int precision)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (*s == 0)
|
||||
break;
|
||||
|
||||
putc(*s++);
|
||||
n++;
|
||||
if (precision && n >= precision)
|
||||
break;
|
||||
}
|
||||
|
||||
while (n < width) { putc(' '); n++; }
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int print_string_1arg(const char * s)
|
||||
{
|
||||
int n = 0;
|
||||
int width = 0;
|
||||
int precision = 0;
|
||||
|
||||
for (;;) {
|
||||
if (*s == 0)
|
||||
break;
|
||||
|
||||
putc(*s++);
|
||||
n++;
|
||||
if (precision && n >= precision)
|
||||
break;
|
||||
}
|
||||
|
||||
while (n < width) {
|
||||
putc(' ');
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print hexadecimal value with a separator
|
||||
*
|
||||
* @param val value to print
|
||||
* @param bits number of lower-most bits before which to
|
||||
* place the separator
|
||||
* @param sep the separator to print
|
||||
*
|
||||
* @returns the number of charaters printed.
|
||||
*/
|
||||
int print_hex_sep(const word_t val, const int bits, const char *sep)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
n = print_hex_3arg(val >> bits, 0, 0);
|
||||
n += print_string_1arg(sep);
|
||||
n += print_hex_3arg(val & ((1 << bits) - 1), 0, 0);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print decimal value
|
||||
*
|
||||
* @param val value to print
|
||||
* @param width width of field
|
||||
* @param pad character used for padding value up to width
|
||||
*
|
||||
* Prints a value as a decimal in the given WIDTH with leading
|
||||
* whitespaces.
|
||||
*
|
||||
* @returns the number of characters printed (may be more than WIDTH)
|
||||
*/
|
||||
int print_dec(const word_t val, int width)
|
||||
{
|
||||
word_t divisor;
|
||||
int digits;
|
||||
/* estimate number of spaces and digits */
|
||||
for (divisor = 1, digits = 1; val/divisor >= 10; divisor *= 10, digits++);
|
||||
|
||||
/* print spaces */
|
||||
for ( ; digits < width; digits++ )
|
||||
putc(' ');
|
||||
|
||||
/* print digits */
|
||||
do {
|
||||
putc(((val/divisor) % 10) + '0');
|
||||
} while (divisor /= 10);
|
||||
|
||||
/* report number of digits printed */
|
||||
return digits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the real printk work
|
||||
*
|
||||
* @param format_p pointer to format string
|
||||
* @param args list of arguments, variable length
|
||||
*
|
||||
* Prints the given arguments as specified by the format string.
|
||||
* Implements a subset of the well-known printf plus some L4-specifics.
|
||||
*
|
||||
* @returns the number of characters printed
|
||||
*/
|
||||
int do_printk(char* format_p, va_list args)
|
||||
{
|
||||
const char* format = format_p;
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
int width = 8;
|
||||
int precision = 0;
|
||||
int adjleft = 0, nullpad = 0;
|
||||
|
||||
#define arg(x) va_arg(args, x)
|
||||
|
||||
/* sanity check */
|
||||
if (format == '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*format)
|
||||
{
|
||||
switch (*(format))
|
||||
{
|
||||
case '%':
|
||||
width = precision = 0;
|
||||
adjleft = nullpad = 0;
|
||||
reentry:
|
||||
switch (*(++format))
|
||||
{
|
||||
/* modifiers */
|
||||
case '.':
|
||||
for (format++; *format >= '0' && *format <= '9'; format++)
|
||||
precision = precision * 10 + (*format) - '0';
|
||||
if (*format == 'w')
|
||||
{
|
||||
// Set precision to printsize of a hex word
|
||||
precision = sizeof (word_t) * 2;
|
||||
format++;
|
||||
}
|
||||
format--;
|
||||
goto reentry;
|
||||
case '0':
|
||||
nullpad = (width == 0);
|
||||
case '1'...'9':
|
||||
width = width*10 + (*format)-'0';
|
||||
goto reentry;
|
||||
case 'w':
|
||||
// Set width to printsize of a hex word
|
||||
width = sizeof (word_t) * 2;
|
||||
goto reentry;
|
||||
case '-':
|
||||
adjleft = 0;
|
||||
goto reentry;
|
||||
case 'l':
|
||||
goto reentry;
|
||||
break;
|
||||
case 'c':
|
||||
putc(arg(int));
|
||||
n++;
|
||||
break;
|
||||
case 'm': /* microseconds */
|
||||
{
|
||||
n += print_hex64(arg(unsigned long long), width, precision,
|
||||
adjleft, nullpad);
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
{
|
||||
long val = arg(long);
|
||||
if (val < 0)
|
||||
{
|
||||
putc('-');
|
||||
val = -val;
|
||||
}
|
||||
n += print_dec(val, width);
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
n += print_dec(arg(long), width);
|
||||
break;
|
||||
case 'p':
|
||||
precision = sizeof (word_t) * 2;
|
||||
case 'x':
|
||||
n += print_hex_5arg(arg(long), width, precision, adjleft, nullpad);
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
char* s = arg(char*);
|
||||
if (s)
|
||||
n += print_string_3arg(s, width, precision);
|
||||
else
|
||||
n += print_string_3arg("(null)", width, precision);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
case 'T':
|
||||
// Do nothing for now.
|
||||
//n += print_tid (arg (word_t), width, precision, adjleft);
|
||||
break;
|
||||
|
||||
case '%':
|
||||
putc('%');
|
||||
n++;
|
||||
format++;
|
||||
continue;
|
||||
default:
|
||||
n += print_string_1arg("?");
|
||||
break;
|
||||
};
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
putc(*format);
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flexible print function
|
||||
*
|
||||
* @param format string containing formatting and parameter type
|
||||
* information
|
||||
* @param ... variable list of parameters
|
||||
*
|
||||
* @returns the number of characters printed
|
||||
*/
|
||||
int printf(char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, format);
|
||||
i = do_printk(format, args);
|
||||
va_end(args);
|
||||
return i;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user