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