Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

uprntf_p.c

00001 /*
00002 *******************************************************************************
00003 *
00004 *   Copyright (C) 1998-1999, International Business Machines
00005 *   Corporation and others.  All Rights Reserved.
00006 *
00007 *******************************************************************************
00008 *
00009 * File uprntf_p.c
00010 *
00011 * Modification History:
00012 *
00013 *   Date        Name        Description
00014 *   11/23/98    stephen        Creation.
00015 *   03/12/99    stephen     Modified for new C API.
00016 *******************************************************************************
00017 */
00018 
00019 #include "uprntf_p.h"
00020 #include "ufmt_cmn.h"
00021 
00022 /* flag characters for uprintf */
00023 #define FLAG_MINUS 0x002D
00024 #define FLAG_PLUS 0x002B
00025 #define FLAG_SPACE 0x0020
00026 #define FLAG_POUND 0x0023
00027 #define FLAG_ZERO  0x0030
00028 #define FLAG_PAREN 0x0028
00029 
00030 #define ISFLAG(s)    (s) == FLAG_MINUS || \
00031             (s) == FLAG_PLUS || \
00032             (s) == FLAG_SPACE || \
00033             (s) == FLAG_POUND || \
00034             (s) == FLAG_ZERO || \
00035             (s) == FLAG_PAREN
00036 
00037 /* special characters for uprintf */
00038 #define SPEC_ASTERISK 0x002A
00039 #define SPEC_DOLLARSIGN 0x0024
00040 #define SPEC_PERIOD 0x002E
00041 #define SPEC_PERCENT 0x0025
00042 
00043 /* unicode digits */
00044 #define DIGIT_ZERO 0x0030
00045 #define DIGIT_ONE 0x0031
00046 #define DIGIT_TWO 0x0032
00047 #define DIGIT_THREE 0x0033
00048 #define DIGIT_FOUR 0x0034
00049 #define DIGIT_FIVE 0x0035
00050 #define DIGIT_SIX 0x0036
00051 #define DIGIT_SEVEN 0x0037
00052 #define DIGIT_EIGHT 0x0038
00053 #define DIGIT_NINE 0x0039
00054 
00055 #define ISDIGIT(s)    (s) == DIGIT_ZERO || \
00056             (s) == DIGIT_ONE || \
00057             (s) == DIGIT_TWO || \
00058             (s) == DIGIT_THREE || \
00059             (s) == DIGIT_FOUR || \
00060             (s) == DIGIT_FIVE || \
00061             (s) == DIGIT_SIX || \
00062             (s) == DIGIT_SEVEN || \
00063             (s) == DIGIT_EIGHT || \
00064             (s) == DIGIT_NINE
00065 
00066 /* u_printf modifiers */
00067 #define MOD_H 0x0068
00068 #define MOD_LOWERL 0x006C
00069 #define MOD_L 0x004C
00070 
00071 #define ISMOD(s)    (s) == MOD_H || \
00072             (s) == MOD_LOWERL || \
00073             (s) == MOD_L
00074 
00075 /* We parse the argument list in Unicode */
00076 int32_t
00077 u_printf_parse_spec (const UChar     *fmt,
00078              u_printf_spec    *spec)
00079 {
00080   const UChar *s = fmt;
00081   const UChar *backup;
00082   u_printf_spec_info *info = &(spec->fInfo);
00083 
00084   /* initialize spec to default values */  
00085   spec->fWidthPos     = -1;
00086   spec->fPrecisionPos = -1;
00087   spec->fArgPos       = -1;
00088 
00089   info->fPrecision    = -1;
00090   info->fWidth        = -1;
00091   info->fSpec         = 0x0000;
00092   info->fPadChar      = 0x0020;
00093   info->fAlt          = FALSE;
00094   info->fSpace        = FALSE;
00095   info->fLeft         = FALSE;
00096   info->fShowSign     = FALSE;
00097   info->fZero         = FALSE;
00098   info->fIsLongDouble = FALSE;
00099   info->fIsShort      = FALSE;
00100   info->fIsLong       = FALSE;
00101   info->fIsLongLong   = FALSE;
00102 
00103   /* skip over the initial '%' */
00104   s++;
00105 
00106   /* Check for positional argument */
00107   if(ISDIGIT(*s)) {
00108 
00109     /* Save the current position */
00110     backup = s;
00111     
00112     /* handle positional parameters */
00113     if(ISDIGIT(*s)) {
00114       spec->fArgPos = (int) (*s++ - DIGIT_ZERO);
00115       
00116       while(ISDIGIT(*s)) {
00117         spec->fArgPos *= 10;
00118         spec->fArgPos += (int) (*s++ - DIGIT_ZERO);
00119       }
00120     }
00121     
00122     /* if there is no '$', don't read anything */
00123     if(*s != SPEC_DOLLARSIGN) {
00124       spec->fArgPos = -1;
00125       s = backup;
00126     }
00127     /* munge the '$' */
00128     else
00129       s++;
00130   }
00131   
00132   /* Get any format flags */
00133   while(ISFLAG(*s)) {
00134     switch(*s++) {
00135       
00136       /* left justify */
00137     case FLAG_MINUS:
00138       info->fLeft = TRUE;
00139       break;
00140       
00141       /* always show sign */
00142     case FLAG_PLUS:
00143       info->fShowSign = TRUE;
00144       break;
00145 
00146       /* use space if no sign present */
00147     case FLAG_SPACE:
00148       info->fSpace = TRUE;
00149       break;
00150 
00151       /* use alternate form */
00152     case FLAG_POUND:
00153       info->fAlt = TRUE;
00154       break;
00155 
00156       /* pad with leading zeroes */
00157     case FLAG_ZERO:
00158       info->fZero = TRUE;
00159       info->fPadChar = 0x0030;
00160       break;
00161 
00162       /* pad character specified */
00163     case FLAG_PAREN:
00164 
00165       /* first four characters are hex values for pad char */
00166       info->fPadChar = (UChar)ufmt_digitvalue(*s++);
00167       info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
00168       info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
00169       info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
00170       
00171       /* final character is ignored */
00172       s++;
00173       
00174       break;
00175     }
00176   }
00177 
00178   /* Get the width */
00179 
00180   /* width is specified out of line */
00181   if(*s == SPEC_ASTERISK) {
00182 
00183     info->fWidth = -2;
00184 
00185     /* Skip the '*' */
00186     s++;
00187 
00188     /* Save the current position */
00189     backup = s;
00190     
00191     /* handle positional parameters */
00192     if(ISDIGIT(*s)) {
00193       spec->fWidthPos = (int) (*s++ - DIGIT_ZERO);
00194       
00195       while(ISDIGIT(*s)) {
00196         spec->fWidthPos *= 10;
00197         spec->fWidthPos += (int) (*s++ - DIGIT_ZERO);
00198       }
00199     }
00200 
00201     /* if there is no '$', don't read anything */
00202     if(*s != SPEC_DOLLARSIGN) {
00203       spec->fWidthPos = -1;
00204       s = backup;
00205     }
00206     /* munge the '$' */
00207     else
00208       s++;
00209   }
00210   /* read the width, if present */
00211   else if(ISDIGIT(*s)){
00212     info->fWidth = (int) (*s++ - DIGIT_ZERO);
00213     
00214     while(ISDIGIT(*s)) {
00215       info->fWidth *= 10;
00216       info->fWidth += (int) (*s++ - DIGIT_ZERO);
00217     }
00218   }
00219   
00220   /* Get the precision */
00221   
00222   if(*s == SPEC_PERIOD) {
00223     
00224     /* eat up the '.' */
00225     s++;
00226     
00227     /* precision is specified out of line */
00228     if(*s == SPEC_ASTERISK) {
00229 
00230       info->fPrecision = -2;
00231 
00232       /* Skip the '*' */
00233       s++;
00234 
00235       /* save the current position */
00236       backup = s;
00237       
00238       /* handle positional parameters */
00239       if(ISDIGIT(*s)) {
00240         spec->fPrecisionPos = (int) (*s++ - DIGIT_ZERO);
00241 
00242         while(ISDIGIT(*s)) {
00243           spec->fPrecisionPos *= 10;
00244           spec->fPrecisionPos += (int) (*s++ - DIGIT_ZERO);
00245         }
00246     
00247         /* if there is no '$', don't read anything */
00248         if(*s != SPEC_DOLLARSIGN) {
00249           spec->fPrecisionPos = -1;
00250           s = backup;
00251         }
00252         else {
00253           /* munge the '$' */
00254           s++; 
00255         }
00256       }
00257     }
00258     /* read the precision */
00259     else if(ISDIGIT(*s)){
00260       info->fPrecision = (int) (*s++ - DIGIT_ZERO);
00261       
00262       while(ISDIGIT(*s)) {
00263         info->fPrecision *= 10;
00264         info->fPrecision += (int) (*s++ - DIGIT_ZERO);
00265       }
00266     }
00267   }
00268 
00269   /* Get any modifiers */
00270   if(ISMOD(*s)) {
00271     switch(*s++) {
00272 
00273       /* short */
00274     case MOD_H:
00275       info->fIsShort = TRUE;
00276       break;
00277 
00278       /* long or long long */
00279     case MOD_LOWERL:
00280       if(*s == MOD_LOWERL) {
00281         info->fIsLongLong = TRUE;
00282         /* skip over the next 'l' */
00283         s++;
00284       }
00285       else
00286         info->fIsLong = TRUE;
00287       break;
00288       
00289       /* long double */
00290     case MOD_L:
00291       info->fIsLongDouble = TRUE;
00292       break;
00293     }
00294   }
00295 
00296   /* finally, get the specifier letter */
00297   info->fSpec = *s++;
00298 
00299   /* return # of characters in this specifier */
00300   return (s - fmt);
00301 }

Generated at Tue Dec 5 10:48:10 2000 for ICU by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000