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