]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/moe/server/src/log.cc
update
[l4.git] / l4 / pkg / moe / server / src / log.cc
1 /*
2  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *               Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #include <l4/re/log>
11 #include <l4/re/log-sys.h>
12 #include <l4/sys/kdebug.h>
13 #include <l4/cxx/minmax>
14
15 #include "globals.h"
16 #include "log.h"
17
18 #include <unistd.h>
19 #include <cstdio>
20 #include <stdarg.h>
21
22 static Moe::Log *last_log = 0;
23
24 class Pbuf
25 {
26 public:
27   Pbuf() : _p(0) {}
28   unsigned long size() const { return sizeof(_b); }
29   void flush();
30   void printf(char const *fmt, ...);
31     __attribute__((format(printf, 2, 3)));
32   void outnstring(char const *str, unsigned long len);
33
34 private:
35   void checknflush(int n);
36   char _b[1024];
37   unsigned long _p;
38
39   bool fits(unsigned l) const { return (_p + l) < sizeof(_b); }
40 };
41
42 static void my_outnstring(char const *s, unsigned long len)
43 {
44   write(1, s, len);
45 }
46
47
48
49 void Pbuf::flush()
50 {
51   my_outnstring(_b, _p);
52   _p = 0;
53 }
54
55 void Pbuf::checknflush(int n)
56 {
57   char *x = 0;
58   x = (char*)memchr(_b, '\n', _p + n);
59
60   if (x)
61     {
62       int rem = n - (x - _b + 1 - _p);
63       _p = x - _b + 1;
64       flush();
65       if (rem)
66         memmove(_b, x + 1, rem);
67       _p = rem;
68     }
69   else
70     _p += n;
71 }
72
73 void Pbuf::printf(char const *fmt, ...)
74 {
75   if (!fits(strlen(fmt) + 50))
76     flush();
77   int n;
78   va_list arg;
79   va_start(arg, fmt);
80   n = vsnprintf(_b + _p, size() - _p, fmt, arg);
81   va_end(arg);
82   checknflush(n);
83 }
84
85 void Pbuf::outnstring(char const *str, unsigned long len)
86 {
87   if (!fits(len))
88     flush();
89   memcpy(_b + _p, str, len);
90   checknflush(len);
91 }
92
93 int
94 Moe::Log::dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
95 {
96   enum { Max_tag = 8 };
97   l4_msgtag_t tag;
98   ios >> tag;
99
100   if (tag.label() != L4_PROTO_LOG)
101     return -L4_EBADPROTO;
102
103   L4::Opcode op;
104
105   // get opcode out of the message stream
106   ios >> op;
107
108   // we only have one opcode
109   if (op != L4Re::Log_::Print)
110     return -L4_ENOSYS;
111
112   char *msg = log_buffer;
113   unsigned long len_msg = sizeof(log_buffer);
114
115   static Pbuf ob;
116
117   ios >> L4::Ipc::Buf_cp_in<char>(msg, len_msg);
118
119   while (len_msg > 0 && msg[0])
120     {
121       if (color())
122         ob.printf("\033[%s3%dm", (color() & 8) ? "01;" : "", (color() & 7));
123       else
124         ob.printf("\033[0m");
125
126       if (last_log != this)
127         {
128           if (last_log != 0)
129             ob.printf("\n");
130
131           ob.outnstring(_tag, cxx::min<unsigned long>(_l, Max_tag));
132           if (_l < Max_tag)
133             ob.outnstring("             ", Max_tag-_l);
134
135           if (_in_line)
136             ob.printf(": ");
137           else
138             ob.printf("| ");
139         }
140
141       long i;
142       for (i = 0; i < (long)len_msg; ++i)
143         if (msg[i] == '\n' || msg[i] == 0)
144           break;
145
146       ob.outnstring(msg, i);
147
148       if (i < (long)len_msg && msg[i] == '\n')
149         {
150           if (color())
151             ob.printf("\033[0m\n");
152           else
153             ob.printf("\n");
154           _in_line = false;
155           last_log = 0;
156           ++i;
157         }
158       else
159         {
160           last_log = this;
161           _in_line = true;
162         }
163
164       msg += i;
165       len_msg -= i;
166     }
167
168   if (_in_line && color())
169     ob.printf("\033[0m");
170
171   // and finally done
172   return -L4_ENOREPLY;
173 }
174
175
176 int
177 Moe::Log::color_value(cxx::String const &col)
178 {
179   int c = 0, bright = 0;
180
181   if (col.empty())
182     return 0;
183
184   switch(col[0])
185     {
186     case 'N': bright = 1; case 'n': c = 0; break;
187     case 'R': bright = 1; case 'r': c = 1; break;
188     case 'G': bright = 1; case 'g': c = 2; break;
189     case 'Y': bright = 1; case 'y': c = 3; break;
190     case 'B': bright = 1; case 'b': c = 4; break;
191     case 'M': bright = 1; case 'm': c = 5; break;
192     case 'C': bright = 1; case 'c': c = 6; break;
193     case 'W': bright = 1; case 'w': c = 7; break;
194     default: c = 0;
195     }
196
197   return (bright << 3) | c;
198 }
199
200