]> git.saurik.com Git - apple/icu.git/blob - icuSources/extra/ustdio/uprntf_p.c
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / extra / ustdio / uprntf_p.c
1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 1998-1999, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 *******************************************************************************
8 *
9 * File uprntf_p.c
10 *
11 * Modification History:
12 *
13 * Date Name Description
14 * 11/23/98 stephen Creation.
15 * 03/12/99 stephen Modified for new C API.
16 *******************************************************************************
17 */
18
19 #include "unicode/utypes.h"
20
21 #if !UCONFIG_NO_FORMATTING
22
23 #include "uprntf_p.h"
24 #include "ufmt_cmn.h"
25
26 /* flag characters for uprintf */
27 #define FLAG_MINUS 0x002D
28 #define FLAG_PLUS 0x002B
29 #define FLAG_SPACE 0x0020
30 #define FLAG_POUND 0x0023
31 #define FLAG_ZERO 0x0030
32 #define FLAG_PAREN 0x0028
33
34 #define ISFLAG(s) (s) == FLAG_MINUS || \
35 (s) == FLAG_PLUS || \
36 (s) == FLAG_SPACE || \
37 (s) == FLAG_POUND || \
38 (s) == FLAG_ZERO || \
39 (s) == FLAG_PAREN
40
41 /* special characters for uprintf */
42 #define SPEC_ASTERISK 0x002A
43 #define SPEC_DOLLARSIGN 0x0024
44 #define SPEC_PERIOD 0x002E
45 #define SPEC_PERCENT 0x0025
46
47 /* unicode digits */
48 #define DIGIT_ZERO 0x0030
49 #define DIGIT_ONE 0x0031
50 #define DIGIT_TWO 0x0032
51 #define DIGIT_THREE 0x0033
52 #define DIGIT_FOUR 0x0034
53 #define DIGIT_FIVE 0x0035
54 #define DIGIT_SIX 0x0036
55 #define DIGIT_SEVEN 0x0037
56 #define DIGIT_EIGHT 0x0038
57 #define DIGIT_NINE 0x0039
58
59 #define ISDIGIT(s) (s) == DIGIT_ZERO || \
60 (s) == DIGIT_ONE || \
61 (s) == DIGIT_TWO || \
62 (s) == DIGIT_THREE || \
63 (s) == DIGIT_FOUR || \
64 (s) == DIGIT_FIVE || \
65 (s) == DIGIT_SIX || \
66 (s) == DIGIT_SEVEN || \
67 (s) == DIGIT_EIGHT || \
68 (s) == DIGIT_NINE
69
70 /* u_printf modifiers */
71 #define MOD_H 0x0068
72 #define MOD_LOWERL 0x006C
73 #define MOD_L 0x004C
74
75 #define ISMOD(s) (s) == MOD_H || \
76 (s) == MOD_LOWERL || \
77 (s) == MOD_L
78
79 /* We parse the argument list in Unicode */
80 int32_t
81 u_printf_parse_spec (const UChar *fmt,
82 u_printf_spec *spec)
83 {
84 const UChar *s = fmt;
85 const UChar *backup;
86 u_printf_spec_info *info = &(spec->fInfo);
87
88 /* initialize spec to default values */
89 spec->fWidthPos = -1;
90 spec->fPrecisionPos = -1;
91 spec->fArgPos = -1;
92
93 info->fPrecision = -1;
94 info->fWidth = -1;
95 info->fSpec = 0x0000;
96 info->fPadChar = 0x0020;
97 info->fAlt = FALSE;
98 info->fSpace = FALSE;
99 info->fLeft = FALSE;
100 info->fShowSign = FALSE;
101 info->fZero = FALSE;
102 info->fIsLongDouble = FALSE;
103 info->fIsShort = FALSE;
104 info->fIsLong = FALSE;
105 info->fIsLongLong = FALSE;
106
107 /* skip over the initial '%' */
108 s++;
109
110 /* Check for positional argument */
111 if(ISDIGIT(*s)) {
112
113 /* Save the current position */
114 backup = s;
115
116 /* handle positional parameters */
117 if(ISDIGIT(*s)) {
118 spec->fArgPos = (int) (*s++ - DIGIT_ZERO);
119
120 while(ISDIGIT(*s)) {
121 spec->fArgPos *= 10;
122 spec->fArgPos += (int) (*s++ - DIGIT_ZERO);
123 }
124 }
125
126 /* if there is no '$', don't read anything */
127 if(*s != SPEC_DOLLARSIGN) {
128 spec->fArgPos = -1;
129 s = backup;
130 }
131 /* munge the '$' */
132 else
133 s++;
134 }
135
136 /* Get any format flags */
137 while(ISFLAG(*s)) {
138 switch(*s++) {
139
140 /* left justify */
141 case FLAG_MINUS:
142 info->fLeft = TRUE;
143 break;
144
145 /* always show sign */
146 case FLAG_PLUS:
147 info->fShowSign = TRUE;
148 break;
149
150 /* use space if no sign present */
151 case FLAG_SPACE:
152 info->fShowSign = TRUE;
153 info->fSpace = TRUE;
154 break;
155
156 /* use alternate form */
157 case FLAG_POUND:
158 info->fAlt = TRUE;
159 break;
160
161 /* pad with leading zeroes */
162 case FLAG_ZERO:
163 info->fZero = TRUE;
164 info->fPadChar = 0x0030;
165 break;
166
167 /* pad character specified */
168 case FLAG_PAREN:
169
170 /* first four characters are hex values for pad char */
171 info->fPadChar = (UChar)ufmt_digitvalue(*s++);
172 info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
173 info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
174 info->fPadChar = (UChar)((info->fPadChar * 16) + 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 info->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 info->fWidth = (int) (*s++ - DIGIT_ZERO);
218
219 while(ISDIGIT(*s)) {
220 info->fWidth *= 10;
221 info->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 info->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 info->fPrecision = (int) (*s++ - DIGIT_ZERO);
266
267 while(ISDIGIT(*s)) {
268 info->fPrecision *= 10;
269 info->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 info->fIsShort = TRUE;
281 break;
282
283 /* long or long long */
284 case MOD_LOWERL:
285 if(*s == MOD_LOWERL) {
286 info->fIsLongLong = TRUE;
287 /* skip over the next 'l' */
288 s++;
289 }
290 else
291 info->fIsLong = TRUE;
292 break;
293
294 /* long double */
295 case MOD_L:
296 info->fIsLongDouble = TRUE;
297 break;
298 }
299 }
300
301 /* finally, get the specifier letter */
302 info->fSpec = *s++;
303
304 /* return # of characters in this specifier */
305 return (int32_t)(s - fmt);
306 }
307
308 #endif /* #if !UCONFIG_NO_FORMATTING */