C++ fixes.
[bertos.git] / mware / sprintf.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2002, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
5  * This file is part of DevLib - See README.devlib for information.
6  * -->
7  *
8  * \brief sprintf() implementation based on _formatted_write()
9  *
10  * \version $Id$
11  * \author Bernardo Innocenti <bernie@develer.com>
12  */
13
14 /*#*
15  *#* $Log$
16  *#* Revision 1.10  2005/04/11 19:10:28  bernie
17  *#* Include top-level headers from cfg/ subdir.
18  *#*
19  *#* Revision 1.9  2005/02/18 12:48:01  bernie
20  *#* Fix bug with NULL buffers (caught with unit test).
21  *#*
22  *#* Revision 1.8  2005/02/18 12:34:29  bernie
23  *#* Include <mware/pgm.h> explicitly for non-Harvard archs.
24  *#*
25  *#* Revision 1.7  2004/12/31 17:47:45  bernie
26  *#* Rename UNUSED() to UNUSED_ARG().
27  *#*
28  *#* Revision 1.6  2004/11/16 21:15:19  bernie
29  *#* Fix off-by-one bug in [v]snprintf().
30  *#*
31  *#* Revision 1.5  2004/10/03 18:54:36  bernie
32  *#* sprintf(): Fix a serious bug; snprintf(): New function.
33  *#*
34  *#* Revision 1.4  2004/08/25 14:12:09  rasky
35  *#* Aggiornato il comment block dei log RCS
36  *#*
37  *#* Revision 1.3  2004/06/27 15:20:26  aleph
38  *#* Change UNUSED() macro to accept two arguments: type and name;
39  *#* Add macro GNUC_PREREQ to detect GCC version during build;
40  *#* Some spacing cleanups and typo fix
41  *#*
42  *#* Revision 1.2  2004/06/03 11:27:09  bernie
43  *#* Add dual-license information.
44  *#*/
45
46 #include <mware/formatwr.h>
47 #include <mware/pgm.h>
48 #include <cfg/compiler.h>
49
50 #include <stdio.h>
51
52
53 static void __str_put_char(char c, void *ptr)
54 {
55         /*
56          * This Does not work on Code Warrior. Hmm...
57          *      *(*((char **)ptr))++ = c;
58          */
59
60         **((char **)ptr) = c;
61         (*((char **)ptr))++;
62 }
63
64 static void __null_put_char(UNUSED_ARG(char, c), UNUSED_ARG(void *, ptr))
65 {
66         /* nop */
67 }
68
69
70 int PGM_FUNC(vsprintf)(char *str, const char * PGM_ATTR fmt, va_list ap)
71 {
72         int result;
73
74         if (str)
75         {
76                 result = PGM_FUNC(_formatted_write)(fmt, __str_put_char, &str, ap);
77
78                 /* Terminate string */
79                 *str = '\0';
80         }
81         else
82                 result = PGM_FUNC(_formatted_write)(fmt, __null_put_char, 0, ap);
83
84
85         return result;
86 }
87
88
89 int PGM_FUNC(sprintf)(char *str, const char * fmt, ...)
90 {
91         int result;
92         va_list ap;
93
94         va_start(ap, fmt);
95         result = PGM_FUNC(vsprintf)(str, fmt, ap);
96         va_end(ap);
97
98         return result;
99 }
100
101 /*!
102  * State information for __sn_put_char()
103  */
104 struct __sn_state
105 {
106         char *str;
107         size_t len;
108 };
109
110 /*!
111  * formatted_write() callback used [v]snprintf().
112  */
113 static void __sn_put_char(char c, void *ptr)
114 {
115         struct __sn_state *state = (struct __sn_state *)ptr;
116
117         if (state->len)
118         {
119                 --state->len;
120                 *state->str++ = c;
121         }
122 }
123
124
125 int PGM_FUNC(vsnprintf)(char *str, size_t size, const char * PGM_ATTR fmt, va_list ap)
126 {
127         int result = 0;
128
129         /* Make room for traling '\0'. */
130         if (size--)
131         {
132                 if (str)
133                 {
134                         struct __sn_state state;
135                         state.str = str;
136                         state.len = size;
137
138                         result = PGM_FUNC(_formatted_write)(fmt, __sn_put_char, &state, ap);
139
140                         /* Terminate string. */
141                         *state.str = '\0';
142                 }
143                 else
144                         result = PGM_FUNC(_formatted_write)(fmt, __null_put_char, 0, ap);
145         }
146
147         return result;
148 }
149
150
151 int PGM_FUNC(snprintf)(char *str, size_t size, const char * fmt, ...)
152 {
153         int result;
154         va_list ap;
155
156         va_start(ap, fmt);
157         result = PGM_FUNC(vsnprintf)(str, size, fmt, ap);
158         va_end(ap);
159
160         return result;
161 }