2 * $Id: snprintf-imp.h,v 1.4 2002/08/28 21:00:41 jmayer Exp $
6 Unix snprintf implementation.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13 It can be redistribute also under the terms of GNU Library General
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 * added changes from Miles Bader
31 * corrected a bug with %f
32 * added support for %#g
33 * added more comments :-)
35 * supporting must ANSI syntaxic_sugars(see below)
51 Formating conversion flags:
53 + Justify right or put a plus if number
54 # prefix 0x, 0X for hexa and 0 for octal
55 * precision/witdth is specify as an (int) in the arguments
56 ' ' leave a blank for number with no sign
57 l the later should be a long
58 h the later should be a short
61 snprintf(holder, sizeof_holder, format, ...)
67 THANKS(for the patches and ideas):
73 Alain Magloire: alainm@rcsm.ee.mcgill.ca
78 * For the FLOATING POINT FORMAT :
79 * the challenge was finding a way to
80 * manipulate the Real numbers without having
81 * to resort to mathematical function(it
82 * would require to link with -lm) and not
83 * going down to the bit pattern(not portable)
85 * so a number, a real is:
87 real = integral + fraction
89 integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
90 fraction = b(1)*10^-1 + b(2)*10^-2 + ...
96 from then it was simple math
100 * size of the buffer for the integral part
101 * and the fraction part
103 #define MAX_INT 99 + 1 /* 1 for the null */
104 #define MAX_FRACT 29 + 1
107 * numtoa() uses PRIVATE buffers to store the results,
108 * So this function is not reentrant
110 #define itoa(n) numtoa(n, 10, 0, (char **)0)
111 #define otoa(n) numtoa(n, 8, 0, (char **)0)
112 #define htoa(n) numtoa(n, 16, 0, (char **)0)
113 #define dtoa(n, p, f) numtoa(n, 10, p, f)
115 #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
117 /* this struct holds everything we need */
128 int width, precision;
129 int justify; char pad;
130 int square, space, star_w, star_p, a_long ;
133 #define PRIVATE static
135 /* signature of the functions */
137 /* the floating point stuff */
138 PRIVATE double pow_10(int);
139 PRIVATE int log_10(double);
140 PRIVATE double integral(double, double *);
141 PRIVATE char * numtoa(double, int, int, char **);
144 PRIVATE void conv_flag(char *, struct DATA *);
145 PRIVATE void floating(struct DATA *, double);
146 PRIVATE void exponent(struct DATA *, double);
147 PRIVATE void decimal(struct DATA *, double);
148 PRIVATE void octal(struct DATA *, double);
149 PRIVATE void hexa(struct DATA *, double);
150 PRIVATE void strings(struct DATA *, char *);
153 /* the floating point stuff */
154 PRIVATE double pow_10();
155 PRIVATE int log_10();
156 PRIVATE double integral();
157 PRIVATE char * numtoa();
160 PRIVATE void conv_flag();
161 PRIVATE void floating();
162 PRIVATE void exponent();
163 PRIVATE void decimal();
164 PRIVATE void octal();
166 PRIVATE void strings();
169 /* those are defines specific to snprintf to hopefully
170 * make the code clearer :-)
178 /* the conversion flags */
179 #define isflag(c) ((c) == '#' || (c) == ' ' || \
180 (c) == '*' || (c) == '+' || \
181 (c) == '-' || (c) == '.' || \
184 /* round off to the precision */
185 #define ROUND(d, p) \
187 d - pow_10(-(p)->precision) * 0.5 : \
188 d + pow_10(-(p)->precision) * 0.5
190 /* set default precision */
191 #define DEF_PREC(p) \
192 if ((p)->precision == NOT_FOUND) \
196 #define PUT_CHAR(c, p) \
197 if ((p)->counter < (p)->length) { \
198 *(p)->holder++ = (c); \
202 #define PUT_PLUS(d, p) \
203 if ((d) > 0. && (p)->justify == RIGHT) \
206 #define PUT_SPACE(d, p) \
207 if ((p)->space == FOUND && (d) > 0.) \
211 #define PAD_RIGHT(p) \
212 if ((p)->width > 0 && (p)->justify != LEFT) \
213 for (; (p)->width > 0; (p)->width--) \
214 PUT_CHAR((p)->pad, p)
217 #define PAD_LEFT(p) \
218 if ((p)->width > 0 && (p)->justify == LEFT) \
219 for (; (p)->width > 0; (p)->width--) \
220 PUT_CHAR((p)->pad, p)
222 /* if width and prec. in the args */
223 #define STAR_ARGS(p) \
224 if ((p)->star_w == FOUND) \
225 (p)->width = va_arg(args, int); \
226 if ((p)->star_p == FOUND) \
227 (p)->precision = va_arg(args, int)