Index: libc/generic/io/io.c
===================================================================
--- libc/generic/io/io.c	(revision fcd10af6fb760d39a824242ffd2987aa8db7c809)
+++ libc/generic/io/io.c	(revision c9857c6049423e28c75585d50f395e3aa0da24d3)
@@ -38,4 +38,8 @@
 	size_t count;
 	
+	if (str == NULL) {
+		return putnchars("(NULL)",6 );
+	}
+	
 	for (count = 0; str[count] != 0; count++);
 	if (write(1, (void * ) str, count) == count) {
@@ -48,5 +52,5 @@
 
 /** Put count chars from buffer to stdout without adding newline
- * @param buf Buffer with size at least count bytes
+ * @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
  * @param count 
  * @return 0 on succes, EOF on fail
@@ -80,4 +84,14 @@
 }
 
+int putchar(int c)
+{
+	unsigned char ch = c;
+	if (write(1, (void *)&ch , 1) == 1) {
+			return c;
+	}
+	
+	return EOF;
+}
+
 ssize_t write(int fd, const void * buf, size_t count)
 {
Index: libc/generic/io/print.c
===================================================================
--- libc/generic/io/print.c	(revision fcd10af6fb760d39a824242ffd2987aa8db7c809)
+++ libc/generic/io/print.c	(revision c9857c6049423e28c75585d50f395e3aa0da24d3)
@@ -32,4 +32,6 @@
 #include <io/io.h>
 #include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
 
 #define __PRINTF_FLAG_PREFIX		0x00000001	/* show prefixes 0x or 0*/
@@ -60,4 +62,91 @@
 static char digits_big[] = "0123456789ABCDEF"; 	/* Big hexadecimal characters */
 
+
+/** Print one formatted character
+ * @param c character to print
+ * @param width 
+ * @param flags
+ * @return number of printed characters or EOF
+ */
+						
+static int print_char(char c, int width, uint64_t flags)
+{
+	int counter = 0;
+	char space = ' ';
+	
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		while (--width > 0) { 	/* one space is consumed by character itself hence predecrement */
+			/* FIXME: painful slow */
+			putchar(' ');	
+			++counter;
+		}
+	}
+	
+ 	if (putchar(c) == EOF) {
+		return EOF;
+	}
+
+	while (--width > 0) { /* one space is consumed by character itself hence predecrement */
+		putchar(' ');
+		++counter;
+	}
+	
+	return ++counter;
+}
+
+/** Print one string
+ * @param s string
+ * @param width 
+ * @param precision
+ * @param flags
+ * @return number of printed characters or EOF
+ */
+						
+static int print_string(char *s, int width, int precision, uint64_t flags)
+{
+	int counter = 0;
+	size_t size;
+
+	if (s == NULL) {
+		return putstr("(NULL)");
+	}
+	
+	size = strlen(s);
+
+	/* print leading spaces */
+
+	if (precision == 0) 
+		precision = size;
+
+	width -= precision;
+	
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		while (width-- > 0) { 	
+			putchar(' ');	
+			counter++;
+		}
+	}
+
+	while (precision > size) {
+		precision--;
+		putchar(' ');	
+		++counter;
+	}
+	
+ 	if (putnchars(s, precision) == EOF) {
+		return EOF;
+	}
+
+	counter += precision;
+
+	while (width-- > 0) {
+		putchar(' ');	
+		++counter;
+	}
+	
+	return ++counter;
+}
+
+
 /** Print number in given base
  *
@@ -66,5 +155,6 @@
  *
  * @param num  Number to print.
- * @param size not used, in future releases will be replaced with precision and width params
+ * @param width
+ * @param precision
  * @param base Base to print the number in (should
  *             be in range 2 .. 16).
@@ -73,14 +163,12 @@
  *
  */
-static int print_number(uint64_t num, size_t size, int base , uint64_t flags)
+static int print_number(uint64_t num, int width, int precision, int base , uint64_t flags)
 {
-	/* FIXME: This is only first version.
-	 * Printf does not have support for specification of size 
-	 * and precision, so this function writes with parameters defined by
-	 * their type size.
-	 */
 	char *digits = digits_small;
 	char d[PRINT_NUMBER_BUFFER_SIZE];	/* this is good enough even for base == 2, prefix and sign */
 	char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
+	int size = 0;
+	int written = 0;
+	char sgn;
 	
 	if (flags & __PRINTF_FLAG_BIGCHARS) 
@@ -91,51 +179,120 @@
 	if (num == 0) {
 		*ptr-- = '0';
+		size++;
 	} else {
 		do {
 			*ptr-- = digits[num % base];
+			size++;
 		} while (num /= base);
 	}
-	if (flags & __PRINTF_FLAG_PREFIX) { /*FIXME*/
+
+	/* Collect sum of all prefixes/signs/... to calculate padding and leading zeroes */
+	if (flags & __PRINTF_FLAG_PREFIX) {
 		switch(base) {
 			case 2:	/* Binary formating is not standard, but usefull */
-				*ptr = 'b';
-				if (flags & __PRINTF_FLAG_BIGCHARS) *ptr = 'B';
-				ptr--;
-				*ptr-- = '0';
+				size += 2;
 				break;
 			case 8:
-				*ptr-- = 'o';
+				size++;
 				break;
 			case 16:
-				*ptr = 'x';
-				if (flags & __PRINTF_FLAG_BIGCHARS) *ptr = 'X';
-				ptr--;
-				*ptr-- = '0';
+				size += 2;
 				break;
 		}
 	}
-	
+
+	sgn = 0;
 	if (flags & __PRINTF_FLAG_SIGNED) {
 		if (flags & __PRINTF_FLAG_NEGATIVE) {
-			*ptr-- = '-';
+			sgn = '-';
+			size++;
 		} else if (flags & __PRINTF_FLAG_SHOWPLUS) {
-				*ptr-- = '+';
+				sgn = '+';
+				size++;
 			} else if (flags & __PRINTF_FLAG_SPACESIGN) {
-					*ptr-- = ' ';
-				}
-	}
-
-	/* Print leading zeroes */
+					sgn = ' ';
+					size++;
+				}
+	}
 
 	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
 		flags &= ~__PRINTF_FLAG_ZEROPADDED;
 	}
+
+	/* if number is leftaligned or precision is specified then zeropadding is ignored */
 	if (flags & __PRINTF_FLAG_ZEROPADDED) {
-	       	while (ptr != d ) {
-			*ptr-- = '0';
+		if ((precision == 0) && (width > size)) {
+			precision = width - size;
 		}
 	}
-	
-	return putstr(++ptr);
+
+	/* print leading spaces */
+	if (size > precision) /* We must print whole number not only a part */
+		precision = size;
+
+	width -= precision;
+	
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		while (width-- > 0) { 	
+			putchar(' ');	
+			written++;
+		}
+	}
+	
+	/* print sign */
+	if (sgn) {
+		putchar(sgn);
+		written++;
+	}
+	
+	/* print prefix */
+	
+	if (flags & __PRINTF_FLAG_PREFIX) {
+		switch(base) {
+			case 2:	/* Binary formating is not standard, but usefull */
+				putchar('0');
+				if (flags & __PRINTF_FLAG_BIGCHARS) {
+					putchar('B');
+				} else {
+					putchar('b');
+				}
+				written == 2;
+				break;
+			case 8:
+				putchar('o');
+				written++;
+				break;
+			case 16:
+				putchar('0');
+				if (flags & __PRINTF_FLAG_BIGCHARS) {
+					putchar('X');
+				} else {
+					putchar('x');
+				}
+				written += 2;
+				break;
+		}
+	}
+
+	/* print leading zeroes */
+	precision -= size;
+	while (precision-- > 0) { 	
+		putchar('0');	
+		written++;
+	}
+
+	
+	/* print number itself */
+
+	written += putstr(++ptr);
+	
+	/* print ending spaces */
+	
+	while (width-- > 0) { 	
+		putchar(' ');	
+		written++;
+	}
+
+	return written;
 }
 
@@ -209,9 +366,10 @@
 	uint64_t number; /* argument value */
 	size_t	size; /* byte size of integer parameter */
+	int width, precision;
 	uint64_t flags;
 	
 	counter = 0;
 	va_start(ap, fmt);
-
+	
 	while ((c = fmt[i])) {
 		/* control character */
@@ -242,8 +400,47 @@
 				
 			} while (end == 0);	
-			/* TODO: width & '*' operator */
-			/* TODO: precision and '*' operator */	
+			
+			/* width & '*' operator */
+			width = 0;
+			if (isdigit(fmt[i])) {
+				while (isdigit(fmt[i])) {
+					width *= 10;
+					width += fmt[i++] - '0';
+				}
+			} else if (fmt[i] == '*') {
+				/* get width value from argument list*/
+				i++;
+				width = (int)va_arg(ap, int);
+				if (width < 0) {
+					/* negative width means to set '-' flag */
+					width *= -1;
+					flags |= __PRINTF_FLAG_LEFTALIGNED;
+				}
+			}
+			
+			/* precision and '*' operator */	
+			precision = 0;
+			if (fmt[i] == '.') {
+				++i;
+				if (isdigit(fmt[i])) {
+					while (isdigit(fmt[i])) {
+						precision *= 10;
+						precision += fmt[i++] - '0';
+					}
+				} else if (fmt[i] == '*') {
+					/* get precision value from argument list*/
+					i++;
+					precision = (int)va_arg(ap, int);
+					if (precision < 0) {
+						/* negative precision means to ignore it */
+						precision = 0;
+					}
+				}
+			}
 
 			switch (fmt[i++]) {
+				/** TODO: unimplemented qualifiers:
+				 * t ptrdiff_t - ISO C 99
+				 */
 				case 'h':	/* char or short */
 					qualifier = PrintfQualifierShort;
@@ -276,5 +473,5 @@
 				*/
 				case 's':
-					if ((retval = putstr(va_arg(ap, char*))) == EOF) {
+					if ((retval = print_string(va_arg(ap, char*), width, precision, flags)) == EOF) {
 						return -counter;
 					};
@@ -284,6 +481,6 @@
 					goto next_char;
 				case 'c':
-					c = va_arg(ap, unsigned long);
-					if ((retval = putnchars(&c, sizeof(char))) == EOF) {
+					c = va_arg(ap, unsigned int);
+					if ((retval = print_char(c, width, flags )) == EOF) {
 						return -counter;
 					};
@@ -385,5 +582,5 @@
 			}
 
-			if ((retval = print_number(number, size, base, flags)) == EOF ) {
+			if ((retval = print_number(number, width, precision, base, flags)) == EOF ) {
 				return -counter;
 			};
Index: libc/generic/string.c
===================================================================
--- libc/generic/string.c	(revision fcd10af6fb760d39a824242ffd2987aa8db7c809)
+++ libc/generic/string.c	(revision c9857c6049423e28c75585d50f395e3aa0da24d3)
@@ -27,5 +27,4 @@
  */
 
-#include <types.h>
 #include <string.h>
 
@@ -48,2 +47,13 @@
 	return dest;
 }
+
+size_t strlen(const char *str) 
+{
+	int counter = 0;
+
+	while (str[counter] != 0) {
+		counter++;
+	}
+
+	return counter;
+}
Index: libc/include/ctype.h
===================================================================
--- libc/include/ctype.h	(revision c9857c6049423e28c75585d50f395e3aa0da24d3)
+++ libc/include/ctype.h	(revision c9857c6049423e28c75585d50f395e3aa0da24d3)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2006 Josef Cejka
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ */
+
+#ifndef __CTYPE_H__
+#define __CTYPE_H__
+
+static inline int isdigit(int c)
+{
+	return ((c >= '0' )&&( c <= '9'));
+}
+
+#endif
+
Index: libc/include/io/io.h
===================================================================
--- libc/include/io/io.h	(revision fcd10af6fb760d39a824242ffd2987aa8db7c809)
+++ libc/include/io/io.h	(revision c9857c6049423e28c75585d50f395e3aa0da24d3)
@@ -34,4 +34,5 @@
 int putnchars(const char * buf, size_t count);
 int putstr(const char * str);
+int putchar(int c);
 
 #endif
Index: libc/include/string.h
===================================================================
--- libc/include/string.h	(revision fcd10af6fb760d39a824242ffd2987aa8db7c809)
+++ libc/include/string.h	(revision c9857c6049423e28c75585d50f395e3aa0da24d3)
@@ -31,6 +31,10 @@
 #define __LIBC__STRING_H__
 
+#include <types.h>
+
 void * memset(void *s, int c, size_t n);
 void * memcpy(void *dest, void *src, size_t n);
 
+size_t strlen(const char *str);
+
 #endif
