Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FastAnalogIn MODSERIAL PID QEI RPCInterface Servo mbed-rtos mbed telemetry
Fork of Sequential_Timing by
printf-stdarg.c@10:716484b1ddb5, 2016-04-05 (annotated)
- Committer:
- vsutardja
- Date:
- Tue Apr 05 18:30:41 2016 +0000
- Revision:
- 10:716484b1ddb5
latest
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| vsutardja | 10:716484b1ddb5 | 1 | /* |
| vsutardja | 10:716484b1ddb5 | 2 | Copyright 2001, 2002 Georges Menie (www.menie.org) |
| vsutardja | 10:716484b1ddb5 | 3 | stdarg version contributed by Christian Ettinger |
| vsutardja | 10:716484b1ddb5 | 4 | |
| vsutardja | 10:716484b1ddb5 | 5 | This program is free software; you can redistribute it and/or modify |
| vsutardja | 10:716484b1ddb5 | 6 | it under the terms of the GNU Lesser General Public License as published by |
| vsutardja | 10:716484b1ddb5 | 7 | the Free Software Foundation; either version 2 of the License, or |
| vsutardja | 10:716484b1ddb5 | 8 | (at your option) any later version. |
| vsutardja | 10:716484b1ddb5 | 9 | |
| vsutardja | 10:716484b1ddb5 | 10 | This program is distributed in the hope that it will be useful, |
| vsutardja | 10:716484b1ddb5 | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| vsutardja | 10:716484b1ddb5 | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| vsutardja | 10:716484b1ddb5 | 13 | GNU Lesser General Public License for more details. |
| vsutardja | 10:716484b1ddb5 | 14 | |
| vsutardja | 10:716484b1ddb5 | 15 | You should have received a copy of the GNU Lesser General Public License |
| vsutardja | 10:716484b1ddb5 | 16 | along with this program; if not, write to the Free Software |
| vsutardja | 10:716484b1ddb5 | 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| vsutardja | 10:716484b1ddb5 | 18 | */ |
| vsutardja | 10:716484b1ddb5 | 19 | |
| vsutardja | 10:716484b1ddb5 | 20 | /* |
| vsutardja | 10:716484b1ddb5 | 21 | putchar is the only external dependency for this file, |
| vsutardja | 10:716484b1ddb5 | 22 | if you have a working putchar, leave it commented out. |
| vsutardja | 10:716484b1ddb5 | 23 | If not, uncomment the define below and |
| vsutardja | 10:716484b1ddb5 | 24 | replace outbyte(c) by your own function call. */ |
| vsutardja | 10:716484b1ddb5 | 25 | |
| vsutardja | 10:716484b1ddb5 | 26 | #define putchar(c) putcharNB(c) |
| vsutardja | 10:716484b1ddb5 | 27 | |
| vsutardja | 10:716484b1ddb5 | 28 | |
| vsutardja | 10:716484b1ddb5 | 29 | #include <stdarg.h> |
| vsutardja | 10:716484b1ddb5 | 30 | |
| vsutardja | 10:716484b1ddb5 | 31 | static void printchar(char **str, int c) |
| vsutardja | 10:716484b1ddb5 | 32 | { |
| vsutardja | 10:716484b1ddb5 | 33 | extern int putchar(int c); |
| vsutardja | 10:716484b1ddb5 | 34 | |
| vsutardja | 10:716484b1ddb5 | 35 | if (str) { |
| vsutardja | 10:716484b1ddb5 | 36 | **str = c; |
| vsutardja | 10:716484b1ddb5 | 37 | ++(*str); |
| vsutardja | 10:716484b1ddb5 | 38 | } |
| vsutardja | 10:716484b1ddb5 | 39 | else (void)putchar(c); |
| vsutardja | 10:716484b1ddb5 | 40 | } |
| vsutardja | 10:716484b1ddb5 | 41 | |
| vsutardja | 10:716484b1ddb5 | 42 | #define PAD_RIGHT 1 |
| vsutardja | 10:716484b1ddb5 | 43 | #define PAD_ZERO 2 |
| vsutardja | 10:716484b1ddb5 | 44 | |
| vsutardja | 10:716484b1ddb5 | 45 | static int prints(char **out, const char *string, int width, int pad) |
| vsutardja | 10:716484b1ddb5 | 46 | { |
| vsutardja | 10:716484b1ddb5 | 47 | register int pc = 0, padchar = ' '; |
| vsutardja | 10:716484b1ddb5 | 48 | |
| vsutardja | 10:716484b1ddb5 | 49 | if (width > 0) { |
| vsutardja | 10:716484b1ddb5 | 50 | register int len = 0; |
| vsutardja | 10:716484b1ddb5 | 51 | register const char *ptr; |
| vsutardja | 10:716484b1ddb5 | 52 | for (ptr = string; *ptr; ++ptr) ++len; |
| vsutardja | 10:716484b1ddb5 | 53 | if (len >= width) width = 0; |
| vsutardja | 10:716484b1ddb5 | 54 | else width -= len; |
| vsutardja | 10:716484b1ddb5 | 55 | if (pad & PAD_ZERO) padchar = '0'; |
| vsutardja | 10:716484b1ddb5 | 56 | } |
| vsutardja | 10:716484b1ddb5 | 57 | if (!(pad & PAD_RIGHT)) { |
| vsutardja | 10:716484b1ddb5 | 58 | for ( ; width > 0; --width) { |
| vsutardja | 10:716484b1ddb5 | 59 | printchar (out, padchar); |
| vsutardja | 10:716484b1ddb5 | 60 | ++pc; |
| vsutardja | 10:716484b1ddb5 | 61 | } |
| vsutardja | 10:716484b1ddb5 | 62 | } |
| vsutardja | 10:716484b1ddb5 | 63 | for ( ; *string ; ++string) { |
| vsutardja | 10:716484b1ddb5 | 64 | printchar (out, *string); |
| vsutardja | 10:716484b1ddb5 | 65 | ++pc; |
| vsutardja | 10:716484b1ddb5 | 66 | } |
| vsutardja | 10:716484b1ddb5 | 67 | for ( ; width > 0; --width) { |
| vsutardja | 10:716484b1ddb5 | 68 | printchar (out, padchar); |
| vsutardja | 10:716484b1ddb5 | 69 | ++pc; |
| vsutardja | 10:716484b1ddb5 | 70 | } |
| vsutardja | 10:716484b1ddb5 | 71 | |
| vsutardja | 10:716484b1ddb5 | 72 | return pc; |
| vsutardja | 10:716484b1ddb5 | 73 | } |
| vsutardja | 10:716484b1ddb5 | 74 | |
| vsutardja | 10:716484b1ddb5 | 75 | /* the following should be enough for 32 bit int */ |
| vsutardja | 10:716484b1ddb5 | 76 | #define PRINT_BUF_LEN 12 |
| vsutardja | 10:716484b1ddb5 | 77 | |
| vsutardja | 10:716484b1ddb5 | 78 | static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase) |
| vsutardja | 10:716484b1ddb5 | 79 | { |
| vsutardja | 10:716484b1ddb5 | 80 | char print_buf[PRINT_BUF_LEN]; |
| vsutardja | 10:716484b1ddb5 | 81 | register char *s; |
| vsutardja | 10:716484b1ddb5 | 82 | register int t, neg = 0, pc = 0; |
| vsutardja | 10:716484b1ddb5 | 83 | register unsigned int u = i; |
| vsutardja | 10:716484b1ddb5 | 84 | |
| vsutardja | 10:716484b1ddb5 | 85 | if (i == 0) { |
| vsutardja | 10:716484b1ddb5 | 86 | print_buf[0] = '0'; |
| vsutardja | 10:716484b1ddb5 | 87 | print_buf[1] = '\0'; |
| vsutardja | 10:716484b1ddb5 | 88 | return prints (out, print_buf, width, pad); |
| vsutardja | 10:716484b1ddb5 | 89 | } |
| vsutardja | 10:716484b1ddb5 | 90 | |
| vsutardja | 10:716484b1ddb5 | 91 | if (sg && b == 10 && i < 0) { |
| vsutardja | 10:716484b1ddb5 | 92 | neg = 1; |
| vsutardja | 10:716484b1ddb5 | 93 | u = -i; |
| vsutardja | 10:716484b1ddb5 | 94 | } |
| vsutardja | 10:716484b1ddb5 | 95 | |
| vsutardja | 10:716484b1ddb5 | 96 | s = print_buf + PRINT_BUF_LEN-1; |
| vsutardja | 10:716484b1ddb5 | 97 | *s = '\0'; |
| vsutardja | 10:716484b1ddb5 | 98 | |
| vsutardja | 10:716484b1ddb5 | 99 | while (u) { |
| vsutardja | 10:716484b1ddb5 | 100 | t = u % b; |
| vsutardja | 10:716484b1ddb5 | 101 | if( t >= 10 ) |
| vsutardja | 10:716484b1ddb5 | 102 | t += letbase - '0' - 10; |
| vsutardja | 10:716484b1ddb5 | 103 | *--s = t + '0'; |
| vsutardja | 10:716484b1ddb5 | 104 | u /= b; |
| vsutardja | 10:716484b1ddb5 | 105 | } |
| vsutardja | 10:716484b1ddb5 | 106 | |
| vsutardja | 10:716484b1ddb5 | 107 | if (neg) { |
| vsutardja | 10:716484b1ddb5 | 108 | if( width && (pad & PAD_ZERO) ) { |
| vsutardja | 10:716484b1ddb5 | 109 | printchar (out, '-'); |
| vsutardja | 10:716484b1ddb5 | 110 | ++pc; |
| vsutardja | 10:716484b1ddb5 | 111 | --width; |
| vsutardja | 10:716484b1ddb5 | 112 | } |
| vsutardja | 10:716484b1ddb5 | 113 | else { |
| vsutardja | 10:716484b1ddb5 | 114 | *--s = '-'; |
| vsutardja | 10:716484b1ddb5 | 115 | } |
| vsutardja | 10:716484b1ddb5 | 116 | } |
| vsutardja | 10:716484b1ddb5 | 117 | |
| vsutardja | 10:716484b1ddb5 | 118 | return pc + prints (out, s, width, pad); |
| vsutardja | 10:716484b1ddb5 | 119 | } |
| vsutardja | 10:716484b1ddb5 | 120 | |
| vsutardja | 10:716484b1ddb5 | 121 | static int print(char **out, const char *format, va_list args ) |
| vsutardja | 10:716484b1ddb5 | 122 | { |
| vsutardja | 10:716484b1ddb5 | 123 | register int width, pad; |
| vsutardja | 10:716484b1ddb5 | 124 | register int pc = 0; |
| vsutardja | 10:716484b1ddb5 | 125 | char scr[2]; |
| vsutardja | 10:716484b1ddb5 | 126 | |
| vsutardja | 10:716484b1ddb5 | 127 | for (; *format != 0; ++format) { |
| vsutardja | 10:716484b1ddb5 | 128 | if (*format == '%') { |
| vsutardja | 10:716484b1ddb5 | 129 | ++format; |
| vsutardja | 10:716484b1ddb5 | 130 | width = pad = 0; |
| vsutardja | 10:716484b1ddb5 | 131 | if (*format == '\0') break; |
| vsutardja | 10:716484b1ddb5 | 132 | if (*format == '%') goto out; |
| vsutardja | 10:716484b1ddb5 | 133 | if (*format == '-') { |
| vsutardja | 10:716484b1ddb5 | 134 | ++format; |
| vsutardja | 10:716484b1ddb5 | 135 | pad = PAD_RIGHT; |
| vsutardja | 10:716484b1ddb5 | 136 | } |
| vsutardja | 10:716484b1ddb5 | 137 | while (*format == '0') { |
| vsutardja | 10:716484b1ddb5 | 138 | ++format; |
| vsutardja | 10:716484b1ddb5 | 139 | pad |= PAD_ZERO; |
| vsutardja | 10:716484b1ddb5 | 140 | } |
| vsutardja | 10:716484b1ddb5 | 141 | for ( ; *format >= '0' && *format <= '9'; ++format) { |
| vsutardja | 10:716484b1ddb5 | 142 | width *= 10; |
| vsutardja | 10:716484b1ddb5 | 143 | width += *format - '0'; |
| vsutardja | 10:716484b1ddb5 | 144 | } |
| vsutardja | 10:716484b1ddb5 | 145 | if( *format == 's' ) { |
| vsutardja | 10:716484b1ddb5 | 146 | register char *s = (char *)va_arg( args, int ); |
| vsutardja | 10:716484b1ddb5 | 147 | pc += prints (out, s?s:"(null)", width, pad); |
| vsutardja | 10:716484b1ddb5 | 148 | continue; |
| vsutardja | 10:716484b1ddb5 | 149 | } |
| vsutardja | 10:716484b1ddb5 | 150 | if( *format == 'd' ) { |
| vsutardja | 10:716484b1ddb5 | 151 | pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a'); |
| vsutardja | 10:716484b1ddb5 | 152 | continue; |
| vsutardja | 10:716484b1ddb5 | 153 | } |
| vsutardja | 10:716484b1ddb5 | 154 | if( *format == 'x' ) { |
| vsutardja | 10:716484b1ddb5 | 155 | pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a'); |
| vsutardja | 10:716484b1ddb5 | 156 | continue; |
| vsutardja | 10:716484b1ddb5 | 157 | } |
| vsutardja | 10:716484b1ddb5 | 158 | if( *format == 'X' ) { |
| vsutardja | 10:716484b1ddb5 | 159 | pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A'); |
| vsutardja | 10:716484b1ddb5 | 160 | continue; |
| vsutardja | 10:716484b1ddb5 | 161 | } |
| vsutardja | 10:716484b1ddb5 | 162 | if( *format == 'u' ) { |
| vsutardja | 10:716484b1ddb5 | 163 | pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a'); |
| vsutardja | 10:716484b1ddb5 | 164 | continue; |
| vsutardja | 10:716484b1ddb5 | 165 | } |
| vsutardja | 10:716484b1ddb5 | 166 | if( *format == 'c' ) { |
| vsutardja | 10:716484b1ddb5 | 167 | /* char are converted to int then pushed on the stack */ |
| vsutardja | 10:716484b1ddb5 | 168 | scr[0] = (char)va_arg( args, int ); |
| vsutardja | 10:716484b1ddb5 | 169 | scr[1] = '\0'; |
| vsutardja | 10:716484b1ddb5 | 170 | pc += prints (out, scr, width, pad); |
| vsutardja | 10:716484b1ddb5 | 171 | continue; |
| vsutardja | 10:716484b1ddb5 | 172 | } |
| vsutardja | 10:716484b1ddb5 | 173 | } |
| vsutardja | 10:716484b1ddb5 | 174 | else { |
| vsutardja | 10:716484b1ddb5 | 175 | out: |
| vsutardja | 10:716484b1ddb5 | 176 | printchar (out, *format); |
| vsutardja | 10:716484b1ddb5 | 177 | ++pc; |
| vsutardja | 10:716484b1ddb5 | 178 | } |
| vsutardja | 10:716484b1ddb5 | 179 | } |
| vsutardja | 10:716484b1ddb5 | 180 | if (out) **out = '\0'; |
| vsutardja | 10:716484b1ddb5 | 181 | va_end( args ); |
| vsutardja | 10:716484b1ddb5 | 182 | return pc; |
| vsutardja | 10:716484b1ddb5 | 183 | } |
| vsutardja | 10:716484b1ddb5 | 184 | |
| vsutardja | 10:716484b1ddb5 | 185 | int printfNB(const char *format, ...) |
| vsutardja | 10:716484b1ddb5 | 186 | { |
| vsutardja | 10:716484b1ddb5 | 187 | va_list args; |
| vsutardja | 10:716484b1ddb5 | 188 | |
| vsutardja | 10:716484b1ddb5 | 189 | va_start( args, format ); |
| vsutardja | 10:716484b1ddb5 | 190 | return print( 0, format, args ); |
| vsutardja | 10:716484b1ddb5 | 191 | } |
| vsutardja | 10:716484b1ddb5 | 192 | |
| vsutardja | 10:716484b1ddb5 | 193 | int sprintf(char *out, const char *format, ...) |
| vsutardja | 10:716484b1ddb5 | 194 | { |
| vsutardja | 10:716484b1ddb5 | 195 | va_list args; |
| vsutardja | 10:716484b1ddb5 | 196 | |
| vsutardja | 10:716484b1ddb5 | 197 | va_start( args, format ); |
| vsutardja | 10:716484b1ddb5 | 198 | return print( &out, format, args ); |
| vsutardja | 10:716484b1ddb5 | 199 | } |
| vsutardja | 10:716484b1ddb5 | 200 | |
| vsutardja | 10:716484b1ddb5 | 201 | #ifdef TEST_PRINTF |
| vsutardja | 10:716484b1ddb5 | 202 | int main(void) |
| vsutardja | 10:716484b1ddb5 | 203 | { |
| vsutardja | 10:716484b1ddb5 | 204 | char *ptr = "Hello world!"; |
| vsutardja | 10:716484b1ddb5 | 205 | char *np = 0; |
| vsutardja | 10:716484b1ddb5 | 206 | int i = 5; |
| vsutardja | 10:716484b1ddb5 | 207 | unsigned int bs = sizeof(int)*8; |
| vsutardja | 10:716484b1ddb5 | 208 | int mi; |
| vsutardja | 10:716484b1ddb5 | 209 | char buf[80]; |
| vsutardja | 10:716484b1ddb5 | 210 | |
| vsutardja | 10:716484b1ddb5 | 211 | mi = (1 << (bs-1)) + 1; |
| vsutardja | 10:716484b1ddb5 | 212 | printf("%s\n", ptr); |
| vsutardja | 10:716484b1ddb5 | 213 | printf("printf test\n"); |
| vsutardja | 10:716484b1ddb5 | 214 | printf("%s is null pointer\n", np); |
| vsutardja | 10:716484b1ddb5 | 215 | printf("%d = 5\n", i); |
| vsutardja | 10:716484b1ddb5 | 216 | printf("%d = - max int\n", mi); |
| vsutardja | 10:716484b1ddb5 | 217 | printf("char %c = 'a'\n", 'a'); |
| vsutardja | 10:716484b1ddb5 | 218 | printf("hex %x = ff\n", 0xff); |
| vsutardja | 10:716484b1ddb5 | 219 | printf("hex %02x = 00\n", 0); |
| vsutardja | 10:716484b1ddb5 | 220 | printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3); |
| vsutardja | 10:716484b1ddb5 | 221 | printf("%d %s(s)%", 0, "message"); |
| vsutardja | 10:716484b1ddb5 | 222 | printf("\n"); |
| vsutardja | 10:716484b1ddb5 | 223 | printf("%d %s(s) with %%\n", 0, "message"); |
| vsutardja | 10:716484b1ddb5 | 224 | sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf); |
| vsutardja | 10:716484b1ddb5 | 225 | sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf); |
| vsutardja | 10:716484b1ddb5 | 226 | sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf); |
| vsutardja | 10:716484b1ddb5 | 227 | sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf); |
| vsutardja | 10:716484b1ddb5 | 228 | sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf); |
| vsutardja | 10:716484b1ddb5 | 229 | sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf); |
| vsutardja | 10:716484b1ddb5 | 230 | sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf); |
| vsutardja | 10:716484b1ddb5 | 231 | sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf); |
| vsutardja | 10:716484b1ddb5 | 232 | |
| vsutardja | 10:716484b1ddb5 | 233 | return 0; |
| vsutardja | 10:716484b1ddb5 | 234 | } |
| vsutardja | 10:716484b1ddb5 | 235 | |
| vsutardja | 10:716484b1ddb5 | 236 | /* |
| vsutardja | 10:716484b1ddb5 | 237 | * if you compile this file with |
| vsutardja | 10:716484b1ddb5 | 238 | * gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c |
| vsutardja | 10:716484b1ddb5 | 239 | * you will get a normal warning: |
| vsutardja | 10:716484b1ddb5 | 240 | * printf.c:214: warning: spurious trailing `%' in format |
| vsutardja | 10:716484b1ddb5 | 241 | * this line is testing an invalid % at the end of the format string. |
| vsutardja | 10:716484b1ddb5 | 242 | * |
| vsutardja | 10:716484b1ddb5 | 243 | * this should display (on 32bit int machine) : |
| vsutardja | 10:716484b1ddb5 | 244 | * |
| vsutardja | 10:716484b1ddb5 | 245 | * Hello world! |
| vsutardja | 10:716484b1ddb5 | 246 | * printf test |
| vsutardja | 10:716484b1ddb5 | 247 | * (null) is null pointer |
| vsutardja | 10:716484b1ddb5 | 248 | * 5 = 5 |
| vsutardja | 10:716484b1ddb5 | 249 | * -2147483647 = - max int |
| vsutardja | 10:716484b1ddb5 | 250 | * char a = 'a' |
| vsutardja | 10:716484b1ddb5 | 251 | * hex ff = ff |
| vsutardja | 10:716484b1ddb5 | 252 | * hex 00 = 00 |
| vsutardja | 10:716484b1ddb5 | 253 | * signed -3 = unsigned 4294967293 = hex fffffffd |
| vsutardja | 10:716484b1ddb5 | 254 | * 0 message(s) |
| vsutardja | 10:716484b1ddb5 | 255 | * 0 message(s) with % |
| vsutardja | 10:716484b1ddb5 | 256 | * justif: "left " |
| vsutardja | 10:716484b1ddb5 | 257 | * justif: " right" |
| vsutardja | 10:716484b1ddb5 | 258 | * 3: 0003 zero padded |
| vsutardja | 10:716484b1ddb5 | 259 | * 3: 3 left justif. |
| vsutardja | 10:716484b1ddb5 | 260 | * 3: 3 right justif. |
| vsutardja | 10:716484b1ddb5 | 261 | * -3: -003 zero padded |
| vsutardja | 10:716484b1ddb5 | 262 | * -3: -3 left justif. |
| vsutardja | 10:716484b1ddb5 | 263 | * -3: -3 right justif. |
| vsutardja | 10:716484b1ddb5 | 264 | */ |
| vsutardja | 10:716484b1ddb5 | 265 | |
| vsutardja | 10:716484b1ddb5 | 266 | #endif |
