0
|
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 }
|