source: trunk/libs/newlib/src/newlib/libc/misc/__dprintf.c

Last change on this file was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 5.1 KB
Line 
1/* Debugging printf, for debugging the library itself.
2
3   We don't assume stdio is working.
4   We do assume _write_r is working.
5*/
6
7#include <_ansi.h>
8#include "ctype.h"
9#include "reent.h"
10#include "string.h"
11#include "unctrl.h"
12
13#ifdef __STDC__
14#include "stdarg.h"
15#else
16#include "varargs.h"
17#endif
18
19#if 0
20static char *parse_number ();
21#endif
22
23static long get_number (char *, long, int);
24static void print_number (int, int, long);
25static void write_char (char c);
26static void write_string (const char *s);
27
28/* Non-zero for big-endian systems.  */
29static int big_endian_p;
30
31/* For now hardcode 2 (stderr) as the console file descriptor.
32   May wish to let the caller pass in a file descriptor or some such but
33   this is only for debugging purposes anyway.  */
34#define CONSOLE_FD 2
35
36/* Standalone printf routine.
37
38   The format string has been enhanced so that multiple values can be dumped
39   without having to have a %-field for each one (say if you want to dump
40   20 words at a certain address).  A modifier of `N' says the next argument
41   is a count, and the one after that is a pointer.
42
43   Example: __dprintf ("%Nx\n", 20, p); /-* print 20 ints at `p' *-/
44
45   Supported formats are: c d u x s p.
46
47   All ints are retrieved a byte at a time so alignment issues are not
48   a problem.
49
50   This routine is used in situations where the only debugging capability
51   is console output and was written to aid debugging newlib itself.  We don't
52   use printf ourselves as we may be debugging it.  We do assume _write_r is
53   working.
54*/
55
56void
57#ifdef __STDC__
58__dprintf (const char *fmt, ...)
59#else
60__dprintf (fmt, va_alist)
61     char *fmt;
62     va_dcl
63#endif
64{
65  va_list args;
66
67  /* Which endian are we?  */
68  {
69    short tmp = 1;
70    big_endian_p = *(char *) &tmp == 0;
71  }
72
73#ifdef __STDC__
74  va_start (args, fmt);
75#else
76  va_start (args);
77#endif
78
79  while (*fmt)
80    {
81      char c, *p;
82      int count;
83      long l;
84
85      if (*fmt != '%' || *++fmt == '%')
86        {
87          write_char (*fmt++);
88          continue;
89        }
90
91      if (*fmt == 'N')
92        {
93          count = va_arg (args, int);
94          p = va_arg (args, char *);
95          ++fmt;
96          c = *fmt++;
97
98          while (--count >= 0)
99            {
100              switch (c)
101                {
102                case 'c' :
103                  write_string (unctrl (*p++));
104                  break;
105                case 'p' :
106                  print_number (16, 1, get_number (p, sizeof (char *), 1));
107                  p += sizeof (char *);
108                  break;
109                case 'd' :
110                case 'u' :
111                case 'x' :
112                  print_number (c == 'x' ? 16 : 10, c != 'd',
113                                get_number (p, sizeof (int), c != 'd'));
114                  p += sizeof (int);
115                  break;
116                case 's' :
117                  write_string (*(char **) p);
118                  p += sizeof (char *);
119                  break;
120                }
121              if (count > 0)
122                write_char (' ');
123            }
124        }
125      else
126        {
127          switch (c = *fmt++)
128            {
129            case 'c' :
130              c = va_arg (args, int);
131              write_string (unctrl (c));
132              break;
133            case 'p' :
134              l = (_POINTER_INT) va_arg (args, char *);
135              print_number (16, 1, l);
136              break;
137            case 'd' :
138            case 'u' :
139            case 'x' :
140              l = va_arg (args, int);
141              print_number (c == 'x' ? 16 : 10, c != 'd', l);
142              break;
143            case 's' :
144              p = va_arg (args, char *);
145              write_string (p);
146              break;
147            }
148        }
149    }
150
151  va_end (args);
152}
153
154#if 0
155/* Parse a positive decimal integer at S.
156   FIXME: Was used in earlier version, but not currently used.
157   Keep for now.  */
158
159static char *
160parse_number (s, p)
161     char *s;
162     long *p;
163{
164  long x = 0;
165
166  while (isdigit (*s))
167    {
168      x = (x * 10) + (*s - '0');
169      ++s;
170    }
171
172  *p = x;
173  return s;
174}
175#endif
176
177/* Fetch the number at S of SIZE bytes.  */
178
179static long
180get_number (char *s,
181     long size,
182     int unsigned_p)
183{
184  long x;
185  unsigned char *p = (unsigned char *) s;
186
187  switch (size)
188    {
189    case 1 :
190      x = *p;
191      if (!unsigned_p)
192        x = (x ^ 0x80) - 0x80;
193      return x;
194    case 2 :
195      if (big_endian_p)
196        x = (p[0] << 8) | p[1];
197      else
198        x = (p[1] << 8) | p[0];
199      if (!unsigned_p)
200        x = (x ^ 0x8000) - 0x8000;
201      return x;
202    case 4 :
203      if (big_endian_p)
204        x = ((long)p[0] << 24) | ((long)p[1] << 16) | (p[2] << 8) | p[3];
205      else
206        x = ((long)p[3] << 24) | ((long)p[2] << 16) | (p[1] << 8) | p[0];
207      if (!unsigned_p)
208        x = (x ^ 0x80000000L) - 0x80000000L;
209      return x;
210#if 0 /* FIXME: Is there a standard mechanism for knowing if
211         long longs exist?  */
212    case 8 :
213#endif
214    default :
215      return 0;
216  }
217}
218
219/* Print X in base BASE.  */
220
221static void
222print_number (int base,
223     int unsigned_p,
224     long n)
225{
226  static char chars[16] = "0123456789abcdef";
227  char *p, buf[32];
228  unsigned long x;
229
230  if (!unsigned_p && n < 0)
231    {
232      write_char ('-');
233      x = -n;
234    }
235  else
236    x = n;
237
238  p = buf + sizeof (buf);
239  *--p = '\0';
240  do
241    {
242      *--p = chars[x % base];
243      x /= base;
244    }
245  while (x != 0);
246
247  write_string (p);
248}
249
250/* Write C to the console.
251   We go through the file descriptor directly because we can't assume
252   stdio is working.  */
253
254static void
255write_char (char c)
256{
257  _write_r (_REENT, CONSOLE_FD, &c, 1);
258}
259
260/* Write S to the console.
261   We go through the file descriptor directly because we can't assume
262   stdio is working.  */
263
264static void
265write_string (const char *s)
266{
267  _write_r (_REENT, CONSOLE_FD, s, strlen (s));
268}
Note: See TracBrowser for help on using the repository browser.