]> Git Repo - binutils.git/blob - gdb/rdi-share/logging.c
This commit was generated by cvs2svn to track changes on a CVS vendor
[binutils.git] / gdb / rdi-share / logging.c
1 /* 
2  * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3  * 
4  * This software may be freely used, copied, modified, and distributed
5  * provided that the above copyright notice is preserved in all copies of the
6  * software.
7  */
8
9 /* -*-C-*-
10  *
11  * $Revision$
12  *     $Date$
13  *
14  *
15  * logging.c - methods for logging warnings, errors and trace info
16  *
17  */
18
19 #include <stdarg.h>     /* ANSI varargs support */
20
21 #ifdef TARGET
22 # include "angel.h"
23 # include "devconf.h"
24 #else
25 # include "host.h"
26 #endif
27
28 #include "logging.h"    /* Header file for this source code */
29
30 #ifndef UNUSED
31 # define UNUSED(x) ((x)=(x))
32 #endif
33
34 /*
35  * __rt_warning
36  * ------------
37  * This routine is provided as a standard method of generating
38  * run-time system warnings. The actual action taken by this code can
39  * be board or target application specific, e.g. internal logging,
40  * debug message, etc.
41  */
42
43 #ifdef DEBUG
44
45 # ifdef DEBUG_METHOD
46
47 #  define  STRINGIFY2(x) #x
48 #  define  STRINGIFY(x)  STRINGIFY2(x)
49 #  define  DEBUG_METHOD_HEADER        STRINGIFY(DEBUG_METHOD##.h)
50
51 #  include DEBUG_METHOD_HEADER
52
53 #  define  METHOD_EXPAND_2(m, p, c) m##p(c)
54 #  define  METHOD_EXPAND(m, p, c)   METHOD_EXPAND_2(m, p, c)
55
56 #  define  CHAROUT(c)    METHOD_EXPAND(DEBUG_METHOD, _PutChar,  (c))
57 #  define  PRE_DEBUG(l)  METHOD_EXPAND(DEBUG_METHOD, _PreWarn,  (l))
58 #  define  POST_DEBUG(n) METHOD_EXPAND(DEBUG_METHOD, _PostWarn, (n))
59
60 # else
61 #  error Must define DEBUG_METHOD
62 # endif
63
64 #endif /* def DEBUG */
65
66 /*
67  * the guts of __rt_warning
68  */
69
70 #pragma no_check_stack
71 #ifdef DEBUG
72
73 static const char hextab[] = "0123456789ABCDEF";
74
75 /*
76  * If debugging, then we break va_warn into sub-functions which
77  * allow us to get an easy breakpoint on the formatted string
78  */
79 static int va_warn0(char *format, va_list args)
80 {
81     int len = 0;
82
83     while ((format != NULL) && (*format != '\0'))
84     {
85         if (*format == '%')
86         {
87             char fch = *(++format); /* get format character (skipping '%') */
88             int ival; /* holder for integer arguments */
89             char *string; /* holder for string arguments */
90             int width = 0; /* No field width by default */
91             int padzero = FALSE; /* By default we pad with spaces */
92
93             /*
94              * Check if the format has a width specified. NOTE: We do
95              * not use the "isdigit" function here, since it will
96              * require run-time support. The current ARM Ltd header
97              * defines "isdigit" as a macro, that uses a fixed
98              * character description table.
99              */
100             if ((fch >= '0') && (fch <= '9'))
101             {
102                 if (fch == '0')
103                 {
104                     /* Leading zeroes padding */
105                     padzero = TRUE;
106                     fch = *(++format);
107                 }
108
109                 while ((fch >= '0') && (fch <= '9'))
110                 {
111                     width = ((width * 10) + (fch - '0'));
112                     fch = *(++format);
113                 }
114             }
115
116             if (fch == 'l')
117                 /* skip 'l' in "%lx", etc. */
118                 fch = *(++format);
119
120             switch (fch)
121             {
122               case 'c':
123                   /* char */
124                   ival = va_arg(args, int);
125                   CHAROUT((char)ival);
126                   len++;
127                   break;
128
129               case 'x':
130               case 'X':
131               {
132                   /* hexadecimal */
133                   unsigned int uval = va_arg(args, unsigned int);
134                   int loop;
135
136                   UNUSED(uval);
137
138                   if ((width == 0) || (width > 8))
139                       width = 8;
140
141                   for(loop = (width * 4); (loop != 0); loop -= 4)
142                   {
143                       CHAROUT(hextab[(uval >> (loop - 4)) & 0xF]);
144                       len++;
145                   }
146               }
147
148               break;
149
150               case 'd':
151                   /* decimal */
152                   ival = va_arg(args, int);
153
154                   if (ival < 0)
155                   {
156                       ival = -ival;
157                       CHAROUT('-');
158                       len++;
159                   }
160
161                   if (ival == 0)
162                   {
163                       CHAROUT('0');
164                       len++;
165                   }
166                   else
167                   {
168                       /*
169                        * The simplest method of displaying numbers is
170                        * to provide a small recursive routine, that
171                        * nests until the most-significant digit is
172                        * reached, and then falls back out displaying
173                        * individual digits. However, we want to avoid
174                        * using recursive code within the lo-level
175                        * parts of Angel (to minimise the stack
176                        * usage). The following number conversion is a
177                        * non-recursive solution.
178                        */
179                       char buffer[16]; /* stack space used to hold number */
180                       int count = 0; /* pointer into buffer */
181
182                       /*
183                        * Place the conversion into the buffer in
184                        * reverse order:
185                        */
186                       while (ival != 0)
187                       {
188                           buffer[count++] = ('0' + ((unsigned int)ival % 10));
189                           ival = ((unsigned int)ival / 10);
190                       }
191
192                       /*
193                        * Check if we are placing the data in a
194                        * fixed width field:
195                        */
196                       if (width != 0)
197                       {
198                           width -= count;
199
200                           for (; (width != 0); width--)
201                           {
202                               CHAROUT(padzero ? '0': ' ');
203                               len++;
204                           }
205                       }
206
207                       /* then display the buffer in reverse order */
208                       for (; (count != 0); count--)
209                       {
210                           CHAROUT(buffer[count - 1]);
211                           len++;
212                       }
213                   }
214
215                   break;
216
217               case 's':
218                   /* string */
219                   string = va_arg(args, char *);
220
221                   /* we only need this test once */
222                   if (string != NULL)
223                       /* whilst we check this for every character */
224                       while (*string)
225                       {
226                           CHAROUT(*string);
227                           len++;
228                           string++;
229
230                           /*
231                            * NOTE: We do not use "*string++" as the macro
232                            * parameter, since we do not know how many times
233                            *the parameter may be expanded within the macro.
234                            */
235                       }
236
237                   break;
238
239               case '\0':
240                   /*
241                    * string terminated by '%' character, bodge things
242                    * to prepare for default "format++" below
243                    */
244                   format--;
245
246                   break;
247
248               default:
249                   /* just display the character */
250                   CHAROUT(*format);
251                   len++;
252
253                   break;
254             }
255
256             format++; /* step over format character */
257         }
258         else
259         {
260             CHAROUT(*format);
261             len++;
262             format++;
263         }
264     }
265     return len;
266 }
267
268 /*
269  * this routine is simply here as a good breakpoint for dumping msg -
270  * can be used by DEBUG_METHOD macros or functions, if required.
271  */
272 # ifdef DEBUG_NEED_VA_WARN1
273 static void va_warn1(int len, char *msg)
274 {
275     UNUSED(len); UNUSED(msg);
276 }
277 # endif
278
279 void va_warn(WarnLevel level, char *format, va_list args)
280 {
281     int len;
282
283     if ( PRE_DEBUG( level ) )
284     {
285         len = va_warn0(format, args);
286         POST_DEBUG( len );
287     }
288 }
289
290 #else /* ndef DEBUG */
291
292 void va_warn(WarnLevel level, char *format, va_list args)
293 {
294     UNUSED(level); UNUSED(format); UNUSED(args);
295 }
296
297 #endif /* ... else ndef(DEBUG) ... */
298 #pragma check_stack
299
300 #pragma no_check_stack
301 void __rt_warning(char *format, ...)
302 {
303     va_list args;
304
305     /*
306      * For a multi-threaded system we should provide a lock at this point
307      * to ensure that the warning messages are sequenced properly.
308      */
309
310     va_start(args, format);
311     va_warn(WL_WARN, format, args);
312     va_end(args);
313
314     return;
315 }
316 #pragma check_stack
317
318 #ifdef TARGET
319
320 #pragma no_check_stack
321 void __rt_uninterruptable_loop( void ); /* in suppasm.s */
322
323 void __rt_error(char *format, ...)
324 {
325     va_list args;
326
327     va_start(args, format);
328
329     /* Display warning message */
330     va_warn(WL_ERROR, format, args);
331
332     __rt_uninterruptable_loop();
333
334     va_end(args);
335     return;
336 }
337 #pragma check_stack
338
339 #endif /* def TARGET */
340
341 #ifdef DO_TRACE
342
343 static bool trace_on = FALSE; /* must be set true in debugger if req'd */
344
345 #pragma no_check_stack
346 void __rt_trace(char *format, ...)
347 {
348     va_list args;
349
350     /*
351      * For a multi-threaded system we should provide a lock at this point
352      * to ensure that the warning messages are sequenced properly.
353      */
354
355     if (trace_on)
356     {
357         va_start(args, format);
358         va_warn(WL_TRACE, format, args);
359         va_end(args);
360     }
361
362     return;
363 }
364 #pragma check_stack
365
366 #endif /* def DO_TRACE */
367
368
369 /* EOF logging.c */
This page took 0.045066 seconds and 4 git commands to generate.