]> git.sur5r.net Git - freertos/blob
0f0db4fc9d8aa24c2cf31c9c0bc2b9e07bd15371
[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 "xil_types.h"
10 #include "xil_assert.h"
11 #include <ctype.h>
12 #include <string.h>
13 #include <stdarg.h>
14
15 static void padding( const s32 l_flag,const struct params_s *par);
16 static void outs(const charptr lp, struct params_s *par);
17 static s32 getnum( charptr* linep);
18
19 typedef struct params_s {
20     s32 len;
21     s32 num1;
22     s32 num2;
23     char8 pad_character;
24     s32 do_padding;
25     s32 left_flag;
26     s32 unsigned_flag;
27 } params_t;
28
29
30 /*---------------------------------------------------*/
31 /* The purpose of this routine is to output data the */
32 /* same as the standard printf function without the  */
33 /* overhead most run-time libraries involve. Usually */
34 /* the printf brings in many kilobytes of code and   */
35 /* that is unacceptable in most embedded systems.    */
36 /*---------------------------------------------------*/
37
38
39 /*---------------------------------------------------*/
40 /*                                                   */
41 /* This routine puts pad characters into the output  */
42 /* buffer.                                           */
43 /*                                                   */
44 static void padding( const s32 l_flag, const struct params_s *par)
45 {
46     s32 i;
47
48     if ((par->do_padding != 0) && (l_flag != 0) && (par->len < par->num1)) {
49                 i=(par->len);
50         for (; i<(par->num1); i++) {
51 #ifdef STDOUT_BASEADDRESS
52             outbyte( par->pad_character);
53 #endif
54                 }
55     }
56 }
57
58 /*---------------------------------------------------*/
59 /*                                                   */
60 /* This routine moves a string to the output buffer  */
61 /* as directed by the padding and positioning flags. */
62 /*                                                   */
63 static void outs(const charptr lp, struct params_s *par)
64 {
65     charptr LocalPtr;
66         LocalPtr = lp;
67     /* pad on left if needed                         */
68         if(LocalPtr != NULL) {
69                 par->len = (s32)strlen( LocalPtr);
70         }
71     padding( !(par->left_flag), par);
72
73     /* Move string to the buffer                     */
74     while (((*LocalPtr) != (char8)0) && ((par->num2) != 0)) {
75                 (par->num2)--;
76 #ifdef STDOUT_BASEADDRESS
77         outbyte(*LocalPtr);
78                 LocalPtr += 1;
79 #endif
80 }
81
82     /* Pad on right if needed                        */
83     /* CR 439175 - elided next stmt. Seemed bogus.   */
84     /* par->len = strlen( lp)                      */
85     padding( par->left_flag, par);
86 }
87
88 /*---------------------------------------------------*/
89 /*                                                   */
90 /* This routine moves a number to the output buffer  */
91 /* as directed by the padding and positioning flags. */
92 /*                                                   */
93
94 static void outnum( const s32 n, const s32 base, struct params_s *par)
95 {
96     charptr cp;
97     s32 negative;
98         s32 i;
99     char8 outbuf[32];
100     const char8 digits[] = "0123456789ABCDEF";
101     u32 num;
102     for(i = 0; i<32; i++) {
103         outbuf[i] = '0';
104     }
105
106     /* Check if number is negative                   */
107     if ((par->unsigned_flag == 0) && (base == 10) && (n < 0L)) {
108         negative = 1;
109                 num =(-(n));
110     }
111     else{
112         num = n;
113         negative = 0;
114     }
115
116     /* Build number (backwards) in outbuf            */
117     i = 0;
118     do {
119                 outbuf[i] = digits[(num % base)];
120                 i++;
121                 num /= base;
122     } while (num > 0);
123
124     if (negative != 0) {
125                 outbuf[i] = '-';
126                 i++;
127         }
128
129     outbuf[i] = 0;
130     i--;
131
132     /* Move the converted number to the buffer and   */
133     /* add in the padding where needed.              */
134     par->len = (s32)strlen(outbuf);
135     padding( !(par->left_flag), par);
136     while (&outbuf[i] >= outbuf) {
137 #ifdef STDOUT_BASEADDRESS
138         outbyte( outbuf[i] );
139                 i--;
140 #endif
141 }
142     padding( par->left_flag, par);
143 }
144
145 /*---------------------------------------------------*/
146 /*                                                   */
147 /* This routine gets a number from the format        */
148 /* string.                                           */
149 /*                                                   */
150 static s32 getnum( charptr* linep)
151 {
152     s32 n;
153     s32 ResultIsDigit = 0;
154     charptr cptr;
155     n = 0;
156     cptr = *linep;
157         if(cptr != NULL){
158                 ResultIsDigit = isdigit(((s32)*cptr));
159         }
160     while (ResultIsDigit != 0) {
161                 if(cptr != NULL){
162                         n = ((n*10) + (((s32)*cptr) - (s32)'0'));
163                         cptr += 1;
164                         if(cptr != NULL){
165                                 ResultIsDigit = isdigit(((s32)*cptr));
166                         }
167                 }
168                 ResultIsDigit = isdigit(((s32)*cptr));
169         }
170     *linep = ((charptr )(cptr));
171     return(n);
172 }
173
174 /*---------------------------------------------------*/
175 /*                                                   */
176 /* This routine operates just like a printf/sprintf  */
177 /* routine. It outputs a set of data under the       */
178 /* control of a formatting string. Not all of the    */
179 /* standard C format control are supported. The ones */
180 /* provided are primarily those needed for embedded  */
181 /* systems work. Primarily the floating point        */
182 /* routines are omitted. Other formats could be      */
183 /* added easily by following the examples shown for  */
184 /* the supported formats.                            */
185 /*                                                   */
186
187 /* void esp_printf( const func_ptr f_ptr,
188    const charptr ctrl1, ...) */
189 void xil_printf( const char8 *ctrl1, ...)
190 {
191         s32 Check;
192     s32 long_flag;
193     s32 dot_flag;
194
195     params_t par;
196
197     char8 ch;
198     va_list argp;
199     char8 *ctrl = (char8 *)ctrl1;
200
201     va_start( argp, ctrl1);
202
203     while ((ctrl != NULL) && (*ctrl != (char8)0)) {
204
205         /* move format string chars to buffer until a  */
206         /* format control is found.                    */
207         if (*ctrl != '%') {
208 #ifdef STDOUT_BASEADDRESS
209             outbyte(*ctrl);
210                         ctrl += 1;
211 #endif
212             continue;
213         }
214
215         /* initialize all the flags for this format.   */
216         dot_flag = 0;
217                 long_flag = 0;
218         par.unsigned_flag = 0;
219                 par.left_flag = 0;
220                 par.do_padding = 0;
221         par.pad_character = ' ';
222         par.num2=32767;
223                 par.num1=0;
224                 par.len=0;
225
226  try_next:
227                 if(ctrl != NULL) {
228                         ctrl += 1;
229                 }
230                 if(ctrl != NULL) {
231                         ch = *ctrl;
232                 }
233                 else {
234                         ch = *ctrl;
235                 }
236
237         if (isdigit((s32)ch) != 0) {
238             if (dot_flag != 0) {
239                 par.num2 = getnum(&ctrl);
240                         }
241             else {
242                 if (ch == '0') {
243                     par.pad_character = '0';
244                                 }
245                                 if(ctrl != NULL) {
246                         par.num1 = getnum(&ctrl);
247                                 }
248                 par.do_padding = 1;
249             }
250             if(ctrl != NULL) {
251                         ctrl -= 1;
252                         }
253             goto try_next;
254         }
255
256         switch (tolower((s32)ch)) {
257             case '%':
258 #ifdef STDOUT_BASEADDRESS
259                 outbyte( '%');
260 #endif
261                 Check = 1;
262                 break;
263
264             case '-':
265                 par.left_flag = 1;
266                 Check = 0;
267                 break;
268
269             case '.':
270                 dot_flag = 1;
271                 Check = 0;
272                 break;
273
274             case 'l':
275                 long_flag = 1;
276                 Check = 0;
277                 break;
278
279             case 'u':
280                 par.unsigned_flag = 1;
281                 /* fall through */
282             case 'i':
283             case 'd':
284                 if ((long_flag != 0) || (ch == 'D')) {
285                     outnum( va_arg(argp, s32), 10L, &par);
286                 }
287                 else {
288                     outnum( va_arg(argp, s32), 10L, &par);
289                 }
290                                 Check = 1;
291                 break;
292             case 'p':
293             case 'X':
294             case 'x':
295                 par.unsigned_flag = 1;
296                 outnum((s32)va_arg(argp, s32), 16L, &par);
297                 Check = 1;
298                 break;
299
300             case 's':
301                 outs( va_arg( argp, char *), &par);
302                 Check = 1;
303                 break;
304
305             case 'c':
306 #ifdef STDOUT_BASEADDRESS
307                 outbyte( va_arg( argp, s32));
308 #endif
309                 Check = 1;
310                 break;
311
312             case '\\':
313                 switch (*ctrl) {
314                     case 'a':
315 #ifdef STDOUT_BASEADDRESS
316                         outbyte( ((char8)0x07));
317 #endif
318                         break;
319                     case 'h':
320 #ifdef STDOUT_BASEADDRESS
321                         outbyte( ((char8)0x08));
322 #endif
323                         break;
324                     case 'r':
325 #ifdef STDOUT_BASEADDRESS
326                         outbyte( ((char8)0x0D));
327 #endif
328                         break;
329                     case 'n':
330 #ifdef STDOUT_BASEADDRESS
331                         outbyte( ((char8)0x0D));
332                         outbyte( ((char8)0x0A));
333 #endif
334                         break;
335                     default:
336 #ifdef STDOUT_BASEADDRESS
337                         outbyte( *ctrl);
338 #endif
339                         break;
340                 }
341                 ctrl += 1;
342                 Check = 0;
343                 break;
344
345             default:
346                 Check = 1;
347                 break;
348         }
349         if(Check == 1) {
350                         if(ctrl != NULL) {
351                                 ctrl += 1;
352                         }
353                 continue;
354         }
355         goto try_next;
356     }
357     va_end( argp);
358 }
359
360 /*---------------------------------------------------*/