Index: libc/generic/io/print.c
===================================================================
--- libc/generic/io/print.c	(revision 11a4fbf3d932714911471f5631d3814591b6851e)
+++ 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;
 			};
