~ubuntu-branches/ubuntu/quantal/icu/quantal

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Yves Arrouye
  • Date: 2002-03-03 15:31:13 UTC
  • Revision ID: package-import@ubuntu.com-20020303153113-3ssceqlq45xbmbnc
Tags: upstream-2.0-2.1pre20020303
ImportĀ upstreamĀ versionĀ 2.0-2.1pre20020303

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
}