summaryrefslogtreecommitdiff
path: root/kernel/vsprintf.c
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-06-17 17:00:45 +1000
committerJake Mannens <jake72360@gmail.com>2018-06-17 17:00:45 +1000
commitaa289699cd65e59bd107fc9827995e39bf98e2d0 (patch)
tree0ae55b724b60318a5a2c1eb41d573f3fd65e232e /kernel/vsprintf.c
parentdc862c6346ac0d762d98cee9bcb5ed09dd5e3066 (diff)
Added zero padding and field width interpretation to vsprintf.
Diffstat (limited to 'kernel/vsprintf.c')
-rw-r--r--kernel/vsprintf.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/kernel/vsprintf.c b/kernel/vsprintf.c
index 20489f4..93a2ada 100644
--- a/kernel/vsprintf.c
+++ b/kernel/vsprintf.c
@@ -8,22 +8,51 @@ enum TYPE {
TYPE_STRING = 4
};
-static void hex(char **str, int x) {
- int n;
+enum FLAGS {
+ FL_ZERO = 1, /* zero padded */
+};
+
+static void hex(char **str, char flags, int fwidth, int size, int x) {
+ int i, y, len;
+ char c;
char *s = "0x";
while(*s)
*(*str)++ = *s++;
- n = sizeof(x) << 1;
- while(n--) {
- *(*str)++ = ((unsigned int) x >> 28) + 0x30;
+ /* calculate the number of digits */
+ len = 0;
+ y = x;
+ for(i = 0; i < sizeof(y) << 1; i++) {
+ c = ((unsigned int) y >> 28);
+ if(c)
+ len++;
+ y = y << 4;
+ }
+
+ /* print the padding characters (if any) */
+ c = ' ';
+ if(flags & FL_ZERO)
+ c = '0';
+ for(i = 0; i < fwidth - len; i++)
+ *(*str)++ = c;
+
+ /* actually print the digits */
+ for(i = 0; i < sizeof(x) << 1; i++) {
+ c = ((unsigned int) x >> 28) + '0';
+ if(c > '9')
+ c += 7;
+
+ if(c != '0')
+ *(*str)++ = c;
+
x = x << 4;
}
}
int vsprintf(char *str, char *fmt, va_list ap) {
- int x;
+ int x, fwidth;
+ char flags;
char *s;
char *start = str;
uint8_t type;
@@ -35,8 +64,10 @@ int vsprintf(char *str, char *fmt, va_list ap) {
}
type = 0;
+ flags = 0;
+ fwidth = 0;
- fmt++;
+ fmt++;
while(1) {
switch(*fmt) {
case 's':
@@ -50,9 +81,22 @@ int vsprintf(char *str, char *fmt, va_list ap) {
type = TYPE_HEX;
break;
default:
+ /* the first zero enables zero-padding */
+ if(*fmt == '0' && !fwidth) {
+ flags |= FL_ZERO;
+ goto next;;
+ }
+
+ /* subsequent numbers indicate field width */
+ if(*fmt >= '0' && *fmt <= '9') {
+ fwidth = (fwidth * 10) + (*fmt - '0');
+ goto next;;
+ }
+
goto done;
break;
}
+next:
fmt++;
}
@@ -66,7 +110,7 @@ done:
break;
case TYPE_HEX:
x = va_arg(ap, int);
- hex(&str, x);
+ hex(&str, flags, fwidth, 4, x);
break;
}
}