home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / extra / ustdio / uprintf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-07  |  45.9 KB  |  1,738 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright International Business Machines Corporation, 1998           *
  6. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  7. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  8. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  9. *                                                                             *
  10. *******************************************************************************
  11. *
  12. * File uprintf.c
  13. *
  14. * Modification History:
  15. *
  16. *   Date        Name        Description
  17. *   11/19/98    stephen        Creation.
  18. *   03/12/99    stephen     Modified for new C API.
  19. *                           Added conversion from default codepage.
  20. *******************************************************************************
  21. */
  22.  
  23. #include "uprintf.h"
  24. #include "uprntf_p.h"
  25. #include "ustdio.h"
  26. #include "ufile.h"
  27. #include "ustring.h"
  28. #include "locbund.h"
  29. #include "umutex.h"
  30. #include "unum.h"
  31. #include "udat.h"
  32.  
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <math.h>
  36. #include <float.h>
  37. #include <limits.h>
  38. #include <wchar.h>
  39.  
  40.  
  41. u_printf_handler     g_u_printf_handlers     [256];
  42. u_printf_info       g_u_printf_infos     [256];
  43. bool_t            g_u_printf_inited    = FALSE;
  44.  
  45. /* buffer size for formatting */
  46. #define UFPRINTF_BUFFER_SIZE 1024
  47.  
  48. int32_t 
  49. u_fprintf(    UFILE        *f,
  50.         const char    *patternSpecification,
  51.         ... )
  52. {
  53.   va_list ap;
  54.   int32_t count;
  55.   
  56.   va_start(ap, patternSpecification);
  57.   count = u_vfprintf(f, patternSpecification, ap);
  58.   va_end(ap);
  59.   
  60.   return count;
  61. }
  62.  
  63. int32_t 
  64. u_fprintf_u(    UFILE        *f,
  65.         const UChar    *patternSpecification,
  66.         ... )
  67. {
  68.   va_list ap;
  69.   int32_t count;
  70.   
  71.   va_start(ap, patternSpecification);
  72.   count = u_vfprintf_u(f, patternSpecification, ap);
  73.   va_end(ap);
  74.   
  75.   return count;
  76. }
  77.  
  78. int32_t 
  79. u_vfprintf(    UFILE        *f,
  80.         const char    *patternSpecification,
  81.         va_list        ap)
  82. {
  83.   int32_t count;
  84.   UChar *pattern;
  85.   
  86.   /* convert from the default codepage to Unicode */
  87.   pattern = ufmt_defaultCPToUnicode(patternSpecification, 
  88.                     strlen(patternSpecification));
  89.   if(pattern == 0) {
  90.     return 0;
  91.   }
  92.   
  93.   /* do the work */
  94.   count = u_vfprintf_u(f, pattern, ap);
  95.  
  96.   /* clean up */
  97.   free(pattern);
  98.   
  99.   return count;
  100. }
  101.  
  102. int32_t
  103. u_printf_register_handler(UChar            spec, 
  104.               u_printf_info     info,
  105.               u_printf_handler     handler)
  106. {
  107.   /* lock the cache */
  108.   umtx_lock(0);
  109.  
  110.   /* add to our list of function pointers */
  111.   g_u_printf_infos[ (unsigned char) spec ]     = info;
  112.   g_u_printf_handlers[ (unsigned char) spec ]     = handler;
  113.  
  114.   /* unlock the cache */
  115.   umtx_unlock(0);
  116.   return 0;
  117. }
  118.  
  119. /* handle a '%' */
  120.  
  121. int32_t 
  122. u_printf_simple_percent_info(const u_printf_spec_info     *info,
  123.                  int32_t             *argtypes,
  124.                  int32_t             n)
  125. {
  126.   /* we don't need any arguments */
  127.   return 0;
  128. }
  129.  
  130. int32_t
  131. u_printf_simple_percent_handler(UFILE                 *stream,
  132.                 const u_printf_spec_info     *info,
  133.                 const ufmt_args            *args)
  134. {
  135.   /* put a single '%' on the stream */
  136.   u_fputc(0x0025, stream);
  137.   /* we wrote one character */
  138.   return 1;
  139. }
  140.  
  141. /* handle 's' */
  142.  
  143. int32_t 
  144. u_printf_string_info(const u_printf_spec_info     *info,
  145.              int32_t             *argtypes,
  146.              int32_t             n)
  147. {
  148.   /* handle error */
  149.   if(n < 1)
  150.     return 0;
  151.  
  152.   /* we need 1 argument of type string */
  153.   argtypes[0] = ufmt_string;
  154.   return 1;
  155. }
  156.  
  157. int32_t
  158. u_printf_string_handler(UFILE                 *stream,
  159.             const u_printf_spec_info     *info,
  160.             const ufmt_args            *args)
  161. {
  162.   UChar *s;
  163.   int32_t len, written, i;
  164.   const char *arg = (const char*)(args[0].ptrValue);
  165.  
  166.   /* convert from the default codepage to Unicode */
  167.   s = ufmt_defaultCPToUnicode(arg, strlen(arg));
  168.   if(s == 0) {
  169.     return 0;
  170.   }
  171.   len = u_strlen(s);
  172.   
  173.   /* width = minimum # of characters to write */
  174.   /* precision = maximum # of characters to write */
  175.  
  176.   /* precision takes precedence over width */
  177.   /* determine if the string should be truncated */
  178.   if(info->fPrecision != -1 && len > info->fPrecision) {
  179.     written = u_file_write(s, info->fPrecision, stream);
  180.   }
  181.   
  182.   /* determine if the string should be padded */
  183.   else if(info->fWidth != -1 && len < info->fWidth) {
  184.     /* left justify */
  185.     if(info->fLeft) {
  186.       written = u_file_write(s, len, stream);
  187.       for(i = 0; i < info->fWidth - len; ++i)
  188.     written += u_file_write(&info->fPadChar, 1, stream);
  189.     }
  190.     /* right justify */
  191.     else {
  192.       written = 0;
  193.       for(i = 0; i < info->fWidth - len; ++i)
  194.     written += u_file_write(&info->fPadChar, 1, stream);
  195.       written += u_file_write(s, len, stream);
  196.     }
  197.   }
  198.  
  199.   /* just write the string */
  200.   else 
  201.     written = u_file_write(s, len, stream);
  202.  
  203.   /* clean up */
  204.   free(s);
  205.   
  206.   return written;
  207. }
  208.  
  209. int32_t 
  210. u_printf_integer_info(const u_printf_spec_info     *info,
  211.               int32_t             *argtypes,
  212.               int32_t             n)
  213. {
  214.   /* handle error */
  215.   if(n < 1)
  216.     return 0;
  217.  
  218.   /* we need 1 argument of type int */
  219.   argtypes[0] = ufmt_int;
  220.   return 1;
  221. }
  222. /* HSYS */
  223. int32_t
  224. u_printf_integer_handler(UFILE                 *stream,
  225.              const u_printf_spec_info     *info,
  226.              const ufmt_args            *args)
  227. {
  228.   int32_t         written     = 0;
  229.   int32_t         len;
  230.   long            num         = (long) (args[0].intValue);
  231.   UNumberFormat        *format;
  232.   UChar            result        [UFPRINTF_BUFFER_SIZE];
  233.   int32_t        i, minDigits     = -1;
  234.   UErrorCode        status        = U_ZERO_ERROR;
  235.  
  236.  
  237.   /* mask off any necessary bits */
  238.   if(info->fIsShort)
  239.     num &= SHRT_MAX;
  240.   else if(! info->fIsLong || ! info->fIsLongLong)
  241.     num &= INT_MAX;
  242.  
  243.   /* get the formatter */
  244.   format = u_locbund_getNumberFormat(stream->fBundle);
  245.  
  246.   /* handle error */
  247.   if(format == 0)
  248.     return 0;
  249.  
  250.   /* set the appropriate flags on the formatter */
  251.  
  252.   /* set the minimum integer digits */
  253.   if(info->fPrecision != -1) {
  254.     /* clone the stream's bundle if it isn't owned */
  255.     if(! stream->fOwnBundle) {
  256.       stream->fBundle     = u_locbund_clone(stream->fBundle);
  257.       stream->fOwnBundle = TRUE;
  258.       format           = u_locbund_getNumberFormat(stream->fBundle);
  259.     }
  260.  
  261.     /* set the minimum # of digits */
  262.     minDigits = unum_getAttribute(format, UNUM_MIN_INTEGER_DIGITS);
  263.     unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, info->fPrecision);
  264.   }
  265.  
  266.   /* set whether to show the sign */
  267.   if(info->fShowSign) {
  268.     /* clone the stream's bundle if it isn't owned */
  269.     if(! stream->fOwnBundle) {
  270.       stream->fBundle     = u_locbund_clone(stream->fBundle);
  271.       stream->fOwnBundle = TRUE;
  272.       format           = u_locbund_getNumberFormat(stream->fBundle);
  273.     }
  274.  
  275.     /* set whether to show the sign*/
  276.     /* {sfb} TBD */
  277.   }
  278.  
  279.   /* format the number */
  280.   unum_format(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
  281.   len = u_strlen(result);
  282.   
  283.   /* pad and justify, if needed */
  284.   if(info->fWidth != -1 && len < info->fWidth) {
  285.     /* left justify */
  286.     if(info->fLeft) {
  287.       written = u_file_write(result, len, stream);
  288.       for(i = 0; i < info->fWidth - len; ++i)
  289.     written += u_file_write(&info->fPadChar, 1, stream);
  290.     }
  291.     /* right justify */
  292.     else {
  293.       written = 0;
  294.       for(i = 0; i < info->fWidth - len; ++i)
  295.     written += u_file_write(&info->fPadChar, 1, stream);
  296.       written += u_file_write(result, len, stream);
  297.     }
  298.   }
  299.   /* just write the formatted output */
  300.   else
  301.     written = u_file_write(result, len, stream);
  302.   
  303.   /* restore the number format */
  304.   if(minDigits != -1)
  305.     unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, minDigits);
  306.  
  307.   return written;
  308. }
  309.  
  310. int32_t 
  311. u_printf_hex_info(const u_printf_spec_info     *info,
  312.           int32_t             *argtypes,
  313.           int32_t             n)
  314. {
  315.   /* handle error */
  316.   if(n < 1)
  317.     return 0;
  318.  
  319.   /* we need 1 argument of type int */
  320.   argtypes[0] = ufmt_int;
  321.   return 1;
  322. }
  323.  
  324. int32_t
  325. u_printf_hex_handler(UFILE             *stream,
  326.              const u_printf_spec_info     *info,
  327.              const ufmt_args            *args)
  328. {
  329.   int32_t         written     = 0;
  330.   long            num         = (long) (args[0].intValue);
  331.   int32_t        i;
  332.   UChar            result         [UFPRINTF_BUFFER_SIZE];
  333.   int32_t         len        = UFPRINTF_BUFFER_SIZE;
  334.  
  335.  
  336.   /* mask off any necessary bits */
  337.   if(info->fIsShort)
  338.     num &= SHRT_MAX;
  339.   else if(! info->fIsLong || ! info->fIsLongLong)
  340.     num &= INT_MAX;
  341.  
  342.   /* format the number, preserving the minimum # of digits */
  343.   ufmt_ltou(result, &len, num, 16,
  344.         (bool_t)(info->fSpec == 0x0078),
  345.         (info->fPrecision == -1 && info->fZero) ? info->fWidth : info->fPrecision);
  346.   
  347.   /* convert to alt form, if desired */
  348.   if(num != 0 && info->fAlt && len < UFPRINTF_BUFFER_SIZE - 2) {
  349.     /* shift the formatted string right by 2 chars */
  350.     memmove(result + 2, result, len * sizeof(UChar));
  351.     result[0] = 0x0030;
  352.     result[1] = info->fSpec;
  353.     len += 2;
  354.   }
  355.  
  356.   /* pad and justify, if needed */
  357.   if(info->fWidth != -1 && len < info->fWidth) {
  358.     /* left justify */
  359.     if(info->fLeft) {
  360.       written = u_file_write(result, len, stream);
  361.       for(i = 0; i < info->fWidth - len; ++i)
  362.     written += u_file_write(&info->fPadChar, 1, stream);
  363.     }
  364.     /* right justify */
  365.     else {
  366.       written = 0;
  367.       for(i = 0; i < info->fWidth - len; ++i)
  368.     written += u_file_write(&info->fPadChar, 1, stream);
  369.       written += u_file_write(result, len, stream);
  370.     }
  371.   }
  372.   /* just write the formatted output */
  373.   else
  374.     written = u_file_write(result, len, stream);
  375.   
  376.   return written;
  377. }
  378.  
  379. int32_t 
  380. u_printf_octal_info(const u_printf_spec_info     *info,
  381.             int32_t             *argtypes,
  382.             int32_t             n)
  383. {
  384.   /* handle error */
  385.   if(n < 1)
  386.     return 0;
  387.  
  388.   /* we need 1 argument of type int */
  389.   argtypes[0] = ufmt_int;
  390.   return 1;
  391. }
  392.  
  393. int32_t
  394. u_printf_octal_handler(UFILE                 *stream,
  395.                const u_printf_spec_info     *info,
  396.                const ufmt_args            *args)
  397. {
  398.   int32_t         written     = 0;
  399.   long            num         = (long) (args[0].intValue);
  400.   int32_t        i;
  401.   UChar            result         [UFPRINTF_BUFFER_SIZE];
  402.   int32_t         len        = UFPRINTF_BUFFER_SIZE;
  403.  
  404.  
  405.   /* mask off any necessary bits */
  406.   if(info->fIsShort)
  407.     num &= SHRT_MAX;
  408.   else if(! info->fIsLong || ! info->fIsLongLong)
  409.     num &= INT_MAX;
  410.  
  411.   /* format the number, preserving the minimum # of digits */
  412.   ufmt_ltou(result, &len, num, 8,
  413.         FALSE, /* doesn't matter for octal */
  414.         info->fPrecision == -1 && info->fZero ? info->fWidth : info->fPrecision);
  415.  
  416.   /* convert to alt form, if desired */
  417.   if(info->fAlt && result[0] != 0x0030 && len < UFPRINTF_BUFFER_SIZE - 1) {
  418.     /* shift the formatted string right by 1 char */
  419.     memmove(result + 1, result, len * sizeof(UChar));
  420.     result[0] = 0x0030;
  421.     len += 1;
  422.   }
  423.  
  424.   /* pad and justify, if needed */
  425.   if(info->fWidth != -1 && len < info->fWidth) {
  426.     /* left justify */
  427.     if(info->fLeft) {
  428.       written = u_file_write(result, len, stream);
  429.       for(i = 0; i < info->fWidth - len; ++i)
  430.     written += u_file_write(&info->fPadChar, 1, stream);
  431.     }
  432.     /* right justify */
  433.     else {
  434.       written = 0;
  435.       for(i = 0; i < info->fWidth - len; ++i)
  436.     written += u_file_write(&info->fPadChar, 1, stream);
  437.       written += u_file_write(result, len, stream);
  438.     }
  439.   }
  440.   /* just write the formatted output */
  441.   else
  442.     written = u_file_write(result, len, stream);
  443.   
  444.   return written;
  445. }
  446.  
  447.  
  448. int32_t 
  449. u_printf_double_info(const u_printf_spec_info     *info,
  450.              int32_t             *argtypes,
  451.              int32_t             n)
  452. {
  453.   /* handle error */
  454.   if(n < 1)
  455.     return 0;
  456.  
  457.   /* we need 1 argument of type double */
  458.   argtypes[0] = ufmt_double;
  459.   return 1;
  460. }
  461.  
  462. int32_t
  463. u_printf_double_handler(UFILE                 *stream,
  464.             const u_printf_spec_info     *info,
  465.             const ufmt_args            *args)
  466. {
  467.   int32_t         written     = 0;
  468.   int32_t         len;
  469.   double        num         = (double) (args[0].doubleValue);
  470.   UNumberFormat        *format;
  471.   UChar            result        [UFPRINTF_BUFFER_SIZE];
  472.   int32_t        i, minDecimalDigits;
  473.   int32_t        maxDecimalDigits;
  474.   UErrorCode        status        = U_ZERO_ERROR;
  475.  
  476.   /* mask off any necessary bits */
  477.   /*  if(! info->fIsLongDouble)
  478.       num &= DBL_MAX;*/
  479.  
  480.   /* get the formatter */
  481.   format = u_locbund_getNumberFormat(stream->fBundle);
  482.  
  483.   /* handle error */
  484.   if(format == 0)
  485.     return 0;
  486.  
  487.   /* set the appropriate flags on the formatter */
  488.  
  489.   /* clone the stream's bundle if it isn't owned */
  490.   if(! stream->fOwnBundle) {
  491.     stream->fBundle     = u_locbund_clone(stream->fBundle);
  492.     stream->fOwnBundle     = TRUE;
  493.     format           = u_locbund_getNumberFormat(stream->fBundle);
  494.   }
  495.  
  496.   /* set the number of decimal digits */
  497.  
  498.   /* save the formatter's state */
  499.   minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
  500.   maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
  501.  
  502.   if(info->fPrecision != -1) {
  503.     /* set the # of decimal digits */
  504.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
  505.   }
  506.   else if(info->fPrecision == 0 && ! info->fAlt) {
  507.     /* no decimal point in this case */
  508.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
  509.   }
  510.   else if(info->fAlt) {
  511.     /* '#' means always show decimal point */
  512.     /* copy of printf behavior on Solaris - '#' shows 6 digits */
  513.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  514.   }
  515.   else {
  516.     /* # of decimal digits is 6 if precision not specified */
  517.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  518.   }
  519.  
  520.   /* set whether to show the sign */
  521.   if(info->fShowSign) {
  522.     /* set whether to show the sign*/
  523.     /* {sfb} TBD */
  524.   }
  525.  
  526.   /* format the number */
  527.   unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
  528.   len = u_strlen(result);
  529.  
  530.   /* pad and justify, if needed */
  531.   if(info->fWidth != -1 && len < info->fWidth) {
  532.     /* left justify */
  533.     if(info->fLeft) {
  534.       written = u_file_write(result, len, stream);
  535.       for(i = 0; i < info->fWidth - len; ++i)
  536.     written += u_file_write(&info->fPadChar, 1, stream);
  537.     }
  538.     /* right justify */
  539.     else {
  540.       written = 0;
  541.       for(i = 0; i < info->fWidth - len; ++i)
  542.     written += u_file_write(&info->fPadChar, 1, stream);
  543.       written += u_file_write(result, len, stream);
  544.     }
  545.   }
  546.   /* just write the formatted output */
  547.   else
  548.     written = u_file_write(result, len, stream);
  549.   
  550.   /* restore the number format */
  551.   unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
  552.   unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
  553.  
  554.   return written;
  555. }
  556.  
  557.  
  558. int32_t 
  559. u_printf_char_info(const u_printf_spec_info     *info,
  560.            int32_t             *argtypes,
  561.            int32_t             n)
  562. {
  563.   /* handle error */
  564.   if(n < 1)
  565.     return 0;
  566.  
  567.   /* we need 1 argument of type char */
  568.   argtypes[0] = ufmt_char;
  569.   return 1;
  570. }
  571.  
  572. int32_t
  573. u_printf_char_handler(UFILE                 *stream,
  574.               const u_printf_spec_info         *info,
  575.               const ufmt_args              *args)
  576. {
  577.   UChar *s;
  578.   int32_t len, written = 0, i;
  579.   unsigned char arg = (unsigned char)(args[0].intValue);
  580.  
  581.   /* convert from default codepage to Unicode */
  582.   s = ufmt_defaultCPToUnicode(&arg, 1);
  583.   if(s == 0) {
  584.     return 0;
  585.   }
  586.   len = u_strlen(s);
  587.   
  588.   /* width = minimum # of characters to write */
  589.   /* precision = maximum # of characters to write */
  590.  
  591.   /* precision takes precedence over width */
  592.   /* determine if the string should be truncated */
  593.   if(info->fPrecision != -1 && len > info->fPrecision) {
  594.     written = u_file_write(s, info->fPrecision, stream);
  595.   }
  596.   
  597.   /* determine if the string should be padded */
  598.   else if(info->fWidth != -1 && len < info->fWidth) {
  599.     /* left justify */
  600.     if(info->fLeft) {
  601.       written = u_file_write(s, len, stream);
  602.       for(i = 0; i < info->fWidth - len; ++i)
  603.     written += u_file_write(&info->fPadChar, 1, stream);
  604.     }
  605.     /* right justify */
  606.     else {
  607.       written = 0;
  608.       for(i = 0; i < info->fWidth - len; ++i)
  609.     written += u_file_write(&info->fPadChar, 1, stream);
  610.       written += u_file_write(s, len, stream);
  611.     }
  612.   }
  613.  
  614.   /* just write the string */
  615.   else 
  616.     written = u_file_write(s, len, stream);
  617.  
  618.   /* clean up */
  619.   free(s);
  620.  
  621.   return written;
  622. }
  623.  
  624.  
  625. int32_t 
  626. u_printf_pointer_info(const u_printf_spec_info     *info,
  627.               int32_t             *argtypes,
  628.               int32_t             n)
  629. {
  630.   /* handle error */
  631.   if(n < 1)
  632.     return 0;
  633.  
  634.   /* we need 1 argument of type void* */
  635.   argtypes[0] = ufmt_pointer;
  636.   return 1;
  637. }
  638.  
  639. int32_t
  640. u_printf_pointer_handler(UFILE                 *stream,
  641.              const u_printf_spec_info     *info,
  642.              const ufmt_args            *args)
  643. {
  644.   int32_t         written     = 0;
  645.   long            num         = (long) (args[0].intValue);
  646.   int32_t        i;
  647.   UChar            result         [UFPRINTF_BUFFER_SIZE];
  648.   int32_t         len        = UFPRINTF_BUFFER_SIZE;
  649.  
  650.  
  651.   /* format the pointer in hex */
  652.   ufmt_ltou(result, &len, num, 16, TRUE, info->fPrecision);
  653.  
  654.   /* pad and justify, if needed */
  655.   if(info->fWidth != -1 && len < info->fWidth) {
  656.     /* left justify */
  657.     if(info->fLeft) {
  658.       written = u_file_write(result, len, stream);
  659.       for(i = 0; i < info->fWidth - len; ++i)
  660.     written += u_file_write(&info->fPadChar, 1, stream);
  661.     }
  662.     /* right justify */
  663.     else {
  664.       written = 0;
  665.       for(i = 0; i < info->fWidth - len; ++i)
  666.     written += u_file_write(&info->fPadChar, 1, stream);
  667.       written += u_file_write(result, len, stream);
  668.     }
  669.   }
  670.   /* just write the formatted output */
  671.   else
  672.     written = u_file_write(result, len, stream);
  673.   
  674.   return written;
  675. }
  676.  
  677.  
  678. int32_t 
  679. u_printf_scientific_info(const u_printf_spec_info     *info,
  680.              int32_t             *argtypes,
  681.              int32_t             n)
  682. {
  683.   /* handle error */
  684.   if(n < 1)
  685.     return 0;
  686.   
  687.   /* we need 1 argument of type double */
  688.   argtypes[0] = ufmt_double;
  689.   return 1;
  690. }
  691.  
  692. int32_t
  693. u_printf_scientific_handler(UFILE             *stream,
  694.                 const u_printf_spec_info     *info,
  695.                 const ufmt_args            *args)
  696. {
  697.   int32_t         written     = 0;
  698.   int32_t         len;
  699.   double        num         = (double) (args[0].doubleValue);
  700.   UNumberFormat        *format;
  701.   UChar            result        [UFPRINTF_BUFFER_SIZE];
  702.   int32_t        i, minDecimalDigits;
  703.   int32_t        maxDecimalDigits;
  704.   UErrorCode        status        = U_ZERO_ERROR;
  705.   
  706.  
  707.   /* mask off any necessary bits */
  708.   /*  if(! info->fIsLongDouble)
  709.       num &= DBL_MAX;*/
  710.  
  711.   /* get the formatter */
  712.   format = u_locbund_getScientificFormat(stream->fBundle);
  713.  
  714.   /* handle error */
  715.   if(format == 0)
  716.     return 0;
  717.  
  718.   /* set the appropriate flags on the formatter */
  719.  
  720.   /* clone the stream's bundle if it isn't owned */
  721.   if(! stream->fOwnBundle) {
  722.     stream->fBundle     = u_locbund_clone(stream->fBundle);
  723.     stream->fOwnBundle     = TRUE;
  724.     format           = u_locbund_getScientificFormat(stream->fBundle);
  725.   }
  726.  
  727.   /* set the number of decimal digits */
  728.  
  729.   /* save the formatter's state */
  730.   minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
  731.   maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
  732.  
  733.   if(info->fPrecision != -1) {
  734.     /* set the # of decimal digits */
  735.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
  736.   }
  737.   else if(info->fPrecision == 0 && ! info->fAlt) {
  738.     /* no decimal point in this case */
  739.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
  740.   }
  741.   else if(info->fAlt) {
  742.     /* '#' means always show decimal point */
  743.     /* copy of printf behavior on Solaris - '#' shows 6 digits */
  744.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  745.   }
  746.   else {
  747.     /* # of decimal digits is 6 if precision not specified */
  748.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  749.   }
  750.  
  751.   /* set whether to show the sign */
  752.   if(info->fShowSign) {
  753.     /* set whether to show the sign*/
  754.     /* {sfb} TBD */
  755.   }
  756.  
  757.   /* format the number */
  758.   unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
  759.   len = u_strlen(result);
  760.  
  761.   /* pad and justify, if needed */
  762.   if(info->fWidth != -1 && len < info->fWidth) {
  763.     /* left justify */
  764.     if(info->fLeft) {
  765.       written = u_file_write(result, len, stream);
  766.       for(i = 0; i < info->fWidth - len; ++i)
  767.     written += u_file_write(&info->fPadChar, 1, stream);
  768.     }
  769.     /* right justify */
  770.     else {
  771.       written = 0;
  772.       for(i = 0; i < info->fWidth - len; ++i)
  773.     written += u_file_write(&info->fPadChar, 1, stream);
  774.       written += u_file_write(result, len, stream);
  775.     }
  776.   }
  777.   /* just write the formatted output */
  778.   else
  779.     written = u_file_write(result, len, stream);
  780.   
  781.   /* restore the number format */
  782.   unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
  783.   unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
  784.  
  785.   return written;
  786. }
  787.  
  788. int32_t 
  789. u_printf_date_info(const u_printf_spec_info     *info,
  790.            int32_t             *argtypes,
  791.            int32_t             n)
  792. {
  793.   /* handle error */
  794.   if(n < 1)
  795.     return 0;
  796.   
  797.   /* we need 1 argument of type Date */
  798.   argtypes[0] = ufmt_date;
  799.   return 1;
  800. }
  801.  
  802. int32_t
  803. u_printf_date_handler(UFILE             *stream,
  804.               const u_printf_spec_info     *info,
  805.               const ufmt_args         *args)
  806. {
  807.   int32_t         written     = 0;
  808.   int32_t         len;
  809.   UDate            num         = (UDate) (args[0].dateValue);
  810.   UDateFormat        *format;
  811.   UChar            result        [UFPRINTF_BUFFER_SIZE];
  812.   int32_t        i;
  813.   UErrorCode        status        = U_ZERO_ERROR;
  814.  
  815.  
  816.   /* get the formatter */
  817.   format = u_locbund_getDateFormat(stream->fBundle);
  818.   
  819.   /* handle error */
  820.   if(format == 0)
  821.     return 0;
  822.  
  823.   /* format the date */
  824.   udat_format(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
  825.   len = u_strlen(result);
  826.  
  827.   /* pad and justify, if needed */
  828.   if(info->fWidth != -1 && len < info->fWidth) {
  829.     /* left justify */
  830.     if(info->fLeft) {
  831.       written = u_file_write(result, len, stream);
  832.       for(i = 0; i < info->fWidth - len; ++i)
  833.     written += u_file_write(&info->fPadChar, 1, stream);
  834.     }
  835.     /* right justify */
  836.     else {
  837.       written = 0;
  838.       for(i = 0; i < info->fWidth - len; ++i)
  839.     written += u_file_write(&info->fPadChar, 1, stream);
  840.       written += u_file_write(result, len, stream);
  841.     }
  842.   }
  843.   /* just write the formatted output */
  844.   else
  845.     written = u_file_write(result, len, stream);
  846.   
  847.   return written;
  848. }
  849.  
  850. int32_t 
  851. u_printf_time_info(const u_printf_spec_info     *info,
  852.            int32_t             *argtypes,
  853.            int32_t             n)
  854. {
  855.   /* handle error */
  856.   if(n < 1)
  857.     return 0;
  858.   
  859.   /* we need 1 argument of type date */
  860.   argtypes[0] = ufmt_date;
  861.   return 1;
  862. }
  863.  
  864. int32_t
  865. u_printf_time_handler(UFILE             *stream,
  866.               const u_printf_spec_info     *info,
  867.               const ufmt_args         *args)
  868. {
  869.   int32_t         written     = 0;
  870.   int32_t         len;
  871.   UDate            num         = (UDate) (args[0].dateValue);
  872.   UDateFormat        *format;
  873.   UChar            result        [UFPRINTF_BUFFER_SIZE];
  874.   int32_t        i;
  875.   UErrorCode        status        = U_ZERO_ERROR;
  876.  
  877.  
  878.   /* get the formatter */
  879.   format = u_locbund_getTimeFormat(stream->fBundle);
  880.   
  881.   /* handle error */
  882.   if(format == 0)
  883.     return 0;
  884.  
  885.   /* format the time */
  886.   udat_format(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
  887.   len = u_strlen(result);
  888.  
  889.   /* pad and justify, if needed */
  890.   if(info->fWidth != -1 && len < info->fWidth) {
  891.     /* left justify */
  892.     if(info->fLeft) {
  893.       written = u_file_write(result, len, stream);
  894.       for(i = 0; i < info->fWidth - len; ++i)
  895.     written += u_file_write(&info->fPadChar, 1, stream);
  896.     }
  897.     /* right justify */
  898.     else {
  899.       written = 0;
  900.       for(i = 0; i < info->fWidth - len; ++i)
  901.     written += u_file_write(&info->fPadChar, 1, stream);
  902.       written += u_file_write(result, len, stream);
  903.     }
  904.   }
  905.   /* just write the formatted output */
  906.   else
  907.     written = u_file_write(result, len, stream);
  908.   
  909.   return written;
  910. }
  911.  
  912.  
  913. int32_t 
  914. u_printf_percent_info(const u_printf_spec_info     *info,
  915.               int32_t             *argtypes,
  916.               int32_t             n)
  917. {
  918.   /* handle error */
  919.   if(n < 1)
  920.     return 0;
  921.  
  922.   /* we need 1 argument of type double */
  923.   argtypes[0] = ufmt_double;
  924.   return 1;
  925. }
  926.  
  927. int32_t
  928. u_printf_percent_handler(UFILE                 *stream,
  929.              const u_printf_spec_info     *info,
  930.              const ufmt_args            *args)
  931. {
  932.   int32_t         written     = 0;
  933.   int32_t         len;
  934.   double        num         = (double) (args[0].doubleValue);
  935.   UNumberFormat        *format;
  936.   UChar            result        [UFPRINTF_BUFFER_SIZE];
  937.   int32_t        i, minDecimalDigits;
  938.   int32_t        maxDecimalDigits;
  939.   UErrorCode        status        = U_ZERO_ERROR;
  940.  
  941.  
  942.   /* mask off any necessary bits */
  943.   /*  if(! info->fIsLongDouble)
  944.       num &= DBL_MAX;*/
  945.  
  946.   /* get the formatter */
  947.   format = u_locbund_getPercentFormat(stream->fBundle);
  948.  
  949.   /* handle error */
  950.   if(format == 0)
  951.     return 0;
  952.  
  953.   /* set the appropriate flags on the formatter */
  954.  
  955.   /* clone the stream's bundle if it isn't owned */
  956.   if(! stream->fOwnBundle) {
  957.     stream->fBundle     = u_locbund_clone(stream->fBundle);
  958.     stream->fOwnBundle     = TRUE;
  959.     format           = u_locbund_getPercentFormat(stream->fBundle);
  960.   }
  961.  
  962.   /* set the number of decimal digits */
  963.  
  964.   /* save the formatter's state */
  965.   minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
  966.   maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
  967.  
  968.   if(info->fPrecision != -1) {
  969.     /* set the # of decimal digits */
  970.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
  971.   }
  972.   else if(info->fPrecision == 0 && ! info->fAlt) {
  973.     /* no decimal point in this case */
  974.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
  975.   }
  976.   else if(info->fAlt) {
  977.     /* '#' means always show decimal point */
  978.     /* copy of printf behavior on Solaris - '#' shows 6 digits */
  979.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  980.   }
  981.   else {
  982.     /* # of decimal digits is 6 if precision not specified */
  983.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  984.   }
  985.  
  986.   /* set whether to show the sign */
  987.   if(info->fShowSign) {
  988.     /* set whether to show the sign*/
  989.     /* {sfb} TBD */
  990.   }
  991.  
  992.   /* format the number */
  993.   unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
  994.   len = u_strlen(result);
  995.  
  996.   /* pad and justify, if needed */
  997.   if(info->fWidth != -1 && len < info->fWidth) {
  998.     /* left justify */
  999.     if(info->fLeft) {
  1000.       written = u_file_write(result, len, stream);
  1001.       for(i = 0; i < info->fWidth - len; ++i)
  1002.     written += u_file_write(&info->fPadChar, 1, stream);
  1003.     }
  1004.     /* right justify */
  1005.     else {
  1006.       written = 0;
  1007.       for(i = 0; i < info->fWidth - len; ++i)
  1008.     written += u_file_write(&info->fPadChar, 1, stream);
  1009.       written += u_file_write(result, len, stream);
  1010.     }
  1011.   }
  1012.   /* just write the formatted output */
  1013.   else
  1014.     written = u_file_write(result, len, stream);
  1015.   
  1016.   /* restore the number format */
  1017.   unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
  1018.   unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
  1019.  
  1020.   return written;
  1021. }
  1022.  
  1023.  
  1024. int32_t 
  1025. u_printf_currency_info(const u_printf_spec_info     *info,
  1026.                int32_t                 *argtypes,
  1027.                int32_t                 n)
  1028. {
  1029.   /* handle error */
  1030.   if(n < 1)
  1031.     return 0;
  1032.  
  1033.   /* we need 1 argument of type double */
  1034.   argtypes[0] = ufmt_double;
  1035.   return 1;
  1036. }
  1037.  
  1038. int32_t
  1039. u_printf_currency_handler(UFILE             *stream,
  1040.               const u_printf_spec_info     *info,
  1041.               const ufmt_args            *args)
  1042. {
  1043.   int32_t         written     = 0;
  1044.   int32_t         len;
  1045.   double        num         = (double) (args[0].doubleValue);
  1046.   UNumberFormat        *format;
  1047.   UChar            result        [UFPRINTF_BUFFER_SIZE];
  1048.   int32_t        i, minDecimalDigits;
  1049.   int32_t        maxDecimalDigits;
  1050.   UErrorCode        status        = U_ZERO_ERROR;
  1051.  
  1052.  
  1053.   /* mask off any necessary bits */
  1054.   /*  if(! info->fIsLongDouble)
  1055.       num &= DBL_MAX;*/
  1056.  
  1057.   /* get the formatter */
  1058.   format = u_locbund_getCurrencyFormat(stream->fBundle);
  1059.  
  1060.   /* handle error */
  1061.   if(format == 0)
  1062.     return 0;
  1063.  
  1064.   /* set the appropriate flags on the formatter */
  1065.  
  1066.   /* clone the stream's bundle if it isn't owned */
  1067.   if(! stream->fOwnBundle) {
  1068.     stream->fBundle     = u_locbund_clone(stream->fBundle);
  1069.     stream->fOwnBundle     = TRUE;
  1070.     format           = u_locbund_getCurrencyFormat(stream->fBundle);
  1071.   }
  1072.  
  1073.   /* set the number of decimal digits */
  1074.  
  1075.   /* save the formatter's state */
  1076.   minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
  1077.   maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
  1078.  
  1079.   if(info->fPrecision != -1) {
  1080.     /* set the # of decimal digits */
  1081.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
  1082.   }
  1083.   else if(info->fPrecision == 0 && ! info->fAlt) {
  1084.     /* no decimal point in this case */
  1085.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
  1086.   }
  1087.   else if(info->fAlt) {
  1088.     /* '#' means always show decimal point */
  1089.     /* copy of printf behavior on Solaris - '#' shows 6 digits */
  1090.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  1091.   }
  1092.   else {
  1093.     /* # of decimal digits is 6 if precision not specified */
  1094.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  1095.   }
  1096.  
  1097.   /* set whether to show the sign */
  1098.   if(info->fShowSign) {
  1099.     /* set whether to show the sign*/
  1100.     /* {sfb} TBD */
  1101.   }
  1102.  
  1103.   /* format the number */
  1104.   unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
  1105.   len = u_strlen(result);
  1106.  
  1107.   /* pad and justify, if needed */
  1108.   if(info->fWidth != -1 && len < info->fWidth) {
  1109.     /* left justify */
  1110.     if(info->fLeft) {
  1111.       written = u_file_write(result, len, stream);
  1112.       for(i = 0; i < info->fWidth - len; ++i)
  1113.     written += u_file_write(&info->fPadChar, 1, stream);
  1114.     }
  1115.     /* right justify */
  1116.     else {
  1117.       written = 0;
  1118.       for(i = 0; i < info->fWidth - len; ++i)
  1119.     written += u_file_write(&info->fPadChar, 1, stream);
  1120.       written += u_file_write(result, len, stream);
  1121.     }
  1122.   }
  1123.   /* just write the formatted output */
  1124.   else
  1125.     written = u_file_write(result, len, stream);
  1126.   
  1127.   /* restore the number format */
  1128.   unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
  1129.   unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
  1130.  
  1131.   return written;
  1132. }
  1133.  
  1134. int32_t 
  1135. u_printf_ustring_info(const u_printf_spec_info     *info,
  1136.               int32_t             *argtypes,
  1137.               int32_t             n)
  1138. {
  1139.   /* handle error */
  1140.   if(n < 1)
  1141.     return 0;
  1142.  
  1143.   /* we need 1 argument of type ustring */
  1144.   argtypes[0] = ufmt_ustring;
  1145.   return 1;
  1146. }
  1147.  
  1148. int32_t
  1149. u_printf_ustring_handler(UFILE                 *stream,
  1150.              const u_printf_spec_info     *info,
  1151.              const ufmt_args         *args)
  1152. {
  1153.   int32_t len, written, i;
  1154.   const UChar *arg = (const UChar*)(args[0].ptrValue);
  1155.  
  1156.   /* allocate enough space for the buffer */
  1157.   len = u_strlen(arg);
  1158.  
  1159.   /* width = minimum # of characters to write */
  1160.   /* precision = maximum # of characters to write */
  1161.  
  1162.   /* precision takes precedence over width */
  1163.   /* determine if the string should be truncated */
  1164.   if(info->fPrecision != -1 && len > info->fPrecision) {
  1165.     written = u_file_write(arg, info->fPrecision, stream);
  1166.   }
  1167.   
  1168.   /* determine if the string should be padded */
  1169.   else if(info->fWidth != -1 && len < info->fWidth) {
  1170.     /* left justify */
  1171.     if(info->fLeft) {
  1172.       written = u_file_write(arg, len, stream);
  1173.       for(i = 0; i < info->fWidth - len; ++i)
  1174.     written += u_file_write(&info->fPadChar, 1, stream);
  1175.     }
  1176.     /* right justify */
  1177.     else {
  1178.       written = 0;
  1179.       for(i = 0; i < info->fWidth - len; ++i)
  1180.     written += u_file_write(&info->fPadChar, 1, stream);
  1181.       written += u_file_write(arg, len, stream);
  1182.     }
  1183.   }
  1184.  
  1185.   /* just write the string */
  1186.   else 
  1187.     written = u_file_write(arg, len, stream);
  1188.  
  1189.   return written;
  1190. }
  1191.  
  1192.  
  1193.  
  1194. int32_t 
  1195. u_printf_uchar_info(const u_printf_spec_info     *info,
  1196.             int32_t             *argtypes,
  1197.             int32_t             n)
  1198. {
  1199.   /* handle error */
  1200.   if(n < 1)
  1201.     return 0;
  1202.  
  1203.   /* we need 1 argument of type uchar */
  1204.   argtypes[0] = ufmt_uchar;
  1205.   return 1;
  1206. }
  1207.  
  1208. int32_t
  1209. u_printf_uchar_handler(UFILE                 *stream,
  1210.                const u_printf_spec_info     *info,
  1211.                const ufmt_args            *args)
  1212. {
  1213.   int32_t written = 0, i;
  1214.   UChar arg = (UChar)(args[0].intValue);
  1215.   
  1216.  
  1217.   /* width = minimum # of characters to write */
  1218.   /* precision = maximum # of characters to write */
  1219.  
  1220.   /* precision takes precedence over width */
  1221.   /* determine if the char should be printed */
  1222.   if(info->fPrecision != -1 && info->fPrecision < 1) {
  1223.     /* write nothing */
  1224.     written = 0;
  1225.   }
  1226.   
  1227.   /* determine if the character should be padded */
  1228.   else if(info->fWidth != -1 && info->fWidth > 1) {
  1229.     /* left justify */
  1230.     if(info->fLeft) {
  1231.       written = u_file_write(&arg, 1, stream);
  1232.       for(i = 0; i < info->fWidth - 1; ++i)
  1233.     written += u_file_write(&info->fPadChar, 1, stream);
  1234.     }
  1235.     /* right justify */
  1236.     else {
  1237.       written = 0;
  1238.       for(i = 0; i < info->fWidth - 1; ++i)
  1239.     written += u_file_write(&info->fPadChar, 1, stream);
  1240.       written += u_file_write(&arg, 1, stream);
  1241.     }
  1242.   }
  1243.  
  1244.   /* just write the character */
  1245.   else 
  1246.     written = u_file_write(&arg, 1, stream);
  1247.  
  1248.   return written;
  1249. }
  1250.  
  1251. int32_t 
  1252. u_printf_scidbl_info(const u_printf_spec_info     *info,
  1253.              int32_t             *argtypes,
  1254.              int32_t             n)
  1255. {
  1256.   /* handle error */
  1257.   if(n < 1)
  1258.     return 0;
  1259.  
  1260.   /* we need 1 argument of type double */
  1261.   argtypes[0] = ufmt_double;
  1262.   return 1;
  1263. }
  1264.  
  1265. int32_t
  1266. u_printf_scidbl_handler(UFILE                 *stream,
  1267.             const u_printf_spec_info     *info,
  1268.             const ufmt_args            *args)
  1269. {
  1270.   double     num = (double)(args[0].doubleValue);
  1271.   bool_t     useE;
  1272.  
  1273.   /* a precision of 0 is taken as 1 */
  1274.   if(info->fPrecision == 0)
  1275.     ((u_printf_spec_info*)info)->fPrecision = 1;
  1276.  
  1277.   /* determine whether to use 'e' or 'f' */
  1278.   useE = (num < 0.0001 || (info->fPrecision != -1 && num > pow(10.0, info->fPrecision)));
  1279.   
  1280.   /* use 'e' */
  1281.   if(useE) {
  1282.     /* adjust the specifier */
  1283.     ((u_printf_spec_info*)info)->fSpec = 0x0065;
  1284.     /* call the scientific handler */
  1285.     return u_printf_scientific_handler(stream, info, args);
  1286.   }
  1287.   /* use 'f' */
  1288.   else {
  1289.     /* adjust the specifier */
  1290.     ((u_printf_spec_info*)info)->fSpec = 0x0066;
  1291.     /* call the double handler */
  1292.     return u_printf_double_handler(stream, info, args);
  1293.   }
  1294. }
  1295.  
  1296.  
  1297. int32_t 
  1298. u_printf_count_info(const u_printf_spec_info     *info,
  1299.             int32_t             *argtypes,
  1300.             int32_t             n)
  1301. {
  1302.   /* handle error */
  1303.   if(n < 1)
  1304.     return 0;
  1305.  
  1306.   /* we need 1 argument of type count */
  1307.   argtypes[0] = ufmt_count;
  1308.   return 1;
  1309. }
  1310.  
  1311. int32_t
  1312. u_printf_count_handler(UFILE                 *stream,
  1313.                const u_printf_spec_info     *info,
  1314.                const ufmt_args            *args)
  1315. {
  1316.   int *count = (int*)(args[0].ptrValue);
  1317.  
  1318.   /* in the special case of count, the u_printf_spec_info's width */
  1319.   /* will contain the # of chars written thus far */
  1320.   *count = info->fWidth;
  1321.  
  1322.   return 0;
  1323. }
  1324.  
  1325.  
  1326. int32_t 
  1327. u_printf_spellout_info(const u_printf_spec_info *info,
  1328.                int32_t             *argtypes,
  1329.                int32_t             n)
  1330. {
  1331.   /* handle error */
  1332.   if(n < 1)
  1333.     return 0;
  1334.  
  1335.   /* we need 1 argument of type double */
  1336.   argtypes[0] = ufmt_double;
  1337.   return 1;
  1338. }
  1339.  
  1340. int32_t
  1341. u_printf_spellout_handler(UFILE             *stream,
  1342.               const u_printf_spec_info     *info,
  1343.               const ufmt_args            *args)
  1344. {
  1345.   int32_t         written     = 0;
  1346.   int32_t         len;
  1347.   double        num         = (double) (args[0].doubleValue);
  1348.   UNumberFormat        *format;
  1349.   UChar            result        [UFPRINTF_BUFFER_SIZE];
  1350.   int32_t        i, minDecimalDigits;
  1351.   int32_t        maxDecimalDigits;
  1352.   UErrorCode        status        = U_ZERO_ERROR;
  1353.  
  1354.  
  1355.   /* mask off any necessary bits */
  1356.   /*  if(! info->fIsLongDouble)
  1357.       num &= DBL_MAX;*/
  1358.  
  1359.   /* get the formatter */
  1360.   format = u_locbund_getSpelloutFormat(stream->fBundle);
  1361.  
  1362.   /* handle error */
  1363.   if(format == 0)
  1364.     return 0;
  1365.  
  1366.   /* set the appropriate flags on the formatter */
  1367.  
  1368.   /* clone the stream's bundle if it isn't owned */
  1369.   if(! stream->fOwnBundle) {
  1370.     stream->fBundle     = u_locbund_clone(stream->fBundle);
  1371.     stream->fOwnBundle     = TRUE;
  1372.     format           = u_locbund_getSpelloutFormat(stream->fBundle);
  1373.   }
  1374.  
  1375.   /* set the number of decimal digits */
  1376.  
  1377.   /* save the formatter's state */
  1378.   minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
  1379.   maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
  1380.  
  1381.   if(info->fPrecision != -1) {
  1382.     /* set the # of decimal digits */
  1383.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
  1384.   }
  1385.   else if(info->fPrecision == 0 && ! info->fAlt) {
  1386.     /* no decimal point in this case */
  1387.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 0);
  1388.   }
  1389.   else if(info->fAlt) {
  1390.     /* '#' means always show decimal point */
  1391.     /* copy of printf behavior on Solaris - '#' shows 6 digits */
  1392.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  1393.   }
  1394.   else {
  1395.     /* # of decimal digits is 6 if precision not specified */
  1396.     unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
  1397.   }
  1398.  
  1399.   /* set whether to show the sign */
  1400.   if(info->fShowSign) {
  1401.     /* set whether to show the sign*/
  1402.     /* {sfb} TBD */
  1403.   }
  1404.  
  1405.   /* format the number */
  1406.   unum_formatDouble(format, num, result, UFPRINTF_BUFFER_SIZE, 0, &status);
  1407.   len = u_strlen(result);
  1408.  
  1409.   /* pad and justify, if needed */
  1410.   if(info->fWidth != -1 && len < info->fWidth) {
  1411.     /* left justify */
  1412.     if(info->fLeft) {
  1413.       written = u_file_write(result, len, stream);
  1414.       for(i = 0; i < info->fWidth - len; ++i)
  1415.     written += u_file_write(&info->fPadChar, 1, stream);
  1416.     }
  1417.     /* right justify */
  1418.     else {
  1419.       written = 0;
  1420.       for(i = 0; i < info->fWidth - len; ++i)
  1421.     written += u_file_write(&info->fPadChar, 1, stream);
  1422.       written += u_file_write(result, len, stream);
  1423.     }
  1424.   }
  1425.   /* just write the formatted output */
  1426.   else
  1427.     written = u_file_write(result, len, stream);
  1428.   
  1429.   /* restore the number format */
  1430.   unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
  1431.   unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
  1432.  
  1433.   return written;
  1434. }
  1435.  
  1436. void
  1437. u_printf_init()
  1438. {
  1439.   int32_t i;
  1440.   /*Mutex *lock;*/
  1441.  
  1442.   /* if we're already inited, do nothing */
  1443.   if(g_u_printf_inited)
  1444.     return;
  1445.  
  1446.   /* lock the cache */
  1447.   umtx_lock(0);
  1448.  
  1449.   /* if we're already inited, do nothing */
  1450.   if(g_u_printf_inited) {
  1451.     umtx_unlock(0);
  1452.     return;
  1453.   }
  1454.  
  1455.   /* initialize all handlers and infos to 0 */
  1456.   for(i = 0; i < 256; ++i) {
  1457.     g_u_printf_infos[i]         = 0;
  1458.     g_u_printf_handlers[i]     = 0;
  1459.   }
  1460.  
  1461.   /* register the handlers for standard specifiers */
  1462.   /* don't use u_printf_register_handler to avoid mutex creation */
  1463.  
  1464.   /* handle '%' */
  1465.   g_u_printf_infos[ 0x0025 ]     = u_printf_simple_percent_info;
  1466.   g_u_printf_handlers[ 0x0025 ] = u_printf_simple_percent_handler;
  1467.  
  1468.   /* handle 's' */
  1469.   g_u_printf_infos[ 0x0073 ]     = u_printf_string_info;
  1470.   g_u_printf_handlers[ 0x0073 ] = u_printf_string_handler;
  1471.  
  1472.   /* handle 'd' */
  1473.   g_u_printf_infos[ 0x0064 ]     = u_printf_integer_info;
  1474.   g_u_printf_handlers[ 0x0064 ] = u_printf_integer_handler;
  1475.  
  1476.   /* handle 'i' */
  1477.   g_u_printf_infos[ 0x0069 ]     = u_printf_integer_info;
  1478.   g_u_printf_handlers[ 0x0069 ] = u_printf_integer_handler;
  1479.  
  1480.   /* handle 'o' */
  1481.   g_u_printf_infos[ 0x006F ]     = u_printf_octal_info;
  1482.   g_u_printf_handlers[ 0x006F ] = u_printf_octal_handler;
  1483.  
  1484.   /* handle 'u' */
  1485.   g_u_printf_infos[ 0x0075 ]     = u_printf_integer_info;
  1486.   g_u_printf_handlers[ 0x0075 ] = u_printf_integer_handler;
  1487.  
  1488.   /* handle 'x' */
  1489.   g_u_printf_infos[ 0x0078 ]     = u_printf_hex_info;
  1490.   g_u_printf_handlers[ 0x0078 ] = u_printf_hex_handler;
  1491.  
  1492.   /* handle 'X' */
  1493.   g_u_printf_infos[ 0x0058 ]     = u_printf_hex_info;
  1494.   g_u_printf_handlers[ 0x0058 ] = u_printf_hex_handler;
  1495.  
  1496.   /* handle 'f' */
  1497.   g_u_printf_infos[ 0x0066 ]     = u_printf_double_info;
  1498.   g_u_printf_handlers[ 0x0066 ] = u_printf_double_handler;
  1499.  
  1500.   /* handle 'c' */
  1501.   g_u_printf_infos[ 0x0063 ]     = u_printf_char_info;
  1502.   g_u_printf_handlers[ 0x0063 ] = u_printf_char_handler;
  1503.  
  1504.   /* handle 'p' */
  1505.   g_u_printf_infos[ 0x0070 ]     = u_printf_pointer_info;
  1506.   g_u_printf_handlers[ 0x0070 ] = u_printf_pointer_handler;
  1507.  
  1508.   /* handle 'e' */
  1509.   g_u_printf_infos[ 0x0065 ]     = u_printf_scientific_info;
  1510.   g_u_printf_handlers[ 0x0065 ] = u_printf_scientific_handler;
  1511.  
  1512.   /* handle 'E' */
  1513.   g_u_printf_infos[ 0x0045 ]     = u_printf_scientific_info;
  1514.   g_u_printf_handlers[ 0x0045 ] = u_printf_scientific_handler;
  1515.  
  1516.   /* handle 'D' */
  1517.   g_u_printf_infos[ 0x0044 ]     = u_printf_date_info;
  1518.   g_u_printf_handlers[ 0x0044 ] = u_printf_date_handler;
  1519.  
  1520.   /* handle 'P' */
  1521.   g_u_printf_infos[ 0x0050 ]     = u_printf_percent_info;
  1522.   g_u_printf_handlers[ 0x0050 ] = u_printf_percent_handler;
  1523.  
  1524.   /* handle 'M' */
  1525.   g_u_printf_infos[ 0x004D ]     = u_printf_currency_info;
  1526.   g_u_printf_handlers[ 0x004D ] = u_printf_currency_handler;
  1527.  
  1528.   /* handle 'T' */
  1529.   g_u_printf_infos[ 0x0054 ]     = u_printf_time_info;
  1530.   g_u_printf_handlers[ 0x0054 ] = u_printf_time_handler;
  1531.  
  1532.   /* handle 'K' */
  1533.   g_u_printf_infos[ 0x004B ]     = u_printf_uchar_info;
  1534.   g_u_printf_handlers[ 0x004B ] = u_printf_uchar_handler;
  1535.  
  1536.   /* handle 'U' */
  1537.   g_u_printf_infos[ 0x0055 ]     = u_printf_ustring_info;
  1538.   g_u_printf_handlers[ 0x0055 ] = u_printf_ustring_handler;
  1539.  
  1540.   /* handle 'g' */
  1541.   g_u_printf_infos[ 0x0067 ]     = u_printf_scidbl_info;
  1542.   g_u_printf_handlers[ 0x0067 ] = u_printf_scidbl_handler;
  1543.  
  1544.   /* handle 'G' */
  1545.   g_u_printf_infos[ 0x0047 ]     = u_printf_scidbl_info;
  1546.   g_u_printf_handlers[ 0x0047 ] = u_printf_scidbl_handler;
  1547.  
  1548.   /* handle 'n' */
  1549.   g_u_printf_infos[ 0x006E ]     = u_printf_count_info;
  1550.   g_u_printf_handlers[ 0x006E ] = u_printf_count_handler;
  1551.  
  1552.   /* handle 'V' */
  1553.   g_u_printf_infos[ 0x0056 ]     = u_printf_spellout_info;
  1554.   g_u_printf_handlers[ 0x0056 ] = u_printf_spellout_handler;
  1555.  
  1556.  
  1557.   /* we're finished */
  1558.   g_u_printf_inited = TRUE;
  1559.  
  1560.   /* unlock the cache */
  1561.   umtx_unlock(0);
  1562. }
  1563.  
  1564.  
  1565. #define U_PRINTF_MAX_ARGS 32
  1566. #define UP_PERCENT 0x0025
  1567.  
  1568. int32_t 
  1569. u_vfprintf_u(    UFILE        *f,
  1570.         const UChar    *patternSpecification,
  1571.         va_list        ap)
  1572. {
  1573.   u_printf_spec         spec;
  1574.   const UChar         *alias;
  1575.   int32_t         count, written;
  1576.  
  1577.   int32_t         num_args_wanted;
  1578.   int32_t         ufmt_types     [U_PRINTF_MAX_ARGS];
  1579.   ufmt_args     args[U_PRINTF_MAX_ARGS];  
  1580.         
  1581.   u_printf_info        info;
  1582.   u_printf_handler    handler;
  1583.  
  1584.   int32_t         cur_arg;
  1585.  
  1586.  
  1587.   /* init our function tables */
  1588.   if(! g_u_printf_inited)
  1589.     u_printf_init();
  1590.  
  1591.   /* alias the pattern */
  1592.   alias = patternSpecification;
  1593.   
  1594.   /* haven't written anything yet */
  1595.   written = 0;
  1596.  
  1597.   /* iterate through the pattern */
  1598.   for(;;) {
  1599.  
  1600.     /* find the next '%' */
  1601.     count = 0;
  1602.     while(*alias != UP_PERCENT && *alias != 0x0000) {
  1603.       *alias++;
  1604.       ++count;
  1605.     }
  1606.  
  1607.     /* write any characters before the '%' */
  1608.     if(count > 0)
  1609.       written += u_file_write(alias - count, count, f);
  1610.  
  1611.     /* break if at end of string */
  1612.     if(*alias == 0x0000)
  1613.       break;
  1614.     
  1615.     /* parse the specifier */
  1616.     count = u_printf_parse_spec(alias, &spec);
  1617.  
  1618.     /* fill in the precision and width, if specified out of line */
  1619.  
  1620.     /* width specified out of line */
  1621.     if(spec.fInfo.fWidth == -2) {
  1622.       if(spec.fWidthPos != -1) {
  1623.     /* handle positional parameter */
  1624.       }
  1625.       else {
  1626.     /* read the width from the argument list */
  1627.     spec.fInfo.fWidth = va_arg(ap, int);
  1628.       }
  1629.     
  1630.       /* if it's negative, take the absolute value and set left alignment */
  1631.       if(spec.fInfo.fWidth < 0) {
  1632.     spec.fInfo.fWidth     *= -1;
  1633.     spec.fInfo.fLeft     = TRUE;
  1634.       }
  1635.     }
  1636.  
  1637.     /* precision specified out of line */
  1638.     if(spec.fInfo.fPrecision == -2) {
  1639.       if(spec.fPrecisionPos != -1) {
  1640.     /* handle positional parameter */
  1641.       }
  1642.       else {
  1643.     /* read the precision from the argument list */
  1644.     spec.fInfo.fPrecision = va_arg(ap, int);
  1645.       }
  1646.       
  1647.       /* if it's negative, set it to zero */
  1648.       if(spec.fInfo.fPrecision < 0)
  1649.     spec.fInfo.fPrecision = 0;
  1650.     }
  1651.     
  1652.     /* query the info function for argument information */
  1653.     info = g_u_printf_infos[ (unsigned char) spec.fInfo.fSpec ];
  1654.     if(info != 0) { 
  1655.       num_args_wanted = (*info)(&spec.fInfo, 
  1656.                 ufmt_types,
  1657.                 U_PRINTF_MAX_ARGS);
  1658.     }
  1659.     else
  1660.       num_args_wanted = 0;
  1661.  
  1662.     /* fill in the requested arguments */
  1663.     for(cur_arg = 0; 
  1664.     cur_arg < num_args_wanted && cur_arg < U_PRINTF_MAX_ARGS; 
  1665.     ++cur_arg) {
  1666.       
  1667.       switch(ufmt_types[cur_arg]) {
  1668.  
  1669.       case ufmt_count:
  1670.     args[cur_arg].intValue = va_arg(ap, int);
  1671.     /* set the spec's width to the # of chars written */
  1672.     spec.fInfo.fWidth = written;
  1673.     break;
  1674.  
  1675.       case ufmt_int:
  1676.     args[cur_arg].intValue = va_arg(ap, int);
  1677.     break;
  1678.     
  1679.       case ufmt_char:
  1680.     args[cur_arg].intValue = va_arg(ap, int);
  1681.     break;
  1682.     
  1683.       case ufmt_wchar:
  1684.     args[cur_arg].wcharValue = va_arg(ap, wchar_t);
  1685.     break;
  1686.     
  1687.       case ufmt_string:
  1688.     args[cur_arg].ptrValue = va_arg(ap, char*);
  1689.     break;
  1690.     
  1691.       case ufmt_wstring:
  1692.     args[cur_arg].ptrValue = va_arg(ap, wchar_t*);
  1693.     break;
  1694.     
  1695.       case ufmt_pointer:
  1696.     args[cur_arg].ptrValue = va_arg(ap, void*);
  1697.     break;
  1698.     
  1699.       case ufmt_float:
  1700.     args[cur_arg].floatValue = va_arg(ap, float);
  1701.     break;
  1702.     
  1703.       case ufmt_double:
  1704.     args[cur_arg].doubleValue = va_arg(ap, double);
  1705.     break;
  1706.  
  1707.       case ufmt_date:
  1708.     args[cur_arg].dateValue = va_arg(ap, UDate);
  1709.     break;
  1710.  
  1711.       case ufmt_ustring:
  1712.     args[cur_arg].ptrValue = va_arg(ap, UChar*);
  1713.     break;
  1714.  
  1715.       case ufmt_uchar:
  1716.     args[cur_arg].intValue = va_arg(ap, int);
  1717.     break;
  1718.       }
  1719.     }
  1720.     
  1721.     /* call the handler function */
  1722.     handler = g_u_printf_handlers[ (unsigned char) spec.fInfo.fSpec ];
  1723.     if(handler != 0) {
  1724.       written += (*handler)(f, &spec.fInfo, args);
  1725.     }
  1726.     /* just echo unknown tags */
  1727.     else
  1728.       written += u_file_write(alias, count, f);
  1729.     
  1730.     /* update the pointer in pattern and continue */
  1731.     alias += count;
  1732.   }
  1733.   
  1734.   /* return # of UChars written */
  1735.   return written;
  1736. }
  1737.  
  1738.