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