Cygwin: dirent.h: fix a comment
[newlib-cygwin.git] / libgloss / microblaze / xil_printf.c
blobf18ee8446b5fb478f8c2ad3258d3bed17c624f53
1 /* Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved.
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
7 * 1. Redistributions source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Xilinx nor the names of its contributors may be
15 * used to endorse or promote products derived from this software without
16 * specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
19 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <ctype.h>
32 #include <string.h>
33 #include <stdarg.h>
35 extern void outbyte (char);
37 /*----------------------------------------------------*/
38 /* Use the following parameter passing structure to */
39 /* make xil_printf re-entrant. */
40 /*----------------------------------------------------*/
41 typedef struct params_s {
42 int len;
43 int num1;
44 int num2;
45 char pad_character;
46 int do_padding;
47 int left_flag;
48 } params_t;
50 /*---------------------------------------------------*/
51 /* The purpose of this routine is to output data the */
52 /* same as the standard printf function without the */
53 /* overhead most run-time libraries involve. Usually */
54 /* the printf brings in many kilobytes of code and */
55 /* that is unacceptable in most embedded systems. */
56 /*---------------------------------------------------*/
58 typedef char* charptr;
59 typedef int (*func_ptr)(int c);
61 /*---------------------------------------------------*/
62 /* */
63 /* This routine puts pad characters into the output */
64 /* buffer. */
65 /* */
66 static void padding( const int l_flag, params_t *par)
68 int i;
70 if (par->do_padding && l_flag && (par->len < par->num1))
71 for (i=par->len; i<par->num1; i++)
72 outbyte( par->pad_character);
75 /*---------------------------------------------------*/
76 /* */
77 /* This routine moves a string to the output buffer */
78 /* as directed by the padding and positioning flags. */
79 /* */
80 static void outs( charptr lp, params_t *par)
82 /* pad on left if needed */
83 par->len = strlen( lp);
84 padding( !(par->left_flag), par);
86 /* Move string to the buffer */
87 while (*lp && (par->num2)--)
88 outbyte( *lp++);
90 /* Pad on right if needed */
91 /* CR 439175 - elided next stmt. Seemed bogus. */
92 /* par->len = strlen( lp); */
93 padding( par->left_flag, par);
96 /*---------------------------------------------------*/
97 /* */
98 /* This routine moves a number to the output buffer */
99 /* as directed by the padding and positioning flags. */
100 /* */
102 static void outnum( const long n, const long base, params_t *par)
104 charptr cp;
105 int negative;
106 char outbuf[32];
107 const char digits[] = "0123456789ABCDEF";
108 unsigned long num;
110 /* Check if number is negative */
111 if (base == 10 && n < 0L) {
112 negative = 1;
113 num = -(n);
115 else{
116 num = (n);
117 negative = 0;
120 /* Build number (backwards) in outbuf */
121 cp = outbuf;
122 do {
123 *cp++ = digits[(int)(num % base)];
124 } while ((num /= base) > 0);
125 if (negative)
126 *cp++ = '-';
127 *cp-- = 0;
129 /* Move the converted number to the buffer and */
130 /* add in the padding where needed. */
131 par->len = strlen(outbuf);
132 padding( !(par->left_flag), par);
133 while (cp >= outbuf)
134 outbyte( *cp--);
135 padding( par->left_flag, par);
138 /*---------------------------------------------------*/
139 /* */
140 /* This routine gets a number from the format */
141 /* string. */
142 /* */
143 static int getnum( charptr* linep)
145 int n;
146 charptr cp;
148 n = 0;
149 cp = *linep;
150 while (isdigit(*cp))
151 n = n*10 + ((*cp++) - '0');
152 *linep = cp;
153 return(n);
156 /*---------------------------------------------------*/
157 /* */
158 /* This routine operates just like a printf/sprintf */
159 /* routine. It outputs a set of data under the */
160 /* control of a formatting string. Not all of the */
161 /* standard C format control are supported. The ones */
162 /* provided are primarily those needed for embedded */
163 /* systems work. Primarily the floaing point */
164 /* routines are omitted. Other formats could be */
165 /* added easily by following the examples shown for */
166 /* the supported formats. */
167 /* */
169 /* void esp_printf( const func_ptr f_ptr,
170 const charptr ctrl1, ...) */
171 void xil_printf( const charptr ctrl1, ...)
174 int long_flag;
175 int dot_flag;
177 params_t par;
179 char ch;
180 va_list argp;
181 charptr ctrl = ctrl1;
183 va_start( argp, ctrl1);
185 for ( ; *ctrl; ctrl++) {
187 /* move format string chars to buffer until a */
188 /* format control is found. */
189 if (*ctrl != '%') {
190 outbyte(*ctrl);
191 continue;
194 /* initialize all the flags for this format. */
195 dot_flag = long_flag = par.left_flag = par.do_padding = 0;
196 par.pad_character = ' ';
197 par.num2=32767;
199 try_next:
200 ch = *(++ctrl);
202 if (isdigit(ch)) {
203 if (dot_flag)
204 par.num2 = getnum(&ctrl);
205 else {
206 if (ch == '0')
207 par.pad_character = '0';
209 par.num1 = getnum(&ctrl);
210 par.do_padding = 1;
212 ctrl--;
213 goto try_next;
216 switch (tolower(ch)) {
217 case '%':
218 outbyte( '%');
219 continue;
221 case '-':
222 par.left_flag = 1;
223 break;
225 case '.':
226 dot_flag = 1;
227 break;
229 case 'l':
230 long_flag = 1;
231 break;
233 case 'd':
234 if (long_flag || ch == 'D') {
235 outnum( va_arg(argp, long), 10L, &par);
236 continue;
238 else {
239 outnum( va_arg(argp, int), 10L, &par);
240 continue;
242 case 'x':
243 outnum((long)va_arg(argp, int), 16L, &par);
244 continue;
246 case 's':
247 outs( va_arg( argp, charptr), &par);
248 continue;
250 case 'c':
251 outbyte( va_arg( argp, int));
252 continue;
254 case '\\':
255 switch (*ctrl) {
256 case 'a':
257 outbyte( 0x07);
258 break;
259 case 'h':
260 outbyte( 0x08);
261 break;
262 case 'r':
263 outbyte( 0x0D);
264 break;
265 case 'n':
266 outbyte( 0x0D);
267 outbyte( 0x0A);
268 break;
269 default:
270 outbyte( *ctrl);
271 break;
273 ctrl++;
274 break;
276 default:
277 continue;
279 goto try_next;
281 va_end( argp);
284 /*---------------------------------------------------*/