Appiko
tinyprintf.h
1 /*
2 Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the name of Kustaa Nyholm or SpareTimeLabs nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 /*
29 This library is really just two files: 'tinyprintf.h' and 'tinyprintf.c'.
30 
31 They provide a simple and small (+400 loc) printf functionality to
32 be used in embedded systems.
33 
34 I've found them so useful in debugging that I do not bother with a
35 debugger at all.
36 
37 They are distributed in source form, so to use them, just compile them
38 into your project.
39 
40 Two printf variants are provided: printf and the 'sprintf' family of
41 functions ('snprintf', 'sprintf', 'vsnprintf', 'vsprintf').
42 
43 The formats supported by this implementation are:
44 'c' 'd' 'i' 'o' 'p' 'u' 's' 'x' 'X'.
45 
46 Zero padding and field width are also supported.
47 
48 If the library is compiled with 'PRINTF_SUPPORT_LONG' defined, then
49 the long specifier is also supported. Note that this will pull in some
50 long math routines (pun intended!) and thus make your executable
51 noticeably longer. Likewise with 'PRINTF_LONG_LONG_SUPPORT' for the
52 long long specifier, and with 'PRINTF_SIZE_T_SUPPORT' for the size_t
53 specifier.
54 
55 The memory footprint of course depends on the target CPU, compiler and
56 compiler options, but a rough guesstimate (based on a H8S target) is about
57 1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
58 Not too bad. Your mileage may vary. By hacking the source code you can
59 get rid of some hundred bytes, I'm sure, but personally I feel the balance of
60 functionality and flexibility versus code size is close to optimal for
61 many embedded systems.
62 
63 To use the printf, you need to supply your own character output function,
64 something like :
65 
66 void putc ( void* p, char c)
67 {
68  while (!SERIAL_PORT_EMPTY) ;
69  SERIAL_PORT_TX_REGISTER = c;
70 }
71 
72 Before you can call printf, you need to initialize it to use your
73 character output function with something like:
74 
75 init_printf(NULL,putc);
76 
77 Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
78 the NULL (or any pointer) you pass into the 'init_printf' will eventually be
79 passed to your 'putc' routine. This allows you to pass some storage space (or
80 anything really) to the character output function, if necessary.
81 This is not often needed but it was implemented like that because it made
82 implementing the sprintf function so neat (look at the source code).
83 
84 The code is re-entrant, except for the 'init_printf' function, so it is safe
85 to call it from interrupts too, although this may result in mixed output.
86 If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
87 
88 The printf and sprintf functions are actually macros that translate to
89 'tfp_printf' and 'tfp_sprintf' when 'TINYPRINTF_OVERRIDE_LIBC' is set
90 (default). Setting it to 0 makes it possible to use them along with
91 'stdio.h' printf's in a single source file. When
92 'TINYPRINTF_OVERRIDE_LIBC' is set, please note that printf/sprintf are
93 not function-like macros, so if you have variables or struct members
94 with these names, things will explode in your face. Without variadic
95 macros this is the best we can do to wrap these function. If it is a
96 problem, just give up the macros and use the functions directly, or
97 rename them.
98 
99 It is also possible to avoid defining tfp_printf and/or tfp_sprintf by
100 clearing 'TINYPRINTF_DEFINE_TFP_PRINTF' and/or
101 'TINYPRINTF_DEFINE_TFP_SPRINTF' to 0. This allows for example to
102 export only tfp_format, which is at the core of all the other
103 functions.
104 
105 For further details see source code.
106 
107 regs Kusti, 23.10.2004
108 */
109 
110 #ifndef __TFP_PRINTF__
111 #define __TFP_PRINTF__
112 
113 #include <stdarg.h>
114 
115 /* Global configuration */
116 
117 /* Set this to 0 if you do not want to provide tfp_printf */
118 #ifndef TINYPRINTF_DEFINE_TFP_PRINTF
119 # define TINYPRINTF_DEFINE_TFP_PRINTF 1
120 #endif
121 
122 /* Set this to 0 if you do not want to provide
123  tfp_sprintf/snprintf/vsprintf/vsnprintf */
124 #ifndef TINYPRINTF_DEFINE_TFP_SPRINTF
125 # define TINYPRINTF_DEFINE_TFP_SPRINTF 1
126 #endif
127 
128 /* Set this to 0 if you do not want tfp_printf and
129  tfp_{vsn,sn,vs,s}printf to be also available as
130  printf/{vsn,sn,vs,s}printf */
131 #ifndef TINYPRINTF_OVERRIDE_LIBC
132 # define TINYPRINTF_OVERRIDE_LIBC 0
133 #endif
134 
135 /* This is sent at the end of a printf line to inform the output
136  * driver that the line has ended */
137 #define START_TX 0
138 
139 /* Optional external types dependencies */
140 
141 #if TINYPRINTF_DEFINE_TFP_SPRINTF
142 # include <sys/types.h> /* size_t */
143 #endif
144 
145 /* Declarations */
146 
147 #ifdef __GNUC__
148 # define _TFP_SPECIFY_PRINTF_FMT(fmt_idx,arg1_idx) \
149  __attribute__((format (printf, fmt_idx, arg1_idx)))
150 #else
151 # define _TFP_SPECIFY_PRINTF_FMT(fmt_idx,arg1_idx)
152 #endif
153 
154 #ifdef __cplusplus
155 extern "C" {
156 #endif
157 
158 typedef void (*putcf) (void *, char);
159 
160 /*
161  'tfp_format' really is the central function for all tinyprintf. For
162  each output character after formatting, the 'putf' callback is
163  called with 2 args:
164  - an arbitrary void* 'putp' param defined by the user and
165  passed unmodified from 'tfp_format',
166  - the character.
167  The 'tfp_printf' and 'tfp_sprintf' functions simply define their own
168  callback and pass to it the right 'putp' it is expecting.
169 */
170 void tfp_format(void *putp, putcf putf, const char *fmt, va_list va);
171 
172 #if TINYPRINTF_DEFINE_TFP_SPRINTF
173 int tfp_vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
174 int tfp_snprintf(char *str, size_t size, const char *fmt, ...) \
175  _TFP_SPECIFY_PRINTF_FMT(3, 4);
176 int tfp_vsprintf(char *str, const char *fmt, va_list ap);
177 int tfp_sprintf(char *str, const char *fmt, ...) \
178  _TFP_SPECIFY_PRINTF_FMT(2, 3);
179 # if TINYPRINTF_OVERRIDE_LIBC
180 # define vsnprintf tfp_vsnprintf
181 # define snprintf tfp_snprintf
182 # define vsprintf tfp_vsprintf
183 # define sprintf tfp_sprintf
184 # endif
185 #endif
186 
187 #if TINYPRINTF_DEFINE_TFP_PRINTF
188 void init_printf(void *putp, putcf putf);
189 void tfp_printf(char *fmt, ...) _TFP_SPECIFY_PRINTF_FMT(1, 2);
190 # if TINYPRINTF_OVERRIDE_LIBC
191 # define printf tfp_printf
192 # endif
193 #endif
194 
195 #ifdef __cplusplus
196 }
197 #endif
198 
199 #endif