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