POK(kernelpart)
|
00001 /* 00002 * POK header 00003 * 00004 * The following file is a part of the POK project. Any modification should 00005 * made according to the POK licence. You CANNOT use this file or a part of 00006 * this file is this part of a file for your own project 00007 * 00008 * For more information on the POK licence, please see our LICENCE FILE 00009 * 00010 * Please follow the coding guidelines described in doc/CODING_GUIDELINES 00011 * 00012 * Copyright (c) 2007-2009 POK team 00013 * 00014 * Created by julien on Thu Jan 15 23:34:13 2009 00015 */ 00016 00017 00018 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_INSTRUMENTATION) || defined (POK_NEEDS_COVERAGE_INFOS) 00019 00020 #include <types.h> 00021 #include <libc.h> 00022 #include <stdarg.h> 00023 #include <bsp.h> 00024 00025 static const char digits[] = "0123456789abcdef"; 00026 00027 #define INT_UNSIGNED 1 00028 #define INT_SIGNED 2 00029 00030 #define BASE_HEX 16 00031 #define BASE_OCT 8 00032 00033 #define MY_BUF_SIZE 8192 00034 00035 /* 00036 * some types 00037 */ 00038 00039 struct s_file 00040 { 00041 char buff[MY_BUF_SIZE]; 00042 size_t pos; 00043 }; 00044 00045 union u_arg 00046 { 00047 unsigned long value; 00048 unsigned int uint; 00049 int sint; 00050 void* ptr; 00051 }; 00052 00053 typedef int (*t_fmtfun)(union u_arg *arg, struct s_file *file, int flags); 00054 00055 struct s_format 00056 { 00057 char ch; 00058 t_fmtfun fun; 00059 int flags; 00060 }; 00061 00062 /* 00063 * buffered I/O 00064 */ 00065 00066 static void my_fflush(struct s_file *file) 00067 { 00068 pok_cons_write (file->buff, file->pos); 00069 file->pos = 0; 00070 } 00071 00072 static struct s_file* init_buffered_output(void) 00073 { 00074 static struct s_file res; 00075 00076 res.pos = 0; 00077 return &res; 00078 } 00079 00080 static void my_putc(char c, struct s_file *file) 00081 { 00082 file->buff[file->pos++] = c; 00083 00084 if (file->pos == MY_BUF_SIZE) 00085 { 00086 my_fflush(file); 00087 } 00088 } 00089 00090 static void close_buffered_output(struct s_file *file) 00091 { 00092 my_fflush(file); 00093 } 00094 00095 /* 00096 * formatting functions 00097 */ 00098 00099 static int conv(unsigned int n, int base, int dig[]) 00100 { 00101 int i; 00102 00103 i = 0; 00104 00105 while (n) 00106 { 00107 dig[i] = n % base; 00108 ++i; 00109 n /= base; 00110 } 00111 return i - 1; 00112 } 00113 00114 static int my_printnbr_base (unsigned int n, 00115 const char base[], 00116 int card, 00117 struct s_file *file) 00118 { 00119 int digits[96]; 00120 int i; 00121 int count; 00122 00123 if (n == 0) 00124 { 00125 my_putc ('0', file); 00126 return 1; 00127 } 00128 00129 count = i = conv (n, card, digits); 00130 00131 for (; i >= 0; --i) 00132 { 00133 my_putc(base[digits[i]], file); 00134 } 00135 00136 return count; 00137 } 00138 00139 static int print_int (union u_arg* value, 00140 struct s_file* file, 00141 int flags) 00142 { 00143 int sh; 00144 00145 sh = 0; 00146 00147 if (value->sint == 0) 00148 { 00149 my_putc('0', file); 00150 return 1; 00151 } 00152 00153 if (flags == INT_SIGNED) 00154 { 00155 if (value->sint < 0) 00156 { 00157 my_putc('-', file); 00158 value->uint = -value->sint; 00159 sh = 1; 00160 } 00161 else 00162 { 00163 value->uint = value->sint; 00164 } 00165 } 00166 00167 return my_printnbr_base (value->uint, digits, 10, file) + sh; 00168 } 00169 00170 static int print_str (union u_arg* value, struct s_file* file, int flags) 00171 { 00172 int count; 00173 char* s; 00174 00175 count = 0; 00176 s = value->ptr; 00177 00178 flags = flags; 00179 00180 for (; *s; ++count, ++s) 00181 { 00182 my_putc(*s, file); 00183 } 00184 00185 return count; 00186 } 00187 00188 static int print_char(union u_arg* value, struct s_file* file, int flags) 00189 { 00190 char c; 00191 00192 flags = flags; 00193 c = value->sint; 00194 00195 my_putc (c, file); 00196 00197 return 1; 00198 } 00199 00200 static int print_base(union u_arg* value, struct s_file* file, int flags) 00201 { 00202 return my_printnbr_base (value->uint, digits, flags, file); 00203 } 00204 00205 static const struct s_format formats[] = 00206 { 00207 { 'd', print_int, INT_SIGNED }, 00208 { 'i', print_int, INT_SIGNED }, 00209 { 'u', print_int, INT_UNSIGNED }, 00210 { 's', print_str, 0 }, 00211 { 'c', print_char, 0 }, 00212 { 'o', print_base, BASE_OCT }, 00213 { 'x', print_base, BASE_HEX }, 00214 { 0, NULL, 0 } 00215 }; 00216 00217 static int special_char (char fmt, 00218 union u_arg* value, 00219 struct s_file* file) 00220 { 00221 int i; 00222 00223 for (i = 0; formats[i].fun; ++i) 00224 { 00225 if (formats[i].ch == fmt) 00226 { 00227 break; 00228 } 00229 } 00230 00231 if (formats[i].fun) 00232 { 00233 return formats[i].fun(value, file, formats[i].flags); 00234 } 00235 else 00236 { 00237 if (fmt != '%') 00238 { 00239 my_putc('%', file); 00240 } 00241 00242 my_putc(fmt, file); 00243 00244 return 1 + (fmt != '%'); 00245 } 00246 } 00247 00248 /* 00249 * finally, printf 00250 */ 00251 00252 int vprintf (const char* format, va_list args) 00253 { 00254 struct s_file* file; 00255 union u_arg arg; 00256 int count; 00257 00258 count = 0; 00259 00260 for (file = init_buffered_output(); 00261 *format; 00262 format += (*format == '%' ? 2 : 1)) 00263 { 00264 if (*format == '%') 00265 { 00266 if (!*(format + 1)) 00267 { 00268 break; 00269 } 00270 00271 if (*(format + 1) != '%') 00272 { 00273 arg.value = va_arg(args, unsigned long); 00274 } 00275 00276 count += special_char(*(format + 1), &arg, file); 00277 } 00278 else 00279 { 00280 my_putc(*format, file); 00281 ++count; 00282 } 00283 } 00284 00285 close_buffered_output(file); 00286 return count; 00287 } 00288 00289 int printf (const char *format, ...) 00290 { 00291 int res; 00292 va_list args; 00293 00294 va_start (args, format); 00295 res = vprintf (format, args); 00296 va_end (args); 00297 00298 return res; 00299 } 00300 00301 #endif