]> git.sur5r.net Git - freertos/blob
39e13e82b1d0a8281d14f33af9dd02067b5a9e84
[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 } params_t;
23
24 static void padding( const s32 l_flag,const params_t *par);
25 static void outs(const charptr lp, params_t *par);
26 static void outnum( const s32 n, const s32 base, 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 ((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 gets a number from the format        */
141 /* string.                                           */
142 /*                                                   */
143 static s32 getnum( charptr* linep)
144 {
145     s32 n;
146     s32 ResultIsDigit = 0;
147     charptr cptr;
148     n = 0;
149     cptr = *linep;
150         if(cptr != NULL){
151                 ResultIsDigit = isdigit(((s32)*cptr));
152         }
153     while (ResultIsDigit != 0) {
154                 if(cptr != NULL){
155                         n = ((n*10) + (((s32)*cptr) - (s32)'0'));
156                         cptr += 1;
157                         if(cptr != NULL){
158                                 ResultIsDigit = isdigit(((s32)*cptr));
159                         }
160                 }
161                 ResultIsDigit = isdigit(((s32)*cptr));
162         }
163     *linep = ((charptr )(cptr));
164     return(n);
165 }
166
167 /*---------------------------------------------------*/
168 /*                                                   */
169 /* This routine operates just like a printf/sprintf  */
170 /* routine. It outputs a set of data under the       */
171 /* control of a formatting string. Not all of the    */
172 /* standard C format control are supported. The ones */
173 /* provided are primarily those needed for embedded  */
174 /* systems work. Primarily the floating point        */
175 /* routines are omitted. Other formats could be      */
176 /* added easily by following the examples shown for  */
177 /* the supported formats.                            */
178 /*                                                   */
179
180 /* void esp_printf( const func_ptr f_ptr,
181    const charptr ctrl1, ...) */
182 void xil_printf( const char8 *ctrl1, ...)
183 {
184         s32 Check;
185     s32 long_flag;
186     s32 dot_flag;
187
188     params_t par;
189
190     char8 ch;
191     va_list argp;
192     char8 *ctrl = (char8 *)ctrl1;
193
194     va_start( argp, ctrl1);
195
196     while ((ctrl != NULL) && (*ctrl != (char8)0)) {
197
198         /* move format string chars to buffer until a  */
199         /* format control is found.                    */
200         if (*ctrl != '%') {
201             outbyte(*ctrl);
202                         ctrl += 1;
203             continue;
204         }
205
206         /* initialize all the flags for this format.   */
207         dot_flag = 0;
208                 long_flag = 0;
209                 par.left_flag = 0;
210                 par.do_padding = 0;
211         par.pad_character = ' ';
212         par.num2=32767;
213                 par.num1=0;
214                 par.len=0;
215
216  try_next:
217                 if(ctrl != NULL) {
218                         ctrl += 1;
219                 }
220                 if(ctrl != NULL) {
221                         ch = *ctrl;
222                 }
223                 else {
224                         ch = *ctrl;
225                 }
226
227         if (isdigit((s32)ch) != 0) {
228             if (dot_flag != 0) {
229                 par.num2 = getnum(&ctrl);
230                         }
231             else {
232                 if (ch == '0') {
233                     par.pad_character = '0';
234                                 }
235                                 if(ctrl != NULL) {
236                         par.num1 = getnum(&ctrl);
237                                 }
238                 par.do_padding = 1;
239             }
240             if(ctrl != NULL) {
241                         ctrl -= 1;
242                         }
243             goto try_next;
244         }
245
246         switch (tolower((s32)ch)) {
247             case '%':
248                 outbyte( '%');
249                 Check = 1;
250                 break;
251
252             case '-':
253                 par.left_flag = 1;
254                 Check = 0;
255                 break;
256
257             case '.':
258                 dot_flag = 1;
259                 Check = 0;
260                 break;
261
262             case 'l':
263                 long_flag = 1;
264                 Check = 0;
265                 break;
266
267             case 'd':
268                 if ((long_flag != 0) || (ch == 'D')) {
269                     outnum( va_arg(argp, s32), 10L, &par);
270                 }
271                 else {
272                     outnum( va_arg(argp, s32), 10L, &par);
273                 }
274                                 Check = 1;
275                 break;
276             case 'x':
277                 outnum((s32)va_arg(argp, s32), 16L, &par);
278                 Check = 1;
279                 break;
280
281             case 's':
282                 outs( va_arg( argp, char *), &par);
283                 Check = 1;
284                 break;
285
286             case 'c':
287                 outbyte( va_arg( argp, s32));
288                 Check = 1;
289                 break;
290
291             case '\\':
292                 switch (*ctrl) {
293                     case 'a':
294                         outbyte( ((char8)0x07));
295                         break;
296                     case 'h':
297                         outbyte( ((char8)0x08));
298                         break;
299                     case 'r':
300                         outbyte( ((char8)0x0D));
301                         break;
302                     case 'n':
303                         outbyte( ((char8)0x0D));
304                         outbyte( ((char8)0x0A));
305                         break;
306                     default:
307                         outbyte( *ctrl);
308                         break;
309                 }
310                 ctrl += 1;
311                 Check = 0;
312                 break;
313
314             default:
315                 Check = 1;
316                 break;
317         }
318         if(Check == 1) {
319                         if(ctrl != NULL) {
320                                 ctrl += 1;
321                         }
322                 continue;
323         }
324         goto try_next;
325     }
326     va_end( argp);
327 }
328
329 /*---------------------------------------------------*/