kern
changeset 5:633e35c64772
- added printf family in stdio.c
- added atoi/atol in stdlib.c
- added nonstandard itoa/utoa in stdlib.c
- added strlen/strchr/strrchr in string.c
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 19 Dec 2010 15:07:07 +0200 |
parents | 0489a34ab348 |
children | 7e40f14617ed |
files | src/klibc/stdio.c src/klibc/stdio.h src/klibc/stdlib.h src/klibc/string.c src/klibc/string.h |
diffstat | 5 files changed, 302 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- a/src/klibc/stdio.c Fri Dec 10 03:44:34 2010 +0200 1.2 +++ b/src/klibc/stdio.c Sun Dec 19 15:07:07 2010 +0200 1.3 @@ -1,4 +1,9 @@ 1.4 #include <stdio.h> 1.5 +#include <string.h> 1.6 +#include <ctype.h> 1.7 + 1.8 +static void bwrite(char *buf, size_t buf_sz, char *str, int sz); 1.9 +static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap); 1.10 1.11 /* putchar is defined in term.c */ 1.12 1.13 @@ -10,3 +15,243 @@ 1.14 putchar('\n'); 1.15 return 0; 1.16 } 1.17 + 1.18 +/* -- printf and friends -- */ 1.19 + 1.20 +static char *convc = "dioxXucsfeEgGpn%"; 1.21 + 1.22 +#define IS_CONV(c) strchr(convc, c) 1.23 + 1.24 +int printf(const char *fmt, ...) 1.25 +{ 1.26 + int res; 1.27 + va_list ap; 1.28 + 1.29 + va_start(ap, fmt); 1.30 + res = intern_printf(0, 0, fmt, ap); 1.31 + va_end(ap); 1.32 + return res; 1.33 +} 1.34 + 1.35 +int vprintf(const char *fmt, va_list ap) 1.36 +{ 1.37 + return intern_printf(0, 0, fmt, ap); 1.38 +} 1.39 + 1.40 +int sprintf(char *buf, const char *fmt, ...) 1.41 +{ 1.42 + int res; 1.43 + va_list ap; 1.44 + 1.45 + va_start(ap, fmt); 1.46 + res = intern_printf(buf, 0, fmt, ap); 1.47 + va_end(ap); 1.48 + return res; 1.49 +} 1.50 + 1.51 +int vsprintf(char *buf, const char *fmt, va_list ap) 1.52 +{ 1.53 + return intern_printf(buf, 0, fmt, ap); 1.54 +} 1.55 + 1.56 +int snprintf(char *buf, size_t sz, const char *fmt, ...) 1.57 +{ 1.58 + int res; 1.59 + va_list ap; 1.60 + 1.61 + va_start(ap, fmt); 1.62 + res = intern_printf(buf, sz, fmt, ap); 1.63 + va_end(ap); 1.64 + return res; 1.65 +} 1.66 + 1.67 +int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap) 1.68 +{ 1.69 + return intern_printf(buf, sz, fmt, ap); 1.70 +} 1.71 + 1.72 + 1.73 +/* intern_printf provides all the functionality needed by all the printf 1.74 + * variants. 1.75 + * - buf: optional buffer onto which the formatted results are written. If null 1.76 + * then the output goes to the terminal through putchar calls. This is used 1.77 + * by the (v)sprintf variants which write to an array of char. 1.78 + * - sz: optional maximum size of the output, 0 means unlimited. This is used 1.79 + * by the (v)snprintf variants to avoid buffer overflows. 1.80 + * The rest are obvious, format string and variable argument list. 1.81 + */ 1.82 + 1.83 +#define BUF(x) ((x) ? (x) + cnum : (x)) 1.84 +#define SZ(x) ((x) ? (x) - cnum : (x)) 1.85 + 1.86 +static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) 1.87 +{ 1.88 + char conv_buf[32]; 1.89 + char *str; 1.90 + int i, slen; 1.91 + const char *fstart = 0; 1.92 + 1.93 + /* state */ 1.94 + int cnum = 0; 1.95 + int base = 10; 1.96 + int alt = 0; 1.97 + int fwidth = 0; 1.98 + int padc = ' '; 1.99 + int sign = 0; 1.100 + int left_align = 0; /* not implemented yet */ 1.101 + int hex_caps = 0; 1.102 + int unsig = 0; 1.103 + 1.104 + while(*fmt) { 1.105 + if(*fmt == '%') { 1.106 + fstart = fmt++; 1.107 + continue; 1.108 + } 1.109 + 1.110 + if(fstart) { 1.111 + if(IS_CONV(*fmt)) { 1.112 + switch(*fmt) { 1.113 + case 'X': 1.114 + hex_caps = 1; 1.115 + 1.116 + case 'x': 1.117 + case 'p': 1.118 + base = 16; 1.119 + 1.120 + if(alt) { 1.121 + bwrite(BUF(buf), SZ(sz), "0x", 2); 1.122 + } 1.123 + 1.124 + case 'u': 1.125 + unsig = 1; 1.126 + 1.127 + if(0) { 1.128 + case 'o': 1.129 + base = 8; 1.130 + 1.131 + if(alt) { 1.132 + bwrite(BUF(buf), SZ(sz), "0", 1); 1.133 + } 1.134 + } 1.135 + 1.136 + case 'd': 1.137 + case 'i': 1.138 + if(unsig) { 1.139 + utoa(va_arg(ap, unsigned int), conv_buf, base); 1.140 + } else { 1.141 + itoa(va_arg(ap, int), conv_buf, base); 1.142 + } 1.143 + if(hex_caps) { 1.144 + for(i=0; conv_buf[i]; i++) { 1.145 + conv_buf[i] = toupper(conv_buf[i]); 1.146 + } 1.147 + } 1.148 + 1.149 + slen = strlen(conv_buf); 1.150 + for(i=slen; i<fwidth; i++) { 1.151 + bwrite(BUF(buf), SZ(sz), (char*)&padc, 1); 1.152 + cnum++; 1.153 + } 1.154 + 1.155 + bwrite(BUF(buf), SZ(sz), conv_buf, strlen(conv_buf)); 1.156 + cnum += slen; 1.157 + break; 1.158 + 1.159 + case 'c': 1.160 + { 1.161 + char c = va_arg(ap, int); 1.162 + bwrite(BUF(buf), SZ(sz), &c, 1); 1.163 + cnum++; 1.164 + } 1.165 + break; 1.166 + 1.167 + case 's': 1.168 + str = va_arg(ap, char*); 1.169 + slen = strlen(str); 1.170 + 1.171 + for(i=slen; i<fwidth; i++) { 1.172 + bwrite(BUF(buf), SZ(sz), (char*)&padc, 1); 1.173 + cnum++; 1.174 + } 1.175 + bwrite(BUF(buf), SZ(sz), str, slen); 1.176 + cnum += slen; 1.177 + break; 1.178 + 1.179 + case 'n': 1.180 + *va_arg(ap, int*) = cnum; 1.181 + break; 1.182 + 1.183 + default: 1.184 + break; 1.185 + } 1.186 + 1.187 + /* restore default conversion state */ 1.188 + base = 10; 1.189 + alt = 0; 1.190 + fwidth = 0; 1.191 + padc = ' '; 1.192 + hex_caps = 0; 1.193 + 1.194 + fstart = 0; 1.195 + fmt++; 1.196 + } else { 1.197 + switch(*fmt) { 1.198 + case '#': 1.199 + alt = 1; 1.200 + break; 1.201 + 1.202 + case '+': 1.203 + sign = 1; 1.204 + break; 1.205 + 1.206 + case '-': 1.207 + left_align = 1; 1.208 + break; 1.209 + 1.210 + case 'l': 1.211 + case 'L': 1.212 + break; 1.213 + 1.214 + case '0': 1.215 + padc = '0'; 1.216 + break; 1.217 + 1.218 + default: 1.219 + if(isdigit(*fmt)) { 1.220 + const char *fw = fmt; 1.221 + while(*fmt && isdigit(*fmt)) fmt++; 1.222 + 1.223 + fwidth = atoi(fw); 1.224 + continue; 1.225 + } 1.226 + } 1.227 + fmt++; 1.228 + } 1.229 + } else { 1.230 + bwrite(BUF(buf), SZ(sz), (char*)fmt++, 1); 1.231 + cnum++; 1.232 + } 1.233 + } 1.234 + 1.235 + return 0; 1.236 +} 1.237 + 1.238 + 1.239 +/* bwrite is called by intern_printf to transparently handle writing into a 1.240 + * buffer (if buf is non-null) or to the terminal (if buf is null). 1.241 + */ 1.242 +static void bwrite(char *buf, size_t buf_sz, char *str, int sz) 1.243 +{ 1.244 + if(buf) { 1.245 + if(buf_sz && buf_sz <= sz) sz = buf_sz - 1; 1.246 + memcpy(buf, str, sz); 1.247 + 1.248 + buf[sz] = 0; 1.249 + } else { 1.250 + int i; 1.251 + for(i=0; i<sz; i++) { 1.252 + putchar(*str++); 1.253 + } 1.254 + } 1.255 +} 1.256 +
2.1 --- a/src/klibc/stdio.h Fri Dec 10 03:44:34 2010 +0200 2.2 +++ b/src/klibc/stdio.h Sun Dec 19 15:07:07 2010 +0200 2.3 @@ -1,7 +1,19 @@ 2.4 #ifndef STDIO_H_ 2.5 #define STDIO_H_ 2.6 2.7 +#include <stdlib.h> 2.8 +#include <stdarg.h> 2.9 + 2.10 int putchar(int c); 2.11 int puts(const char *s); 2.12 2.13 +int printf(const char *fmt, ...); 2.14 +int vprintf(const char *fmt, va_list ap); 2.15 + 2.16 +int sprintf(char *buf, const char *fmt, ...); 2.17 +int vsprintf(char *buf, const char *fmt, va_list ap); 2.18 + 2.19 +int snprintf(char *buf, size_t sz, const char *fmt, ...); 2.20 +int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap); 2.21 + 2.22 #endif /* STDIO_H_ */
3.1 --- a/src/klibc/stdlib.h Fri Dec 10 03:44:34 2010 +0200 3.2 +++ b/src/klibc/stdlib.h Sun Dec 19 15:07:07 2010 +0200 3.3 @@ -6,4 +6,10 @@ 3.4 typedef int32_t ssize_t; 3.5 typedef uint32_t size_t; 3.6 3.7 +int atoi(const char *str); 3.8 +long atol(const char *str); 3.9 + 3.10 +void itoa(int val, char *buf, int base); 3.11 +void utoa(unsigned int val, char *buf, int base); 3.12 + 3.13 #endif /* STDLIB_H_ */
4.1 --- a/src/klibc/string.c Fri Dec 10 03:44:34 2010 +0200 4.2 +++ b/src/klibc/string.c Sun Dec 19 15:07:07 2010 +0200 4.3 @@ -54,3 +54,37 @@ 4.4 4.5 return dest; 4.6 } 4.7 + 4.8 +size_t strlen(const char *s) 4.9 +{ 4.10 + size_t len = 0; 4.11 + while(*s++) len++; 4.12 + return len; 4.13 +} 4.14 + 4.15 +char *strchr(const char *s, int c) 4.16 +{ 4.17 + while(*s) { 4.18 + if(*s == c) { 4.19 + return s; 4.20 + } 4.21 + s++; 4.22 + } 4.23 + return 0; 4.24 +} 4.25 + 4.26 +char *strrchr(const char *s, int c) 4.27 +{ 4.28 + char *ptr = s; 4.29 + 4.30 + /* find the end */ 4.31 + while(*ptr) ptr++; 4.32 + 4.33 + /* go back checking for c */ 4.34 + while(*--ptr >= s) { 4.35 + if(*ptr == c) { 4.36 + return ptr; 4.37 + } 4.38 + } 4.39 + return 0; 4.40 +}
5.1 --- a/src/klibc/string.h Fri Dec 10 03:44:34 2010 +0200 5.2 +++ b/src/klibc/string.h Sun Dec 19 15:07:07 2010 +0200 5.3 @@ -9,4 +9,9 @@ 5.4 void *memcpy(void *dest, const void *src, size_t n); 5.5 void *memmove(void *dest, const void *src, size_t n); 5.6 5.7 +size_t strlen(const char *s); 5.8 + 5.9 +char *strchr(const char *s, int c); 5.10 +char *strrchr(const char *s, int c); 5.11 + 5.12 #endif /* STRING_H_ */