f758c2fda5b2b42adfad906b5b2b5c90e6f256dc
[bertos.git] / mware / formatwr.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
5  * This file is part of DevLib - See devlib/README for information.
6  * -->
7  *
8  * \version $Id$
9  *
10  * \brief Basic "printf", "sprintf" and "fprintf" formatter.
11  *
12  * This module is 100% reentrant and can be adapted to user-defined routines
13  * that needs formatters with special properties like different output
14  * channels or new format specifiers.
15  *
16  * To reduce size in applications not using real numbers or long integers
17  * the formatter may be compiled to exclude certain parts.  This is
18  * controlled by giving a -D option a compilation time:
19  *
20  * \code
21  *  -D CONFIG_PRINTF_NOFLOAT      Exclude support for floats
22  *  -D CONFIG_PRINTF_REDUCED      Simplified formatter (see below)
23  *  -D CONFIG_PRINTF_NOMODIFIERS  Exclude 'l' and 'h' modifiers in reduced version
24  * \endcode
25  *
26  * The reduced version of formatter is suitable when program size is critical
27  * rather than formatting power.  This routine uses less than 20 bytes of
28  * stack space which makes it practical even in systems with less than 256
29  * bytes of user RAM.
30  *
31  * The only formatting specifiers supported by the reduced formatter are:
32  * \code
33  *    %% %c %s %d %o %x %X and %hd %ho %hx %hX %ld %lo %lx %lX
34  * \endcode
35  *
36  * It means that real variables are not supported as well as field
37  * width and precision arguments.
38  *
39  * The last eight (h and l modifiers) can easily be removed
40  * by defining the \c CONFIG_PRINTF_NOMODIFIERS macro.
41  */
42
43 /*
44  * $Log$
45  * Revision 1.4  2004/07/21 00:20:20  bernie
46  * Allow completely disabling printf()-like formatter.
47  *
48  * Revision 1.3  2004/07/18 22:00:15  bernie
49  * Reorganize configuration parameters to match DevLib's convention.
50  *
51  * Revision 1.2  2004/06/03 11:27:09  bernie
52  * Add dual-license information.
53  *
54  * Revision 1.1  2004/05/23 15:43:16  bernie
55  * Import mware modules.
56  *
57  */
58
59 #ifndef CONFIG_PRINTF_DISABLED
60
61 #include "formatwr.h"
62 #include <compiler.h> /* progmem macros */
63 #include <config.h> /* CONFIG_ macros */
64
65 #ifndef CONFIG_PRINTF_NOFLOAT
66 #include <float.h>
67 #endif /* CONFIG_PRINTF_NOFLOAT */
68
69 #ifndef FRMWRI_BUFSIZE
70 /*bernie: save some memory, who cares about floats with lots of decimals? */
71 /*#define FRMWRI_BUFSIZE 134*/
72 #define FRMWRI_BUFSIZE 32
73 #endif
74
75 #ifndef MEM_ATTRIBUTE
76 #define MEM_ATTRIBUTE
77 #endif
78
79 #ifndef CONFIG_PRINTF_NOMODIFIERS
80 #define IS_SHORT (h_modifier || (sizeof(int) == 2 && !l_modifier))
81 #else
82 #define IS_SHORT (sizeof(int) == 2)
83 #endif
84
85
86 #ifndef CONFIG_PRINTF_NOFLOAT
87
88 static char *float_conversion(MEM_ATTRIBUTE long double value,
89                 MEM_ATTRIBUTE short nr_of_digits,
90                 MEM_ATTRIBUTE char *buf,
91                 MEM_ATTRIBUTE char format_flag,
92                 MEM_ATTRIBUTE char g_flag,
93                 MEM_ATTRIBUTE char alternate_flag)
94 {
95         MEM_ATTRIBUTE char *cp;
96         MEM_ATTRIBUTE char *buf_pointer;
97         MEM_ATTRIBUTE short n, i, dec_point_pos, integral_10_log;
98
99         buf_pointer = buf;
100         integral_10_log = 0;
101
102         if (value >= 1)
103         {
104                 while (value >= 1e11) /* To speed up things a bit */
105                 {
106                         value /= 1e10;
107                         integral_10_log += 10;
108                 }
109                 while (value >= 10)
110                 {
111                         value /= 10;
112                         integral_10_log++;
113                 }
114         }
115         else if (value) /* Not just 0.0 */
116         {
117                 while (value <= 1e-10) /* To speed up things a bit */
118                 {
119                         value *= 1e10;
120                         integral_10_log -= 10;
121                 }
122                 while (value < 1)
123                 {
124                         value *= 10;
125                         integral_10_log--;
126                 }
127         }
128         if (g_flag)
129         {
130                 if (integral_10_log < nr_of_digits && integral_10_log >= -4)
131                 {
132                         format_flag = 0;
133                         nr_of_digits -= integral_10_log;
134                 }
135                 nr_of_digits--;
136                 if (alternate_flag)
137                         /* %#G - No removal of trailing zeros */
138                         g_flag = 0;
139                 else
140                         /* %G - Removal of trailing zeros */
141                         alternate_flag = 1;
142         }
143
144         /* %e or %E */
145         if (format_flag)
146         {
147                 dec_point_pos = 0;
148         }
149         else
150         {
151                 /* Less than one... */
152                 if (integral_10_log < 0)
153                 {
154                         *buf_pointer++ = '0';
155                         if ((n = nr_of_digits) || alternate_flag)
156                                 *buf_pointer++ = '.';
157                         i = 0;
158                         while (--i > integral_10_log && nr_of_digits)
159                         {
160                                 *buf_pointer++ = '0';
161                                 nr_of_digits--;
162                         }
163                         if (integral_10_log < (-n - 1))
164                                 /* Nothing more to do */
165                                 goto CLEAN_UP;
166                         dec_point_pos = 1;
167                 }
168                 else
169                 {
170                         dec_point_pos = - integral_10_log;
171                 }
172         }
173
174         i = dec_point_pos;
175         while (i <= nr_of_digits )
176         {
177                 value -= (long double)(n = (short)value); /* n=Digit value=Remainder */
178                 value *= 10; /* Prepare for next shot */
179                 *buf_pointer++ = n + '0';
180                 if ( ! i++ && (nr_of_digits || alternate_flag))
181                         *buf_pointer++ = '.';
182         }
183
184         /* Rounding possible */
185         if (value >= 5)
186         {
187                 n = 1; /* Carry */
188                 cp = buf_pointer - 1;
189                 do
190                 {
191                         if (*cp != '.')
192                         {
193                                 if ( (*cp += n) == ('9' + 1) )
194                                 {
195                                         *cp = '0';
196                                         n = 1;
197                                 }
198                                 else
199                                         n = 0;
200                         }
201                 } while (cp-- > buf);
202                 if (n)
203                 {
204                         /* %e or %E */
205                         if (format_flag)
206                         {
207                                 cp = buf_pointer;
208                                 while (cp > buf)
209                                 {
210                                         if (*(cp - 1) == '.')
211                                         {
212                                                 *cp = *(cp - 2);
213                                                 cp--;
214                                         }
215                                         else
216                                                 *cp = *(cp - 1);
217                                         cp--;
218                                 }
219                                 integral_10_log++;
220                         }
221                         else
222                         {
223                                 cp = ++buf_pointer;
224                                 while (cp > buf)
225                                 {
226                                         *cp = *(cp - 1);
227                                         cp--;
228                                 }
229                         }
230                         *buf = '1';
231                 }
232         }
233
234 CLEAN_UP:
235         /* %G - Remove trailing zeros */
236         if (g_flag)
237         {
238                 while (*(buf_pointer - 1) == '0')
239                         buf_pointer--;
240                 if (*(buf_pointer - 1) == '.')
241                         buf_pointer--;
242         }
243
244         /* %e or %E */
245         if (format_flag)
246         {
247                 *buf_pointer++ = format_flag;
248                 if (integral_10_log < 0)
249                 {
250                         *buf_pointer++ = '-';
251                         integral_10_log = -integral_10_log;
252                 }
253                 else
254                         *buf_pointer++ = '+';
255                 n = 0;
256                 buf_pointer +=10;
257                 do
258                 {
259                         n++;
260                         *buf_pointer++ = (integral_10_log % 10) + '0';
261                         integral_10_log /= 10;
262                 } while ( integral_10_log || n < 2 );
263                 for ( i = n ; n > 0 ; n-- )
264                         *(buf_pointer - 11 - i + n) = *(buf_pointer - n);
265                 buf_pointer -= 10;
266         }
267         return (buf_pointer);
268 }
269
270 #endif /* !CONFIG_PRINTF_NOFLOAT */
271
272 /*!
273  * This routine forms the core and entry of the formatter.
274  *
275  * The conversion performed conforms to the ANSI specification for "printf".
276  */
277 int
278 PGM_FUNC(_formatted_write)(const char * PGM_ATTR format,
279                 void put_one_char(char, void *),
280                 void *secret_pointer,
281                 va_list ap)
282 {
283         MEM_ATTRIBUTE static char bad_conversion[] = "???";
284         MEM_ATTRIBUTE static char null_pointer[] = "<NULL>";
285
286 #ifndef CONFIG_PRINTF_REDUCED
287         MEM_ATTRIBUTE char format_flag;
288         MEM_ATTRIBUTE int precision;
289         MEM_ATTRIBUTE int n;
290         MEM_ATTRIBUTE int field_width, nr_of_chars;
291         MEM_ATTRIBUTE char plus_space_flag, left_adjust, l_L_modifier;
292         MEM_ATTRIBUTE char h_modifier, alternate_flag;
293         MEM_ATTRIBUTE char nonzero_value;
294         MEM_ATTRIBUTE unsigned long ulong, div_factor;
295
296 #ifndef CONFIG_PRINTF_NOFLOAT
297         MEM_ATTRIBUTE long double fvalue;
298 #endif
299
300         MEM_ATTRIBUTE char *buf_pointer;
301         MEM_ATTRIBUTE char *ptr;
302         MEM_ATTRIBUTE const char *hex;
303         MEM_ATTRIBUTE char zeropad;
304         MEM_ATTRIBUTE char buf[FRMWRI_BUFSIZE];
305
306         nr_of_chars = 0;
307         for (;;)    /* Until full format string read */
308         {
309                 while ((format_flag = PGM_READ_CHAR(format++)) != '%')    /* Until '%' or '\0' */
310                 {
311                         if (!format_flag)
312                                 return (nr_of_chars);
313                         put_one_char (format_flag, secret_pointer);
314                         nr_of_chars++;
315                 }
316                 if (PGM_READ_CHAR(format) == '%')    /* %% prints as % */
317                 {
318                         format++;
319                         put_one_char('%', secret_pointer);
320                         nr_of_chars++;
321                         continue;
322                 }
323
324                 plus_space_flag = left_adjust = alternate_flag = zeropad = 0;
325                 ptr = buf_pointer = &buf[0];
326                 hex = "0123456789ABCDEF";
327
328                 /* check for leading '-', '+', ' ','#' or '0' flags  */
329                 for (;;)
330                 {
331                         switch (PGM_READ_CHAR(format))
332                         {
333                                 case ' ':
334                                         if (plus_space_flag)
335                                                 goto NEXT_FLAG;
336                                 case '+':
337                                         plus_space_flag = PGM_READ_CHAR(format);
338                                         goto NEXT_FLAG;
339                                 case '-':
340                                         left_adjust++;
341                                         goto NEXT_FLAG;
342                                 case '#':
343                                         alternate_flag++;
344                                         goto NEXT_FLAG;
345                                 case '0':
346                                         zeropad++;
347                                         goto NEXT_FLAG;
348                         }
349                         break;
350 NEXT_FLAG:
351                         format++;
352                 }
353
354                 /* Optional field width (may be '*') */
355                 if (PGM_READ_CHAR(format) == '*')
356                 {
357                         field_width = va_arg(ap, int);
358                         if (field_width < 0)
359                         {
360                                 field_width = -field_width;
361                                 left_adjust++;
362                         }
363                         format++;
364                 }
365                 else
366                 {
367                         field_width = 0;
368                         while (PGM_READ_CHAR(format) >= '0' && PGM_READ_CHAR(format) <= '9')
369                                 field_width = field_width * 10 + (PGM_READ_CHAR(format++) - '0');
370                 }
371
372                 if (left_adjust)
373                         zeropad = 0;
374
375                 /* Optional precision (or '*') */
376                 if (PGM_READ_CHAR(format) == '.')
377                 {
378                         if (PGM_READ_CHAR(++format) == '*')
379                         {
380                                 precision = va_arg(ap, int);
381                                 format++;
382                         }
383                         else
384                         {
385                                 precision = 0;
386                                 while (PGM_READ_CHAR(format) >= '0' && PGM_READ_CHAR(format) <= '9')
387                                         precision = precision * 10 + (PGM_READ_CHAR(format++) - '0');
388                         }
389                 }
390                 else
391                         precision = -1;
392
393                 /* At this point, "left_adjust" is nonzero if there was
394                  * a sign, "zeropad" is 1 if there was a leading zero
395                  * and 0 otherwise, "field_width" and "precision"
396                  * contain numbers corresponding to the digit strings
397                  * before and after the decimal point, respectively,
398                  * and "plus_space_flag" is either 0 (no flag) or
399                  * contains a plus or space character. If there was no
400                  * decimal point, "precision" will be -1.
401                  */
402
403                 l_L_modifier = h_modifier = 0;
404
405                 /* Optional 'l','L' r 'h' modifier? */
406                 switch (PGM_READ_CHAR(format))
407                 {
408                         case 'l':
409                         case 'L':
410                                 l_L_modifier++;
411                                 format++;
412                                 break;
413                         case 'h':
414                                 h_modifier++;
415                                 format++;
416                                 break;
417                 }
418
419                 /*
420                  * At exit from the following switch, we will emit
421                  * the characters starting at "buf_pointer" and
422                  * ending at "ptr"-1
423                  */
424                 switch (format_flag = PGM_READ_CHAR(format++))
425                 {
426 #if 0 /* bernie */
427                         case 'n':
428                                 if (sizeof(short) != sizeof(int))
429                                 {
430                                         if (sizeof(int) != sizeof(long))
431                                         {
432                                                 if (h_modifier)
433                                                         *va_arg(ap, short *) = nr_of_chars;
434                                                 else if (l_L_modifier)
435                                                         *va_arg(ap, long *) = nr_of_chars;
436                                                 else
437                                                         *va_arg(ap, int *) = nr_of_chars;
438                                         }
439                                         else
440                                         {
441                                                 if (h_modifier)
442                                                         *va_arg(ap, short *) = nr_of_chars;
443                                                 else
444                                                         *va_arg(ap, int *) = nr_of_chars;
445                                         }
446                                 }
447                                 else
448                                 {
449                                         if (l_L_modifier)
450                                                 *va_arg(ap, long *) = nr_of_chars;
451                                         else
452                                                 *va_arg(ap, int *) = nr_of_chars;
453                                 }
454                                 continue;
455 #endif
456                         case 'c':
457                                 buf[0] = va_arg(ap, int);
458                                 ptr++;
459                                 break;
460
461                         case 's':
462                                 if ( !(buf_pointer = va_arg(ap, char *)) )
463                                         buf_pointer = null_pointer;
464                                 if (precision < 0)
465                                         precision = 10000;
466                                 for (n=0; *buf_pointer++ && n < precision; n++)
467                                         ;
468                                 ptr = --buf_pointer;
469                                 buf_pointer -= n;
470                                 break;
471
472                         case 'o':
473                                 if (alternate_flag && !precision)
474                                         precision++;
475                         case 'x':
476                                 hex = "0123456789abcdef";
477                         case 'u':
478                         case 'p':
479                         case 'X':
480                                 if (format_flag == 'p')
481 #if defined(__AVR__) || defined(__I196__) /* 16bit pointers */
482                                         ulong = (unsigned long)(unsigned short)va_arg(ap, char *);
483 #else /* 32bit pointers */
484                                 ulong = (unsigned long)va_arg(ap, char *);
485 #endif /* 32bit pointers */
486                                 else if (sizeof(short) == sizeof(int))
487                                         ulong = l_L_modifier ?
488                                                 va_arg(ap, unsigned long) : (unsigned long)va_arg(ap, unsigned int);
489                                 else
490                                         ulong = h_modifier ?
491                                                 (unsigned long)(unsigned short) va_arg(ap, int)
492                                                 : (unsigned long)va_arg(ap, int);
493                                 div_factor = (format_flag == 'o') ?
494                                         8 : (format_flag == 'u') ? 10 : 16;
495                                 plus_space_flag = 0;
496                                 goto INTEGRAL_CONVERSION;
497
498                         case 'd':
499                         case 'i':
500                                 if (sizeof(short) == sizeof(long))
501                                 {
502                                         if ( (long)(ulong = va_arg(ap, unsigned long)) < 0)
503                                         {
504                                                 plus_space_flag = '-';
505                                                 ulong = (unsigned long)(-((signed long)ulong));
506                                         }
507                                 }
508                                 else if (sizeof(short) == sizeof(int))
509                                 {
510                                         if ( (long)(ulong = l_L_modifier ?
511                                                                 va_arg(ap,unsigned long) : (unsigned long)va_arg(ap,int)) < 0)
512                                         {
513                                                 plus_space_flag = '-';
514                                                 ulong = (unsigned long)(-((signed long)ulong));
515                                         }
516                                 }
517                                 else
518                                 {
519                                         if ( (signed long)(ulong = (unsigned long) (h_modifier ?
520                                                                         (short) va_arg(ap, int) : va_arg(ap,int))) < 0)
521                                         {
522                                                 plus_space_flag = '-';
523                                                 ulong = (unsigned long)(-((signed long)ulong));
524                                         }
525                                 }
526                                 div_factor = 10;
527
528                                 /* Now convert to digits */
529 INTEGRAL_CONVERSION:
530                                 ptr = buf_pointer = &buf[FRMWRI_BUFSIZE - 1];
531                                 nonzero_value = (ulong != 0);
532
533                                 /* No char if zero and zero precision */
534                                 if (precision != 0 || nonzero_value)
535                                         do
536                                                 *--buf_pointer = hex[ulong % div_factor];
537                                         while (ulong /= div_factor);
538
539                                 /* "precision" takes precedence */
540                                 if (precision < 0)
541                                         if (zeropad)
542                                                 precision = field_width - (plus_space_flag != 0);
543                                 while (precision > (int)(ptr - buf_pointer))
544                                         *--buf_pointer = '0';
545
546                                 if (alternate_flag && nonzero_value)
547                                 {
548                                         if (format_flag == 'x' || format_flag == 'X')
549                                         {
550                                                 *--buf_pointer = format_flag;
551                                                 *--buf_pointer = '0';
552                                         }
553                                         else if ((format_flag == 'o') && (*buf_pointer != '0'))
554                                         {
555                                                 *--buf_pointer = '0';
556                                         }
557                                 }
558                                 break;
559
560 #ifndef CONFIG_PRINTF_NOFLOAT
561                         case 'g':
562                         case 'G':
563                                 n = 1;
564                                 format_flag -= 2;
565                                 if (! precision)
566                                 {
567                                         precision = 1;
568                                 }
569                                 goto FLOATING_CONVERSION;
570                         case 'f':
571                                 format_flag = 0;
572                         case 'e':
573                         case 'E':
574                                 n = 0;
575 FLOATING_CONVERSION:
576                                 if (precision < 0)
577                                 {
578                                         precision = 6;
579                                 }
580                                 if (sizeof(double) != sizeof(long double))
581                                 {
582                                         if ( (fvalue = l_L_modifier ?
583                                                                 va_arg(ap,long double) : va_arg(ap,double)) < 0)
584                                         {
585                                                 plus_space_flag = '-';
586                                                 fvalue = -fvalue;
587                                         }
588                                 }
589                                 else if ( (fvalue = va_arg(ap,long double)) < 0)
590                                 {
591                                         plus_space_flag = '-';
592                                         fvalue = -fvalue;
593                                 }
594                                 ptr = float_conversion (fvalue,
595                                                 (short)precision,
596                                                 buf_pointer += field_width,
597                                                 format_flag,
598                                                 (char)n,
599                                                 alternate_flag);
600                                 if (zeropad)
601                                 {
602                                         precision = field_width - (plus_space_flag != 0);
603                                         while (precision > ptr - buf_pointer)
604                                                 *--buf_pointer = '0';
605                                 }
606                                 break;
607
608 #else /* CONFIG_PRINTF_NOFLOAT */
609                         case 'g':
610                         case 'G':
611                         case 'f':
612                         case 'e':
613                         case 'E':
614                                 ptr = buf_pointer = bad_conversion;
615                                 while (*ptr)
616                                         ptr++;
617                                 break;
618 #endif /* CONFIG_PRINTF_NOFLOAT */
619
620                         case '\0': /* Really bad place to find NUL in */
621                                 format--;
622
623                         default:
624                                 /* Undefined conversion! */
625                                 ptr = buf_pointer = bad_conversion;
626                                 ptr += 3;
627                                 break;
628
629                 }
630
631                 /*
632                  * This part emittes the formatted string to "put_one_char".
633                  */
634
635                 /* If field_width == 0 then nothing should be written. */
636                 precision = ptr - buf_pointer;
637
638                 if ( precision > field_width)
639                 {
640                         n = 0;
641                 }
642                 else
643                 {
644                         n = field_width - precision - (plus_space_flag != 0);
645                 }
646
647                 /* emit any leading pad characters */
648                 if (!left_adjust)
649                         while (--n >= 0)
650                         {
651                                 put_one_char(' ', secret_pointer);
652                                 nr_of_chars++;
653                         }
654
655                 /* emit flag characters (if any) */
656                 if (plus_space_flag)
657                 {
658                         put_one_char(plus_space_flag, secret_pointer);
659                         nr_of_chars++;
660                 }
661
662                 /* emit the string itself */
663                 while (--precision >= 0)
664                 {
665                         put_one_char(*buf_pointer++, secret_pointer);
666                         nr_of_chars++;
667                 }
668
669                 /* emit trailing space characters */
670                 if (left_adjust)
671                         while (--n >= 0)
672                         {
673                                 put_one_char(' ', secret_pointer);
674                                 nr_of_chars++;
675                         }
676         }
677
678 #else /* CONFIG_PRINTF_REDUCED starts here */
679
680 #ifndef CONFIG_PRINTF_NOMODIFIERS
681         char l_modifier, h_modifier;
682         unsigned long u_val, div_val;
683 #else
684         unsigned int u_val, div_val;
685 #endif /* CONFIG_PRINTF_NOMODIFIERS */
686
687         char l_modifier, h_modifier;
688         char format_flag;
689         unsigned int nr_of_chars, base;
690         char outChar;
691         char *ptr;
692
693         nr_of_chars = 0;
694         for (;;)    /* Until full format string read */
695         {
696                 while ((format_flag = PGM_READ_CHAR(format++)) != '%')    /* Until '%' or '\0' */
697                 {
698                         if (!format_flag)
699                                 return (nr_of_chars);
700                         put_one_char (format_flag, secret_pointer);
701                         nr_of_chars++;
702                 }
703
704 #ifndef CONFIG_PRINTF_NOMODIFIERS
705                 /*=================================*/
706                 /* Optional 'l' or 'h' modifiers ? */
707                 /*=================================*/
708                 l_modifier = h_modifier = 0;
709                 switch (PGM_READ_CHAR(format))
710                 {
711                         case 'l':
712                                 l_modifier = 1;
713                                 format++;
714                                 break;
715
716                         case 'h':
717                                 h_modifier = 1;
718                                 format++;
719                                 break;
720                 }
721 #endif /* !CONFIG_PRINTF_NOMODIFIERS */
722
723                 switch (format_flag = PGM_READ_CHAR(format++))
724                 {
725                         case 'c':
726                                 format_flag = va_arg(ap, int);
727                         default:
728                                 put_one_char (format_flag, secret_pointer);
729                                 nr_of_chars++;
730                                 continue;
731
732                         case 's':
733                                 ptr = va_arg(ap, char *);
734                                 while (format_flag = *ptr++)
735                                 {
736                                         put_one_char (format_flag, secret_pointer);
737                                         nr_of_chars++;
738                                 }
739                                 continue;
740
741                         case 'o':
742                                 base = 8;
743                                 if (IS_SHORT)
744                                         div_val = 0x8000;
745                                 else
746                                         div_val = 0x40000000;
747                                 goto CONVERSION_LOOP;
748
749                         case 'd':
750                                 base = 10;
751                                 if (IS_SHORT)
752                                         div_val = 10000;
753                                 else
754                                         div_val = 1000000000;
755                                 goto CONVERSION_LOOP;
756
757                         case 'X':
758                         case 'x':
759                                 base = 16;
760                                 if (IS_SHORT)
761                                         div_val = 0x1000;
762                                 else
763                                         div_val = 0x10000000;
764
765 CONVERSION_LOOP:
766 #ifndef CONFIG_PRINTF_NOMODIFIERS
767                                 if (h_modifier)
768                                         u_val = (format_flag == 'd') ?
769                                                 (short)va_arg(ap, int) : (unsigned short)va_arg(ap, int);
770                                 else if (l_modifier)
771                                         u_val = va_arg(ap, long);
772                                 else
773                                         u_val = (format_flag == 'd') ?
774                                                 va_arg(ap,int) : va_arg(ap,unsigned int);
775 #else /* CONFIG_PRINTF_NOMODIFIERS */
776                                 u_val = va_arg(ap,int);
777 #endif /* CONFIG_PRINTF_NOMODIFIERS */
778                                 if (format_flag == 'd')
779                                 {
780                                         if (((int)u_val) < 0)
781                                         {
782                                                 u_val = - u_val;
783                                                 put_one_char ('-', secret_pointer);
784                                                 nr_of_chars++;
785                                         }
786                                 }
787                                 while (div_val > 1 && div_val > u_val)
788                                 {
789                                         div_val /= base;
790                                 }
791                                 do
792                                 {
793                                         outChar = (u_val / div_val) + '0';
794                                         if (outChar > '9')
795                                                 if (format_flag == 'x')
796                                                         outChar += 'a'-'9'-1;
797                                                 else
798                                                         outChar += 'A'-'9'-1;
799                                         put_one_char (outChar, secret_pointer);
800                                         nr_of_chars++;
801                                         u_val %= div_val;
802                                         div_val /= base;
803                                 }
804                                 while (div_val);
805
806                 } /* end switch(format_flag...) */
807         }
808 #endif /* CONFIG_PRINTF_REDUCED */
809 }
810
811 #endif /* CONFIG_PRINTF_DISABLED */