~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/extra/ustdio/sprntf_p.c

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

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