comparison packages/infra/current/src/diag.c @ 0:3111d98ba7b3 ecos-v1_1-release

Initial commit of eCos version 1.1
author jlarmour
date Tue, 11 May 1999 11:16:07 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3111d98ba7b3
1 /*========================================================================
2 //
3 // diag.c
4 //
5 // Infrastructure diagnostic output code
6 //
7 //========================================================================
8 //####COPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 // The contents of this file are subject to the Cygnus eCos Public License
12 // Version 1.0 (the "License"); you may not use this file except in
13 // compliance with the License. You may obtain a copy of the License at
14 // http://sourceware.cygnus.com/ecos
15 //
16 // Software distributed under the License is distributed on an "AS IS"
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 // License for the specific language governing rights and limitations under
19 // the License.
20 //
21 // The Original Code is eCos - Embedded Cygnus Operating System, released
22 // September 30, 1998.
23 //
24 // The Initial Developer of the Original Code is Cygnus. Portions created
25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved.
26 // -------------------------------------------
27 //
28 //####COPYRIGHTEND####
29 //========================================================================
30 //#####DESCRIPTIONBEGIN####
31 //
32 // Author(s): nickg
33 // Contributors: nickg
34 // Date: 1998-03-02
35 // Purpose: Infrastructure diagnostic output
36 // Description: Implementations of infrastructure diagnostic routines.
37 //
38 //####DESCRIPTIONEND####
39 //
40 //======================================================================*/
41
42 #include <pkgconf/system.h>
43 #include <pkgconf/hal.h>
44 #include <pkgconf/infra.h>
45
46 #include <cyg/infra/cyg_type.h> // base types
47
48 #include <cyg/infra/diag.h> // HAL polled output
49 #include <cyg/hal/hal_arch.h> // architectural stuff for...
50 #include <cyg/hal/hal_intr.h> // interrupt control
51 #include <cyg/hal/hal_diag.h> // diagnostic output routines
52
53 #ifdef CYGDBG_INFRA_DIAG_PRINTF_USE_VARARG
54
55 #include <stdarg.h>
56
57 #endif
58
59
60
61 /*----------------------------------------------------------------------*/
62
63 void diag_write_num(
64 cyg_uint32 n, /* number to write */
65 cyg_ucount8 base, /* radix to write to */
66 cyg_ucount8 sign, /* sign, '-' if -ve, '+' if +ve */
67 cyg_bool pfzero, /* prefix with zero ? */
68 cyg_ucount8 width /* min width of number */
69 );
70
71 #ifdef CYGDBG_INFRA_DIAG_USE_DEVICE
72
73 // this is not properly supported; in particular, there is no properly
74 // defined API (extern definition) for the diag_device routines used below.
75
76 /*----------------------------------------------------------------------*/
77 /* Initialize, call before any others */
78
79 externC void diag_init()
80 {
81 }
82
83 /*----------------------------------------------------------------------*/
84 /* Write single char to output */
85
86 externC void diag_write_char(char c)
87 {
88 diag_device_write_char(c);
89 }
90
91 #else
92
93 /*----------------------------------------------------------------------*/
94 /* Initialize, call before any others */
95
96 externC void diag_init(void)
97 {
98 HAL_DIAG_INIT();
99 }
100
101 /*----------------------------------------------------------------------*/
102 /* Write single char to output */
103
104 #define PREFIX()
105 //#define PREFIX() HAL_DIAG_WRITE_CHAR(0x0F)
106
107 externC void diag_write_char(char c)
108 {
109 /* Translate LF into CRLF */
110
111 if( c == '\n' )
112 {
113 PREFIX();
114 HAL_DIAG_WRITE_CHAR('\r');
115 }
116
117 PREFIX();
118 HAL_DIAG_WRITE_CHAR(c);
119 }
120 #endif
121
122 /*----------------------------------------------------------------------*/
123 /* Write zero terminated string */
124
125 externC void diag_write_string(char *psz)
126 {
127 while( *psz ) diag_write_char( *psz++ );
128 }
129
130 /*----------------------------------------------------------------------*/
131 /* Write decimal value */
132
133 externC void diag_write_dec( cyg_int32 n)
134 {
135 cyg_ucount8 sign;
136
137 if( n < 0 ) n = -n, sign = '-';
138 else sign = '+';
139
140 diag_write_num( n, 10, sign, false, 0);
141 }
142
143 /*----------------------------------------------------------------------*/
144 /* Write hexadecimal value */
145
146 externC void diag_write_hex( cyg_uint32 n)
147 {
148 diag_write_num( n, 16, '+', false, 0);
149 }
150
151 /*----------------------------------------------------------------------*/
152 /* Generic number writing function */
153 /* The parameters determine what radix is used, the signed-ness of the */
154 /* number, its minimum width and whether it is zero or space filled on */
155 /* the left. */
156
157 void diag_write_num(
158 cyg_uint32 n, /* number to write */
159 cyg_ucount8 base, /* radix to write to */
160 cyg_ucount8 sign, /* sign, '-' if -ve, '+' if +ve */
161 cyg_bool pfzero, /* prefix with zero ? */
162 cyg_ucount8 width /* min width of number */
163 )
164 {
165 char buf[16];
166 cyg_count8 bpos;
167 char bufinit = pfzero?'0':' ';
168 char *digits = "0123456789ABCDEF";
169
170 /* init buffer to padding char: space or zero */
171 for( bpos = 0; bpos < (cyg_count8)sizeof(buf); bpos++ ) buf[bpos] = bufinit;
172
173 /* Set pos to start */
174 bpos = 0;
175
176 /* construct digits into buffer in reverse order */
177 if( n == 0 ) buf[bpos++] = '0';
178 else while( n != 0 )
179 {
180 cyg_ucount8 d = n % base;
181 buf[bpos++] = digits[d];
182 n /= base;
183 }
184
185 /* set pos to width if less. */
186 if( (cyg_count8)width > bpos ) bpos = width;
187
188 /* set sign if negative. */
189 if( sign == '-' )
190 {
191 if( buf[bpos-1] == bufinit ) bpos--;
192 buf[bpos] = sign;
193 }
194 else bpos--;
195
196 /* Now write it out in correct order. */
197 while( bpos >= 0 )
198 diag_write_char(buf[bpos--]);
199 }
200
201 /*----------------------------------------------------------------------*/
202 /* perform some simple sanity checks on a string to ensure that it */
203 /* consists of printable characters and is of reasonable length. */
204
205 static cyg_bool diag_check_string( char *str )
206 {
207 cyg_bool result = true;
208 char *s;
209
210 if( str == NULL ) return false;
211
212 for( s = str ; result && *s ; s++ )
213 {
214 char c = *s;
215
216 /* Check for a reasonable length string. */
217
218 if( s-str > 256 ) result = false;
219
220 /* We only really support CR and NL at present. If we want to
221 * use tabs or other special chars, this test will have to be
222 * expanded.
223 */
224
225 if( c == '\n' || c == '\r' )
226 continue;
227
228 /* Check for printable chars. This assumes ASCII */
229
230 if( c < ' ' || c > '~' )
231 result = false;
232
233 }
234
235 return result;
236 }
237
238 /*----------------------------------------------------------------------*/
239
240 externC void diag_vprintf( char *fmt, CYG_ADDRWORD *args)
241 {
242 if( !diag_check_string(fmt) )
243 {
244 int i;
245 diag_write_string("<Bad format string: ");
246 diag_write_hex((cyg_uint32)fmt);
247 diag_write_string(" :");
248 for( i = 0; i < 8; i++ )
249 {
250 diag_write_char(' ');
251 diag_write_hex(args[i]);
252 }
253 diag_write_string(">\n");
254 return;
255 }
256
257 while( *fmt != '\0' )
258 {
259 char c = *fmt;
260
261 if( c != '%' ) diag_write_char( c );
262 else
263 {
264 cyg_bool pfzero = false;
265 cyg_count8 width = 0;
266 char sign = '+';
267
268 c = *++fmt;
269
270 if( c == '0' ) pfzero = true;
271
272 while( '0' <= c && c <= '9' )
273 {
274 width = width*10 + c - '0';
275 c = *++fmt;
276 }
277
278 switch( c )
279 {
280 case 'd':
281 case 'D':
282 {
283 long val = (long)(*args++);
284 if( val < 0 ) val = -val, sign = '-';
285 diag_write_num(val, 10, sign, pfzero, width);
286 break;
287 }
288
289 case 'x':
290 case 'X':
291 {
292 unsigned long val = (long)(*args++);
293 diag_write_num(val, 16, sign, pfzero, width);
294 break;
295 }
296
297 case 'c':
298 case 'C':
299 {
300 char ch = (char)(*args++);
301 diag_write_char(ch);
302 break;
303 }
304
305 case 's':
306 case 'S':
307 {
308 char *s = (char *)(*args++);
309 cyg_count32 len = 0;
310 cyg_count32 pre = 0, post = 0;
311
312 if( s == NULL ) s = "<null>";
313 else if( !diag_check_string(s) )
314 {
315 diag_write_string("<Not a string: 0x");
316 diag_write_hex((cyg_uint32)s);
317 s = ">";
318 if( width > 25 ) width -= 25;
319 pfzero = false;
320 /* Drop through to print the closing ">" */
321 /* and pad to the required length. */
322 }
323
324 while( s[len] != 0 ) len++;
325
326 if( width && len > width ) len = width;
327
328 if( pfzero ) pre = width-len;
329 else post = width-len;
330
331 while( pre-- > 0 ) diag_write_char(' ');
332
333 while( *s != '\0' && len-- != 0)
334 diag_write_char(*s++);
335
336 while( post-- > 0 ) diag_write_char(' ');
337
338 break;
339 }
340
341 case 'b':
342 case 'B':
343 {
344 unsigned long val = (unsigned long)(*args++);
345 cyg_uint32 i;
346 if( width == 0 ) width = 32;
347
348 for( i = width-1; i >= 0; i-- )
349 diag_write_char( (val&(1<<i))?'1':'.' );
350
351 break;
352 }
353
354 default:
355 diag_write_char('%');
356 diag_write_char(c);
357 break;
358 }
359 }
360
361 fmt++;
362 }
363
364 }
365
366 /*-----------------------------------------------------------------------*/
367 /* Formatted diagnostic output. */
368
369 #ifdef CYGDBG_INFRA_DIAG_PRINTF_USE_VARARG
370
371 externC void diag_printf(char *fmt, ... )
372 {
373
374 CYG_ADDRWORD args[8];
375
376 va_list a;
377
378 va_start(a, fmt);
379
380 /* Move all of the arguments into simple scalars. This avoids
381 * having to use varargs to define diag_vprintf().
382 */
383
384 args[0] = va_arg(a,CYG_ADDRWORD);
385 args[1] = va_arg(a,CYG_ADDRWORD);
386 args[2] = va_arg(a,CYG_ADDRWORD);
387 args[3] = va_arg(a,CYG_ADDRWORD);
388 args[4] = va_arg(a,CYG_ADDRWORD);
389 args[5] = va_arg(a,CYG_ADDRWORD);
390 args[6] = va_arg(a,CYG_ADDRWORD);
391 args[7] = va_arg(a,CYG_ADDRWORD);
392
393 va_end(a);
394
395 diag_vprintf( fmt, args);
396 }
397
398 #else
399
400 /* The prototype for diag_printf in diag.h is defined using K&R syntax */
401 /* to allow us to use a variable number of arguments in the call without */
402 /* using ellipses, which would require use of varargs stuff. If we ever */
403 /* need to support arguments that are not simple words, we may need to */
404 /* use varargs. */
405 /* For the actual implementation, a normal ANSI C prototype is */
406 /* acceptable. */
407
408 externC void diag_printf(char *fmt, CYG_ADDRWORD a1, CYG_ADDRWORD a2,
409 CYG_ADDRWORD a3, CYG_ADDRWORD a4,
410 CYG_ADDRWORD a5, CYG_ADDRWORD a6,
411 CYG_ADDRWORD a7, CYG_ADDRWORD a8)
412 {
413
414 CYG_ADDRWORD args[8];
415
416 args[0] = a1;
417 args[1] = a2;
418 args[2] = a3;
419 args[3] = a4;
420 args[4] = a5;
421 args[5] = a6;
422 args[6] = a7;
423 args[7] = a8;
424
425 diag_vprintf( fmt, args);
426 }
427
428 #endif
429
430 /*-----------------------------------------------------------------------*/
431 /* EOF trace/diag.c */