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