home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / extra / ustdio / uprntf_p.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-16  |  7.3 KB  |  307 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 uprntf_p.c
  13. *
  14. * Modification History:
  15. *
  16. *   Date        Name        Description
  17. *   11/23/98    stephen        Creation.
  18. *   03/12/99    stephen     Modified for new C API.
  19. *******************************************************************************
  20. */
  21.  
  22. #include "uprntf_p.h"
  23. #include "ufmt_cmn.h"
  24.  
  25. /* flag characters for uprintf */
  26. #define FLAG_MINUS 0x002D
  27. #define FLAG_PLUS 0x002B
  28. #define FLAG_SPACE 0x0020
  29. #define FLAG_POUND 0x0023
  30. #define FLAG_ZERO  0x0030
  31. #define FLAG_PAREN 0x0028
  32.  
  33. #define ISFLAG(s)    (s) == FLAG_MINUS || \
  34.             (s) == FLAG_PLUS || \
  35.             (s) == FLAG_SPACE || \
  36.             (s) == FLAG_POUND || \
  37.             (s) == FLAG_ZERO || \
  38.             (s) == FLAG_PAREN
  39.  
  40. /* special characters for uprintf */
  41. #define SPEC_ASTERISK 0x002A
  42. #define SPEC_DOLLARSIGN 0x0024
  43. #define SPEC_PERIOD 0x002E
  44. #define SPEC_PERCENT 0x0025
  45.  
  46. /* unicode digits */
  47. #define DIGIT_ZERO 0x0030
  48. #define DIGIT_ONE 0x0031
  49. #define DIGIT_TWO 0x0032
  50. #define DIGIT_THREE 0x0033
  51. #define DIGIT_FOUR 0x0034
  52. #define DIGIT_FIVE 0x0035
  53. #define DIGIT_SIX 0x0036
  54. #define DIGIT_SEVEN 0x0037
  55. #define DIGIT_EIGHT 0x0038
  56. #define DIGIT_NINE 0x0039
  57.  
  58. #define ISDIGIT(s)    (s) == DIGIT_ZERO || \
  59.             (s) == DIGIT_ONE || \
  60.             (s) == DIGIT_TWO || \
  61.             (s) == DIGIT_THREE || \
  62.             (s) == DIGIT_FOUR || \
  63.             (s) == DIGIT_FIVE || \
  64.             (s) == DIGIT_SIX || \
  65.             (s) == DIGIT_SEVEN || \
  66.             (s) == DIGIT_EIGHT || \
  67.             (s) == DIGIT_NINE
  68.  
  69. /* u_printf modifiers */
  70. #define MOD_H 0x0068
  71. #define MOD_LOWERL 0x006C
  72. #define MOD_L 0x004C
  73.  
  74. #define ISMOD(s)    (s) == MOD_H || \
  75.             (s) == MOD_LOWERL || \
  76.             (s) == MOD_L
  77.  
  78. /* We parse the argument list in Unicode */
  79. int32_t
  80. u_printf_parse_spec (const UChar     *fmt,
  81.              u_printf_spec    *spec)
  82. {
  83.   const UChar *s = fmt;
  84.   const UChar *backup;
  85.  
  86.   /* initialize spec to default values */  
  87.   spec->fWidthPos        = -1;
  88.   spec->fPrecisionPos        = -1;
  89.   spec->fArgPos            = -1;
  90.  
  91.   spec->fInfo.fPrecision    = -1;
  92.   spec->fInfo.fWidth         = -1;
  93.   spec->fInfo.fSpec         = 0x0000;
  94.   spec->fInfo.fPadChar         = 0x0020;
  95.   spec->fInfo.fAlt         = FALSE;
  96.   spec->fInfo.fSpace         = FALSE;
  97.   spec->fInfo.fLeft         = FALSE;
  98.   spec->fInfo.fShowSign     = FALSE;
  99.   spec->fInfo.fZero        = FALSE;
  100.   spec->fInfo.fIsLongDouble     = FALSE;
  101.   spec->fInfo.fIsShort         = FALSE;
  102.   spec->fInfo.fIsLong         = FALSE;
  103.   spec->fInfo.fIsLongLong    = FALSE;
  104.  
  105.   /* skip over the initial '%' */
  106.   *s++;
  107.  
  108.   /* Check for positional argument */
  109.   if(ISDIGIT(*s)) {
  110.  
  111.     /* Save the current position */
  112.     backup = s;
  113.     
  114.     /* handle positional parameters */
  115.     if(ISDIGIT(*s)) {
  116.       spec->fArgPos = (int) (*s++ - DIGIT_ZERO);
  117.       
  118.       while(ISDIGIT(*s)) {
  119.     spec->fArgPos *= 10;
  120.     spec->fArgPos += (int) (*s++ - DIGIT_ZERO);
  121.       }
  122.     }
  123.     
  124.     /* if there is no '$', don't read anything */
  125.     if(*s != SPEC_DOLLARSIGN) {
  126.       spec->fArgPos = -1;
  127.       s = backup;
  128.     }
  129.     /* munge the '$' */
  130.     else
  131.       *s++;
  132.   }
  133.   
  134.   /* Get any format flags */
  135.   while(ISFLAG(*s)) {
  136.     switch(*s++) {
  137.       
  138.       /* left justify */
  139.     case FLAG_MINUS:
  140.       spec->fInfo.fLeft = TRUE;
  141.       break;
  142.       
  143.       /* always show sign */
  144.     case FLAG_PLUS:
  145.       spec->fInfo.fShowSign = TRUE;
  146.       break;
  147.  
  148.       /* use space if no sign present */
  149.     case FLAG_SPACE:
  150.       spec->fInfo.fSpace = TRUE;
  151.       break;
  152.  
  153.       /* use alternate form */
  154.     case FLAG_POUND:
  155.       spec->fInfo.fAlt = TRUE;
  156.       break;
  157.  
  158.       /* pad with leading zeroes */
  159.     case FLAG_ZERO:
  160.       spec->fInfo.fZero = TRUE;
  161.       spec->fInfo.fPadChar = 0x0030;
  162.       break;
  163.  
  164.       /* pad character specified */
  165.     case FLAG_PAREN:
  166.  
  167.       /* first four characters are hex values for pad char */
  168.       spec->fInfo.fPadChar = ufmt_digitvalue(*s++);
  169.       spec->fInfo.fPadChar *= 16;
  170.       spec->fInfo.fPadChar += ufmt_digitvalue(*s++);
  171.       spec->fInfo.fPadChar *= 16;
  172.       spec->fInfo.fPadChar += ufmt_digitvalue(*s++);
  173.       spec->fInfo.fPadChar *= 16;
  174.       spec->fInfo.fPadChar += ufmt_digitvalue(*s++);
  175.       
  176.       /* final character is ignored */
  177.       *s++;
  178.       
  179.       break;
  180.     }
  181.   }
  182.  
  183.   /* Get the width */
  184.  
  185.   /* width is specified out of line */
  186.   if(*s == SPEC_ASTERISK) {
  187.  
  188.     spec->fInfo.fWidth = -2;
  189.  
  190.     /* Skip the '*' */
  191.     *s++;
  192.  
  193.     /* Save the current position */
  194.     backup = s;
  195.     
  196.     /* handle positional parameters */
  197.     if(ISDIGIT(*s)) {
  198.       spec->fWidthPos = (int) (*s++ - DIGIT_ZERO);
  199.       
  200.       while(ISDIGIT(*s)) {
  201.     spec->fWidthPos *= 10;
  202.     spec->fWidthPos += (int) (*s++ - DIGIT_ZERO);
  203.       }
  204.     }
  205.  
  206.     /* if there is no '$', don't read anything */
  207.     if(*s != SPEC_DOLLARSIGN) {
  208.       spec->fWidthPos = -1;
  209.       s = backup;
  210.     }
  211.     /* munge the '$' */
  212.     else
  213.       *s++;
  214.   }
  215.   /* read the width, if present */
  216.   else if(ISDIGIT(*s)){
  217.     spec->fInfo.fWidth = (int) (*s++ - DIGIT_ZERO);
  218.     
  219.     while(ISDIGIT(*s)) {
  220.       spec->fInfo.fWidth *= 10;
  221.       spec->fInfo.fWidth += (int) (*s++ - DIGIT_ZERO);
  222.     }
  223.   }
  224.   
  225.   /* Get the precision */
  226.   
  227.   if(*s == SPEC_PERIOD) {
  228.     
  229.     /* eat up the '.' */
  230.     *s++;
  231.     
  232.     /* precision is specified out of line */
  233.     if(*s == SPEC_ASTERISK) {
  234.  
  235.       spec->fInfo.fPrecision = -2;
  236.  
  237.       /* Skip the '*' */
  238.       *s++;
  239.  
  240.       /* save the current position */
  241.       backup = s;
  242.       
  243.       /* handle positional parameters */
  244.       if(ISDIGIT(*s)) {
  245.     spec->fPrecisionPos = (int) (*s++ - DIGIT_ZERO);
  246.  
  247.     while(ISDIGIT(*s)) {
  248.       spec->fPrecisionPos *= 10;
  249.       spec->fPrecisionPos += (int) (*s++ - DIGIT_ZERO);
  250.     }
  251.     
  252.     /* if there is no '$', don't read anything */
  253.     if(*s != SPEC_DOLLARSIGN) {
  254.       spec->fPrecisionPos = -1;
  255.       s = backup;
  256.     }
  257.     else {
  258.       /* munge the '$' */
  259.       *s++; 
  260.     }
  261.       }
  262.     }
  263.     /* read the precision */
  264.     else if(ISDIGIT(*s)){
  265.       spec->fInfo.fPrecision = (int) (*s++ - DIGIT_ZERO);
  266.       
  267.       while(ISDIGIT(*s)) {
  268.     spec->fInfo.fPrecision *= 10;
  269.     spec->fInfo.fPrecision += (int) (*s++ - DIGIT_ZERO);
  270.       }
  271.     }
  272.   }
  273.  
  274.   /* Get any modifiers */
  275.   if(ISMOD(*s)) {
  276.     switch(*s++) {
  277.  
  278.       /* short */
  279.     case MOD_H:
  280.       spec->fInfo.fIsShort = TRUE;
  281.       break;
  282.  
  283.       /* long or long long */
  284.     case MOD_LOWERL:
  285.       if(*s == MOD_LOWERL) {
  286.     spec->fInfo.fIsLongLong = TRUE;
  287.     /* skip over the next 'l' */
  288.     *s++;
  289.       }
  290.       else
  291.     spec->fInfo.fIsLong = TRUE;
  292.       break;
  293.       
  294.       /* long double */
  295.     case MOD_L:
  296.       spec->fInfo.fIsLongDouble = TRUE;
  297.       break;
  298.     }
  299.   }
  300.  
  301.   /* finally, get the specifier letter */
  302.   spec->fInfo.fSpec = *s++;
  303.  
  304.   /* return # of characters in this specifier */
  305.   return (s - fmt);
  306. }
  307.