POK(kernelpart)
printf.c
Go to the documentation of this file.
1 /*
2  * POK header
3  *
4  * The following file is a part of the POK project. Any modification should
5  * made according to the POK licence. You CANNOT use this file or a part of
6  * this file is this part of a file for your own project
7  *
8  * For more information on the POK licence, please see our LICENCE FILE
9  *
10  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
11  *
12  * Copyright (c) 2007-2009 POK team
13  *
14  * Created by julien on Thu Jan 15 23:34:13 2009
15  */
16 
17 
18 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_INSTRUMENTATION) || defined (POK_NEEDS_COVERAGE_INFOS)
19 
20 #include <types.h>
21 #include <libc.h>
22 #include <stdarg.h>
23 #include <bsp.h>
24 
25 static const char digits[] = "0123456789abcdef";
26 
27 #define INT_UNSIGNED 1
28 #define INT_SIGNED 2
29 
30 #define BASE_HEX 16
31 #define BASE_OCT 8
32 
33 #define MY_BUF_SIZE 8192
34 
35 /*
36  * some types
37  */
38 
39 struct s_file
40 {
41  char buff[MY_BUF_SIZE];
42  size_t pos;
43 };
44 
45 union u_arg
46 {
47  unsigned long value;
48  unsigned int uint;
49  int sint;
50  void* ptr;
51 };
52 
53 typedef int (*t_fmtfun)(union u_arg *arg, struct s_file *file, int flags);
54 
55 struct s_format
56 {
57  char ch;
58  t_fmtfun fun;
59  int flags;
60 };
61 
62 /*
63  * buffered I/O
64  */
65 
66 static void my_fflush(struct s_file *file)
67 {
68  pok_cons_write (file->buff, file->pos);
69  file->pos = 0;
70 }
71 
72 static struct s_file* init_buffered_output(void)
73 {
74  static struct s_file res;
75 
76  res.pos = 0;
77  return &res;
78 }
79 
80 static void my_putc(char c, struct s_file *file)
81 {
82  file->buff[file->pos++] = c;
83 
84  if (file->pos == MY_BUF_SIZE)
85  {
86  my_fflush(file);
87  }
88 }
89 
90 static void close_buffered_output(struct s_file *file)
91 {
92  my_fflush(file);
93 }
94 
95 /*
96  * formatting functions
97  */
98 
99 static int conv(unsigned int n, int base, int dig[])
100 {
101  int i;
102 
103  i = 0;
104 
105  while (n)
106  {
107  dig[i] = n % base;
108  ++i;
109  n /= base;
110  }
111  return i - 1;
112 }
113 
114 static int my_printnbr_base (unsigned int n,
115  const char base[],
116  int card,
117  struct s_file *file)
118 {
119  int digits[96];
120  int i;
121  int count;
122 
123  if (n == 0)
124  {
125  my_putc ('0', file);
126  return 1;
127  }
128 
129  count = i = conv (n, card, digits);
130 
131  for (; i >= 0; --i)
132  {
133  my_putc(base[digits[i]], file);
134  }
135 
136  return count;
137 }
138 
139 static int print_int (union u_arg* value,
140  struct s_file* file,
141  int flags)
142 {
143  int sh;
144 
145  sh = 0;
146 
147  if (value->sint == 0)
148  {
149  my_putc('0', file);
150  return 1;
151  }
152 
153  if (flags == INT_SIGNED)
154  {
155  if (value->sint < 0)
156  {
157  my_putc('-', file);
158  value->uint = -value->sint;
159  sh = 1;
160  }
161  else
162  {
163  value->uint = value->sint;
164  }
165  }
166 
167  return my_printnbr_base (value->uint, digits, 10, file) + sh;
168 }
169 
170 static int print_str (union u_arg* value, struct s_file* file, int flags)
171 {
172  int count;
173  char* s;
174 
175  count = 0;
176  s = value->ptr;
177 
178  flags = flags;
179 
180  for (; *s; ++count, ++s)
181  {
182  my_putc(*s, file);
183  }
184 
185  return count;
186 }
187 
188 static int print_char(union u_arg* value, struct s_file* file, int flags)
189 {
190  char c;
191 
192  flags = flags;
193  c = value->sint;
194 
195  my_putc (c, file);
196 
197  return 1;
198 }
199 
200 static int print_base(union u_arg* value, struct s_file* file, int flags)
201 {
202  return my_printnbr_base (value->uint, digits, flags, file);
203 }
204 
205 static const struct s_format formats[] =
206 {
207  { 'd', print_int, INT_SIGNED },
208  { 'i', print_int, INT_SIGNED },
209  { 'u', print_int, INT_UNSIGNED },
210  { 's', print_str, 0 },
211  { 'c', print_char, 0 },
212  { 'o', print_base, BASE_OCT },
213  { 'x', print_base, BASE_HEX },
214  { 0, NULL, 0 }
215 };
216 
217 static int special_char (char fmt,
218  union u_arg* value,
219  struct s_file* file)
220 {
221  int i;
222 
223  for (i = 0; formats[i].fun; ++i)
224  {
225  if (formats[i].ch == fmt)
226  {
227  break;
228  }
229  }
230 
231  if (formats[i].fun)
232  {
233  return formats[i].fun(value, file, formats[i].flags);
234  }
235  else
236  {
237  if (fmt != '%')
238  {
239  my_putc('%', file);
240  }
241 
242  my_putc(fmt, file);
243 
244  return 1 + (fmt != '%');
245  }
246 }
247 
248 /*
249  * finally, printf
250  */
251 
252 int vprintf (const char* format, va_list args)
253 {
254  struct s_file* file;
255  union u_arg arg;
256  int count;
257 
258  count = 0;
259 
260  for (file = init_buffered_output();
261  *format;
262  format += (*format == '%' ? 2 : 1))
263  {
264  if (*format == '%')
265  {
266  if (!*(format + 1))
267  {
268  break;
269  }
270 
271  if (*(format + 1) != '%')
272  {
273  arg.value = va_arg(args, unsigned long);
274  }
275 
276  count += special_char(*(format + 1), &arg, file);
277  }
278  else
279  {
280  my_putc(*format, file);
281  ++count;
282  }
283  }
284 
285  close_buffered_output(file);
286  return count;
287 }
288 
289 int printf (const char *format, ...)
290 {
291  int res;
292  va_list args;
293 
294  va_start (args, format);
295  res = vprintf (format, args);
296  va_end (args);
297 
298  return res;
299 }
300 
301 #endif