Mercurial > pub > halpp
comparison l476rg-hal-test/src/tiny_printf.c @ 0:32a3b1785697
a rough draft of Hardware Abstraction Layer for C++
STM32L476RG drivers
| author | cin |
|---|---|
| date | Thu, 12 Jan 2017 02:45:43 +0300 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:32a3b1785697 |
|---|---|
| 1 /* | |
| 2 ****************************************************************************** | |
| 3 File: tiny_printf.c | |
| 4 Info: Generated by Atollic TrueSTUDIO 7.0.1 2017-01-12 | |
| 5 | |
| 6 Abstract: Atollic TrueSTUDIO Minimal iprintf/siprintf/fiprintf | |
| 7 and puts/fputs. | |
| 8 Provides aliased declarations for printf/sprintf/fprintf | |
| 9 pointing to *iprintf variants. | |
| 10 | |
| 11 The argument contains a format string that may include | |
| 12 conversion specifications. Each conversion specification | |
| 13 is introduced by the character %, and ends with a | |
| 14 conversion specifier. | |
| 15 | |
| 16 The following conversion specifiers are supported | |
| 17 cdisuxX% | |
| 18 | |
| 19 Usage: | |
| 20 c character | |
| 21 d,i signed integer (-sign added, + sign not supported) | |
| 22 s character string | |
| 23 u unsigned integer as decimal | |
| 24 x,X unsigned integer as hexadecimal (uppercase letter) | |
| 25 % % is written (conversion specification is '%%') | |
| 26 | |
| 27 Note: | |
| 28 Character padding is not supported | |
| 29 | |
| 30 The MIT License (MIT) | |
| 31 Copyright (c) 2009-2016 Atollic AB | |
| 32 | |
| 33 Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 34 of this software and associated documentation files (the "Software"), to deal | |
| 35 in the Software without restriction, including without limitation the rights | |
| 36 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 37 copies of the Software, and to permit persons to whom the Software is | |
| 38 furnished to do so, subject to the following conditions: | |
| 39 | |
| 40 The above copyright notice and this permission notice shall be included in all | |
| 41 copies or substantial portions of the Software. | |
| 42 | |
| 43 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 44 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 45 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 46 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 47 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 48 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 49 SOFTWARE. | |
| 50 ****************************************************************************** | |
| 51 */ | |
| 52 | |
| 53 /* Includes */ | |
| 54 #include <stdarg.h> | |
| 55 #include <stdio.h> | |
| 56 #include <string.h> | |
| 57 | |
| 58 /* Create aliases for *printf to integer variants *iprintf */ | |
| 59 __attribute__ ((alias("iprintf"))) int printf(const char *fmt, ...); | |
| 60 __attribute__ ((alias("fiprintf"))) int fprintf(FILE* fp, const char *fmt, ...); | |
| 61 __attribute__ ((alias("siprintf"))) int sprintf(char* str, const char *fmt, ...); | |
| 62 | |
| 63 /* External function prototypes (defined in syscalls.c) */ | |
| 64 extern int _write(int fd, char *str, int len); | |
| 65 | |
| 66 /* Private function prototypes */ | |
| 67 void ts_itoa(char **buf, unsigned int d, int base); | |
| 68 int ts_formatstring(char *buf, const char *fmt, va_list va); | |
| 69 int ts_formatlength(const char *fmt, va_list va); | |
| 70 | |
| 71 /* Private functions */ | |
| 72 | |
| 73 /** | |
| 74 **--------------------------------------------------------------------------- | |
| 75 ** Abstract: Convert integer to ascii | |
| 76 ** Returns: void | |
| 77 **--------------------------------------------------------------------------- | |
| 78 */ | |
| 79 void ts_itoa(char **buf, unsigned int d, int base) | |
| 80 { | |
| 81 int div = 1; | |
| 82 while (d/div >= base) | |
| 83 div *= base; | |
| 84 | |
| 85 while (div != 0) | |
| 86 { | |
| 87 int num = d/div; | |
| 88 d = d%div; | |
| 89 div /= base; | |
| 90 if (num > 9) | |
| 91 *((*buf)++) = (num-10) + 'A'; | |
| 92 else | |
| 93 *((*buf)++) = num + '0'; | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 /** | |
| 98 **--------------------------------------------------------------------------- | |
| 99 ** Abstract: Writes arguments va to buffer buf according to format fmt | |
| 100 ** Returns: Length of string | |
| 101 **--------------------------------------------------------------------------- | |
| 102 */ | |
| 103 int ts_formatstring(char *buf, const char *fmt, va_list va) | |
| 104 { | |
| 105 char *start_buf = buf; | |
| 106 while(*fmt) | |
| 107 { | |
| 108 /* Character needs formating? */ | |
| 109 if (*fmt == '%') | |
| 110 { | |
| 111 switch (*(++fmt)) | |
| 112 { | |
| 113 case 'c': | |
| 114 *buf++ = va_arg(va, int); | |
| 115 break; | |
| 116 case 'd': | |
| 117 case 'i': | |
| 118 { | |
| 119 signed int val = va_arg(va, signed int); | |
| 120 if (val < 0) | |
| 121 { | |
| 122 val *= -1; | |
| 123 *buf++ = '-'; | |
| 124 } | |
| 125 ts_itoa(&buf, val, 10); | |
| 126 } | |
| 127 break; | |
| 128 case 's': | |
| 129 { | |
| 130 char * arg = va_arg(va, char *); | |
| 131 while (*arg) | |
| 132 { | |
| 133 *buf++ = *arg++; | |
| 134 } | |
| 135 } | |
| 136 break; | |
| 137 case 'u': | |
| 138 ts_itoa(&buf, va_arg(va, unsigned int), 10); | |
| 139 break; | |
| 140 case 'x': | |
| 141 case 'X': | |
| 142 ts_itoa(&buf, va_arg(va, int), 16); | |
| 143 break; | |
| 144 case '%': | |
| 145 *buf++ = '%'; | |
| 146 break; | |
| 147 } | |
| 148 fmt++; | |
| 149 } | |
| 150 /* Else just copy */ | |
| 151 else | |
| 152 { | |
| 153 *buf++ = *fmt++; | |
| 154 } | |
| 155 } | |
| 156 *buf = 0; | |
| 157 | |
| 158 return (int)(buf - start_buf); | |
| 159 } | |
| 160 | |
| 161 | |
| 162 /** | |
| 163 **--------------------------------------------------------------------------- | |
| 164 ** Abstract: Calculate maximum length of the resulting string from the | |
| 165 ** format string and va_list va | |
| 166 ** Returns: Maximum length | |
| 167 **--------------------------------------------------------------------------- | |
| 168 */ | |
| 169 int ts_formatlength(const char *fmt, va_list va) | |
| 170 { | |
| 171 int length = 0; | |
| 172 while (*fmt) | |
| 173 { | |
| 174 if (*fmt == '%') | |
| 175 { | |
| 176 ++fmt; | |
| 177 switch (*fmt) | |
| 178 { | |
| 179 case 'c': | |
| 180 va_arg(va, int); | |
| 181 ++length; | |
| 182 break; | |
| 183 case 'd': | |
| 184 case 'i': | |
| 185 case 'u': | |
| 186 /* 32 bits integer is max 11 characters with minus sign */ | |
| 187 length += 11; | |
| 188 va_arg(va, int); | |
| 189 break; | |
| 190 case 's': | |
| 191 { | |
| 192 char * str = va_arg(va, char *); | |
| 193 while (*str++) | |
| 194 ++length; | |
| 195 } | |
| 196 break; | |
| 197 case 'x': | |
| 198 case 'X': | |
| 199 /* 32 bits integer as hex is max 8 characters */ | |
| 200 length += 8; | |
| 201 va_arg(va, unsigned int); | |
| 202 break; | |
| 203 default: | |
| 204 ++length; | |
| 205 break; | |
| 206 } | |
| 207 } | |
| 208 else | |
| 209 { | |
| 210 ++length; | |
| 211 } | |
| 212 ++fmt; | |
| 213 } | |
| 214 return length; | |
| 215 } | |
| 216 | |
| 217 /** | |
| 218 **=========================================================================== | |
| 219 ** Abstract: Loads data from the given locations and writes them to the | |
| 220 ** given character string according to the format parameter. | |
| 221 ** Returns: Number of bytes written | |
| 222 **=========================================================================== | |
| 223 */ | |
| 224 int siprintf(char *buf, const char *fmt, ...) | |
| 225 { | |
| 226 int length; | |
| 227 va_list va; | |
| 228 va_start(va, fmt); | |
| 229 length = ts_formatstring(buf, fmt, va); | |
| 230 va_end(va); | |
| 231 return length; | |
| 232 } | |
| 233 | |
| 234 /** | |
| 235 **=========================================================================== | |
| 236 ** Abstract: Loads data from the given locations and writes them to the | |
| 237 ** given file stream according to the format parameter. | |
| 238 ** Returns: Number of bytes written | |
| 239 **=========================================================================== | |
| 240 */ | |
| 241 int fiprintf(FILE * stream, const char *fmt, ...) | |
| 242 { | |
| 243 int length = 0; | |
| 244 va_list va; | |
| 245 va_start(va, fmt); | |
| 246 length = ts_formatlength(fmt, va); | |
| 247 va_end(va); | |
| 248 { | |
| 249 char buf[length]; | |
| 250 va_start(va, fmt); | |
| 251 length = ts_formatstring(buf, fmt, va); | |
| 252 length = _write(stream->_file, buf, length); | |
| 253 va_end(va); | |
| 254 } | |
| 255 return length; | |
| 256 } | |
| 257 | |
| 258 /** | |
| 259 **=========================================================================== | |
| 260 ** Abstract: Loads data from the given locations and writes them to the | |
| 261 ** standard output according to the format parameter. | |
| 262 ** Returns: Number of bytes written | |
| 263 ** | |
| 264 **=========================================================================== | |
| 265 */ | |
| 266 int iprintf(const char *fmt, ...) | |
| 267 { | |
| 268 int length = 0; | |
| 269 va_list va; | |
| 270 va_start(va, fmt); | |
| 271 length = ts_formatlength(fmt, va); | |
| 272 va_end(va); | |
| 273 { | |
| 274 char buf[length]; | |
| 275 va_start(va, fmt); | |
| 276 length = ts_formatstring(buf, fmt, va); | |
| 277 length = _write(1, buf, length); | |
| 278 va_end(va); | |
| 279 } | |
| 280 return length; | |
| 281 } | |
| 282 | |
| 283 /** | |
| 284 **=========================================================================== | |
| 285 ** Abstract: fputs writes the string at s (but without the trailing null) to | |
| 286 ** the file or stream identified by fp. | |
| 287 ** Returns: If successful, the result is 0; otherwise, the result is EOF. | |
| 288 ** | |
| 289 **=========================================================================== | |
| 290 */ | |
| 291 int fputs(const char *s, FILE *fp) | |
| 292 { | |
| 293 int length = strlen(s); | |
| 294 int wlen = 0; | |
| 295 int res; | |
| 296 | |
| 297 wlen = _write((fp->_file), (char*)s, length); | |
| 298 wlen += _write((fp->_file), "\n", 1); | |
| 299 | |
| 300 if (wlen == (length+1)) | |
| 301 { | |
| 302 res = 0; | |
| 303 } | |
| 304 else | |
| 305 { | |
| 306 res = EOF; | |
| 307 } | |
| 308 | |
| 309 return res; | |
| 310 } | |
| 311 | |
| 312 /** | |
| 313 **=========================================================================== | |
| 314 ** Abstract: puts writes the string at s (followed by a newline, instead of | |
| 315 ** the trailing null) to the standard output stream. | |
| 316 ** Returns: If successful, the result is a nonnegative integer; otherwise, | |
| 317 ** the result is EOF. | |
| 318 ** | |
| 319 **=========================================================================== | |
| 320 */ | |
| 321 int puts(const char *s) | |
| 322 { | |
| 323 int length = strlen(s); | |
| 324 int numbytes = 0; | |
| 325 int res; | |
| 326 | |
| 327 numbytes = _write(1, (char*)s, length); | |
| 328 numbytes += _write(1, "\n", 1); | |
| 329 | |
| 330 if (numbytes == (length+1)) | |
| 331 { | |
| 332 res = 0; | |
| 333 } | |
| 334 else | |
| 335 { | |
| 336 res = EOF; | |
| 337 } | |
| 338 | |
| 339 return res; | |
| 340 } | |
| 341 | |
| 342 /** | |
| 343 **=========================================================================== | |
| 344 ** Abstract: Copy, starting from the memory location buf, count elements | |
| 345 ** (each of size size) into the file or stream identified by fp. | |
| 346 ** Returns: Number of elements written | |
| 347 ** | |
| 348 **=========================================================================== | |
| 349 */ | |
| 350 size_t fwrite(const void * buf, size_t size, size_t count, FILE * fp) | |
| 351 { | |
| 352 return (_write((fp->_file), (char*)buf, size * count) / size); | |
| 353 } |
