[444] | 1 | /* Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. |
---|
| 2 | * |
---|
| 3 | * Redistribution and use in source and binary forms, with or without |
---|
| 4 | * modification, are permitted provided that the following conditions are |
---|
| 5 | * met: |
---|
| 6 | * |
---|
| 7 | * 1. Redistributions source code must retain the above copyright notice, |
---|
| 8 | * this list of conditions and the following disclaimer. |
---|
| 9 | * |
---|
| 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. |
---|
| 13 | * |
---|
| 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. |
---|
| 17 | * |
---|
| 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. |
---|
| 29 | */ |
---|
| 30 | |
---|
| 31 | #include <ctype.h> |
---|
| 32 | #include <string.h> |
---|
| 33 | #include <stdarg.h> |
---|
| 34 | |
---|
| 35 | extern void outbyte (char); |
---|
| 36 | |
---|
| 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; |
---|
| 49 | |
---|
| 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 | /*---------------------------------------------------*/ |
---|
| 57 | |
---|
| 58 | typedef char* charptr; |
---|
| 59 | typedef int (*func_ptr)(int c); |
---|
| 60 | |
---|
| 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) |
---|
| 67 | { |
---|
| 68 | int i; |
---|
| 69 | |
---|
| 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); |
---|
| 73 | } |
---|
| 74 | |
---|
| 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) |
---|
| 81 | { |
---|
| 82 | /* pad on left if needed */ |
---|
| 83 | par->len = strlen( lp); |
---|
| 84 | padding( !(par->left_flag), par); |
---|
| 85 | |
---|
| 86 | /* Move string to the buffer */ |
---|
| 87 | while (*lp && (par->num2)--) |
---|
| 88 | outbyte( *lp++); |
---|
| 89 | |
---|
| 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); |
---|
| 94 | } |
---|
| 95 | |
---|
| 96 | /*---------------------------------------------------*/ |
---|
| 97 | /* */ |
---|
| 98 | /* This routine moves a number to the output buffer */ |
---|
| 99 | /* as directed by the padding and positioning flags. */ |
---|
| 100 | /* */ |
---|
| 101 | |
---|
| 102 | static void outnum( const long n, const long base, params_t *par) |
---|
| 103 | { |
---|
| 104 | charptr cp; |
---|
| 105 | int negative; |
---|
| 106 | char outbuf[32]; |
---|
| 107 | const char digits[] = "0123456789ABCDEF"; |
---|
| 108 | unsigned long num; |
---|
| 109 | |
---|
| 110 | /* Check if number is negative */ |
---|
| 111 | if (base == 10 && n < 0L) { |
---|
| 112 | negative = 1; |
---|
| 113 | num = -(n); |
---|
| 114 | } |
---|
| 115 | else{ |
---|
| 116 | num = (n); |
---|
| 117 | negative = 0; |
---|
| 118 | } |
---|
| 119 | |
---|
| 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; |
---|
| 128 | |
---|
| 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); |
---|
| 136 | } |
---|
| 137 | |
---|
| 138 | /*---------------------------------------------------*/ |
---|
| 139 | /* */ |
---|
| 140 | /* This routine gets a number from the format */ |
---|
| 141 | /* string. */ |
---|
| 142 | /* */ |
---|
| 143 | static int getnum( charptr* linep) |
---|
| 144 | { |
---|
| 145 | int n; |
---|
| 146 | charptr cp; |
---|
| 147 | |
---|
| 148 | n = 0; |
---|
| 149 | cp = *linep; |
---|
| 150 | while (isdigit(*cp)) |
---|
| 151 | n = n*10 + ((*cp++) - '0'); |
---|
| 152 | *linep = cp; |
---|
| 153 | return(n); |
---|
| 154 | } |
---|
| 155 | |
---|
| 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 | /* */ |
---|
| 168 | |
---|
| 169 | /* void esp_printf( const func_ptr f_ptr, |
---|
| 170 | const charptr ctrl1, ...) */ |
---|
| 171 | void xil_printf( const charptr ctrl1, ...) |
---|
| 172 | { |
---|
| 173 | |
---|
| 174 | int long_flag; |
---|
| 175 | int dot_flag; |
---|
| 176 | |
---|
| 177 | params_t par; |
---|
| 178 | |
---|
| 179 | char ch; |
---|
| 180 | va_list argp; |
---|
| 181 | charptr ctrl = ctrl1; |
---|
| 182 | |
---|
| 183 | va_start( argp, ctrl1); |
---|
| 184 | |
---|
| 185 | for ( ; *ctrl; ctrl++) { |
---|
| 186 | |
---|
| 187 | /* move format string chars to buffer until a */ |
---|
| 188 | /* format control is found. */ |
---|
| 189 | if (*ctrl != '%') { |
---|
| 190 | outbyte(*ctrl); |
---|
| 191 | continue; |
---|
| 192 | } |
---|
| 193 | |
---|
| 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; |
---|
| 198 | |
---|
| 199 | try_next: |
---|
| 200 | ch = *(++ctrl); |
---|
| 201 | |
---|
| 202 | if (isdigit(ch)) { |
---|
| 203 | if (dot_flag) |
---|
| 204 | par.num2 = getnum(&ctrl); |
---|
| 205 | else { |
---|
| 206 | if (ch == '0') |
---|
| 207 | par.pad_character = '0'; |
---|
| 208 | |
---|
| 209 | par.num1 = getnum(&ctrl); |
---|
| 210 | par.do_padding = 1; |
---|
| 211 | } |
---|
| 212 | ctrl--; |
---|
| 213 | goto try_next; |
---|
| 214 | } |
---|
| 215 | |
---|
| 216 | switch (tolower(ch)) { |
---|
| 217 | case '%': |
---|
| 218 | outbyte( '%'); |
---|
| 219 | continue; |
---|
| 220 | |
---|
| 221 | case '-': |
---|
| 222 | par.left_flag = 1; |
---|
| 223 | break; |
---|
| 224 | |
---|
| 225 | case '.': |
---|
| 226 | dot_flag = 1; |
---|
| 227 | break; |
---|
| 228 | |
---|
| 229 | case 'l': |
---|
| 230 | long_flag = 1; |
---|
| 231 | break; |
---|
| 232 | |
---|
| 233 | case 'd': |
---|
| 234 | if (long_flag || ch == 'D') { |
---|
| 235 | outnum( va_arg(argp, long), 10L, &par); |
---|
| 236 | continue; |
---|
| 237 | } |
---|
| 238 | else { |
---|
| 239 | outnum( va_arg(argp, int), 10L, &par); |
---|
| 240 | continue; |
---|
| 241 | } |
---|
| 242 | case 'x': |
---|
| 243 | outnum((long)va_arg(argp, int), 16L, &par); |
---|
| 244 | continue; |
---|
| 245 | |
---|
| 246 | case 's': |
---|
| 247 | outs( va_arg( argp, charptr), &par); |
---|
| 248 | continue; |
---|
| 249 | |
---|
| 250 | case 'c': |
---|
| 251 | outbyte( va_arg( argp, int)); |
---|
| 252 | continue; |
---|
| 253 | |
---|
| 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; |
---|
| 272 | } |
---|
| 273 | ctrl++; |
---|
| 274 | break; |
---|
| 275 | |
---|
| 276 | default: |
---|
| 277 | continue; |
---|
| 278 | } |
---|
| 279 | goto try_next; |
---|
| 280 | } |
---|
| 281 | va_end( argp); |
---|
| 282 | } |
---|
| 283 | |
---|
| 284 | /*---------------------------------------------------*/ |
---|