3939int ce_vsprintf (char * buf , const char * fmt , va_list ap ) {
4040 char * p = buf ;
4141 const char * f = fmt ;
42- char tmp [32 ];
43- int precision ;
42+ char tmp [64 ];
43+ int flag_minus , flag_plus , flag_space , flag_hash , flag_zero ;
44+ int width , precision , is_long ;
4445
4546 while (* f ) {
4647 if (* f != '%' ) {
@@ -49,22 +50,39 @@ int ce_vsprintf(char *buf, const char *fmt, va_list ap) {
4950 }
5051 f ++ ; /* skip '%' */
5152
52- /* Handle flags and width (simplified - just skip them) */
53- while (* f == '-' || * f == '+' || * f == ' ' || * f == '#' || * f == '0' ) f ++ ;
54- /* Handle * width specifier - consume the argument */
53+ /* Parse flags */
54+ flag_minus = flag_plus = flag_space = flag_hash = flag_zero = 0 ;
55+ while (1 ) {
56+ if (* f == '-' ) { flag_minus = 1 ; f ++ ; }
57+ else if (* f == '+' ) { flag_plus = 1 ; f ++ ; }
58+ else if (* f == ' ' ) { flag_space = 1 ; f ++ ; }
59+ else if (* f == '#' ) { flag_hash = 1 ; f ++ ; }
60+ else if (* f == '0' ) { flag_zero = 1 ; f ++ ; }
61+ else break ;
62+ }
63+ if (flag_minus ) flag_zero = 0 ; /* - overrides 0 */
64+ if (flag_plus ) flag_space = 0 ; /* + overrides space */
65+
66+ /* Parse width */
67+ width = 0 ;
5568 if (* f == '*' ) {
56- (void )va_arg (ap , int );
69+ width = va_arg (ap , int );
70+ if (width < 0 ) { flag_minus = 1 ; width = - width ; }
5771 f ++ ;
5872 } else {
59- while (* f >= '0' && * f <= '9' ) f ++ ;
73+ while (* f >= '0' && * f <= '9' ) {
74+ width = width * 10 + (* f - '0' );
75+ f ++ ;
76+ }
6077 }
6178
6279 /* Parse precision */
63- precision = -1 ; /* -1 means use default */
80+ precision = -1 ;
6481 if (* f == '.' ) {
6582 f ++ ;
6683 if (* f == '*' ) {
6784 precision = va_arg (ap , int );
85+ if (precision < 0 ) precision = -1 ;
6886 f ++ ;
6987 } else {
7088 precision = 0 ;
@@ -75,83 +93,245 @@ int ce_vsprintf(char *buf, const char *fmt, va_list ap) {
7593 }
7694 }
7795
78- /* Handle length modifiers */
79- if (* f == 'l' ) f ++ ;
80- if (* f == 'l' ) f ++ ; /* ll */
96+ /* Parse length modifier */
97+ is_long = 0 ;
98+ if (* f == 'l' ) { is_long = 1 ; f ++ ; }
99+ if (* f == 'l' ) { f ++ ; } /* ll treated as l on 32-bit */
81100
101+ /* Format specifier */
82102 switch (* f ) {
83103 case 'd' : case 'i' : {
84- int val = va_arg (ap , int );
104+ long val = is_long ? va_arg ( ap , long ) : ( long ) va_arg (ap , int );
85105 int neg = 0 ;
86106 char * t = tmp + sizeof (tmp ) - 1 ;
87- unsigned int uval ;
107+ unsigned long uval ;
108+ int len , pad ;
109+ char sign = 0 ;
110+
88111 * t = '\0' ;
89- if (val < 0 ) { neg = 1 ; uval = (unsigned int )(- (val + 1 )) + 1 ; }
90- else { uval = (unsigned int )val ; }
112+ if (val < 0 ) { neg = 1 ; uval = (unsigned long )(- (val + 1 )) + 1 ; }
113+ else { uval = (unsigned long )val ; }
91114 if (uval == 0 ) * -- t = '0' ;
92115 while (uval > 0 ) { * -- t = '0' + (uval % 10 ); uval /= 10 ; }
93- if (neg ) * -- t = '-' ;
116+
117+ /* Apply precision (minimum digits) */
118+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t );
119+ if (precision > 0 ) {
120+ while (len < precision ) { * -- t = '0' ; len ++ ; }
121+ }
122+
123+ /* Determine sign character */
124+ if (neg ) sign = '-' ;
125+ else if (flag_plus ) sign = '+' ;
126+ else if (flag_space ) sign = ' ' ;
127+
128+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t );
129+ if (sign ) len ++ ;
130+ pad = (width > len ) ? width - len : 0 ;
131+
132+ if (!flag_minus && !flag_zero ) while (pad -- > 0 ) * p ++ = ' ' ;
133+ if (sign ) * p ++ = sign ;
134+ if (!flag_minus && flag_zero ) while (pad -- > 0 ) * p ++ = '0' ;
94135 while (* t ) * p ++ = * t ++ ;
136+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
95137 break ;
96138 }
97139 case 'u' : {
98- unsigned val = va_arg (ap , unsigned );
140+ unsigned long val = is_long ? va_arg ( ap , unsigned long ) : ( unsigned long ) va_arg (ap , unsigned );
99141 char * t = tmp + sizeof (tmp ) - 1 ;
142+ int len , pad ;
143+
100144 * t = '\0' ;
101145 if (val == 0 ) * -- t = '0' ;
102146 while (val > 0 ) { * -- t = '0' + (val % 10 ); val /= 10 ; }
147+
148+ if (precision > 0 ) {
149+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t );
150+ while (len < precision ) { * -- t = '0' ; len ++ ; }
151+ }
152+
153+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t );
154+ pad = (width > len ) ? width - len : 0 ;
155+
156+ if (!flag_minus && !flag_zero ) while (pad -- > 0 ) * p ++ = ' ' ;
157+ if (!flag_minus && flag_zero ) while (pad -- > 0 ) * p ++ = '0' ;
103158 while (* t ) * p ++ = * t ++ ;
159+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
160+ break ;
161+ }
162+ case 'o' : {
163+ unsigned long val = is_long ? va_arg (ap , unsigned long ) : (unsigned long )va_arg (ap , unsigned );
164+ char * t = tmp + sizeof (tmp ) - 1 ;
165+ int len , pad , need_prefix ;
166+
167+ * t = '\0' ;
168+ need_prefix = (flag_hash && val != 0 );
169+ if (val == 0 ) * -- t = '0' ;
170+ while (val > 0 ) { * -- t = '0' + (val & 7 ); val >>= 3 ; }
171+
172+ if (precision > 0 ) {
173+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t );
174+ while (len < precision ) { * -- t = '0' ; len ++ ; }
175+ }
176+ if (need_prefix && * t != '0' ) * -- t = '0' ;
177+
178+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t );
179+ pad = (width > len ) ? width - len : 0 ;
180+
181+ if (!flag_minus && !flag_zero ) while (pad -- > 0 ) * p ++ = ' ' ;
182+ if (!flag_minus && flag_zero ) while (pad -- > 0 ) * p ++ = '0' ;
183+ while (* t ) * p ++ = * t ++ ;
184+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
104185 break ;
105186 }
106187 case 'x' : case 'X' : {
107- unsigned val = va_arg (ap , unsigned );
188+ unsigned long val = is_long ? va_arg ( ap , unsigned long ) : ( unsigned long ) va_arg (ap , unsigned );
108189 char * t = tmp + sizeof (tmp ) - 1 ;
109190 const char * hex = (* f == 'X' ) ? "0123456789ABCDEF" : "0123456789abcdef" ;
191+ int len , pad , need_prefix ;
192+
110193 * t = '\0' ;
194+ need_prefix = (flag_hash && val != 0 );
111195 if (val == 0 ) * -- t = '0' ;
112196 while (val > 0 ) { * -- t = hex [val & 0xF ]; val >>= 4 ; }
197+
198+ if (precision > 0 ) {
199+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t );
200+ while (len < precision ) { * -- t = '0' ; len ++ ; }
201+ }
202+
203+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t );
204+ if (need_prefix ) len += 2 ;
205+ pad = (width > len ) ? width - len : 0 ;
206+
207+ if (!flag_minus && !flag_zero ) while (pad -- > 0 ) * p ++ = ' ' ;
208+ if (need_prefix ) { * p ++ = '0' ; * p ++ = (* f == 'X' ) ? 'X' : 'x' ; }
209+ if (!flag_minus && flag_zero ) while (pad -- > 0 ) * p ++ = '0' ;
113210 while (* t ) * p ++ = * t ++ ;
211+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
114212 break ;
115213 }
116214 case 'p' : {
117215 unsigned long val = (unsigned long )va_arg (ap , void * );
118216 char * t = tmp + sizeof (tmp ) - 1 ;
217+ int len , pad ;
218+
119219 * t = '\0' ;
120220 if (val == 0 ) * -- t = '0' ;
121221 while (val > 0 ) { * -- t = "0123456789abcdef" [val & 0xF ]; val >>= 4 ; }
122- * -- t = 'x' ; * -- t = '0' ;
222+
223+ len = (int )((tmp + sizeof (tmp ) - 1 ) - t ) + 2 ;
224+ pad = (width > len ) ? width - len : 0 ;
225+
226+ if (!flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
227+ * p ++ = '0' ; * p ++ = 'x' ;
123228 while (* t ) * p ++ = * t ++ ;
229+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
124230 break ;
125231 }
126232 case 's' : {
127233 const char * s = va_arg (ap , const char * );
128- int len ;
234+ int len = 0 , pad ;
235+ const char * t ;
236+
129237 if (!s ) s = "(null)" ;
130- if (precision >= 0 ) {
131- /* Copy at most 'precision' characters */
132- for (len = 0 ; len < precision && s [len ]; len ++ )
133- * p ++ = s [len ];
134- } else {
135- while (* s ) * p ++ = * s ++ ;
136- }
238+ t = s ;
239+ while (* t ) { len ++ ; t ++ ; }
240+ if (precision >= 0 && len > precision ) len = precision ;
241+ pad = (width > len ) ? width - len : 0 ;
242+
243+ if (!flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
244+ while (len -- > 0 ) * p ++ = * s ++ ;
245+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
137246 break ;
138247 }
139248 case 'c' : {
140249 char c = (char )va_arg (ap , int );
250+ int pad = (width > 1 ) ? width - 1 : 0 ;
251+
252+ if (!flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
141253 * p ++ = c ;
254+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
142255 break ;
143256 }
144257 case '%' :
145258 * p ++ = '%' ;
146259 break ;
260+ case 'e' : case 'E' : {
261+ double val = va_arg (ap , double );
262+ int neg = 0 , exp = 0 , i ;
263+ int prec = (precision < 0 ) ? 6 : precision ;
264+ char * t ;
265+ double rounder ;
266+ int len , pad ;
267+ char sign = 0 ;
268+ char expchar = * f ;
269+
270+ if (val < 0 ) { neg = 1 ; val = - val ; }
271+
272+ /* Normalize to 1.xxx * 10^exp */
273+ if (val != 0 ) {
274+ while (val >= 10 ) { val /= 10 ; exp ++ ; }
275+ while (val < 1 ) { val *= 10 ; exp -- ; }
276+ }
277+
278+ /* Apply rounding */
279+ rounder = 0.5 ;
280+ for (i = 0 ; i < prec ; i ++ ) rounder *= 0.1 ;
281+ val += rounder ;
282+ if (val >= 10 ) { val /= 10 ; exp ++ ; }
283+
284+ /* Build number in tmp */
285+ t = tmp ;
286+ if (neg ) sign = '-' ;
287+ else if (flag_plus ) sign = '+' ;
288+ else if (flag_space ) sign = ' ' ;
289+
290+ /* Integer part (single digit) */
291+ * t ++ = '0' + (int )val ;
292+ val -= (int )val ;
293+
294+ /* Fractional part */
295+ if (prec > 0 || flag_hash ) {
296+ * t ++ = '.' ;
297+ for (i = 0 ; i < prec ; i ++ ) {
298+ val *= 10 ;
299+ * t ++ = '0' + (int )val ;
300+ val -= (int )val ;
301+ }
302+ }
303+
304+ /* Exponent */
305+ * t ++ = expchar ;
306+ * t ++ = (exp < 0 ) ? '-' : '+' ;
307+ if (exp < 0 ) exp = - exp ;
308+ if (exp < 10 ) * t ++ = '0' ;
309+ if (exp >= 100 ) { * t ++ = '0' + (exp / 100 ); exp %= 100 ; }
310+ if (exp >= 10 ) { * t ++ = '0' + (exp / 10 ); exp %= 10 ; }
311+ * t ++ = '0' + exp ;
312+ * t = '\0' ;
313+
314+ len = (int )(t - tmp );
315+ if (sign ) len ++ ;
316+ pad = (width > len ) ? width - len : 0 ;
317+
318+ if (!flag_minus && !flag_zero ) while (pad -- > 0 ) * p ++ = ' ' ;
319+ if (sign ) * p ++ = sign ;
320+ if (!flag_minus && flag_zero ) while (pad -- > 0 ) * p ++ = '0' ;
321+ t = tmp ;
322+ while (* t ) * p ++ = * t ++ ;
323+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
324+ break ;
325+ }
147326 case 'g' : case 'f' : {
148327 double val = va_arg (ap , double );
149328 int neg = 0 ;
150329 int prec = (precision < 0 ) ? 6 : precision ;
151- int intpart ;
330+ int intpart , i ;
152331 char * t ;
153332 double rounder ;
154- int i ;
333+ int len , pad ;
334+ char sign = 0 ;
155335
156336 if (val < 0 ) { neg = 1 ; val = - val ; }
157337
@@ -162,24 +342,38 @@ int ce_vsprintf(char *buf, const char *fmt, va_list ap) {
162342
163343 intpart = (int )val ;
164344
165- /* Output sign and integer part */
166- t = tmp + sizeof ( tmp ) - 1 ;
345+ /* Build number in tmp */
346+ t = tmp + 30 ; /* Start in middle, build int part backwards */
167347 * t = '\0' ;
168348 if (intpart == 0 ) * -- t = '0' ;
169349 while (intpart > 0 ) { * -- t = '0' + (intpart % 10 ); intpart /= 10 ; }
170- if (neg ) * -- t = '-' ;
350+
351+ if (neg ) sign = '-' ;
352+ else if (flag_plus ) sign = '+' ;
353+ else if (flag_space ) sign = ' ' ;
354+
355+ /* Calculate length */
356+ len = (int )((tmp + 30 ) - t );
357+ if (prec > 0 || flag_hash ) len += 1 + prec ;
358+ if (sign ) len ++ ;
359+ pad = (width > len ) ? width - len : 0 ;
360+
361+ /* Output */
362+ if (!flag_minus && !flag_zero ) while (pad -- > 0 ) * p ++ = ' ' ;
363+ if (sign ) * p ++ = sign ;
364+ if (!flag_minus && flag_zero ) while (pad -- > 0 ) * p ++ = '0' ;
171365 while (* t ) * p ++ = * t ++ ;
172366
173- /* Output fractional part if precision > 0 */
174- if (prec > 0 ) {
367+ if (prec > 0 || flag_hash ) {
175368 * p ++ = '.' ;
176- val = val - (int )val ;
369+ val = val - (int )( val + rounder ) ;
177370 for (i = 0 ; i < prec ; i ++ ) {
178371 val *= 10 ;
179372 * p ++ = '0' + (int )val ;
180373 val -= (int )val ;
181374 }
182375 }
376+ if (flag_minus ) while (pad -- > 0 ) * p ++ = ' ' ;
183377 break ;
184378 }
185379 default :
0 commit comments