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:
Bahadir Balban
2009-08-27 12:00:04 +03:00
parent 87e2aeaf58
commit a41caeebd2
67 changed files with 2760 additions and 53 deletions

View File

@@ -0,0 +1 @@
arch-arm

View File

@@ -0,0 +1,12 @@
/* Dummies to keep Codesourcery 4.1.1 libgcc division exceptions silent. */
void raise(void)
{
}
void __aeabi_unwind_cpp_pr0(void)
{
}

View File

@@ -0,0 +1,191 @@
/*
* Ties up platform's uart driver functions with generic API
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <arch/uart.h>
#include <arch/pl011_uart.h>
/* UART-specific internal error codes */
#define PL011_ERROR 1
#define PL011_EAGAIN 2
/* Error status bits in receive status register */
#define PL011_FE (1 << 0)
#define PL011_PE (1 << 1)
#define PL011_BE (1 << 2)
#define PL011_OE (1 << 3)
/* Status bits in flag register */
#define PL011_TXFE (1 << 7)
#define PL011_RXFF (1 << 6)
#define PL011_TXFF (1 << 5)
#define PL011_RXFE (1 << 4)
#define PL011_BUSY (1 << 3)
#define PL011_DCD (1 << 2)
#define PL011_DSR (1 << 1)
#define PL011_CTS (1 << 0)
struct pl011_uart uart;
int pl011_tx_char(char c)
{
unsigned int val;
val = 0;
read(val, PL011_UARTFR);
if(val & PL011_TXFF) { /* TX FIFO Full */
return -PL011_EAGAIN;
}
write(c, PL011_UARTDR);
return 0;
}
int pl011_rx_char(char * c)
{
unsigned int data;
unsigned int val;
val = 0;
read(val, PL011_UARTFR);
if(val & PL011_RXFE) { /* RX FIFO Empty */
return -PL011_EAGAIN;
}
read(data, PL011_UARTDR);
*c = (char) data;
if((data >> 8) & 0xF) { /* There were errors */
return -1; /* Signal error in xfer */
}
return 0; /* No error return */
}
/*
* Sets the baud rate in kbps. It is recommended to use
* standard rates such as: 1200, 2400, 3600, 4800, 7200,
* 9600, 14400, 19200, 28800, 38400, 57600 76800, 115200.
*/
void pl011_set_baudrate(unsigned int baud, unsigned int clkrate)
{
const unsigned int uartclk = 24000000; /* 24Mhz clock fixed on pb926 */
unsigned int val;
unsigned int ipart, fpart;
unsigned int remainder;
remainder = 0;
ipart = 0;
fpart = 0;
val = 0;
/* Use default pb926 rate if no rate is supplied */
if(clkrate == 0) {
clkrate = uartclk;
}
if(baud > 115200 || baud < 1200) {
baud = 38400; /* Default rate. */
}
/* 24000000 / (38400 * 16) */
ipart = 39;
write(ipart, PL011_UARTIBRD);
write(fpart, PL011_UARTFBRD);
/* For the IBAUD and FBAUD to update, we need to
* write to UARTLCR_H because the 3 registers are
* actually part of a single register in hardware
* which only updates by a write to UARTLCR_H */
read(val, PL011_UARTLCR_H);
write(val, PL011_UARTLCR_H);
return;
}
/* Masks the irqs given in the flags bitvector. */
void pl011_set_irq_mask(unsigned int flags)
{
unsigned int val;
val = 0;
if(flags > 0x3FF) { /* Invalid irqmask bitvector */
return;
}
read(val, PL011_UARTIMSC);
val |= flags;
write(val, PL011_UARTIMSC);
return;
}
/* Clears the irqs given in flags from masking */
void pl011_clr_irq_mask(unsigned int flags)
{
unsigned int val;
val = 0;
if(flags > 0x3FF) { /* Invalid irqmask bitvector */
return;
}
read(val, PL011_UARTIMSC);
val &= ~flags;
write(val, PL011_UARTIMSC);
return;
}
int pl011_initialise(struct pl011_uart * uart)
{
uart->frame_errors = 0;
uart->parity_errors = 0;
uart->break_errors = 0;
uart->overrun_errors = 0;
/* Initialise data register for 8 bit data read/writes */
pl011_set_word_width(8);
/* Fifos are disabled because by default it is assumed the port
* will be used as a user terminal, and in that case the typed
* characters will only show up when fifos are flushed, rather than
* when each character is typed. We avoid this by not using fifos.
*/
pl011_disable_fifos();
/* Set default baud rate of 38400 */
pl011_set_baudrate(38400, 24000000);
/* Set default settings of 1 stop bit, no parity, no hw flow ctrl */
pl011_set_stopbits(1);
pl011_parity_disable();
/* Disable all irqs */
pl011_set_irq_mask(0x3FF);
/* Enable rx, tx, and uart chip */
pl011_tx_enable();
pl011_rx_enable();
pl011_uart_enable();
return 0;
}
void uart_init()
{
uart.base = PL011_BASE;
pl011_initialise(&uart);
}
/* Generic uart function that lib/putchar.c expects to see implemented */
void uart_putc(char c)
{
int res;
/* Platform specific uart implementation */
do {
res = pl011_tx_char(c);
} while (res < 0);
}

View File

@@ -0,0 +1,543 @@
/*
* Australian Public Licence B (OZPLB)
*
* Version 1-0
*
* Copyright (c) 2004 University of New South Wales
*
* All rights reserved.
*
* Developed by: Operating Systems and Distributed Systems Group (DiSy)
* University of New South Wales
* http://www.disy.cse.unsw.edu.au
*
* Permission is granted by University of New South Wales, free of charge, to
* any person obtaining a copy of this software and any associated
* documentation files (the "Software") to deal with the Software without
* restriction, including (without limitation) the rights to use, copy,
* modify, adapt, merge, publish, distribute, communicate to the public,
* sublicense, and/or sell, lend or rent out copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimers.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimers in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of University of New South Wales, nor the names of its
* contributors, may be used to endorse or promote products derived
* from this Software without specific prior written permission.
*
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
* ERRORS, WHETHER OR NOT DISCOVERABLE.
*
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
* DAMAGES OR OTHER LIABILITY.
*
* If applicable legislation implies representations, warranties, or
* conditions, or imposes obligations or liability on University of New South
* Wales or one of its contributors in respect of the Software that
* cannot be wholly or partly excluded, restricted or modified, the
* liability of University of New South Wales or the contributor is limited, to
* the full extent permitted by the applicable legislation, at its
* option, to:
* a. in the case of goods, any one or more of the following:
* i. the replacement of the goods or the supply of equivalent goods;
* ii. the repair of the goods;
* iii. the payment of the cost of replacing the goods or of acquiring
* equivalent goods;
* iv. the payment of the cost of having the goods repaired; or
* b. in the case of services:
* i. the supplying of the services again; or
* ii. the payment of the cost of having the services supplied again.
*
* The construction, validity and performance of this licence is governed
* by the laws in force in New South Wales, Australia.
*/
/*
Authors: Cristan Szmadja, Ben Leslie
*/
#include <stdint.h>
#include "stdio.h"
#include <stdbool.h>
#include <string.h>
#include "format.h"
#define fputc putc
/*
* lookup tables for umaxtostr
*/
static const char xdigits[16] = "0123456789abcdef";
static const char Xdigits[16] = "0123456789ABCDEF";
/*
* Convert an unsigned integer to a string of digits in the specified base.
* Buf should point to the END of the buffer: 22 characters is probably big
* enough. NO '\0' is appended to buf.
*
* If u == 0, NO digits are generated. The '0' is supplied by vfprintf using
* its default zero padding, except in certain rare situations (e.g., "%.0d").
*/
static inline char *
umaxtostr(char *buf, uintmax_t u, int base, const char *digits)
{
unsigned long u2;
/*
* generate the digits in reverse order
*/
#if UINTMAX_MAX > ULONG_MAX
/*
* Uintmax_t arithmetic may be very slow. Use it only until the
* residual fits in an unsigned long.
*/
while (u > ULONG_MAX) {
*--buf = digits[u % base];
u /= base;
}
#endif
for (u2 = u; u2 != 0UL;) {
*--buf = digits[u2 % base];
u2 /= base;
}
return buf;
}
/*
This macro is *really* nasty.
It isn't an inline function because it relies on variables declared in the
surrounding scope. Specifically:
stream_or_memory -> Indicates if we are going to a file, or memory
r -> The output counter
n -> max size
output -> output buffer (if going to memory)
stream -> output stream (if going to file)
*/
#define WRITE_CHAR(x) { \
if (n != -1 && r == n) { \
*output++ = '\0'; \
overflowed = 1; \
} \
if (stream_or_memory) { \
fputc(x, stream); \
} else if (! overflowed) { \
*output++ = x; \
} \
r++; \
} \
/*
* Print one formatted field. The length of s is len; any '\0's in s are
* IGNORED. The field may have an optional prefix ('+', ' ', '-', '0x', or
* '0X', packed into an unsigned int), and is padded appropriately to the
* specified width. If width < 0, the field is left-justified.
*/
static inline int
fprintf1(char *output, FILE *stream, bool stream_or_memory, size_t r, size_t n,
const char *s, int len, unsigned int prefix,
int prefixlen, int width, int prec, bool *over)
{
size_t i;
size_t y = r; /* Keep a copy the starting value */
bool overflowed = *over; /* Current start of overflow flag */
if (stream != NULL)
lock_stream(stream);
if (width - prec - prefixlen > 0) {
for (i = 0; i < width - prec - prefixlen; i++) {
WRITE_CHAR(' '); /* left-padding (if any) */
}
}
for (; prefix != 0; prefix >>= 8) {
WRITE_CHAR(prefix & 0377); /* prefix string */
}
for (i = 0; i < prec - len; i++) {
WRITE_CHAR('0'); /* zero-padding (if any) */
}
for (i = 0; i < len; i++) {
WRITE_CHAR(s[i]); /* actual string */
}
if (width < 0) {
while(y < -width) {
WRITE_CHAR(' '); /* right-padding (if any) */
}
}
*over = overflowed; /* Set overflow flag in the caller */
if (stream != NULL)
unlock_stream(stream);
return r - y; /* We return the number of chars added */
}
#include <assert.h>
/*
* parse printf format string
* if stream_or_memory == 1 -> use fputc, otherwise write to memory
* if n == -1, then don't check overflow
*/
int
format_string(char *output, FILE *stream, bool stream_or_memory, size_t n,
const char *fmt, va_list ap)
{
bool alt, ljust, point, zeropad, overflowed = 0;
int lflags; /* 'h', 'j', 'l', 't', 'z' */
unsigned int prefix; /* a very small string */
int width, prec, base = 0, prefixlen;
size_t r, len;
const char *p, *s, *digits;
char buf[24], *const buf_end = buf + sizeof buf;
intmax_t d;
uintmax_t u = 0;
r = 0;
if (stream != NULL)
lock_stream(stream);
for (p = fmt; *p != '\0'; p++) {
if (*p != '%') {
putc:
WRITE_CHAR(*p);
continue;
}
alt = false;
ljust = false;
point = false;
zeropad = false;
lflags = 0;
prefix = '\0';
prefixlen = 0;
width = 0;
prec = 1; /* make sure 0 prints as "0" */
digits = xdigits;
for (p++;; p++) {
again:
switch (*p) {
case '%':
goto putc;
case '#':
alt = true;
continue;
case '-': /* takes precedence over '0' */
ljust = true;
continue;
case '0':
zeropad = true;
continue;
case '+': /* XXX should take precedence over
* ' ' */
case ' ':
prefix = *p;
prefixlen = 1;
continue;
case '*':
width = va_arg(ap, int);
if (ljust)
width = -width;
continue;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/*
* width = strtol(p, &p, 10), sort of
*/
width = *p - '0';
for (p++; (unsigned int) (*p - '0') < 10;
p++)
width = width * 10 + (*p - '0');
if (ljust)
width = -width;
goto again; /* don't increment p */
case '.':
point = true;
if (*++p == '*') {
prec = va_arg(ap, int);
continue;
} else {
/*
* prec = strtol(p, &p, 10), sort
* of
*/
for (prec = 0;
(unsigned int) (*p - '0') <
10; p++)
prec =
prec * 10 + (*p - '0');
goto again; /* don't increment
* p */
}
case 'h':
lflags--;
continue;
case 'L':
case 'l':
lflags++;
continue;
case 't':
case 'z':
lflags = 1; /* assume ptrdiff_t and
* size_t are long */
continue;
case 'j':
lflags = 2; /* assume intmax_t is long
* long */
continue;
#ifndef NO_FLOAT
case 'a':
case 'A':
case 'e':
case 'E':
case 'f':
case 'g':
case 'G':
/*
* NOT IMPLEMENTED
*/
switch (lflags) {
case 0:
va_arg(ap, double);
break;
case 1:
va_arg(ap, long double);
break;
default:
goto default_case;
}
break;
#endif /* !NO_FLOAT */
case 'c':
#ifndef NO_WCHAR
/*
* NOT IMPLEMENTED
*/
if (lflags > 0)
va_arg(ap, wchar_t);
else
#endif
*(buf_end - 1) = va_arg(ap, int);
s = buf_end - 1;
len = 1;
goto common3;
case 'd':
case 'i':
switch (lflags) {
case -2:
// d = va_arg(ap, signed char);
d = va_arg(ap, int);
break;
case -1:
// d = va_arg(ap, short);
d = va_arg(ap, int);
break;
case 0:
d = va_arg(ap, int);
break;
case 1:
d = va_arg(ap, long);
break;
#ifndef NO_LONG_LONG
case 2:
d = va_arg(ap, long long);
break;
#endif
default:
goto default_case;
}
if (d < 0LL) {
/*
* safely negate d, even
* INTMAX_MIN
*/
u = -(uintmax_t) d;
prefix = '-'; /* override ' ' or
* '+' */
prefixlen = 1;
} else {
u = d;
}
base = 10;
goto common2;
case 'n':
switch (lflags) {
case -2:
*va_arg(ap, signed char *) = r;
break;
case -1:
*va_arg(ap, short *) = r;
break;
case 0:
*va_arg(ap, int *) = r;
break;
case 1:
*va_arg(ap, long *) = r;
break;
case 2:
*va_arg(ap, long long *) = r;
break;
default:
goto default_case;
}
break;
case 'o':
base = 8;
goto common1;
case 'p':
u = (uintptr_t) va_arg(ap, const void *);
if (u != (uintptr_t) NULL) {
base = 16;
prec = 2 * sizeof(const void *);
prefix = '0' | 'x' << 8;
prefixlen = 2;
goto common2;
} else {
s = "(nil)";
len = 5;
goto common3;
}
case 's':
s = va_arg(ap, const char *);
/*
* XXX left-justified strings are scanned
* twice
*/
if (point) {
/*
* len = min(prec, strlen(s))
*/
for (len = 0; len < prec; len++)
if (s[len] == '\0')
break;
} else {
len = strlen(s);
}
goto common3;
case 'u':
base = 10;
goto common1;
case 'X':
digits = Xdigits;
/*
* FALLTHROUGH
*/
case 'x':
base = 16;
if (alt) {
prefix = '0' | *p << 8;
prefixlen = 2;
}
/*
* FALLTHROUGH
*/
common1:
/*
* common code for %o, %u, %X, and %x
*/
switch (lflags) {
case -2:
// u = va_arg(ap, unsigned char);
u = va_arg(ap, int);
break;
case -1:
// u = va_arg(ap, unsigned short);
u = va_arg(ap, int);
break;
case 0:
u = va_arg(ap, unsigned int);
break;
case 1:
u = va_arg(ap, unsigned long);
break;
#ifndef NO_LONG_LONG
case 2:
u = va_arg(ap, unsigned long long);
break;
#endif
default:
goto default_case;
}
/*
* FALLTHROUGH
*/
common2:
s = umaxtostr(buf_end, u, base, digits);
len = buf_end - s;
/*
* the field may overflow prec
*/
if (prec < len)
/*
* FALLTHOUGH
*/
common3:
prec = len;
if (zeropad && prec < width - prefixlen)
prec = width - prefixlen;
else if (alt && base == 8 && u != 0LL)
prec++;
{
int tmp = fprintf1(output, stream, stream_or_memory, r, n,
s, len, prefix,
prefixlen, width, prec, &overflowed);
r += tmp;
output += tmp;
}
break;
default: /* unrecognized conversion
* specifier */
default_case:
/*
* print uninterpreted
*/
for (s = p - 1; *s != '%'; s--);
for (; s <= p; s++) {
WRITE_CHAR(*p);
}
break;
}
break; /* finished the conversion specifier */
}
}
if (! stream_or_memory && ! overflowed)
*output++ = '\0';
if (stream != NULL)
unlock_stream(stream);
return r;
}

View File

@@ -0,0 +1,86 @@
/*
* Australian Public Licence B (OZPLB)
*
* Version 1-0
*
* Copyright (c) 2004 National ICT Australia
*
* All rights reserved.
*
* Developed by: Embedded, Real-time and Operating Systems Program (ERTOS)
* National ICT Australia
* http://www.ertos.nicta.com.au
*
* Permission is granted by National ICT Australia, free of charge, to
* any person obtaining a copy of this software and any associated
* documentation files (the "Software") to deal with the Software without
* restriction, including (without limitation) the rights to use, copy,
* modify, adapt, merge, publish, distribute, communicate to the public,
* sublicense, and/or sell, lend or rent out copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimers.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimers in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of National ICT Australia, nor the names of its
* contributors, may be used to endorse or promote products derived
* from this Software without specific prior written permission.
*
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
* ERRORS, WHETHER OR NOT DISCOVERABLE.
*
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
* DAMAGES OR OTHER LIABILITY.
*
* If applicable legislation implies representations, warranties, or
* conditions, or imposes obligations or liability on National ICT
* Australia or one of its contributors in respect of the Software that
* cannot be wholly or partly excluded, restricted or modified, the
* liability of National ICT Australia or the contributor is limited, to
* the full extent permitted by the applicable legislation, at its
* option, to:
* a. in the case of goods, any one or more of the following:
* i. the replacement of the goods or the supply of equivalent goods;
* ii. the repair of the goods;
* iii. the payment of the cost of replacing the goods or of acquiring
* equivalent goods;
* iv. the payment of the cost of having the goods repaired; or
* b. in the case of services:
* i. the supplying of the services again; or
* ii. the payment of the cost of having the services supplied again.
*
* The construction, validity and performance of this licence is governed
* by the laws in force in New South Wales, Australia.
*/
/*
Author: Ben Leslie
*/
#ifndef _FORMAT_H_
#define _FORMAT_H_
#include <stdbool.h>
int format_string(char *output, FILE *stream, bool stream_or_memory, size_t n, const char *fmt, va_list ap);
#endif

View 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;
};

View File

@@ -0,0 +1,8 @@
#include <arch/uart.h>
void putc(char c)
{
if (c == '\n')
uart_putc('\r');
uart_putc(c);
}

View File

@@ -0,0 +1,107 @@
/*
* Australian Public Licence B (OZPLB)
*
* Version 1-0
*
* Copyright (c) 2004 National ICT Australia
*
* All rights reserved.
*
* Developed by: Embedded, Real-time and Operating Systems Program (ERTOS)
* National ICT Australia
* http://www.ertos.nicta.com.au
*
* Permission is granted by National ICT Australia, free of charge, to
* any person obtaining a copy of this software and any associated
* documentation files (the "Software") to deal with the Software without
* restriction, including (without limitation) the rights to use, copy,
* modify, adapt, merge, publish, distribute, communicate to the public,
* sublicense, and/or sell, lend or rent out copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimers.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimers in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of National ICT Australia, nor the names of its
* contributors, may be used to endorse or promote products derived
* from this Software without specific prior written permission.
*
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
* ERRORS, WHETHER OR NOT DISCOVERABLE.
*
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
* DAMAGES OR OTHER LIABILITY.
*
* If applicable legislation implies representations, warranties, or
* conditions, or imposes obligations or liability on National ICT
* Australia or one of its contributors in respect of the Software that
* cannot be wholly or partly excluded, restricted or modified, the
* liability of National ICT Australia or the contributor is limited, to
* the full extent permitted by the applicable legislation, at its
* option, to:
* a. in the case of goods, any one or more of the following:
* i. the replacement of the goods or the supply of equivalent goods;
* ii. the repair of the goods;
* iii. the payment of the cost of replacing the goods or of acquiring
* equivalent goods;
* iv. the payment of the cost of having the goods repaired; or
* b. in the case of services:
* i. the supplying of the services again; or
* ii. the payment of the cost of having the services supplied again.
*
* The construction, validity and performance of this licence is governed
* by the laws in force in New South Wales, Australia.
*/
/*
Author: Ben Leslie <benjl@cse.unsw.edu.au>
*/
#ifndef NULL
#define NULL 0
#endif
#include <stdio.h>
#include "format.h"
#include <assert.h>
int
vsprintf(char *s, const char *format, va_list arg)
{
return format_string(s, NULL, 0, -1, format, arg);
}
int
sprintf(char *s, const char *format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = vsprintf(s, format, ap);
va_end(ap);
return ret;
}

View File

@@ -0,0 +1,84 @@
#include <string.h>
int strlen(const char *s)
{
const char *p;
for (p = s; *p != '\0'; p++);
return p - s;
}
char *strcpy(char *to, const char *from)
{
char *t = to;
while ((*to++ = *from++) != '\0')
;
return t;
}
void *memset(void *p, int c, int size)
{
char ch;
char *pp;
pp = (char *)p;
ch = (char)c;
for (int i = 0; i < size; i++) {
*pp++ = ch;
}
return p;
}
void *memcpy(void *d, void *s, int size)
{
char *dst = (char *)d;
char *src = (char *)s;
for (int i = 0; i < size; i++) {
*dst = *src;
dst++;
src++;
}
return d;
}
int strcmp(const char *s1, const char *s2)
{
unsigned int i = 0;
int d;
while(1) {
d = (unsigned char)s1[i] - (unsigned char)s2[i];
if (d != 0 || s1[i] == '\0')
return d;
i++;
}
}
/*
* Copies string pointed by @from to string pointed by @to.
*
* If count is greater than the length of string in @from,
* pads rest of the locations with null.
*/
char *strncpy(char *to, const char *from, int count)
{
char *temp = to;
while (count) {
*temp = *from;
/*
* Stop updating from if null
* terminator is reached.
*/
if (*from)
from++;
temp++;
count--;
}
return to;
}