]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_list.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_list.cpp
1 INTERFACE:
2
3 #include "string_buffer.h"
4
5 class Jdb_list
6 {
7 public:
8   virtual char const *get_mode_str() const { return "[std mode]"; }
9   virtual void next_mode() {}
10   virtual void next_sort() {}
11   virtual void *get_head() const = 0;
12   virtual void show_item(String_buffer *buffer, void *item) const = 0;
13   virtual char const *show_head() const = 0;
14   virtual int seek(int cnt, void **item) = 0;
15   virtual bool enter_item(void * /*item*/) const { return true; }
16   virtual void *follow_link(void *a) { return a; }
17   virtual bool handle_key(void * /*item*/, int /*keycode*/) { return false; }
18   virtual void *parent(void * /*item*/) { return 0; }
19   virtual void *get_valid(void *a) { return a; }
20
21 private:
22   typedef String_buf<256> Line_buf;
23   void *_start, *_last;
24   void *_current;
25   char _filter_str[20];
26 };
27
28
29 // ---------------------------------------------------------------------------
30 IMPLEMENTATION:
31
32 #include <climits>
33 #include <cstring>
34 #include <cstdio>
35
36 #include "jdb.h"
37 #include "jdb_core.h"
38 #include "jdb_input.h"
39 #include "jdb_regex.h"
40 #include "jdb_screen.h"
41 #include "kernel_console.h"
42 #include "keycodes.h"
43 #include "simpleio.h"
44 #include <minmax.h>
45
46
47
48 PUBLIC
49 Jdb_list::Jdb_list()
50   : _start(0), _current(0)
51 {
52   _filter_str[0] = 0;
53 }
54
55 // set _t_start element of list
56 PUBLIC
57 void
58 Jdb_list::set_start(void *start)
59 {
60   _start = start;
61 }
62
63 // _t_start-- if possible
64 PUBLIC inline
65 bool
66 Jdb_list::line_back()
67 { return filtered_seek(-1, &_start); }
68
69 // _t_start++ if possible
70 PUBLIC inline
71 bool
72 Jdb_list::line_forw()
73 {
74   if (filtered_seek(1, &_last))
75     return filtered_seek(1, &_start);
76   else
77     return false;
78 }
79 #if 0
80   Thread *t = _t_start;
81   iter(+Jdb_screen::height()-2, &_t_start);
82   iter(-Jdb_screen::height()+3, &_t_start);
83   return t != _t_start;
84 }
85 #endif
86
87 // _t_start -= 24 if possible
88 PUBLIC
89 bool
90 Jdb_list::page_back()
91 { return filtered_seek(-Jdb_screen::height()+2, &_start); }
92
93 // _t_start += 24 if possible
94 PUBLIC
95 bool
96 Jdb_list::page_forw()
97 {
98   int fwd = filtered_seek(Jdb_screen::height()-2, &_last);
99   if (fwd)
100     return filtered_seek(fwd, &_start);
101   return false;
102 }
103
104 #if 0
105   Thread *t = _t_start;
106   iter(+Jdb_screen::height()*2-5, &_t_start);
107   iter(-Jdb_screen::height()  +3, &_t_start);
108   return t != _t_start;
109 }
110 #endif
111
112 // _t_start = first element of list
113 PUBLIC
114 bool
115 Jdb_list::goto_home()
116 { return filtered_seek(-99999, &_start); }
117
118 // _t_start = last element of list
119 PUBLIC
120 bool
121 Jdb_list::goto_end()
122 { return filtered_seek(99999, &_start); }
123 #if 0
124   Thread *t = _t_start;
125   iter(+9999, &_t_start);
126   iter(-Jdb_screen::height()+2, &_t_start);
127   return t != _t_start;
128 }
129 #endif
130
131 // search index of search starting from _start
132 PRIVATE
133 int
134 Jdb_list::lookup_in_visible_area(void *search)
135 {
136   unsigned i;
137   void *t;
138
139   for (i = 0, t = _start; i < Jdb_screen::height() - 3; ++i)
140     {
141       if (t == search)
142         return i;
143
144       filtered_seek(1, &t);
145     }
146
147   return -1;
148 }
149
150 // get y'th element of thread list starting from _t_start
151 PRIVATE
152 void *
153 Jdb_list::index(int y)
154 {
155   void *t = _start;
156
157   filtered_seek(y, &t);
158   return t;
159 }
160
161 PRIVATE
162 void
163 Jdb_list::handle_string_filter_input()
164 {
165   Jdb::printf_statline("filter", 0, "%s=%s",
166                        Jdb_regex::avail() ? "Regexp" : "Search",
167                        _filter_str);
168
169   Jdb::cursor(Jdb_screen::height(), 16 + strlen(_filter_str));
170   if (!Jdb_input::get_string(_filter_str, sizeof(_filter_str)) ||
171       !_filter_str[0])
172     return;
173
174
175   if (Jdb_regex::avail() && !Jdb_regex::start(_filter_str))
176     {
177       _filter_str[0] = 0;
178       Jdb::printf_statline("search", 0, "Error in regexp");
179       Jdb::getchar();
180     }
181 }
182
183 PRIVATE
184 Jdb_list::Line_buf *
185 Jdb_list::render_visible(void *i)
186 {
187   static Line_buf buffer;
188   buffer.clear();
189   void *p = i;
190   while ((p = parent(p)))
191     buffer.append(' ');
192
193   show_item(&buffer, i);
194   if (_filter_str[0])
195     {
196       buffer.terminate();
197       if (Jdb_regex::avail())
198         {
199           if (!Jdb_regex::find(buffer.begin(), 0, 0))
200             i = 0;
201         }
202       else if (!strstr(buffer.begin(), _filter_str))
203         i = 0;
204     }
205
206   if (i)
207     return &buffer;
208
209   return 0;
210 }
211
212 PRIVATE
213 void
214 Jdb_list::show_line(Jdb_list::Line_buf *b)
215 {
216   Kconsole::console()->getchar_chance();
217
218   printf("%.*s\033[K\n",
219          min((int)Jdb_screen::width(), b->length()), b->begin());
220 }
221
222 PRIVATE
223 void *
224 Jdb_list::get_visible(void *i)
225 {
226   if (render_visible(i))
227     return i;
228
229   filtered_seek(1, &i);
230
231   return i;
232 }
233
234 PRIVATE
235 int
236 Jdb_list::filtered_seek(int cnt, void **item, Jdb_list::Line_buf **buf = 0)
237 {
238   if (cnt == 0)
239     return 0;
240
241   int c = 0;
242   int d = cnt < 0 ? -1 : 1;
243   for (;;)
244     {
245       int i;
246
247       if ((i = seek(d, item)) == 0)
248         return c;
249
250       if (Line_buf *b = render_visible(*item))
251         {
252           if (buf)
253             *buf = b;
254           c += d;
255           if (cnt == c)
256             return c;
257         }
258     }
259 }
260
261 // show complete page using show callback function
262 PUBLIC
263 int
264 Jdb_list::page_show()
265 {
266   void *t = _start;
267   unsigned i = 0;
268
269   if (Jdb_regex::avail() && _filter_str[0])
270     assert(Jdb_regex::start(_filter_str));
271
272   if (!t)
273     return 0;
274
275   Line_buf *b = render_visible(t);
276
277   for (i = 0; i < Jdb_screen::height()-3; ++i)
278     {
279       if (!t)
280         break;
281       _last = t;
282
283       if (b)
284         show_line(b);
285
286       if (!filtered_seek(1, &t, &b))
287         return i;
288     }
289
290   return i - 1;
291 }
292
293 #if 0
294 // show complete list using show callback function
295 PRIVATE
296 int
297 Jdb_list::complete_show()
298 {
299   void *t = _start;
300   int i = 0;
301   for (i = 0; ; ++i, seek(1, &t))
302     {
303       if (!t)
304         break;
305
306       show_line(t);
307     }
308
309   return i;
310 }
311
312 PUBLIC
313 Jdb_module::Action_code
314 Jdb_thread_list::action(int cmd, void *&argbuf, char const *&fmt, int &)
315 {
316   static char const *const cpu_fmt = " cpu=%i\n";
317   static char const *const nfmt = "\n";
318   if (cmd == 0)
319     {
320       if (fmt != cpu_fmt && fmt != nfmt)
321         {
322           if (subcmd == 'c')
323             {
324               argbuf = &cpu;
325               fmt = cpu_fmt;
326             }
327           else
328             fmt = nfmt;
329           return EXTRA_INPUT;
330         }
331
332       Thread *t = Jdb::get_current_active();
333       switch (subcmd)
334         {
335         case 'r': cpu = 0; list_threads(t, 'r'); break;
336         case 'p': list_threads(t, 'p'); break;
337         case 'c': 
338                   if (Cpu::online(cpu))
339                     list_threads(Jdb::get_thread(cpu), 'r');
340                   else
341                     printf("\nCPU %u is not online!\n", cpu);
342                   cpu = 0;
343                   break;
344         case 't': Jdb::execute_command("lt"); break; // other module
345         }
346     }
347   else if (cmd == 1)
348     {
349       Console *gzip = Kconsole::console()->find_console(Console::GZIP);
350       if (gzip)
351         {
352           Thread *t = Jdb::get_current_active();
353           gzip->state(gzip->state() | Console::OUTENABLED);
354           long_output = 1;
355           Jdb_thread_list::init('p', t);
356           Jdb_thread_list::set_start(t);
357           Jdb_thread_list::goto_home();
358           Jdb_thread_list::complete_show(list_threads_show_thread);
359           long_output = 0;
360           gzip->state(gzip->state() & ~Console::OUTENABLED);
361         }
362       else
363         puts(" gzip module not available");
364     }
365
366   return NOTHING;
367 }
368 #endif
369
370
371 PUBLIC
372 void
373 Jdb_list::show_header()
374 {
375   Jdb::cursor();
376   printf("%.*s\033[K\n", Jdb_screen::width(), show_head());
377 }
378
379 PUBLIC
380 void
381 Jdb_list::do_list()
382 {
383   int y, y_max;
384   void *t;
385
386   if (!_start)
387     _start = get_head();
388
389   if (!_current)
390     _current = _start;
391
392   Jdb::clear_screen();
393   show_header();
394
395   if (!_start)
396     {
397       printf("[EMPTY]\n");
398       return;
399     }
400
401
402   for (;;)
403     {
404       _start = get_visible(_start);
405       // set y to position of t_current in current displayed list
406       y = lookup_in_visible_area(_current);
407       if (y == -1)
408         {
409           _start = _current;
410           y = 0;
411         }
412
413       for (bool resync=false; !resync;)
414         {
415           Jdb::cursor(2, 1);
416           y_max = page_show();
417
418           // clear rest of screen (if where less than 24 lines)
419           for (unsigned i = y_max; i < Jdb_screen::height()-3; ++i)
420             putstr("\033[K\n");
421
422           Jdb::printf_statline("Objs",
423                                "<Space>=mode <Tab>=link <CR>=select /=filter",
424                                _filter_str[0] ? "%s (%s)" : "%s",
425                                get_mode_str(), _filter_str);
426
427           // key event loop
428           for (bool redraw=false; !redraw; )
429             {
430               Jdb::cursor(y+2, 1);
431               switch (int c=Jdb_core::getchar())
432                 {
433                 case KEY_CURSOR_UP:
434                 case 'k':
435                   if (y > 0)
436                     y--;
437                   else
438                     redraw = line_back();
439                   break;
440                 case KEY_CURSOR_DOWN:
441                 case 'j':
442                   if (y < y_max)
443                     y++;
444                   else
445                     redraw = line_forw();
446                   break;
447                 case KEY_PAGE_UP:
448                 case 'K':
449                   if (!(redraw = page_back()))
450                     y = 0;
451                   break;
452                 case KEY_PAGE_DOWN:
453                 case 'J':
454                   if (!(redraw = page_forw()))
455                     y = y_max;
456                   break;
457                 case KEY_CURSOR_HOME:
458                 case 'H':
459                   redraw = goto_home();
460                   y = 0;
461                   break;
462                 case KEY_CURSOR_END:
463                 case 'L':
464                   redraw = goto_end();
465                   y = y_max;
466                   break;
467                 case 's': // switch sort
468                   _current = index(y);
469                   next_sort();
470                   redraw = true;
471                   resync = true;
472                   break;
473                 case ' ': // switch mode
474                   _current = index(y);
475                   next_mode();
476                   _current = get_valid(_current);
477                   _start   = get_valid(_start);
478                   redraw = true;
479                   resync = true;
480                   break;
481                 case '/':
482                   handle_string_filter_input();
483                   _current = get_visible(_current);
484                   redraw = true;
485                   resync = true;
486                   break;
487                 case KEY_TAB: // go to associated object
488                   _current = index(y);
489                   t = follow_link(_current);
490                   if (t != _current)
491                     {
492                       _current = t;
493                       redraw = true;
494                       resync = true;
495                     }
496                   break;
497                 case KEY_RETURN:
498                   _current = index(y);
499                   if (!enter_item(_current))
500                     return;
501                   show_header();
502                   redraw = 1;
503                   break;
504                 case KEY_ESC:
505                   Jdb::abort_command();
506                   return;
507                 default:
508                   _current = index(y);
509                   if (!handle_key(_current, c) && Jdb::is_toplevel_cmd(c))
510                     return;
511
512                   show_header();
513                   redraw = 1;
514                   break;
515                 }
516             }
517         }
518     }
519 }
520