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