| /* |
| ******************************************************************************* |
| * |
| * Copyright (C) 1998-2001, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| * |
| ******************************************************************************* |
| * |
| * File uscnnf_p.c |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 12/02/98 stephen Creation. |
| * 03/13/99 stephen Modified for new C API. |
| ******************************************************************************* |
| */ |
| |
| #include "uscanf_p.h" |
| #include "ufmt_cmn.h" |
| |
| /* flag characters for u_scanf */ |
| #define FLAG_ASTERISK 0x002A |
| #define FLAG_PAREN 0x0028 |
| |
| #define ISFLAG(s) (s) == FLAG_ASTERISK || \ |
| (s) == FLAG_PAREN |
| |
| /* special characters for u_scanf */ |
| #define SPEC_DOLLARSIGN 0x0024 |
| |
| /* unicode digits */ |
| #define DIGIT_ZERO 0x0030 |
| #define DIGIT_ONE 0x0031 |
| #define DIGIT_TWO 0x0032 |
| #define DIGIT_THREE 0x0033 |
| #define DIGIT_FOUR 0x0034 |
| #define DIGIT_FIVE 0x0035 |
| #define DIGIT_SIX 0x0036 |
| #define DIGIT_SEVEN 0x0037 |
| #define DIGIT_EIGHT 0x0038 |
| #define DIGIT_NINE 0x0039 |
| |
| #define ISDIGIT(s) (s) == DIGIT_ZERO || \ |
| (s) == DIGIT_ONE || \ |
| (s) == DIGIT_TWO || \ |
| (s) == DIGIT_THREE || \ |
| (s) == DIGIT_FOUR || \ |
| (s) == DIGIT_FIVE || \ |
| (s) == DIGIT_SIX || \ |
| (s) == DIGIT_SEVEN || \ |
| (s) == DIGIT_EIGHT || \ |
| (s) == DIGIT_NINE |
| |
| /* u_scanf modifiers */ |
| #define MOD_H 0x0068 |
| #define MOD_LOWERL 0x006C |
| #define MOD_L 0x004C |
| |
| #define ISMOD(s) (s) == MOD_H || \ |
| (s) == MOD_LOWERL || \ |
| (s) == MOD_L |
| |
| /* We parse the argument list in Unicode */ |
| int32_t |
| u_scanf_parse_spec (const UChar *fmt, |
| u_scanf_spec *spec) |
| { |
| const UChar *s = fmt; |
| const UChar *backup; |
| u_scanf_spec_info *info = &(spec->fInfo); |
| |
| /* initialize spec to default values */ |
| spec->fArgPos = -1; |
| spec->fSkipArg = FALSE; |
| |
| info->fSpec = 0x0000; |
| info->fWidth = -1; |
| info->fPadChar = 0x0020; |
| info->fIsLongDouble = FALSE; |
| info->fIsShort = FALSE; |
| info->fIsLong = FALSE; |
| info->fIsLongLong = FALSE; |
| |
| |
| /* skip over the initial '%' */ |
| s++; |
| |
| /* Check for positional argument */ |
| if(ISDIGIT(*s)) { |
| |
| /* Save the current position */ |
| backup = s; |
| |
| /* handle positional parameters */ |
| if(ISDIGIT(*s)) { |
| spec->fArgPos = (int) (*s++ - DIGIT_ZERO); |
| |
| while(ISDIGIT(*s)) { |
| spec->fArgPos *= 10; |
| spec->fArgPos += (int) (*s++ - DIGIT_ZERO); |
| } |
| } |
| |
| /* if there is no '$', don't read anything */ |
| if(*s != SPEC_DOLLARSIGN) { |
| spec->fArgPos = -1; |
| s = backup; |
| } |
| /* munge the '$' */ |
| else |
| s++; |
| } |
| |
| /* Get any format flags */ |
| while(ISFLAG(*s)) { |
| switch(*s++) { |
| |
| /* skip argument */ |
| case FLAG_ASTERISK: |
| spec->fSkipArg = TRUE; |
| break; |
| |
| /* pad character specified */ |
| case FLAG_PAREN: |
| |
| /* first four characters are hex values for pad char */ |
| info->fPadChar = (UChar)ufmt_digitvalue(*s++); |
| info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++)); |
| info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++)); |
| info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*s++)); |
| |
| /* final character is ignored */ |
| s++; |
| |
| break; |
| } |
| } |
| |
| /* Get the width */ |
| if(ISDIGIT(*s)){ |
| info->fWidth = (int) (*s++ - DIGIT_ZERO); |
| |
| while(ISDIGIT(*s)) { |
| info->fWidth *= 10; |
| info->fWidth += (int) (*s++ - DIGIT_ZERO); |
| } |
| } |
| |
| /* Get any modifiers */ |
| if(ISMOD(*s)) { |
| switch(*s++) { |
| |
| /* short */ |
| case MOD_H: |
| info->fIsShort = TRUE; |
| break; |
| |
| /* long or long long */ |
| case MOD_LOWERL: |
| if(*s == MOD_LOWERL) { |
| info->fIsLongLong = TRUE; |
| /* skip over the next 'l' */ |
| s++; |
| } |
| else |
| info->fIsLong = TRUE; |
| break; |
| |
| /* long double */ |
| case MOD_L: |
| info->fIsLongDouble = TRUE; |
| break; |
| } |
| } |
| |
| /* finally, get the specifier letter */ |
| info->fSpec = *s++; |
| |
| /* return # of characters in this specifier */ |
| return (s - fmt); |
| } |