Subversion Repositories libSmallPrintf

Rev

Rev 3 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/*
2
        Copyright 2001, 2002 Georges Menie (www.menie.org)
3
        stdarg version contributed by Christian Ettinger
4
 
5 mjames 5
        This program is free software; you can redistribute it and/or modify
6
        it under the terms of the GNU Lesser General Public License as published by
7
        the Free Software Foundation; either version 2 of the License, or
8
        (at your option) any later version.
2 mjames 9
 
5 mjames 10
        This program is distributed in the hope that it will be useful,
11
        but WITHOUT ANY WARRANTY; without even the implied warranty of
12
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
        GNU Lesser General Public License for more details.
2 mjames 14
 
5 mjames 15
        You should have received a copy of the GNU Lesser General Public License
16
        along with this program; if not, write to the Free Software
17
        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
2 mjames 18
*/
19
 
20
/* Includes */
21
 
3 mjames 22
#include "libSmallPrintf/small_printf.h"
2 mjames 23
 
24
#include <stdarg.h>
25
#include <stdio.h>
26
#include <string.h>
27
 
28
/*
29
        putchar is the only external dependency for this file,
30
        if you have a working putchar, leave it commented out.
31
        If not, uncomment the define below and
32
        replace outbyte(c) by your own function call.
33
*/
34
 
35
static void printchar(char **str, int c)
36
{
37
 
5 mjames 38
        if (str)
39
        {
2 mjames 40
                **str = c;
41
                ++(*str);
42
        }
5 mjames 43
#if defined SERIAL_UART1 || defined SERIAL_UART2 || defined SERIAL_UART3 || defined SERIAL_UART4
44
        else
45
                (void)PutCharSerial(c);
46
#endif
2 mjames 47
}
48
 
49
#define PAD_RIGHT 1
50
#define PAD_ZERO 2
51
 
52
static int prints(char **out, const char *string, int width, int pad)
53
{
54
        register int pc = 0, padchar = ' ';
55
 
5 mjames 56
        if (width > 0)
57
        {
2 mjames 58
                register int len = 0;
59
                register const char *ptr;
5 mjames 60
                for (ptr = string; *ptr; ++ptr)
61
                        ++len;
62
                if (len >= width)
63
                        width = 0;
64
                else
65
                        width -= len;
66
                if (pad & PAD_ZERO)
67
                        padchar = '0';
2 mjames 68
        }
5 mjames 69
        if (!(pad & PAD_RIGHT))
70
        {
71
                for (; width > 0; --width)
72
                {
73
                        printchar(out, padchar);
2 mjames 74
                        ++pc;
75
                }
76
        }
5 mjames 77
        for (; *string; ++string)
78
        {
79
                printchar(out, *string);
2 mjames 80
                ++pc;
81
        }
5 mjames 82
        for (; width > 0; --width)
83
        {
84
                printchar(out, padchar);
2 mjames 85
                ++pc;
86
        }
87
 
88
        return pc;
89
}
90
 
91
/* the following should be enough for 32 bit int */
92
#define PRINT_BUF_LEN 12
93
 
94
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
95
{
96
        char print_buf[PRINT_BUF_LEN];
97
        register char *s;
98
        register int t, neg = 0, pc = 0;
99
        register unsigned int u = i;
100
 
5 mjames 101
        if (i == 0)
102
        {
2 mjames 103
                print_buf[0] = '0';
104
                print_buf[1] = '\0';
5 mjames 105
                return prints(out, print_buf, width, pad);
2 mjames 106
        }
107
 
5 mjames 108
        if (sg && b == 10 && i < 0)
109
        {
2 mjames 110
                neg = 1;
111
                u = -i;
112
        }
113
 
5 mjames 114
        s = print_buf + PRINT_BUF_LEN - 1;
2 mjames 115
        *s = '\0';
116
 
5 mjames 117
        while (u)
118
        {
2 mjames 119
                t = u % b;
5 mjames 120
                if (t >= 10)
2 mjames 121
                        t += letbase - '0' - 10;
122
                *--s = t + '0';
123
                u /= b;
124
        }
125
 
5 mjames 126
        if (neg)
127
        {
128
                if (width && (pad & PAD_ZERO))
129
                {
130
                        printchar(out, '-');
2 mjames 131
                        ++pc;
132
                        --width;
133
                }
5 mjames 134
                else
135
                {
2 mjames 136
                        *--s = '-';
137
                }
138
        }
139
 
5 mjames 140
        return pc + prints(out, s, width, pad);
2 mjames 141
}
142
 
5 mjames 143
static int small_print(char **out, const char *format, va_list args)
2 mjames 144
{
145
        register int width, pad;
146
        register int pc = 0;
147
        char scr[2];
148
 
5 mjames 149
        for (; *format != 0; ++format)
150
        {
151
                if (*format == '%')
152
                {
2 mjames 153
                        ++format;
154
                        width = pad = 0;
5 mjames 155
                        if (*format == '\0')
156
                                break;
157
                        if (*format == '%')
158
                                goto out;
159
                        if (*format == '-')
160
                        {
2 mjames 161
                                ++format;
162
                                pad = PAD_RIGHT;
163
                        }
5 mjames 164
                        while (*format == '0')
165
                        {
2 mjames 166
                                ++format;
167
                                pad |= PAD_ZERO;
168
                        }
169
                        if ('*' == *format)
170
                        {
5 mjames 171
                                width = va_arg(args, int); // get width from next argument
2 mjames 172
                                format++;
173
                        }
174
                        else
175
                        {
5 mjames 176
                                for (; *format >= '0' && *format <= '9'; ++format)
2 mjames 177
                                {
178
                                        width *= 10;
179
                                        width += *format - '0';
180
                                }
181
                        }
5 mjames 182
                        if (*format == 'l')
183
                        { /* skip l in ld etc */
2 mjames 184
                                format++;
185
                        }
5 mjames 186
                        if (*format == 's')
187
                        {
188
                                register char *s = (char *)va_arg(args, int);
189
                                pc += prints(out, s ? s : "(null)", width, pad);
2 mjames 190
                                continue;
191
                        }
5 mjames 192
                        if (*format == 'd')
193
                        {
194
                                pc += printi(out, va_arg(args, int), 10, 1, width, pad, 'a');
2 mjames 195
                                continue;
196
                        }
5 mjames 197
                        if (*format == 'x')
198
                        {
199
                                pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'a');
2 mjames 200
                                continue;
201
                        }
5 mjames 202
                        if (*format == 'X')
203
                        {
204
                                pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'A');
2 mjames 205
                                continue;
206
                        }
5 mjames 207
                        if (*format == 'u')
208
                        {
209
                                pc += printi(out, va_arg(args, int), 10, 0, width, pad, 'a');
2 mjames 210
                                continue;
211
                        }
5 mjames 212
                        if (*format == 'c')
213
                        {
2 mjames 214
                                /* char are converted to int then pushed on the stack */
5 mjames 215
                                scr[0] = (char)va_arg(args, int);
2 mjames 216
                                scr[1] = '\0';
5 mjames 217
                                pc += prints(out, scr, width, pad);
2 mjames 218
                                continue;
219
                        }
5 mjames 220
                        if (*format == 'n')
221
                        { /* convert number printed so far and store in *va_arg( args, int)... */
222
                                int *dp = va_arg(args, int);
2 mjames 223
                                *dp = pc;
224
                                continue;
225
                        }
226
                }
5 mjames 227
                else
228
                {
2 mjames 229
                out:
230
                        /* deal with LF -> CRLF mapping */
5 mjames 231
                        if (*format == '\n')
2 mjames 232
                        {
5 mjames 233
                                printchar(out, '\r');
3 mjames 234
                                ++pc; // extra char
2 mjames 235
                        }
5 mjames 236
                        printchar(out, *format);
2 mjames 237
                        ++pc;
238
                }
239
        }
5 mjames 240
        if (out)
241
                **out = '\0';
2 mjames 242
        return pc;
243
}
244
 
245
int small_printf(const char *format, ...)
246
{
247
        int result = 0;
5 mjames 248
        va_list args;
2 mjames 249
 
5 mjames 250
        va_start(args, format);
251
        result = small_print(0, format, args);
252
        va_end(args);
253
        return result;
2 mjames 254
}
255
 
256
int small_sprintf(char *out, const char *format, ...)
257
{
5 mjames 258
        int result = 0;
259
        va_list args;
260
        va_start(args, format);
261
        result = small_print(&out, format, args);
262
        va_end(args);
263
        return result;
2 mjames 264
}