Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / ElectricFence / print.c
bloba9705ac8847af980c756fbd73df3d94fafeba385
1 /* $NetBSD$ */
3 #include "efence.h"
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <stdarg.h>
7 #include <string.h>
8 #include <signal.h>
11 * These routines do their printing without using stdio. Stdio can't
12 * be used because it calls malloc(). Internal routines of a malloc()
13 * debugger should not re-enter malloc(), so stdio is out.
17 * NUMBER_BUFFER_SIZE is the longest character string that could be needed
18 * to represent an unsigned integer, assuming we might print in base 2.
20 #define NUMBER_BUFFER_SIZE (sizeof(ef_number) * NBBY)
22 static void
23 printNumber(ef_number number, ef_number base)
25 char buffer[NUMBER_BUFFER_SIZE];
26 char * s = &buffer[NUMBER_BUFFER_SIZE];
27 int size;
29 do {
30 ef_number digit;
32 if ( --s == buffer )
33 EF_Abort("Internal error printing number.");
35 digit = number % base;
37 if ( digit < 10 )
38 *s = '0' + digit;
39 else
40 *s = 'a' + digit - 10;
42 } while ( (number /= base) > 0 );
44 size = &buffer[NUMBER_BUFFER_SIZE] - s;
46 if ( size > 0 )
47 write(2, s, size);
50 static void
51 vprint(const char * pattern, va_list args)
53 static const char bad_pattern[] =
54 "\nBad pattern specifier %%%c in EF_Print().\n";
55 const char * s = pattern;
56 char c;
58 while ( (c = *s++) != '\0' ) {
59 if ( c == '%' ) {
60 c = *s++;
61 switch ( c ) {
62 case '%':
63 (void) write(2, &c, 1);
64 break;
65 case 'a':
67 * Print an address passed as a void pointer.
68 * The type of ef_number must be set so that
69 * it is large enough to contain all of the
70 * bits of a void pointer.
72 printNumber(
73 (ef_number)va_arg(args, void *)
74 ,0x10);
75 break;
76 case 's':
78 const char * string;
79 size_t length;
81 string = va_arg(args, char *);
82 length = strlen(string);
84 (void) write(2, string, length);
86 break;
87 case 'd':
89 int n = va_arg(args, int);
91 if ( n < 0 ) {
92 char c = '-';
93 write(2, &c, 1);
94 n = -n;
96 printNumber(n, 10);
98 break;
99 case 'x':
100 printNumber(va_arg(args, u_int), 0x10);
101 break;
102 case 'c':
104 char c = va_arg(args, char);
106 (void) write(2, &c, 1);
108 break;
109 default:
111 EF_Print(bad_pattern, c);
116 else
117 (void) write(2, &c, 1);
121 void
122 EF_Abort(const char * pattern, ...)
124 va_list args;
126 va_start(args, pattern);
128 EF_Print("\nElectricFence Aborting: ");
129 vprint(pattern, args);
130 EF_Print("\n");
132 va_end(args);
135 * I use kill(getpid(), SIGILL) instead of abort() because some
136 * mis-guided implementations of abort() flush stdio, which can
137 * cause malloc() or free() to be called.
139 kill(getpid(), SIGILL);
140 /* Just in case something handles SIGILL and returns, exit here. */
141 _exit(-1);
144 void
145 EF_Exit(const char * pattern, ...)
147 va_list args;
149 va_start(args, pattern);
151 EF_Print("\nElectricFence Exiting: ");
152 vprint(pattern, args);
153 EF_Print("\n");
155 va_end(args);
158 * I use _exit() because the regular exit() flushes stdio,
159 * which may cause malloc() or free() to be called.
161 _exit(-1);
164 void
165 EF_Print(const char * pattern, ...)
167 va_list args;
169 va_start(args, pattern);
170 vprint(pattern, args);
171 va_end(args);