]> git.sur5r.net Git - freertos/blob
7660a8b4a8ea0fd936a41bfc7dbd17d9f496121d
[freertos] /
1 /*---------------------------------------------------*/
2 /* Modified from :                                   */
3 /* Public Domain version of printf                   */
4 /* Rud Merriam, Compsult, Inc. Houston, Tx.          */
5 /* For Embedded Systems Programming, 1991            */
6 /*                                                   */
7 /*---------------------------------------------------*/
8 #include "xil_printf.h"
9 #include <ctype.h>
10 #include <string.h>
11 #include <stdarg.h>
12
13
14 typedef struct params_s {
15     int len;
16     int num1;
17     int num2;
18     char pad_character;
19     int do_padding;
20     int left_flag;
21 } params_t;
22
23
24 /*---------------------------------------------------*/
25 /* The purpose of this routine is to output data the */
26 /* same as the standard printf function without the  */
27 /* overhead most run-time libraries involve. Usually */
28 /* the printf brings in many kilobytes of code and   */
29 /* that is unacceptable in most embedded systems.    */
30 /*---------------------------------------------------*/
31
32
33 /*---------------------------------------------------*/
34 /*                                                   */
35 /* This routine puts pad characters into the output  */
36 /* buffer.                                           */
37 /*                                                   */
38 void padding( const int l_flag, params_t *par)
39 {
40     int i;
41
42     if (par->do_padding && l_flag && (par->len < par->num1))
43         for (i=par->len; i<par->num1; i++) {
44 #ifdef STDOUT_BASEADDRESS
45             outbyte( par->pad_character);
46 #endif
47     }
48 }
49
50 /*---------------------------------------------------*/
51 /*                                                   */
52 /* This routine moves a string to the output buffer  */
53 /* as directed by the padding and positioning flags. */
54 /*                                                   */
55 void outs( charptr lp, params_t *par)
56 {
57     /* pad on left if needed                         */
58     par->len = strlen( lp);
59     padding( !(par->left_flag), par);
60
61     /* Move string to the buffer                     */
62     while (*lp && (par->num2)--) {
63 #ifdef STDOUT_BASEADDRESS
64         outbyte( *lp++);
65 #endif
66 }
67
68     /* Pad on right if needed                        */
69     /* CR 439175 - elided next stmt. Seemed bogus.   */
70     /* par->len = strlen( lp);                       */
71     padding( par->left_flag, par);
72 }
73
74 /*---------------------------------------------------*/
75 /*                                                   */
76 /* This routine moves a number to the output buffer  */
77 /* as directed by the padding and positioning flags. */
78 /*                                                   */
79
80 void outnum( const long n, const long base, params_t *par)
81 {
82     charptr cp;
83     int negative;
84     char outbuf[32];
85     const char digits[] = "0123456789ABCDEF";
86     unsigned long num;
87
88     /* Check if number is negative                   */
89     if (base == 10 && n < 0L) {
90         negative = 1;
91         num = -(n);
92     }
93     else{
94         num = (n);
95         negative = 0;
96     }
97
98     /* Build number (backwards) in outbuf            */
99     cp = outbuf;
100     do {
101         *cp++ = digits[(int)(num % base)];
102     } while ((num /= base) > 0);
103     if (negative)
104         *cp++ = '-';
105     *cp-- = 0;
106
107     /* Move the converted number to the buffer and   */
108     /* add in the padding where needed.              */
109     par->len = strlen(outbuf);
110     padding( !(par->left_flag), par);
111     while (cp >= outbuf) {
112 #ifdef STDOUT_BASEADDRESS
113         outbyte( *cp--);
114 #endif
115 }
116     padding( par->left_flag, par);
117 }
118
119 /*---------------------------------------------------*/
120 /*                                                   */
121 /* This routine gets a number from the format        */
122 /* string.                                           */
123 /*                                                   */
124 int getnum( charptr* linep)
125 {
126     int n;
127     charptr cp;
128
129     n = 0;
130     cp = *linep;
131     while (isdigit(((int)*cp)))
132         n = n*10 + ((*cp++) - '0');
133     *linep = cp;
134     return(n);
135 }
136
137 /*---------------------------------------------------*/
138 /*                                                   */
139 /* This routine operates just like a printf/sprintf  */
140 /* routine. It outputs a set of data under the       */
141 /* control of a formatting string. Not all of the    */
142 /* standard C format control are supported. The ones */
143 /* provided are primarily those needed for embedded  */
144 /* systems work. Primarily the floaing point         */
145 /* routines are omitted. Other formats could be      */
146 /* added easily by following the examples shown for  */
147 /* the supported formats.                            */
148 /*                                                   */
149
150 /* void esp_printf( const func_ptr f_ptr,
151    const charptr ctrl1, ...) */
152 void xil_printf( const char *ctrl1, ...)
153 {
154
155     int long_flag;
156     int dot_flag;
157
158     params_t par;
159
160     char ch;
161     va_list argp;
162     char *ctrl = (char *)ctrl1;
163
164     va_start( argp, ctrl1);
165
166     for ( ; *ctrl; ctrl++) {
167
168         /* move format string chars to buffer until a  */
169         /* format control is found.                    */
170         if (*ctrl != '%') {
171 #ifdef STDOUT_BASEADDRESS
172             outbyte(*ctrl);
173 #endif
174             continue;
175         }
176
177         /* initialize all the flags for this format.   */
178         dot_flag   = long_flag = par.left_flag = par.do_padding = 0;
179         par.pad_character = ' ';
180         par.num2=32767;
181
182  try_next:
183         ch = *(++ctrl);
184
185         if (isdigit((int)ch)) {
186             if (dot_flag)
187                 par.num2 = getnum(&ctrl);
188             else {
189                 if (ch == '0')
190                     par.pad_character = '0';
191
192                 par.num1 = getnum(&ctrl);
193                 par.do_padding = 1;
194             }
195             ctrl--;
196             goto try_next;
197         }
198
199         switch (tolower((int)ch)) {
200             case '%':
201 #ifdef STDOUT_BASEADDRESS
202                 outbyte( '%');
203 #endif
204                 continue;
205
206             case '-':
207                 par.left_flag = 1;
208                 break;
209
210             case '.':
211                 dot_flag = 1;
212                 break;
213
214             case 'l':
215                 long_flag = 1;
216                 break;
217
218             case 'd':
219                 if (long_flag || ch == 'D') {
220                     outnum( va_arg(argp, long), 10L, &par);
221                     continue;
222                 }
223                 else {
224                     outnum( va_arg(argp, int), 10L, &par);
225                     continue;
226                 }
227             case 'x':
228                 outnum((long)va_arg(argp, int), 16L, &par);
229                 continue;
230
231             case 's':
232                 outs( va_arg( argp, char *), &par);
233                 continue;
234
235             case 'c':
236 #ifdef STDOUT_BASEADDRESS
237                 outbyte( va_arg( argp, int));
238 #endif
239                 continue;
240
241             case '\\':
242                 switch (*ctrl) {
243                     case 'a':
244 #ifdef STDOUT_BASEADDRESS
245                         outbyte( 0x07);
246 #endif
247                         break;
248                     case 'h':
249 #ifdef STDOUT_BASEADDRESS
250                         outbyte( 0x08);
251 #endif
252                         break;
253                     case 'r':
254 #ifdef STDOUT_BASEADDRESS
255                         outbyte( 0x0D);
256 #endif
257                         break;
258                     case 'n':
259 #ifdef STDOUT_BASEADDRESS
260                         outbyte( 0x0D);
261                         outbyte( 0x0A);
262 #endif
263                         break;
264                     default:
265 #ifdef STDOUT_BASEADDRESS
266                         outbyte( *ctrl);
267 #endif
268                         break;
269                 }
270                 ctrl++;
271                 break;
272
273             default:
274                 continue;
275         }
276         goto try_next;
277     }
278     va_end( argp);
279 }
280
281 /*---------------------------------------------------*/