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

« back to all changes in this revision

Viewing changes to source/extra/ustdio/uscanf_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) 1998-2001, International Business Machines
5
 
*   Corporation and others.  All Rights Reserved.
6
 
*
7
 
*******************************************************************************
8
 
*
9
 
* File uscnnf_p.c
10
 
*
11
 
* Modification History:
12
 
*
13
 
*   Date        Name        Description
14
 
*   12/02/98    stephen        Creation.
15
 
*   03/13/99    stephen     Modified for new C API.
16
 
*******************************************************************************
17
 
*/
18
 
 
19
 
#include "uscanf_p.h"
20
 
#include "ufmt_cmn.h"
21
 
 
22
 
/* flag characters for u_scanf */
23
 
#define FLAG_ASTERISK 0x002A
24
 
#define FLAG_PAREN 0x0028
25
 
 
26
 
#define ISFLAG(s)    (s) == FLAG_ASTERISK || \
27
 
            (s) == FLAG_PAREN
28
 
 
29
 
/* special characters for u_scanf */
30
 
#define SPEC_DOLLARSIGN 0x0024
31
 
 
32
 
/* unicode digits */
33
 
#define DIGIT_ZERO 0x0030
34
 
#define DIGIT_ONE 0x0031
35
 
#define DIGIT_TWO 0x0032
36
 
#define DIGIT_THREE 0x0033
37
 
#define DIGIT_FOUR 0x0034
38
 
#define DIGIT_FIVE 0x0035
39
 
#define DIGIT_SIX 0x0036
40
 
#define DIGIT_SEVEN 0x0037
41
 
#define DIGIT_EIGHT 0x0038
42
 
#define DIGIT_NINE 0x0039
43
 
 
44
 
#define ISDIGIT(s)    (s) == DIGIT_ZERO || \
45
 
            (s) == DIGIT_ONE || \
46
 
            (s) == DIGIT_TWO || \
47
 
            (s) == DIGIT_THREE || \
48
 
            (s) == DIGIT_FOUR || \
49
 
            (s) == DIGIT_FIVE || \
50
 
            (s) == DIGIT_SIX || \
51
 
            (s) == DIGIT_SEVEN || \
52
 
            (s) == DIGIT_EIGHT || \
53
 
            (s) == DIGIT_NINE
54
 
 
55
 
/* u_scanf modifiers */
56
 
#define MOD_H 0x0068
57
 
#define MOD_LOWERL 0x006C
58
 
#define MOD_L 0x004C
59
 
 
60
 
#define ISMOD(s)    (s) == MOD_H || \
61
 
            (s) == MOD_LOWERL || \
62
 
            (s) == MOD_L
63
 
 
64
 
/* We parse the argument list in Unicode */
65
 
int32_t
66
 
u_scanf_parse_spec (const UChar     *fmt,
67
 
            u_scanf_spec    *spec)
68
 
{
69
 
  const UChar *s = fmt;
70
 
  const UChar *backup;
71
 
  u_scanf_spec_info *info = &(spec->fInfo);
72
 
 
73
 
  /* initialize spec to default values */  
74
 
  spec->fArgPos             = -1;
75
 
  spec->fSkipArg            = FALSE;
76
 
 
77
 
  info->fSpec         = 0x0000;
78
 
  info->fWidth        = -1;
79
 
  info->fPadChar      = 0x0020;
80
 
  info->fIsLongDouble = FALSE;
81
 
  info->fIsShort      = FALSE;
82
 
  info->fIsLong       = FALSE;
83
 
  info->fIsLongLong   = FALSE;
84
 
 
85
 
 
86
 
  /* skip over the initial '%' */
87
 
  s++;
88
 
 
89
 
  /* Check for positional argument */
90
 
  if(ISDIGIT(*s)) {
91
 
 
92
 
    /* Save the current position */
93
 
    backup = s;
94
 
    
95
 
    /* handle positional parameters */
96
 
    if(ISDIGIT(*s)) {
97
 
      spec->fArgPos = (int) (*s++ - DIGIT_ZERO);
98
 
      
99
 
      while(ISDIGIT(*s)) {
100
 
        spec->fArgPos *= 10;
101
 
        spec->fArgPos += (int) (*s++ - DIGIT_ZERO);
102
 
      }
103
 
    }
104
 
    
105
 
    /* if there is no '$', don't read anything */
106
 
    if(*s != SPEC_DOLLARSIGN) {
107
 
      spec->fArgPos = -1;
108
 
      s = backup;
109
 
    }
110
 
    /* munge the '$' */
111
 
    else
112
 
      s++;
113
 
  }
114
 
  
115
 
  /* Get any format flags */
116
 
  while(ISFLAG(*s)) {
117
 
    switch(*s++) {
118
 
      
119
 
      /* skip argument */
120
 
    case FLAG_ASTERISK:
121
 
      spec->fSkipArg = TRUE;
122
 
      break;
123
 
 
124
 
      /* pad character specified */
125
 
    case FLAG_PAREN:
126
 
 
127
 
      /* first four characters are hex values for pad char */
128
 
      info->fPadChar = (UChar)ufmt_digitvalue(*s++);
129
 
      info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
130
 
      info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
131
 
      info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++));
132
 
      
133
 
      /* final character is ignored */
134
 
      s++;
135
 
      
136
 
      break;
137
 
    }
138
 
  }
139
 
 
140
 
  /* Get the width */
141
 
  if(ISDIGIT(*s)){
142
 
    info->fWidth = (int) (*s++ - DIGIT_ZERO);
143
 
    
144
 
    while(ISDIGIT(*s)) {
145
 
      info->fWidth *= 10;
146
 
      info->fWidth += (int) (*s++ - DIGIT_ZERO);
147
 
    }
148
 
  }
149
 
  
150
 
  /* Get any modifiers */
151
 
  if(ISMOD(*s)) {
152
 
    switch(*s++) {
153
 
 
154
 
      /* short */
155
 
    case MOD_H:
156
 
      info->fIsShort = TRUE;
157
 
      break;
158
 
 
159
 
      /* long or long long */
160
 
    case MOD_LOWERL:
161
 
      if(*s == MOD_LOWERL) {
162
 
        info->fIsLongLong = TRUE;
163
 
        /* skip over the next 'l' */
164
 
        s++;
165
 
      }
166
 
      else
167
 
        info->fIsLong = TRUE;
168
 
      break;
169
 
      
170
 
      /* long double */
171
 
    case MOD_L:
172
 
      info->fIsLongDouble = TRUE;
173
 
      break;
174
 
    }
175
 
  }
176
 
 
177
 
  /* finally, get the specifier letter */
178
 
  info->fSpec = *s++;
179
 
 
180
 
  /* return # of characters in this specifier */
181
 
  return (s - fmt);
182
 
}