source: rtems/cpukit/libcsupport/src/vprintk.c @ bd5a1386

4.115
Last change on this file since bd5a1386 was bd5a1386, checked in by Sebastian Huber <sebastian.huber@…>, on 08/13/12 at 09:29:13

libcsupport: Add and use rtems_putc()

This reduces code size and provides a function similar to fputc().

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/*
2 * (C) Copyright 1997 -
3 * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
4 *
5 * http://pandora.ist.utl.pt
6 *
7 * Instituto Superior Tecnico * Lisboa * PORTUGAL
8 *
9 * Disclaimer:
10 *
11 * This file is provided "AS IS" without warranty of any kind, either
12 * expressed or implied.
13 *
14 * This code is based on code by: Jose Rufino - IST
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdbool.h>
24#include <rtems/bspIo.h>
25
26static void printNum(
27  long num,
28  unsigned base,
29  bool sign,
30  unsigned maxwidth,
31  char lead
32);
33
34/*
35 *  vprintk
36 *
37 *  A simplified version of printf intended for use when the
38 *  console is not yet initialized or in ISR's.
39 *
40 * Arguments:
41 *    as in printf: fmt - format string, ... - unnamed arguments.
42 */
43void vprintk(
44  const char *fmt,
45  va_list     ap
46)
47{
48  for (; *fmt != '\0'; fmt++) {
49    unsigned base = 0;
50    unsigned width = 0;
51    bool lflag = false;
52    bool minus = false;
53    bool sign = false;
54    char lead = ' ';
55    char c;
56
57    if (*fmt != '%') {
58      rtems_putc(*fmt);
59      continue;
60    }
61    fmt++;
62    if (*fmt == '0' ) {
63      lead = '0';
64      fmt++;
65    }
66    if (*fmt == '-' ) {
67      minus = true;
68      fmt++;
69    }
70    while (*fmt >= '0' && *fmt <= '9' ) {
71      width *= 10;
72      width += ((unsigned) *fmt - '0');
73      fmt++;
74    }
75
76    if ((c = *fmt) == 'l') {
77      lflag = true;
78      c = *++fmt;
79    }
80    if ( c == 'c' ) {
81      /* need a cast here since va_arg() only takes fully promoted types */
82      char chr = (char) va_arg(ap, int);
83      rtems_putc(chr);
84      continue;
85    }
86    if ( c == 's' ) {
87      unsigned i, len;
88      char *s, *str;
89
90      str = va_arg(ap, char *);
91
92      if ( str == NULL ) {
93        str = "";
94      }
95
96      /* calculate length of string */
97      for ( len=0, s=str ; *s ; len++, s++ )
98        ;
99
100      /* leading spaces */
101      if ( !minus )
102        for ( i=len ; i<width ; i++ )
103          rtems_putc(' ');
104
105      /* no width option */
106      if (width == 0) {
107          width = len;
108      }
109
110      /* output the string */
111      for ( i=0 ; i<width && *str ; str++ )
112        rtems_putc(*str);
113
114      /* trailing spaces */
115      if ( minus )
116        for ( i=len ; i<width ; i++ )
117          rtems_putc(' ');
118
119      continue;
120    }
121
122    /* must be a numeric format or something unsupported */
123    if ( c == 'o' || c == 'O' ) {
124      base = 8; sign = false;
125    } else if ( c == 'i' || c == 'I' ||
126                c == 'd' || c == 'D' ) {
127      base = 10; sign = true;
128    } else if ( c == 'u' || c == 'U' ) {
129      base = 10; sign = false;
130    } else if ( c == 'x' || c == 'X' ) {
131      base = 16; sign = false;
132    } else if ( c == 'p' ) {
133      base = 16; sign = false; lflag = true;
134    } else {
135      rtems_putc(c);
136      continue;
137    }
138
139    printNum(
140      lflag ? va_arg(ap, long) : (long) va_arg(ap, int),
141      base,
142      sign,
143      width,
144      lead
145    );
146  }
147}
148
149/*
150 * printNum - print number in a given base.
151 * Arguments
152 *    num - number to print
153 *    base - base used to print the number.
154 */
155static void printNum(
156  long num,
157  unsigned base,
158  bool sign,
159  unsigned maxwidth,
160  char lead
161)
162{
163  unsigned long unsigned_num;
164  unsigned long n;
165  unsigned count;
166  char toPrint[20];
167
168  if ( sign && (num <  0) ) {
169    rtems_putc('-');
170    unsigned_num = (unsigned long) -num;
171    if (maxwidth) maxwidth--;
172  } else {
173    unsigned_num = (unsigned long) num;
174  }
175
176  count = 0;
177  while ((n = unsigned_num / base) > 0) {
178    toPrint[count++] = (char) (unsigned_num - (n * base));
179    unsigned_num = n;
180  }
181  toPrint[count++] = (char) unsigned_num;
182
183  for (n=maxwidth ; n > count; n-- )
184    rtems_putc(lead);
185
186  for (n = 0; n < count; n++) {
187    rtems_putc("0123456789ABCDEF"[(int)(toPrint[count-(n+1)])]);
188  }
189}
Note: See TracBrowser for help on using the repository browser.