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