diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
commit | c906108c21474dfb4ed285bcc0ac6fe02cd400cc (patch) | |
tree | a0015aa5cedc19ccbab307251353a41722a3ae13 /gdb/rdi-share/logging.c | |
parent | cd946cff9ede3f30935803403f06f6ed30cad136 (diff) | |
download | gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.zip gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.gz gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.bz2 |
Initial creation of sourceware repositorygdb-4_18-branchpoint
Diffstat (limited to 'gdb/rdi-share/logging.c')
-rw-r--r-- | gdb/rdi-share/logging.c | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/gdb/rdi-share/logging.c b/gdb/rdi-share/logging.c new file mode 100644 index 0000000..79b70ef --- /dev/null +++ b/gdb/rdi-share/logging.c @@ -0,0 +1,369 @@ +/* + * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved. + * + * This software may be freely used, copied, modified, and distributed + * provided that the above copyright notice is preserved in all copies of the + * software. + */ + +/* -*-C-*- + * + * $Revision$ + * $Date$ + * + * + * logging.c - methods for logging warnings, errors and trace info + * + */ + +#include <stdarg.h> /* ANSI varargs support */ + +#ifdef TARGET +# include "angel.h" +# include "devconf.h" +#else +# include "host.h" +#endif + +#include "logging.h" /* Header file for this source code */ + +#ifndef UNUSED +# define UNUSED(x) ((x)=(x)) +#endif + +/* + * __rt_warning + * ------------ + * This routine is provided as a standard method of generating + * run-time system warnings. The actual action taken by this code can + * be board or target application specific, e.g. internal logging, + * debug message, etc. + */ + +#ifdef DEBUG + +# ifdef DEBUG_METHOD + +# define STRINGIFY2(x) #x +# define STRINGIFY(x) STRINGIFY2(x) +# define DEBUG_METHOD_HEADER STRINGIFY(DEBUG_METHOD##.h) + +# include DEBUG_METHOD_HEADER + +# define METHOD_EXPAND_2(m, p, c) m##p(c) +# define METHOD_EXPAND(m, p, c) METHOD_EXPAND_2(m, p, c) + +# define CHAROUT(c) METHOD_EXPAND(DEBUG_METHOD, _PutChar, (c)) +# define PRE_DEBUG(l) METHOD_EXPAND(DEBUG_METHOD, _PreWarn, (l)) +# define POST_DEBUG(n) METHOD_EXPAND(DEBUG_METHOD, _PostWarn, (n)) + +# else +# error Must define DEBUG_METHOD +# endif + +#endif /* def DEBUG */ + +/* + * the guts of __rt_warning + */ + +#pragma no_check_stack +#ifdef DEBUG + +static const char hextab[] = "0123456789ABCDEF"; + +/* + * If debugging, then we break va_warn into sub-functions which + * allow us to get an easy breakpoint on the formatted string + */ +static int va_warn0(char *format, va_list args) +{ + int len = 0; + + while ((format != NULL) && (*format != '\0')) + { + if (*format == '%') + { + char fch = *(++format); /* get format character (skipping '%') */ + int ival; /* holder for integer arguments */ + char *string; /* holder for string arguments */ + int width = 0; /* No field width by default */ + int padzero = FALSE; /* By default we pad with spaces */ + + /* + * Check if the format has a width specified. NOTE: We do + * not use the "isdigit" function here, since it will + * require run-time support. The current ARM Ltd header + * defines "isdigit" as a macro, that uses a fixed + * character description table. + */ + if ((fch >= '0') && (fch <= '9')) + { + if (fch == '0') + { + /* Leading zeroes padding */ + padzero = TRUE; + fch = *(++format); + } + + while ((fch >= '0') && (fch <= '9')) + { + width = ((width * 10) + (fch - '0')); + fch = *(++format); + } + } + + if (fch == 'l') + /* skip 'l' in "%lx", etc. */ + fch = *(++format); + + switch (fch) + { + case 'c': + /* char */ + ival = va_arg(args, int); + CHAROUT((char)ival); + len++; + break; + + case 'x': + case 'X': + { + /* hexadecimal */ + unsigned int uval = va_arg(args, unsigned int); + int loop; + + UNUSED(uval); + + if ((width == 0) || (width > 8)) + width = 8; + + for(loop = (width * 4); (loop != 0); loop -= 4) + { + CHAROUT(hextab[(uval >> (loop - 4)) & 0xF]); + len++; + } + } + + break; + + case 'd': + /* decimal */ + ival = va_arg(args, int); + + if (ival < 0) + { + ival = -ival; + CHAROUT('-'); + len++; + } + + if (ival == 0) + { + CHAROUT('0'); + len++; + } + else + { + /* + * The simplest method of displaying numbers is + * to provide a small recursive routine, that + * nests until the most-significant digit is + * reached, and then falls back out displaying + * individual digits. However, we want to avoid + * using recursive code within the lo-level + * parts of Angel (to minimise the stack + * usage). The following number conversion is a + * non-recursive solution. + */ + char buffer[16]; /* stack space used to hold number */ + int count = 0; /* pointer into buffer */ + + /* + * Place the conversion into the buffer in + * reverse order: + */ + while (ival != 0) + { + buffer[count++] = ('0' + ((unsigned int)ival % 10)); + ival = ((unsigned int)ival / 10); + } + + /* + * Check if we are placing the data in a + * fixed width field: + */ + if (width != 0) + { + width -= count; + + for (; (width != 0); width--) + { + CHAROUT(padzero ? '0': ' '); + len++; + } + } + + /* then display the buffer in reverse order */ + for (; (count != 0); count--) + { + CHAROUT(buffer[count - 1]); + len++; + } + } + + break; + + case 's': + /* string */ + string = va_arg(args, char *); + + /* we only need this test once */ + if (string != NULL) + /* whilst we check this for every character */ + while (*string) + { + CHAROUT(*string); + len++; + string++; + + /* + * NOTE: We do not use "*string++" as the macro + * parameter, since we do not know how many times + *the parameter may be expanded within the macro. + */ + } + + break; + + case '\0': + /* + * string terminated by '%' character, bodge things + * to prepare for default "format++" below + */ + format--; + + break; + + default: + /* just display the character */ + CHAROUT(*format); + len++; + + break; + } + + format++; /* step over format character */ + } + else + { + CHAROUT(*format); + len++; + format++; + } + } + return len; +} + +/* + * this routine is simply here as a good breakpoint for dumping msg - + * can be used by DEBUG_METHOD macros or functions, if required. + */ +# ifdef DEBUG_NEED_VA_WARN1 +static void va_warn1(int len, char *msg) +{ + UNUSED(len); UNUSED(msg); +} +# endif + +void va_warn(WarnLevel level, char *format, va_list args) +{ + int len; + + if ( PRE_DEBUG( level ) ) + { + len = va_warn0(format, args); + POST_DEBUG( len ); + } +} + +#else /* ndef DEBUG */ + +void va_warn(WarnLevel level, char *format, va_list args) +{ + UNUSED(level); UNUSED(format); UNUSED(args); +} + +#endif /* ... else ndef(DEBUG) ... */ +#pragma check_stack + +#pragma no_check_stack +void __rt_warning(char *format, ...) +{ + va_list args; + + /* + * For a multi-threaded system we should provide a lock at this point + * to ensure that the warning messages are sequenced properly. + */ + + va_start(args, format); + va_warn(WL_WARN, format, args); + va_end(args); + + return; +} +#pragma check_stack + +#ifdef TARGET + +#pragma no_check_stack +void __rt_uninterruptable_loop( void ); /* in suppasm.s */ + +void __rt_error(char *format, ...) +{ + va_list args; + + va_start(args, format); + + /* Display warning message */ + va_warn(WL_ERROR, format, args); + + __rt_uninterruptable_loop(); + + va_end(args); + return; +} +#pragma check_stack + +#endif /* def TARGET */ + +#ifdef DO_TRACE + +static bool trace_on = FALSE; /* must be set true in debugger if req'd */ + +#pragma no_check_stack +void __rt_trace(char *format, ...) +{ + va_list args; + + /* + * For a multi-threaded system we should provide a lock at this point + * to ensure that the warning messages are sequenced properly. + */ + + if (trace_on) + { + va_start(args, format); + va_warn(WL_TRACE, format, args); + va_end(args); + } + + return; +} +#pragma check_stack + +#endif /* def DO_TRACE */ + + +/* EOF logging.c */ |