0b05ce7ba6e3bc2db9a049dcdaf56011d9574ab1
[bertos.git] / bertos / mware / sprintf.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2002, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief sprintf() implementation based on _formatted_write()
34  *
35  * \version $Id$
36  * \author Bernardo Innocenti <bernie@develer.com>
37  */
38
39 #include <mware/formatwr.h>
40 #include <mware/pgm.h>
41 #include <cfg/compiler.h>
42
43 #include <stdio.h>
44
45
46 static void __str_put_char(char c, void *ptr)
47 {
48         /*
49          * This Does not work on Code Warrior. Hmm...
50          *      *(*((char **)ptr))++ = c;
51          */
52
53         **((char **)ptr) = c;
54         (*((char **)ptr))++;
55 }
56
57 static void __null_put_char(UNUSED_ARG(char, c), UNUSED_ARG(void *, ptr))
58 {
59         /* nop */
60 }
61
62
63 int PGM_FUNC(vsprintf)(char *str, const char * PGM_ATTR fmt, va_list ap)
64 {
65         int result;
66
67         if (str)
68         {
69                 result = PGM_FUNC(_formatted_write)(fmt, __str_put_char, &str, ap);
70
71                 /* Terminate string */
72                 *str = '\0';
73         }
74         else
75                 result = PGM_FUNC(_formatted_write)(fmt, __null_put_char, 0, ap);
76
77
78         return result;
79 }
80
81
82 int PGM_FUNC(sprintf)(char *str, const char * fmt, ...)
83 {
84         int result;
85         va_list ap;
86
87         va_start(ap, fmt);
88         result = PGM_FUNC(vsprintf)(str, fmt, ap);
89         va_end(ap);
90
91         return result;
92 }
93
94 /**
95  * State information for __sn_put_char()
96  */
97 struct __sn_state
98 {
99         char *str;
100         size_t len;
101 };
102
103 /**
104  * formatted_write() callback used [v]snprintf().
105  */
106 static void __sn_put_char(char c, void *ptr)
107 {
108         struct __sn_state *state = (struct __sn_state *)ptr;
109
110         if (state->len)
111         {
112                 --state->len;
113                 *state->str++ = c;
114         }
115 }
116
117
118 int PGM_FUNC(vsnprintf)(char *str, size_t size, const char * PGM_ATTR fmt, va_list ap)
119 {
120         int result = 0;
121
122         /* Make room for traling '\0'. */
123         if (size--)
124         {
125                 if (str)
126                 {
127                         struct __sn_state state;
128                         state.str = str;
129                         state.len = size;
130
131                         result = PGM_FUNC(_formatted_write)(fmt, __sn_put_char, &state, ap);
132
133                         /* Terminate string. */
134                         *state.str = '\0';
135                 }
136                 else
137                         result = PGM_FUNC(_formatted_write)(fmt, __null_put_char, 0, ap);
138         }
139
140         return result;
141 }
142
143
144 int PGM_FUNC(snprintf)(char *str, size_t size, const char * fmt, ...)
145 {
146         int result;
147         va_list ap;
148
149         va_start(ap, fmt);
150         result = PGM_FUNC(vsnprintf)(str, size, fmt, ap);
151         va_end(ap);
152
153         return result;
154 }