Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

uscanf.c

00001 /*
00002 *******************************************************************************
00003 *
00004 *   Copyright (C) 1998-1999, International Business Machines
00005 *   Corporation and others.  All Rights Reserved.
00006 *
00007 *******************************************************************************
00008 *
00009 * File uscanf.c
00010 *
00011 * Modification History:
00012 *
00013 *   Date        Name        Description
00014 *   12/02/98    stephen        Creation.
00015 *   03/13/99    stephen     Modified for new C API.
00016 *******************************************************************************
00017 */
00018 
00019 #include "unicode/utypes.h"
00020 #include "unicode/uchar.h"
00021 
00022 #include "uscanf.h"
00023 #include "uscanf_p.h"
00024 #include "uscanset.h"
00025 #include "unicode/ustdio.h"
00026 #include "ufile.h"
00027 #include "unicode/ustring.h"
00028 #include "locbund.h"
00029 #include "umutex.h"
00030 #include "unicode/unum.h"
00031 #include "unicode/udat.h"
00032 
00033 #include <string.h>
00034 #include <stdlib.h>
00035 #include <float.h>
00036 #include <limits.h>
00037 
00038 static u_scanf_handler g_u_scanf_handlers     [256];
00039 static u_scanf_info       g_u_scanf_infos     [256];
00040 static UBool        g_u_scanf_inited    = FALSE;
00041 
00042 int32_t 
00043 u_fscanf(    UFILE        *f,
00044         const char    *patternSpecification,
00045         ... )
00046 {
00047   va_list ap;
00048   int32_t converted;
00049   
00050   va_start(ap, patternSpecification);
00051   converted = u_vfscanf(f, patternSpecification, ap);
00052   va_end(ap);
00053   
00054   return converted;
00055 }
00056 
00057 int32_t 
00058 u_fscanf_u(    UFILE        *f,
00059         const UChar    *patternSpecification,
00060         ... )
00061 {
00062   va_list ap;
00063   int32_t converted;
00064   
00065   va_start(ap, patternSpecification);
00066   converted = u_vfscanf_u(f, patternSpecification, ap);
00067   va_end(ap);
00068   
00069   return converted;
00070 }
00071 
00072 int32_t 
00073 u_vfscanf(    UFILE        *f,
00074         const char    *patternSpecification,
00075         va_list        ap)
00076 {
00077   int32_t converted;
00078   UChar *pattern;
00079   
00080   /* convert from the default codepage to Unicode */
00081   pattern = ufmt_defaultCPToUnicode(patternSpecification, 
00082                     strlen(patternSpecification));
00083   if(pattern == 0) {
00084     return 0;
00085   }
00086   
00087   /* do the work */
00088   converted = u_vfscanf_u(f, pattern, ap);
00089 
00090   /* clean up */
00091   free(pattern);
00092   
00093   return converted;
00094 }
00095 
00096 int32_t
00097 u_scanf_register_handler (UChar            spec, 
00098               u_scanf_info         info,
00099               u_scanf_handler     handler)
00100 {
00101   /* lock the cache */
00102   umtx_lock(0);
00103 
00104   /* add to our list of function pointers */
00105   g_u_scanf_infos[ (unsigned char) spec ]     = info;
00106   g_u_scanf_handlers[ (unsigned char) spec ]     = handler;
00107 
00108   /* unlock the cache */
00109   umtx_unlock(0);
00110   return 0;
00111 }
00112 
00113 int32_t
00114 u_scanf_skip_leading_ws(UFILE     *stream,
00115             UChar     pad)
00116 {
00117   UChar     c;
00118   int32_t    count = 0;
00119   
00120   /* skip all leading ws in the stream */
00121   while( ((c = u_fgetc(stream)) != 0xFFFF) && (c == pad || ufmt_isws(c)) )
00122     ++count;
00123   
00124   /* put the final character back on the stream */  
00125   if(c != 0xFFFF)
00126     u_fungetc(c, stream);
00127 
00128   return count;
00129 }
00130 
00131 int32_t 
00132 u_scanf_simple_percent_info(const u_scanf_spec_info    *info,
00133                 int32_t             *argtypes,
00134                 int32_t             n)
00135 {
00136   /* we don't need any arguments */
00137   return 0;
00138 }
00139 
00140 int32_t 
00141 u_scanf_simple_percent_handler(UFILE            *stream,
00142                    const u_scanf_spec_info     *info,
00143                    ufmt_args             *args,
00144                    const UChar        *fmt,
00145                    int32_t            *consumed)
00146 {
00147   /* make sure the next character in the stream is a percent */
00148   if(u_fgetc(stream) != 0x0025)
00149     return -1;
00150   else
00151     return 0;
00152 }
00153 
00154 int32_t 
00155 u_scanf_string_info(const u_scanf_spec_info     *info,
00156             int32_t             *argtypes,
00157             int32_t             n)
00158 {
00159   /* handle error */
00160   if(n < 1)
00161     return 0;
00162 
00163   /* we need 1 argument of type string */
00164   argtypes[0] = ufmt_string;
00165   return 1;
00166 }
00167 
00168 int32_t
00169 u_scanf_string_handler(UFILE             *stream,
00170                const u_scanf_spec_info     *info,
00171                ufmt_args             *args,
00172                const UChar        *fmt,
00173                int32_t            *consumed)
00174 {
00175   UChar     c;
00176   int32_t     count;
00177   const UChar     *source;
00178   UConverter     *conv;
00179   UErrorCode     status     = U_ZERO_ERROR;
00180   char         *arg     = (char*)(args[0].ptrValue);
00181   char         *alias     = arg;
00182   char         *limit;
00183 
00184   /* skip all ws in the stream */
00185   u_scanf_skip_leading_ws(stream, info->fPadChar);
00186   
00187   /* get the string one character at a time, truncating to the width */
00188   count = 0;
00189 
00190   /* open the default converter */
00191   conv = ucnv_open(ucnv_getDefaultName(), &status);
00192 
00193   if(U_FAILURE(status))
00194     return -1;
00195 
00196   /* since there is no real limit, just use a reasonable value */
00197   limit = alias + 2048;
00198 
00199   while( ((c = u_fgetc(stream)) != 0xFFFF) && 
00200      (c != info->fPadChar && ! ufmt_isws(c)) &&
00201      (info->fWidth == -1 || count < info->fWidth) ) {
00202     
00203     /* put the character from the stream onto the target */
00204     source = &c;
00205 
00206     /* convert the character to the default codepage */
00207     ucnv_fromUnicode(conv, &alias, limit, &source, source + 1,
00208              NULL, TRUE, &status);
00209     
00210     if(U_FAILURE(status))
00211       return -1;
00212     
00213     /* increment the count */
00214     ++count;
00215   }
00216 
00217   /* put the final character we read back on the stream */  
00218   if(c != 0xFFFF)
00219     u_fungetc(c, stream);
00220   
00221   /* add the terminator */
00222   *alias = 0x00;
00223 
00224   /* clean up */
00225   ucnv_close(conv);
00226 
00227   /* we converted 1 arg */
00228   return 1;
00229 }
00230 
00231 int32_t 
00232 u_scanf_ustring_info(const u_scanf_spec_info     *info,
00233              int32_t             *argtypes,
00234              int32_t             n)
00235 {
00236   /* handle error */
00237   if(n < 1)
00238     return 0;
00239 
00240   /* we need 1 argument of type ustring */
00241   argtypes[0] = ufmt_ustring;
00242   return 1;
00243 }
00244 
00245 int32_t
00246 u_scanf_ustring_handler(UFILE             *stream,
00247             const u_scanf_spec_info *info,
00248             ufmt_args        *args,
00249             const UChar        *fmt,
00250             int32_t            *consumed)
00251 {
00252   UChar     c;
00253   int32_t     count;
00254   UChar     *arg     = (UChar*)(args[0].ptrValue);
00255   UChar     *alias     = arg;
00256   
00257   /* skip all ws in the stream */
00258   u_scanf_skip_leading_ws(stream, info->fPadChar);
00259   
00260   /* get the string one character at a time, truncating to the width */
00261   count = 0;
00262 
00263   while( ((c = u_fgetc(stream)) != 0xFFFF) && 
00264      (c != info->fPadChar && ! ufmt_isws(c)) &&
00265      (info->fWidth == -1 || count < info->fWidth) ) {
00266     
00267     /* put the character from the stream onto the target */
00268     *alias++ = c;
00269     
00270     /* increment the count */
00271     ++count;
00272   }
00273 
00274   /* put the final character we read back on the stream */  
00275   if(c != 0xFFFF)
00276     u_fungetc(c, stream);
00277   
00278   /* add the terminator */
00279   *alias = 0x0000;
00280 
00281   /* we converted 1 arg */
00282   return 1;
00283 }
00284 
00285 
00286 int32_t 
00287 u_scanf_count_info(const u_scanf_spec_info     *info,
00288            int32_t             *argtypes,
00289            int32_t             n)
00290 {
00291   /* handle error */
00292   if(n < 1)
00293     return 0;
00294 
00295   /* we need 1 argument of type count */
00296   argtypes[0] = ufmt_count;
00297   return 1;
00298 }
00299 
00300 int32_t
00301 u_scanf_count_handler(UFILE             *stream,
00302               const u_scanf_spec_info     *info,
00303               ufmt_args        *args,
00304               const UChar        *fmt,
00305               int32_t            *consumed)
00306 {
00307   int *converted = (int*)(args[0].ptrValue);
00308   
00309   /* in the special case of count, the u_scanf_spec_info's width */
00310   /* will contain the # of items converted thus far */
00311   *converted = info->fWidth;
00312 
00313   /* we converted 0 args */
00314   return 0;
00315 }
00316 
00317 int32_t 
00318 u_scanf_integer_info(const u_scanf_spec_info     *info,
00319              int32_t             *argtypes,
00320              int32_t             n)
00321 {
00322   /* handle error */
00323   if(n < 1)
00324     return 0;
00325 
00326   /* we need 1 argument of type int */
00327   argtypes[0] = ufmt_int;
00328   return 1;
00329 }
00330 
00331 int32_t
00332 u_scanf_integer_handler(UFILE             *stream,
00333             const u_scanf_spec_info *info,
00334             ufmt_args        *args,
00335             const UChar        *fmt,
00336             int32_t            *consumed)
00337 {
00338   int32_t        len;
00339   long            *num         = (long*) (args[0].ptrValue);
00340   UNumberFormat        *format;
00341   int32_t        parsePos     = 0;
00342   UErrorCode         status         = U_ZERO_ERROR;
00343 
00344 
00345   /* skip all ws in the stream */
00346   u_scanf_skip_leading_ws(stream, info->fPadChar);
00347 
00348   /* fill the stream's internal buffer */
00349   ufile_fill_uchar_buffer(stream);
00350 
00351   /* determine the size of the stream's buffer */
00352   len = stream->fUCLimit - stream->fUCPos;
00353 
00354   /* truncate to the width, if specified */
00355   if(info->fWidth != -1)
00356     len = ufmt_min(len, info->fWidth);
00357 
00358   /* get the formatter */
00359   format = u_locbund_getNumberFormat(stream->fBundle);
00360   
00361   /* handle error */
00362   if(format == 0)
00363     return 0;
00364   
00365   /* parse the number */
00366   *num = unum_parse(format, stream->fUCPos, len, &parsePos, &status);
00367 
00368   /* mask off any necessary bits */
00369   if(info->fIsShort)
00370     *num &= SHRT_MAX;
00371   else if(! info->fIsLong || ! info->fIsLongLong)
00372     *num &= INT_MAX;
00373 
00374   /* update the stream's position to reflect consumed data */
00375   stream->fUCPos += parsePos;
00376   
00377   /* we converted 1 arg */
00378   return 1;
00379 }
00380 
00381 int32_t 
00382 u_scanf_double_info(const u_scanf_spec_info     *info,
00383             int32_t             *argtypes,
00384             int32_t             n)
00385 {
00386   /* handle error */
00387   if(n < 1)
00388     return 0;
00389 
00390   /* we need 1 argument of type double */
00391   argtypes[0] = ufmt_double;
00392   return 1;
00393 }
00394 
00395 int32_t
00396 u_scanf_double_handler(UFILE             *stream,
00397                const u_scanf_spec_info     *info,
00398                ufmt_args        *args,
00399                const UChar        *fmt,
00400                int32_t            *consumed)
00401 {
00402   int32_t        len;
00403   double        *num         = (double*) (args[0].ptrValue);
00404   UNumberFormat        *format;
00405   int32_t        parsePos     = 0;
00406   UErrorCode         status         = U_ZERO_ERROR;
00407 
00408 
00409   /* skip all ws in the stream */
00410   u_scanf_skip_leading_ws(stream, info->fPadChar);
00411 
00412   /* fill the stream's internal buffer */
00413   ufile_fill_uchar_buffer(stream);
00414 
00415   /* determine the size of the stream's buffer */
00416   len = stream->fUCLimit - stream->fUCPos;
00417 
00418   /* truncate to the width, if specified */
00419   if(info->fWidth != -1)
00420     len = ufmt_min(len, info->fWidth);
00421 
00422   /* get the formatter */
00423   format = u_locbund_getNumberFormat(stream->fBundle);
00424   
00425   /* handle error */
00426   if(format == 0)
00427     return 0;
00428   
00429   /* parse the number */
00430   *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
00431 
00432   /* mask off any necessary bits */
00433   /*  if(! info->fIsLong_double)
00434       num &= DBL_MAX;*/
00435 
00436   /* update the stream's position to reflect consumed data */
00437   stream->fUCPos += parsePos;
00438   
00439   /* we converted 1 arg */
00440   return 1;
00441 }
00442 
00443 int32_t 
00444 u_scanf_scientific_info(const u_scanf_spec_info     *info,
00445             int32_t             *argtypes,
00446             int32_t             n)
00447 {
00448   /* handle error */
00449   if(n < 1)
00450     return 0;
00451 
00452   /* we need 1 argument of type double */
00453   argtypes[0] = ufmt_double;
00454   return 1;
00455 }
00456 
00457 int32_t
00458 u_scanf_scientific_handler(UFILE             *stream,
00459                const u_scanf_spec_info     *info,
00460                ufmt_args           *args,
00461                const UChar            *fmt,
00462                int32_t            *consumed)
00463 {
00464   int32_t        len;
00465   double        *num         = (double*) (args[0].ptrValue);
00466   UNumberFormat        *format;
00467   int32_t        parsePos     = 0;
00468   UErrorCode         status         = U_ZERO_ERROR;
00469 
00470 
00471   /* skip all ws in the stream */
00472   u_scanf_skip_leading_ws(stream, info->fPadChar);
00473 
00474   /* fill the stream's internal buffer */
00475   ufile_fill_uchar_buffer(stream);
00476 
00477   /* determine the size of the stream's buffer */
00478   len = stream->fUCLimit - stream->fUCPos;
00479 
00480   /* truncate to the width, if specified */
00481   if(info->fWidth != -1)
00482     len = ufmt_min(len, info->fWidth);
00483 
00484   /* get the formatter */
00485   format = u_locbund_getScientificFormat(stream->fBundle);
00486   
00487   /* handle error */
00488   if(format == 0)
00489     return 0;
00490   
00491   /* parse the number */
00492   *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
00493 
00494   /* mask off any necessary bits */
00495   /*  if(! info->fIsLong_double)
00496       num &= DBL_MAX;*/
00497 
00498   /* update the stream's position to reflect consumed data */
00499   stream->fUCPos += parsePos;
00500   
00501   /* we converted 1 arg */
00502   return 1;
00503 }
00504 
00505 int32_t 
00506 u_scanf_scidbl_info(const u_scanf_spec_info     *info,
00507             int32_t             *argtypes,
00508             int32_t             n)
00509 {
00510   /* handle error */
00511   if(n < 1)
00512     return 0;
00513 
00514   /* we need 1 argument of type double */
00515   argtypes[0] = ufmt_double;
00516   return 1;
00517 }
00518 
00519 int32_t
00520 u_scanf_scidbl_handler(UFILE             *stream,
00521                const u_scanf_spec_info     *info,
00522                ufmt_args        *args,
00523                const UChar        *fmt,
00524                int32_t            *consumed)
00525 {
00526   int32_t        len;
00527   double        *num         = (double*) (args[0].ptrValue);
00528   UNumberFormat *scientificFormat, *genericFormat;
00529   /*int32_t       scientificResult, genericResult;*/
00530   double        scientificResult, genericResult;
00531   int32_t       scientificParsePos = 0, genericParsePos = 0;
00532   UErrorCode    scientificStatus = U_ZERO_ERROR;
00533   UErrorCode    genericStatus = U_ZERO_ERROR;
00534   UBool         useScientific;
00535 
00536 
00537   /* since we can't determine by scanning the characters whether */
00538   /* a number was formatted in the 'f' or 'g' styles, parse the */
00539   /* string with both formatters, and assume whichever one */
00540   /* parsed the most is the correct formatter to use */
00541 
00542 
00543   /* skip all ws in the stream */
00544   u_scanf_skip_leading_ws(stream, info->fPadChar);
00545 
00546   /* fill the stream's internal buffer */
00547   ufile_fill_uchar_buffer(stream);
00548 
00549   /* determine the size of the stream's buffer */
00550   len = stream->fUCLimit - stream->fUCPos;
00551 
00552   /* truncate to the width, if specified */
00553   if(info->fWidth != -1)
00554     len = ufmt_min(len, info->fWidth);
00555 
00556   /* get the formatters */
00557   scientificFormat = u_locbund_getScientificFormat(stream->fBundle);
00558   genericFormat = u_locbund_getNumberFormat(stream->fBundle);
00559   
00560   /* handle error */
00561   if(scientificFormat == 0 || genericFormat == 0)
00562     return 0;
00563   
00564   /* parse the number using each format*/
00565 
00566   scientificResult = unum_parseDouble(scientificFormat, stream->fUCPos, len,
00567                       &scientificParsePos, &scientificStatus);
00568 
00569   genericResult = unum_parseDouble(genericFormat, stream->fUCPos, len,
00570                    &genericParsePos, &genericStatus);
00571 
00572   /* determine which parse made it farther */
00573   useScientific = (UBool)(scientificParsePos > genericParsePos);
00574   
00575   /* stash the result in num */
00576   *num = useScientific ? scientificResult : genericResult;
00577   
00578   /* mask off any necessary bits */
00579   /*  if(! info->fIsLong_double)
00580       num &= DBL_MAX;*/
00581 
00582   /* update the stream's position to reflect consumed data */
00583   stream->fUCPos += useScientific ? scientificParsePos : genericParsePos;
00584   
00585   /* we converted 1 arg */
00586   return 1;
00587 }
00588 
00589 int32_t 
00590 u_scanf_currency_info(const u_scanf_spec_info     *info,
00591               int32_t             *argtypes,
00592               int32_t             n)
00593 {
00594   /* handle error */
00595   if(n < 1)
00596     return 0;
00597 
00598   /* we need 1 argument of type double */
00599   argtypes[0] = ufmt_double;
00600   return 1;
00601 }
00602 
00603 int32_t
00604 u_scanf_currency_handler(UFILE                 *stream,
00605              const u_scanf_spec_info     *info,
00606              ufmt_args            *args,
00607              const UChar            *fmt,
00608              int32_t            *consumed)
00609 {
00610   int32_t        len;
00611   double        *num         = (double*) (args[0].ptrValue);
00612   UNumberFormat        *format;
00613   int32_t        parsePos     = 0;
00614   UErrorCode         status         = U_ZERO_ERROR;
00615 
00616 
00617   /* skip all ws in the stream */
00618   u_scanf_skip_leading_ws(stream, info->fPadChar);
00619 
00620   /* fill the stream's internal buffer */
00621   ufile_fill_uchar_buffer(stream);
00622 
00623   /* determine the size of the stream's buffer */
00624   len = stream->fUCLimit - stream->fUCPos;
00625 
00626   /* truncate to the width, if specified */
00627   if(info->fWidth != -1)
00628     len = ufmt_min(len, info->fWidth);
00629 
00630   /* get the formatter */
00631   format = u_locbund_getCurrencyFormat(stream->fBundle);
00632   
00633   /* handle error */
00634   if(format == 0)
00635     return 0;
00636   
00637   /* parse the number */
00638   *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
00639   
00640   /* mask off any necessary bits */
00641   /*  if(! info->fIsLong_double)
00642       num &= DBL_MAX;*/
00643 
00644   /* update the stream's position to reflect consumed data */
00645   stream->fUCPos += parsePos;
00646   
00647   /* we converted 1 arg */
00648   return 1;
00649 }
00650 
00651 int32_t 
00652 u_scanf_percent_info(const u_scanf_spec_info     *info,
00653              int32_t             *argtypes,
00654              int32_t             n)
00655 {
00656   /* handle error */
00657   if(n < 1)
00658     return 0;
00659 
00660   /* we need 1 argument of type double */
00661   argtypes[0] = ufmt_double;
00662   return 1;
00663 }
00664 
00665 int32_t
00666 u_scanf_percent_handler(UFILE             *stream,
00667             const u_scanf_spec_info *info,
00668             ufmt_args        *args,
00669             const UChar        *fmt,
00670             int32_t            *consumed)
00671 {
00672   int32_t        len;
00673   double        *num         = (double*) (args[0].ptrValue);
00674   UNumberFormat        *format;
00675   int32_t        parsePos     = 0;
00676   UErrorCode         status         = U_ZERO_ERROR;
00677 
00678 
00679   /* skip all ws in the stream */
00680   u_scanf_skip_leading_ws(stream, info->fPadChar);
00681 
00682   /* fill the stream's internal buffer */
00683   ufile_fill_uchar_buffer(stream);
00684 
00685   /* determine the size of the stream's buffer */
00686   len = stream->fUCLimit - stream->fUCPos;
00687 
00688   /* truncate to the width, if specified */
00689   if(info->fWidth != -1)
00690     len = ufmt_min(len, info->fWidth);
00691 
00692   /* get the formatter */
00693   format = u_locbund_getPercentFormat(stream->fBundle);
00694   
00695   /* handle error */
00696   if(format == 0)
00697     return 0;
00698   
00699   /* parse the number */
00700   *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
00701 
00702   /* mask off any necessary bits */
00703   /*  if(! info->fIsLong_double)
00704       num &= DBL_MAX;*/
00705 
00706   /* update the stream's position to reflect consumed data */
00707   stream->fUCPos += parsePos;
00708   
00709   /* we converted 1 arg */
00710   return 1;
00711 }
00712 
00713 int32_t 
00714 u_scanf_date_info(const u_scanf_spec_info     *info,
00715           int32_t             *argtypes,
00716           int32_t             n)
00717 {
00718   /* handle error */
00719   if(n < 1)
00720     return 0;
00721 
00722   /* we need 1 argument of type Date */
00723   argtypes[0] = ufmt_date;
00724   return 1;
00725 }
00726 
00727 int32_t
00728 u_scanf_date_handler(UFILE             *stream,
00729              const u_scanf_spec_info     *info,
00730              ufmt_args        *args,
00731              const UChar        *fmt,
00732              int32_t            *consumed)
00733 {
00734   int32_t        len;
00735   UDate            *date         = (UDate*) (args[0].ptrValue);
00736   UDateFormat        *format;
00737   int32_t        parsePos     = 0;
00738   UErrorCode         status         = U_ZERO_ERROR;
00739 
00740 
00741   /* skip all ws in the stream */
00742   u_scanf_skip_leading_ws(stream, info->fPadChar);
00743 
00744   /* fill the stream's internal buffer */
00745   ufile_fill_uchar_buffer(stream);
00746 
00747   /* determine the size of the stream's buffer */
00748   len = stream->fUCLimit - stream->fUCPos;
00749 
00750   /* truncate to the width, if specified */
00751   if(info->fWidth != -1)
00752     len = ufmt_min(len, info->fWidth);
00753 
00754   /* get the formatter */
00755   format = u_locbund_getDateFormat(stream->fBundle);
00756   
00757   /* handle error */
00758   if(format == 0)
00759     return 0;
00760   
00761   /* parse the number */
00762   *date = udat_parse(format, stream->fUCPos, len, &parsePos, &status);
00763   
00764   /* update the stream's position to reflect consumed data */
00765   stream->fUCPos += parsePos;
00766   
00767   /* we converted 1 arg */
00768   return 1;
00769 }
00770 
00771 int32_t 
00772 u_scanf_time_info(const u_scanf_spec_info     *info,
00773           int32_t             *argtypes,
00774           int32_t             n)
00775 {
00776   /* handle error */
00777   if(n < 1)
00778     return 0;
00779 
00780   /* we need 1 argument of type Date */
00781   argtypes[0] = ufmt_date;
00782   return 1;
00783 }
00784 
00785 int32_t
00786 u_scanf_time_handler(UFILE             *stream,
00787              const u_scanf_spec_info     *info,
00788              ufmt_args        *args,
00789              const UChar        *fmt,
00790              int32_t            *consumed)
00791 {
00792   int32_t        len;
00793   UDate            *time         = (UDate*) (args[0].ptrValue);
00794   UDateFormat        *format;
00795   int32_t        parsePos     = 0;
00796   UErrorCode         status         = U_ZERO_ERROR;
00797 
00798 
00799   /* skip all ws in the stream */
00800   u_scanf_skip_leading_ws(stream, info->fPadChar);
00801 
00802   /* fill the stream's internal buffer */
00803   ufile_fill_uchar_buffer(stream);
00804 
00805   /* determine the size of the stream's buffer */
00806   len = stream->fUCLimit - stream->fUCPos;
00807 
00808   /* truncate to the width, if specified */
00809   if(info->fWidth != -1)
00810     len = ufmt_min(len, info->fWidth);
00811 
00812   /* get the formatter */
00813   format = u_locbund_getTimeFormat(stream->fBundle);
00814   
00815   /* handle error */
00816   if(format == 0)
00817     return 0;
00818   
00819   /* parse the number */
00820   *time = udat_parse(format, stream->fUCPos, len, &parsePos, &status);
00821   
00822   /* update the stream's position to reflect consumed data */
00823   stream->fUCPos += parsePos;
00824   
00825   /* we converted 1 arg */
00826   return 1;
00827 }
00828 
00829 int32_t 
00830 u_scanf_char_info(const u_scanf_spec_info     *info,
00831           int32_t             *argtypes,
00832           int32_t             n)
00833 {
00834   /* handle error */
00835   if(n < 1)
00836     return 0;
00837 
00838   /* we need 1 argument of type char */
00839   argtypes[0] = ufmt_char;
00840   return 1;
00841 }
00842 
00843 int32_t
00844 u_scanf_char_handler(UFILE             *stream,
00845              const u_scanf_spec_info     *info,
00846              ufmt_args        *args,
00847              const UChar        *fmt,
00848              int32_t            *consumed)
00849 {
00850   UChar uc = 0;
00851   char *result;
00852   char *c = (char*)(args[0].ptrValue);
00853   
00854   /* skip all ws in the stream */
00855   u_scanf_skip_leading_ws(stream, info->fPadChar);
00856   
00857   /* get the character from the stream, truncating to the width */
00858   if(info->fWidth == -1 || info->fWidth > 1)
00859     uc = u_fgetc(stream);
00860 
00861   /* handle EOF */
00862   if(uc == 0xFFFF)
00863     return -1;
00864 
00865   /* convert the character to the default codepage */
00866   result = ufmt_unicodeToDefaultCP(&uc, 1);
00867   *c = result[0];
00868 
00869   /* clean up */
00870   free(result);
00871   
00872   /* we converted 1 arg */
00873   return 1;
00874 }
00875 
00876 int32_t 
00877 u_scanf_uchar_info(const u_scanf_spec_info     *info,
00878            int32_t             *argtypes,
00879            int32_t             n)
00880 {
00881   /* handle error */
00882   if(n < 1)
00883     return 0;
00884 
00885   /* we need 1 argument of type uchar */
00886   argtypes[0] = ufmt_uchar;
00887   return 1;
00888 }
00889 
00890 int32_t
00891 u_scanf_uchar_handler(UFILE             *stream,
00892               const u_scanf_spec_info     *info,
00893               ufmt_args        *args,
00894               const UChar        *fmt,
00895               int32_t            *consumed)
00896 {
00897   UChar *c = (UChar*)(args[0].ptrValue);
00898   
00899   /* skip all ws in the stream */
00900   u_scanf_skip_leading_ws(stream, info->fPadChar);
00901   
00902   /* get the character from the stream, truncating to the width */
00903   if(info->fWidth == -1 || info->fWidth > 1)
00904     *c = u_fgetc(stream);
00905 
00906   /* handle EOF */
00907   if(*c == 0xFFFF)
00908     return -1;
00909 
00910   /* we converted 1 arg */
00911   return 1;
00912 }
00913 
00914 int32_t 
00915 u_scanf_spellout_info(const u_scanf_spec_info     *info,
00916               int32_t             *argtypes,
00917               int32_t             n)
00918 {
00919   /* handle error */
00920   if(n < 1)
00921     return 0;
00922 
00923   /* we need 1 argument of type double */
00924   argtypes[0] = ufmt_double;
00925   return 1;
00926 }
00927 
00928 int32_t
00929 u_scanf_spellout_handler(UFILE                 *stream,
00930              const u_scanf_spec_info     *info,
00931              ufmt_args             *args,
00932              const UChar            *fmt,
00933              int32_t            *consumed)
00934 {
00935   int32_t        len;
00936   double        *num         = (double*) (args[0].ptrValue);
00937   UNumberFormat        *format;
00938   int32_t        parsePos     = 0;
00939   UErrorCode         status         = U_ZERO_ERROR;
00940 
00941 
00942   /* skip all ws in the stream */
00943   u_scanf_skip_leading_ws(stream, info->fPadChar);
00944 
00945   /* fill the stream's internal buffer */
00946   ufile_fill_uchar_buffer(stream);
00947 
00948   /* determine the size of the stream's buffer */
00949   len = stream->fUCLimit - stream->fUCPos;
00950 
00951   /* truncate to the width, if specified */
00952   if(info->fWidth != -1)
00953     len = ufmt_min(len, info->fWidth);
00954 
00955   /* get the formatter */
00956   format = u_locbund_getSpelloutFormat(stream->fBundle);
00957   
00958   /* handle error */
00959   if(format == 0)
00960     return 0;
00961   
00962   /* parse the number */
00963   *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
00964 
00965   /* mask off any necessary bits */
00966   /*  if(! info->fIsLong_double)
00967       num &= DBL_MAX;*/
00968 
00969   /* update the stream's position to reflect consumed data */
00970   stream->fUCPos += parsePos;
00971   
00972   /* we converted 1 arg */
00973   return 1;
00974 }
00975 
00976 int32_t 
00977 u_scanf_hex_info(const u_scanf_spec_info     *info,
00978          int32_t             *argtypes,
00979          int32_t             n)
00980 {
00981   /* handle error */
00982   if(n < 1)
00983     return 0;
00984 
00985   /* we need 1 argument of type int */
00986   argtypes[0] = ufmt_int;
00987   return 1;
00988 }
00989 
00990 int32_t
00991 u_scanf_hex_handler(UFILE             *stream,
00992             const u_scanf_spec_info     *info,
00993             ufmt_args            *args,
00994             const UChar            *fmt,
00995             int32_t            *consumed)
00996 {
00997   int32_t        len;
00998   long            *num         = (long*) (args[0].ptrValue);
00999 
01000 
01001   /* skip all ws in the stream */
01002   u_scanf_skip_leading_ws(stream, info->fPadChar);
01003 
01004   /* fill the stream's internal buffer */
01005   ufile_fill_uchar_buffer(stream);
01006 
01007   /* determine the size of the stream's buffer */
01008   len = stream->fUCLimit - stream->fUCPos;
01009 
01010   /* truncate to the width, if specified */
01011   if(info->fWidth != -1)
01012     len = ufmt_min(len, info->fWidth);
01013 
01014   /* check for alternate form */
01015   if( *(stream->fUCPos) == 0x0030 && 
01016       (*(stream->fUCPos + 1) == 0x0078 || *(stream->fUCPos + 1) == 0x0058) ) {
01017 
01018     /* skip the '0' and 'x' or 'X' if present */
01019     stream->fUCPos += 2;
01020     len -= 2;
01021   }
01022 
01023   /* parse the number */
01024   *num = ufmt_utol(stream->fUCPos, &len, 16);
01025 
01026   /* update the stream's position to reflect consumed data */
01027   stream->fUCPos += len;
01028 
01029   /* mask off any necessary bits */
01030   if(info->fIsShort)
01031     *num &= SHRT_MAX;
01032   else if(! info->fIsLong || ! info->fIsLongLong)
01033     *num &= INT_MAX;
01034 
01035   /* we converted 1 arg */
01036   return 1;
01037 }
01038 
01039 int32_t 
01040 u_scanf_octal_info(const u_scanf_spec_info    *info,
01041            int32_t             *argtypes,
01042            int32_t             n)
01043 {
01044   /* handle error */
01045   if(n < 1)
01046     return 0;
01047   
01048   /* we need 1 argument of type int */
01049   argtypes[0] = ufmt_int;
01050   return 1;
01051 }
01052 
01053 int32_t
01054 u_scanf_octal_handler(UFILE             *stream,
01055               const u_scanf_spec_info     *info,
01056               ufmt_args         *args,
01057               const UChar        *fmt,
01058               int32_t            *consumed)
01059 {
01060   int32_t        len;
01061   long            *num         = (long*) (args[0].ptrValue);
01062 
01063 
01064   /* skip all ws in the stream */
01065   u_scanf_skip_leading_ws(stream, info->fPadChar);
01066 
01067   /* fill the stream's internal buffer */
01068   ufile_fill_uchar_buffer(stream);
01069 
01070   /* determine the size of the stream's buffer */
01071   len = stream->fUCLimit - stream->fUCPos;
01072 
01073   /* truncate to the width, if specified */
01074   if(info->fWidth != -1)
01075     len = ufmt_min(len, info->fWidth);
01076 
01077   /* parse the number */
01078   *num = ufmt_utol(stream->fUCPos, &len, 8);
01079 
01080   /* update the stream's position to reflect consumed data */
01081   stream->fUCPos += len;
01082 
01083   /* mask off any necessary bits */
01084   if(info->fIsShort)
01085     *num &= SHRT_MAX;
01086   else if(! info->fIsLong || ! info->fIsLongLong)
01087     *num &= INT_MAX;
01088 
01089   /* we converted 1 arg */
01090   return 1;
01091 }
01092 
01093 int32_t 
01094 u_scanf_pointer_info(const u_scanf_spec_info     *info,
01095              int32_t             *argtypes,
01096              int32_t             n)
01097 {
01098   /* handle error */
01099   if(n < 1)
01100     return 0;
01101 
01102   /* we need 1 argument of type void* */
01103   argtypes[0] = ufmt_pointer;
01104   return 1;
01105 }
01106 
01107 int32_t
01108 u_scanf_pointer_handler(UFILE             *stream,
01109             const u_scanf_spec_info *info,
01110             ufmt_args        *args,
01111             const UChar        *fmt,
01112             int32_t            *consumed)
01113 {
01114   int32_t    len;
01115   void        *p     = (void*)(args[0].ptrValue);
01116 
01117 
01118   /* skip all ws in the stream */
01119   u_scanf_skip_leading_ws(stream, info->fPadChar);
01120 
01121   /* fill the stream's internal buffer */
01122   ufile_fill_uchar_buffer(stream);
01123 
01124   /* determine the size of the stream's buffer */
01125   len = stream->fUCLimit - stream->fUCPos;
01126 
01127   /* truncate to the width, if specified */
01128   if(info->fWidth != -1)
01129     len = ufmt_min(len, info->fWidth);
01130 
01131   /* parse the pointer - cast to void** to assign to *p */
01132   *(void**)p = (void*) ufmt_utol(stream->fUCPos, &len, 16);
01133 
01134   /* update the stream's position to reflect consumed data */
01135   stream->fUCPos += len;
01136 
01137   /* we converted 1 arg */
01138   return 1;
01139 }
01140 
01141 int32_t 
01142 u_scanf_scanset_info(const u_scanf_spec_info     *info,
01143              int32_t             *argtypes,
01144              int32_t             n)
01145 {
01146   /* handle error */
01147   if(n < 1)
01148     return 0;
01149 
01150   /* we need 1 argument of type char* */
01151   argtypes[0] = ufmt_string;
01152   return 1;
01153 }
01154 
01155 int32_t
01156 u_scanf_scanset_handler(UFILE             *stream,
01157             const u_scanf_spec_info *info,
01158             ufmt_args        *args,
01159             const UChar        *fmt,
01160             int32_t            *consumed)
01161 {
01162   u_scanf_scanset    scanset;
01163   int32_t        len;
01164   UBool        success;
01165   UChar            c;
01166   const UChar         *source;
01167   UConverter         *conv;
01168   UErrorCode         status     = U_ZERO_ERROR;
01169   char            *s     = (char*) (args[0].ptrValue);
01170   char             *alias, *limit;
01171 
01172 
01173   /* fill the stream's internal buffer */
01174   ufile_fill_uchar_buffer(stream);
01175 
01176   /* determine the size of the stream's buffer */
01177   len = stream->fUCLimit - stream->fUCPos;
01178 
01179   /* truncate to the width, if specified */
01180   if(info->fWidth != -1)
01181     len = ufmt_min(len, info->fWidth);
01182 
01183   /* alias the target */
01184   alias = s;
01185   limit = alias + len;
01186 
01187   /* parse the scanset from the fmt string */
01188   *consumed = u_strlen(fmt);
01189   success = u_scanf_scanset_init(&scanset, fmt, consumed);
01190 
01191   /* increment consumed by one to eat the final ']' */
01192   ++(*consumed);
01193 
01194   /* open the default converter */
01195   conv = ucnv_open(ucnv_getDefaultName(), &status);
01196 
01197   /* verify that the parse was successful and the converter opened */
01198   if(! success || U_FAILURE(status))
01199     return -1;
01200 
01201   /* grab characters one at a time and make sure they are in the scanset */
01202   while( (c = u_fgetc(stream)) != 0xFFFF && alias < limit) {
01203     if(u_scanf_scanset_in(&scanset, c)) {
01204       source = &c;
01205       /* convert the character to the default codepage */
01206       ucnv_fromUnicode(conv, &alias, limit, &source, source + 1,
01207                NULL, TRUE, &status);
01208       
01209       if(U_FAILURE(status))
01210     return -1;
01211     }
01212     /* if the character's not in the scanset, break out */
01213     else {
01214       break;
01215     }
01216   }
01217 
01218   /* put the final character we read back on the stream */  
01219   if(c != 0xFFFF)
01220     u_fungetc(c, stream);
01221 
01222   /* if we didn't match at least 1 character, fail */
01223   if(alias == s)
01224     return -1;
01225   /* otherwise, add the terminator */
01226   else
01227     *alias = 0x00;
01228 
01229   /* clean up */
01230   ucnv_close(conv);
01231 
01232   /* we converted 1 arg */
01233   return 1;
01234 }
01235 
01236 void
01237 u_scanf_init(void)
01238 {
01239   int32_t i;
01240   /*Mutex *lock;*/
01241   
01242   /* if we're already inited, do nothing */
01243   if(g_u_scanf_inited)
01244     return;
01245 
01246   /* lock the cache */
01247   umtx_lock(0);
01248 
01249   /* if we're already inited, do nothing */
01250   if(g_u_scanf_inited) {
01251     umtx_unlock(0);
01252     return;
01253   }
01254 
01255   /* initialize all handlers and infos to 0 */
01256   for(i = 0; i < 256; ++i) {
01257     g_u_scanf_infos[i]         = 0;
01258     g_u_scanf_handlers[i]     = 0;
01259   }
01260 
01261   /* register the handlers for standard specifiers */
01262   /* don't use u_scanf_register_handler to avoid mutex creation */
01263 
01264   /* handle '%' */
01265   g_u_scanf_infos[ 0x0025 ]     = u_scanf_simple_percent_info;
01266   g_u_scanf_handlers[ 0x0025 ]     = u_scanf_simple_percent_handler;
01267 
01268   /* handle 's' */
01269   g_u_scanf_infos[ 0x0073 ]     = u_scanf_string_info;
01270   g_u_scanf_handlers[ 0x0073 ]     = u_scanf_string_handler;
01271 
01272   /* handle 'U' */
01273   g_u_scanf_infos[ 0x0055 ]     = u_scanf_ustring_info;
01274   g_u_scanf_handlers[ 0x0055 ]     = u_scanf_ustring_handler;
01275 
01276   /* handle 'n' */
01277   g_u_scanf_infos[ 0x006E ]     = u_scanf_count_info;
01278   g_u_scanf_handlers[ 0x006E ]     = u_scanf_count_handler;
01279 
01280   /* handle 'd' */
01281   g_u_scanf_infos[ 0x0064 ]     = u_scanf_integer_info;
01282   g_u_scanf_handlers[ 0x0064 ]     = u_scanf_integer_handler;
01283 
01284   /* handle 'i' */
01285   g_u_scanf_infos[ 0x0069 ]     = u_scanf_integer_info;
01286   g_u_scanf_handlers[ 0x0069 ]     = u_scanf_integer_handler;
01287 
01288   /* handle 'u' */
01289   g_u_scanf_infos[ 0x0075 ]     = u_scanf_integer_info;
01290   g_u_scanf_handlers[ 0x0075 ]     = u_scanf_integer_handler;
01291 
01292   /* handle 'f' */
01293   g_u_scanf_infos[ 0x0066 ]     = u_scanf_double_info;
01294   g_u_scanf_handlers[ 0x0066 ]     = u_scanf_double_handler;
01295 
01296   /* handle 'e' */
01297   g_u_scanf_infos[ 0x0065 ]     = u_scanf_scientific_info;
01298   g_u_scanf_handlers[ 0x0065 ]     = u_scanf_scientific_handler;
01299 
01300   /* handle 'E' */
01301   g_u_scanf_infos[ 0x0045 ]     = u_scanf_scientific_info;
01302   g_u_scanf_handlers[ 0x0045 ]     = u_scanf_scientific_handler;
01303 
01304   /* handle 'g' */
01305   g_u_scanf_infos[ 0x0067 ]     = u_scanf_scidbl_info;
01306   g_u_scanf_handlers[ 0x0067 ]     = u_scanf_scidbl_handler;
01307 
01308   /* handle 'G' */
01309   g_u_scanf_infos[ 0x0047 ]     = u_scanf_scidbl_info;
01310   g_u_scanf_handlers[ 0x0047 ]     = u_scanf_scidbl_handler;
01311 
01312   /* handle 'M' */
01313   g_u_scanf_infos[ 0x004D ]     = u_scanf_currency_info;
01314   g_u_scanf_handlers[ 0x004D ]     = u_scanf_currency_handler;
01315 
01316   /* handle 'P' */
01317   g_u_scanf_infos[ 0x0050 ]     = u_scanf_percent_info;
01318   g_u_scanf_handlers[ 0x0050 ]     = u_scanf_percent_handler;
01319 
01320   /* handle 'D' */
01321   g_u_scanf_infos[ 0x0044 ]     = u_scanf_date_info;
01322   g_u_scanf_handlers[ 0x0044 ]     = u_scanf_date_handler;
01323 
01324   /* handle 'T' */
01325   g_u_scanf_infos[ 0x0054 ]     = u_scanf_time_info;
01326   g_u_scanf_handlers[ 0x0054 ]     = u_scanf_time_handler;
01327 
01328   /* handle 'c' */
01329   g_u_scanf_infos[ 0x0063 ]     = u_scanf_char_info;
01330   g_u_scanf_handlers[ 0x0063 ]     = u_scanf_char_handler;
01331 
01332   /* handle 'K' */
01333   g_u_scanf_infos[ 0x004B ]     = u_scanf_uchar_info;
01334   g_u_scanf_handlers[ 0x004B ]     = u_scanf_uchar_handler;
01335 
01336   /* handle 'V' */
01337   g_u_scanf_infos[ 0x0056 ]     = u_scanf_spellout_info;
01338   g_u_scanf_handlers[ 0x0056 ]     = u_scanf_spellout_handler;
01339 
01340   /* handle 'x' */
01341   g_u_scanf_infos[ 0x0078 ]     = u_scanf_hex_info;
01342   g_u_scanf_handlers[ 0x0078 ]     = u_scanf_hex_handler;
01343 
01344   /* handle 'X' */
01345   g_u_scanf_infos[ 0x0058 ]     = u_scanf_hex_info;
01346   g_u_scanf_handlers[ 0x0058 ]     = u_scanf_hex_handler;
01347 
01348   /* handle 'o' */
01349   g_u_scanf_infos[ 0x006F ]     = u_scanf_octal_info;
01350   g_u_scanf_handlers[ 0x006F ]     = u_scanf_octal_handler;
01351 
01352   /* handle 'p' */
01353   g_u_scanf_infos[ 0x0070 ]     = u_scanf_pointer_info;
01354   g_u_scanf_handlers[ 0x0070 ]     = u_scanf_pointer_handler;
01355 
01356   /* handle '[' */
01357   g_u_scanf_infos[ 0x005B ]     = u_scanf_scanset_info;
01358   g_u_scanf_handlers[ 0x005B ]     = u_scanf_scanset_handler;
01359 
01360   /* we're finished */
01361   g_u_scanf_inited = TRUE;
01362 
01363   /* unlock the cache */
01364   umtx_unlock(0);
01365 }
01366 
01367 
01368 #define U_SCANF_MAX_ARGS 32
01369 #define UP_PERCENT 0x0025
01370 
01371 int32_t 
01372 u_vfscanf_u(    UFILE        *f,
01373         const UChar    *patternSpecification,
01374         va_list        ap)
01375 {
01376   u_scanf_spec         spec;
01377   const UChar         *alias;
01378   int32_t         count, converted, temp;
01379 
01380   int32_t         num_args_wanted;
01381   int32_t         ufmt_types     [U_SCANF_MAX_ARGS];
01382   ufmt_args       args         [U_SCANF_MAX_ARGS];
01383 
01384   u_scanf_info    info;
01385   u_scanf_handler handler;
01386 
01387   int32_t         cur_arg;
01388 
01389 
01390   /* init our function tables */
01391   if(! g_u_scanf_inited)
01392     u_scanf_init();
01393 
01394   /* alias the pattern */
01395   alias = patternSpecification;
01396 
01397   /* haven't converted anything yet */
01398   converted = 0;
01399 
01400   /* iterate through the pattern */
01401   for(;;) {
01402     
01403     /* match any characters up to the next '%' */
01404     while(*alias != UP_PERCENT && *alias != 0x0000 && u_fgetc(f) == *alias) {
01405       alias++;
01406     }
01407 
01408     /* if we aren't at a '%', or if we're at end of string, break*/
01409     if(*alias != UP_PERCENT || *alias == 0x0000)
01410       break;
01411 
01412     /* parse the specifier */
01413     count = u_scanf_parse_spec(alias, &spec);
01414 
01415     /* update the pointer in pattern */
01416     alias += count;
01417 
01418     /* skip the argument, if necessary */
01419     if(spec.fSkipArg)
01420       va_arg(ap, int);
01421 
01422     /* query the info function for argument information */
01423     info = g_u_scanf_infos[ (unsigned char) spec.fInfo.fSpec ];
01424     if(info != 0) { 
01425       num_args_wanted = (*info)(&spec.fInfo, 
01426                 ufmt_types,
01427                 U_SCANF_MAX_ARGS);
01428     }
01429     else
01430       num_args_wanted = 0;
01431 
01432     /* fill in the requested arguments */
01433     for(cur_arg = 0; 
01434     cur_arg < num_args_wanted && cur_arg < U_SCANF_MAX_ARGS; 
01435     ++cur_arg) {
01436 
01437       switch(ufmt_types[cur_arg]) {
01438 
01439       case ufmt_count:
01440         args[cur_arg].intValue = va_arg(ap, int);
01441         /* set the spec's width to the # of items converted */
01442         spec.fInfo.fWidth = converted;
01443         break;
01444 
01445       case ufmt_int:
01446         args[cur_arg].ptrValue = va_arg(ap, int*);
01447         break;
01448 
01449       case ufmt_char:
01450         args[cur_arg].ptrValue = va_arg(ap, int*);
01451         break;
01452 
01453       case ufmt_wchar:
01454         args[cur_arg].ptrValue = va_arg(ap, wchar_t*);
01455         break;
01456 
01457       case ufmt_string:
01458         args[cur_arg].ptrValue = va_arg(ap, char*);
01459         break;
01460 
01461       case ufmt_wstring:
01462         args[cur_arg].ptrValue = va_arg(ap, wchar_t*);
01463         break;
01464 
01465       case ufmt_pointer:
01466         args[cur_arg].ptrValue = va_arg(ap, void*);
01467         break;
01468 
01469       case ufmt_float:
01470         args[cur_arg].ptrValue = va_arg(ap, float*);
01471         break;
01472 
01473       case ufmt_double:
01474         args[cur_arg].ptrValue = va_arg(ap, double*);
01475         break;
01476 
01477       case ufmt_date:
01478         args[cur_arg].ptrValue = va_arg(ap, UDate*);
01479         break;
01480 
01481       case ufmt_ustring:
01482         args[cur_arg].ptrValue = va_arg(ap, UChar*);
01483         break;
01484 
01485       case ufmt_uchar:
01486         args[cur_arg].ptrValue = va_arg(ap, int*);
01487         break;
01488       }
01489     }
01490 
01491     /* call the handler function */
01492     handler = g_u_scanf_handlers[ (unsigned char) spec.fInfo.fSpec ];
01493     if(handler != 0) {
01494 
01495       /* reset count */
01496       count = 0;
01497 
01498       temp = (*handler)(f, &spec.fInfo, args, alias, &count);
01499 
01500       /* if the handler encountered an error condition, break */
01501       if(temp == -1)
01502         break;
01503 
01504       /* add to the # of items converted */
01505       converted += temp;
01506 
01507       /* update the pointer in pattern */
01508       alias += count;
01509     }
01510 
01511     /* just ignore unknown tags */
01512 
01513   }
01514 
01515   /* return # of items converted */
01516   return converted;
01517 }
01518 

Generated at Tue Dec 5 10:48:11 2000 for ICU by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000