]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_console_buffer.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_console_buffer.cpp
1 IMPLEMENTATION:
2
3 #include <cstdio>
4 #include <cstring>
5 #include <cstdlib>
6
7 #include "config.h"
8 #include "jdb_module.h"
9 #include "jdb.h"
10 #include "kernel_console.h"
11 #include "keycodes.h"
12 #include "kmem_alloc.h"
13 #include "koptions.h"
14 #include "static_init.h"
15
16 /**
17  * A output console that stores the output in a buffer.
18  *
19  * This buffer can be usefull for accessing older the debugging 
20  * output without a serial console.
21  */
22 class Console_buffer : public Console
23 {
24 private:
25   static bool _enabled;
26   static size_t out_buf_size;
27   static size_t out_buf_len;
28   static char *out_buf;
29   static char *out_buf_w;
30 };
31
32 bool   Console_buffer::_enabled;
33 size_t Console_buffer::out_buf_size;
34 size_t Console_buffer::out_buf_len;
35 char*  Console_buffer::out_buf;
36 char*  Console_buffer::out_buf_w;
37
38 PRIVATE static
39 void
40 Console_buffer::at_jdb_enter()
41 {
42   _enabled = false;
43 }
44
45 PRIVATE static
46 void
47 Console_buffer::at_jdb_leave()
48 {
49   _enabled = true;
50 }
51
52 PUBLIC
53 Console_buffer::Console_buffer()
54 {
55   static Jdb_handler enter(at_jdb_enter);
56   static Jdb_handler leave(at_jdb_leave);
57
58   Jdb::jdb_enter.add(&enter);
59   Jdb::jdb_leave.add(&leave);
60
61   size_t len = 2 * Config::PAGE_SIZE;
62
63   if (Koptions::o()->opt(Koptions::F_out_buf))
64     len = Koptions::o()->out_buf;
65
66   alloc(len);
67 }
68
69 /**
70  * Allocates a buffer of the given size.
71  * @param size the buffer size in bytes.
72  */
73 PUBLIC static
74 void
75 Console_buffer::alloc( size_t size)
76 {
77   if(!out_buf)
78     {
79       out_buf_size = (size + Config::PAGE_SIZE - 1) & Config::PAGE_MASK;
80       if(out_buf_size)
81         out_buf = (char*)Kmem_alloc::allocator()->
82           unaligned_alloc(out_buf_size);
83
84       out_buf_w = out_buf;
85
86       _enabled = true;
87     }
88 }
89
90 PUBLIC
91 Console_buffer::~Console_buffer()
92 {
93   if(out_buf)
94     Kmem_alloc::allocator()->
95       unaligned_free(out_buf_size, out_buf);
96   out_buf = 0;
97 }
98
99 PUBLIC
100 int
101 Console_buffer::write( char const *str, size_t len )
102 {
103   if (_enabled && out_buf)
104     {
105       while(len)
106         {
107           size_t s;
108           s = out_buf_size - (out_buf_w - out_buf); 
109           if (s>len)
110             s = len;
111           memcpy( out_buf_w, str, s );
112           if (out_buf_w + s >= out_buf + out_buf_size)
113             out_buf_w = out_buf;
114           else
115             out_buf_w += s;
116           len -= s;
117           out_buf_len += s;
118           if (out_buf_len > out_buf_size)
119             out_buf_len = out_buf_size;
120         }
121     }
122   return len;
123 }
124
125 PRIVATE static inline
126 void
127 Console_buffer::inc_ptr(char **c)
128 {
129   if (++*c >= out_buf + out_buf_size)
130     *c = out_buf;
131 }
132
133 PRIVATE static inline
134 void
135 Console_buffer::dec_out_ptr(char **c)
136 {
137   if (--*c < out_buf)
138     *c += out_buf_size;
139 }
140
141 PUBLIC
142 int
143 Console_buffer::getchar(bool)
144 {
145   return -1;
146 }
147
148 /**
149  * Prints the buffer to the standard I/O.
150  * @param lines the number of lines to skip.
151  * This method prints the buffer contents to the normal I/O.
152  * Before doing this the buffer is disabled, that no recursion 
153  * appers even if the buffer is part of the muxed I/O.
154  */
155 PUBLIC static
156 int
157 Console_buffer::print_buffer(unsigned lines)
158 {
159   if (out_buf)
160     {
161       bool page  = (lines == 0);
162       char   *c  = out_buf_w;
163       size_t len = out_buf_len;
164
165       if (out_buf_len == 0)
166         {
167           puts("<empty>\n");
168           return 1;
169         }
170
171       // go back <lines> lines
172       if (lines)
173         {
174           size_t l = out_buf_len;
175
176           // skip terminating 0x00, 0x0a ...
177           while ((*c == '\0' || *c == '\r') && (l > 0))
178             {
179               dec_out_ptr(&c);
180               l--;
181             }
182
183           while (lines-- && (l > 0))
184             {
185               dec_out_ptr(&c);
186               l--;
187
188               while ((*c != '\n') && (l > 0))
189                 {
190                   dec_out_ptr(&c);
191                   l--;
192                 }
193             }
194
195           if (*c == '\n')
196             {
197               inc_ptr(&c);
198               l++;
199             }
200
201           len = out_buf_len - l;
202         }
203       else
204         {
205           c -= out_buf_len;
206           if (c < out_buf)
207             c += out_buf_size;
208         }
209
210       lines = 0;
211       while (len > 0)
212         {
213           putchar(*c);
214           if (*c == '\n') 
215             {
216               if (page && !Jdb_core::new_line(lines))
217                 return 1;
218             }
219           inc_ptr(&c);
220           len--;
221         }
222       
223       putchar('\n');
224       return 1;
225     }
226
227   printf("use -out_buf=<size> to enable output buffer\n");
228   return 0;
229 }
230
231
232 PRIVATE static
233 int
234 Console_buffer::strncmp(char *start, const char *search, size_t len)
235 {
236   while (len && *search && *start == *search)
237     {
238       len--;
239       inc_ptr(&start);
240       search++;
241     }
242
243   return *search == '\0';
244 }
245
246 /**
247  * Prints the buffer to the standard I/O.
248  * @param str the string the output should be filtered for
249  * This method prints the buffer contents to the normal I/O.
250  * Before doing this the buffer is disabled, that no recursion 
251  * appers even if the buffer is part of the muxed I/O.
252  */
253 PUBLIC static
254 int
255 Console_buffer::print_buffer(const char *str)
256 {
257   if (out_buf)
258     {
259       char   *bol = out_buf_w;
260       size_t len  = out_buf_len;
261
262       if (out_buf_len == 0)
263         {
264           puts("<empty>\n");
265           return 1;
266         }
267
268       bol -= out_buf_len;
269       if (bol < out_buf)
270         bol += out_buf_size;
271
272 next_line:
273       while (len > 0)
274         {
275           char   *bos = bol;
276           size_t lens = len;
277           const char *s;
278
279           while (lens > 0)
280             {
281               if (*bos == '\n')
282                 {
283                   bol = bos;
284                   inc_ptr(&bol);
285                   len = lens-1;
286                   goto next_line;
287                 }
288               if (strncmp(bos, str, lens))
289                 {
290                   // found => print whole line
291                   for (; len && bol != bos; len--)
292                     {
293                       putchar(*bol);
294                       inc_ptr(&bol);
295                     }
296             found_again:
297                   putstr(Jdb::esc_emph);
298                   for (s=str; *s && len; len--, s++)
299                     {
300                       putchar(*bol);
301                       inc_ptr(&bol);
302                     }
303                   putstr("\033[m");
304                   for (; len && *bol != '\n'; len--)
305                     {
306                       if (*str && strncmp(bol, str, len))
307                         goto found_again;
308                       putchar(*bol);
309                       inc_ptr(&bol);
310                     }
311                   if (len)
312                     {
313                       putchar(*bol);
314                       inc_ptr(&bol);
315                       len--;
316                     }
317                   goto next_line;
318                 }
319               inc_ptr(&bos);
320               lens--;
321             }
322         }
323
324       putchar('\n');
325       return 1;
326     }
327
328   printf("use -out_buf=<size> to enable output buffer\n");
329   return 0;
330 }
331
332 PUBLIC
333 Mword Console_buffer::get_attributes() const
334 {
335   return BUFFER | OUT;
336 }
337
338
339 PUBLIC static FIASCO_INIT
340 void
341 Console_buffer::init()
342 {
343   static Console_buffer cb;
344   Kconsole::console()->register_console(&cb);
345 }
346
347 STATIC_INITIALIZE(Console_buffer);
348
349
350
351 /// Jdb module
352
353 class Jdb_cb : public Jdb_module
354 {
355 public:
356   Jdb_cb() FIASCO_INIT;
357 private:
358   static char  first_char;
359   static char  search_str[30];
360   static Mword output_lines;
361 };
362
363 char  Jdb_cb::first_char;
364 char  Jdb_cb::search_str[30];
365 Mword Jdb_cb::output_lines;
366
367 PUBLIC
368 Jdb_module::Action_code
369 Jdb_cb::action(int cmd, void *&args, char const *&fmt, int &next_char)
370 {
371   if (cmd != 0)
372     return NOTHING;
373
374   if (args == &first_char)
375     {
376       if (first_char == '/')
377         {
378           putchar(first_char);
379           fmt  = "%30s";
380           args = search_str;
381           return EXTRA_INPUT;
382         }
383       output_lines = 0;
384       if (first_char != ' ' && first_char != KEY_RETURN)
385         {
386           next_char = first_char;
387           args = &output_lines;
388           fmt  = "%4d";
389           return EXTRA_INPUT_WITH_NEXTCHAR;
390         }
391     }
392   else if (args == search_str)
393     {
394       putchar('\n');
395       Console_buffer::print_buffer(search_str);
396       return NOTHING;
397     }
398
399   putchar('\n');
400   Console_buffer::print_buffer(output_lines);
401
402   return NOTHING;
403 }
404
405 PUBLIC
406 Jdb_module::Cmd const *
407 Jdb_cb::cmds() const
408 {
409   static const Cmd cs[] =
410     {
411         { 0, "B", "consolebuffer", "%C",
412           "B[<lines>|/<str>]\tshow (last n lines of) console buffer/search",
413           &first_char },
414     };
415   return cs;
416 }
417
418 PUBLIC
419 int
420 Jdb_cb::num_cmds() const
421 {
422   return 1;
423 }
424
425 IMPLEMENT
426 Jdb_cb::Jdb_cb()
427   : Jdb_module("GENERAL")
428 {
429 }
430
431 static Jdb_cb jdb_cb INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
432