home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / input.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  73KB  |  2,199 lines

  1. /***
  2. *input.c - C formatted input, used by scanf, etc.
  3. *
  4. *       Copyright (c) 1987-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _input() to do formatted input; called from scanf(),
  8. *       etc. functions.  This module defines _cscanf() instead when
  9. *       CPRFLAG is defined.  The file cscanf.c defines that symbol
  10. *       and then includes this file in order to implement _cscanf().
  11. *
  12. *******************************************************************************/
  13.  
  14. #ifdef _WIN32
  15.  
  16.  
  17. #define ALLOW_RANGE /* allow "%[a-z]"-style scansets */
  18.  
  19.  
  20. /* temporary work-around for compiler without 64-bit support */
  21.  
  22. #ifndef _INTEGRAL_MAX_BITS
  23. #define _INTEGRAL_MAX_BITS  64
  24. #endif  /* _INTEGRAL_MAX_BITS */
  25.  
  26.  
  27. #include <cruntime.h>
  28. #include <stdio.h>
  29. #include <ctype.h>
  30. #include <cvt.h>
  31. #include <conio.h>
  32. #include <stdarg.h>
  33. #include <string.h>
  34. #include <internal.h>
  35. #include <fltintrn.h>
  36. #include <mtdll.h>
  37. #include <stdlib.h>
  38. #include <nlsint.h>
  39. #include <dbgint.h>
  40.  
  41. #ifdef _MBCS
  42. #undef _MBCS
  43. #endif  /* _MBCS */
  44. #include <tchar.h>
  45.  
  46. #define HEXTODEC(chr)   _hextodec(chr)
  47. #define LEFT_BRACKET    ('[' | ('a' - 'A')) /* 'lowercase' version */
  48.  
  49. #ifdef _UNICODE
  50. static wchar_t __cdecl _hextodec(wchar_t);
  51. #else  /* _UNICODE */
  52. static int __cdecl _hextodec(int);
  53. #endif  /* _UNICODE */
  54.  
  55. /*
  56.  * Note: CPRFLAG and _UNICODE cases are currently mutually exclusive.
  57.  */
  58.  
  59. #ifdef CPRFLAG
  60.  
  61. #define INC()           (++charcount, _inc())
  62. #define UN_INC(chr)     (--charcount, _ungetch_lk(chr))
  63. #define EAT_WHITE()     _whiteout(&charcount)
  64.  
  65. static int __cdecl _inc(void);
  66. static int __cdecl _whiteout(int *);
  67.  
  68. #else  /* CPRFLAG */
  69.  
  70. #define INC()           (++charcount, _inc(stream))
  71. #define UN_INC(chr)     (--charcount, _un_inc(chr, stream))
  72. #define EAT_WHITE()     _whiteout(&charcount, stream)
  73.  
  74. #ifndef _UNICODE
  75. static int __cdecl _inc(FILE *);
  76. static void __cdecl _un_inc(int, FILE *);
  77. static int __cdecl _whiteout(int *, FILE *);
  78. #else  /* _UNICODE */
  79. static wchar_t __cdecl _inc(FILE *);
  80. static void __cdecl _un_inc(wchar_t, FILE *);
  81. static wchar_t __cdecl _whiteout(int *, FILE *);
  82. #endif  /* _UNICODE */
  83.  
  84. #endif  /* CPRFLAG */
  85.  
  86.  
  87. #ifndef _UNICODE
  88. #define _ISDIGIT(chr)   isdigit(chr)
  89. #define _ISXDIGIT(chr)  isxdigit(chr)
  90. #else  /* _UNICODE */
  91. #define _ISDIGIT(chr)   ( !(chr & 0xff00) && isdigit( chr & 0x00ff ) )
  92. #define _ISXDIGIT(chr)  ( !(chr & 0xff00) && isxdigit( chr & 0x00ff ) )
  93. #endif  /* _UNICODE */
  94.  
  95.  
  96. #ifdef _UNICODE
  97. int __cdecl _winput(FILE *, const wchar_t *, va_list);
  98. #endif  /* _UNICODE */
  99.  
  100. #ifdef CPRFLAG
  101. static int __cdecl input(const unsigned char *, va_list);
  102.  
  103.  
  104. /***
  105. *int _cscanf(format, arglist) - read formatted input direct from console
  106. *
  107. *Purpose:
  108. *   Reads formatted data like scanf, but uses console I/O functions.
  109. *
  110. *Entry:
  111. *   char *format - format string to determine data formats
  112. *   arglist - list of POINTERS to where to put data
  113. *
  114. *Exit:
  115. *   returns number of successfully matched data items (from input)
  116. *
  117. *Exceptions:
  118. *
  119. *******************************************************************************/
  120.  
  121.  
  122. int __cdecl _cscanf (
  123.     const char *format,
  124.     ...
  125.     )
  126. {
  127.     va_list arglist;
  128.  
  129.     va_start(arglist, format);
  130.  
  131.     _ASSERTE(format != NULL);
  132.  
  133.     return input(format,arglist);   /* get the input */
  134. }
  135.  
  136. #endif  /* CPRFLAG */
  137.  
  138.  
  139. #define ASCII       32           /* # of bytes needed to hold 256 bits */
  140.  
  141. #define SCAN_SHORT     0         /* also for FLOAT */
  142. #define SCAN_LONG      1         /* also for DOUBLE */
  143. #define SCAN_L_DOUBLE  2         /* only for LONG DOUBLE */
  144.  
  145. #define SCAN_NEAR    0
  146. #define SCAN_FAR     1
  147.  
  148.  
  149. static _TCHAR sbrackset[] = _T(" \t-\r]"); /* use range-style list */
  150.  
  151.  
  152. static _TCHAR cbrackset[] = _T("]");
  153.  
  154.  
  155.  
  156. /***
  157. *int _input(stream, format, arglist), static int input(format, arglist)
  158. *
  159. *Purpose:
  160. *   get input items (data items or literal matches) from the input stream
  161. *   and assign them if appropriate to the items thru the arglist. this
  162. *   function is intended for internal library use only, not for the user
  163. *
  164. *   The _input entry point is for the normal scanf() functions
  165. *   The input entry point is used when compiling for _cscanf() [CPRFLAF
  166. *   defined] and is a static function called only by _cscanf() -- reads from
  167. *   console.
  168. *
  169. *Entry:
  170. *   FILE *stream - file to read from
  171. *   char *format - format string to determine the data to read
  172. *   arglist - list of pointer to data items
  173. *
  174. *Exit:
  175. *   returns number of items assigned and fills in data items
  176. *   returns EOF if error or EOF found on stream before 1st data item matched
  177. *
  178. *Exceptions:
  179. *
  180. *******************************************************************************/
  181.  
  182. #ifdef CPRFLAG
  183.  
  184. static int __cdecl input (
  185.     const unsigned char *format,
  186.     va_list arglist
  187.     )
  188. #elif defined (_UNICODE)
  189.  
  190. int __cdecl _winput (
  191.     FILE *stream,
  192.     const wchar_t *format,
  193.     va_list arglist
  194.     )
  195. #else  /* defined (_UNICODE) */
  196.  
  197. int __cdecl _input (
  198.     FILE *stream,
  199.     const unsigned char *format,
  200.     va_list arglist
  201.     )
  202. #endif  /* defined (_UNICODE) */
  203.  
  204. {
  205. #ifndef _UNICODE
  206.     char table[ASCII];                  /* which chars allowed for %[], %s   */
  207.     char floatstring[CVTBUFSIZE + 1];   /* ASCII buffer for floats           */
  208. #else  /* _UNICODE */
  209.     char table[256*ASCII];
  210.     wchar_t floatstring[CVTBUFSIZE + 1];
  211. #endif  /* _UNICODE */
  212.  
  213.     unsigned long number;               /* temp hold-value                   */
  214. #if _INTEGRAL_MAX_BITS >= 64   
  215.     unsigned __int64 num64;             /* temp for 64-bit integers          */
  216. #endif  /* _INTEGRAL_MAX_BITS >= 64    */
  217.     void *pointer;                      /* points to user data receptacle    */
  218.     void *start;                        /* indicate non-empty string         */
  219.  
  220.  
  221. #ifdef _UNICODE
  222.     wchar_t *scanptr;           /* for building "table" data         */
  223. REG2 wchar_t ch;
  224. #else  /* _UNICODE */
  225.     wchar_t wctemp;
  226.     unsigned char *scanptr;             /* for building "table" data         */
  227. REG2 int ch;
  228. #endif  /* _UNICODE */
  229.     int charcount;                      /* total number of chars read        */
  230. REG1 int comchr;                        /* holds designator type             */
  231.     int count;                          /* return value.  # of assignments   */
  232.  
  233.     int started;                        /* indicate good number              */
  234.     int width;                          /* width of field                    */
  235.     int widthset;                       /* user has specified width          */
  236.  
  237. /* Neither coerceshort nor farone are need for the 386 */
  238.  
  239.  
  240.     char done_flag;                     /* general purpose loop monitor      */
  241.     char longone;                       /* 0 = SHORT, 1 = LONG, 2 = L_DOUBLE */
  242. #if _INTEGRAL_MAX_BITS >= 64   
  243.     int integer64;                      /* 1 for 64-bit integer, 0 otherwise */
  244. #endif  /* _INTEGRAL_MAX_BITS >= 64    */
  245.     signed char widechar;               /* -1 = char, 0 = ????, 1 = wchar_t  */
  246.     char reject;                        /* %[^ABC] instead of %[ABC]         */
  247.     char negative;                      /* flag for '-' detected             */
  248.     char suppress;                      /* don't assign anything             */
  249.     char match;                         /* flag: !0 if any fields matched    */
  250.     va_list arglistsave;                /* save arglist value                */
  251.  
  252.     char fl_wchar_arg;                  /* flags wide char/string argument   */
  253. #ifdef _UNICODE
  254.     wchar_t rngch;              /* used while scanning range         */
  255.     wchar_t last;               /* also for %[a-z]                   */
  256.     wchar_t prevchar;           /* for %[a-z]                        */
  257.     wchar_t wdecimal;                   /* wide version of decimal point     */
  258.     wchar_t *wptr;                      /* pointer traverses wide floatstring*/
  259. #else  /* _UNICODE */
  260.     unsigned char rngch;                /* used while scanning range         */
  261.     unsigned char last;                 /* also for %[a-z]                   */
  262.     unsigned char prevchar;             /* for %[a-z]                        */
  263. #endif  /* _UNICODE */
  264.  
  265.     _ASSERTE(format != NULL);
  266.  
  267. #ifndef CPRFLAG
  268.     _ASSERTE(stream != NULL);
  269. #endif  /* CPRFLAG */
  270.  
  271.     /*
  272.     count = # fields assigned
  273.     charcount = # chars read
  274.     match = flag indicating if any fields were matched
  275.  
  276.     [Note that we need both count and match.  For example, a field
  277.     may match a format but have assignments suppressed.  In this case,
  278.     match will get set, but 'count' will still equal 0.  We need to
  279.     distinguish 'match vs no-match' when terminating due to EOF.]
  280.     */
  281.  
  282.     count = charcount = match = 0;
  283.  
  284.     while (*format) {
  285.  
  286.         if (_istspace((_TUCHAR)*format)) {
  287.  
  288.             UN_INC(EAT_WHITE()); /* put first non-space char back */
  289.  
  290.             while ((_istspace)(*++format)); /* NULL */
  291.             /* careful: isspace macro may evaluate argument more than once! */
  292.  
  293.         }
  294.  
  295.         if (_T('%') == *format) {
  296.  
  297.             number = 0;
  298.             prevchar = 0;
  299.             width = widthset = started = 0;
  300.             fl_wchar_arg = done_flag = suppress = negative = reject = 0;
  301.             widechar = 0;
  302.  
  303.             longone = 1;
  304.  
  305.             integer64 = 0;
  306.  
  307.             while (!done_flag) {
  308.  
  309.                 comchr = *++format;
  310.                 if (_ISDIGIT((_TUCHAR)comchr)) {
  311.                     ++widthset;
  312.                     width = MUL10(width) + (comchr - _T('0'));
  313.                 } else
  314.                     switch (comchr) {
  315.                         case _T('F') :
  316.                         case _T('N') :   /* no way to push NEAR in large model */
  317.                             break;  /* NEAR is default in small model */
  318.                         case _T('h') :
  319.                             /* set longone to 0 */
  320.                             --longone;
  321.                             --widechar;         /* set widechar = -1 */
  322.                             break;
  323.  
  324. #if _INTEGRAL_MAX_BITS >= 64   
  325.                         case _T('I'):
  326.                             if ( (*(format + 1) == _T('6')) &&
  327.                                  (*(format + 2) == _T('4')) )
  328.                             {
  329.                                 format += 2;
  330.                                 ++integer64;
  331.                                 num64 = 0;
  332.                                 break;
  333.                             }
  334.                             goto DEFAULT_LABEL;
  335. #endif  /* _INTEGRAL_MAX_BITS >= 64    */
  336.  
  337.                         case _T('L') :
  338.                         /*  ++longone;  */
  339.                             ++longone;
  340.                             break;
  341.  
  342.                         case _T('l') :
  343.                             ++longone;
  344.                                     /* NOBREAK */
  345.                         case _T('w') :
  346.                             ++widechar;         /* set widechar = 1 */
  347.                             break;
  348.  
  349.                         case _T('*') :
  350.                             ++suppress;
  351.                             break;
  352.  
  353.                         default:
  354. DEFAULT_LABEL:
  355.                             ++done_flag;
  356.                             break;
  357.                     }
  358.             }
  359.  
  360.             if (!suppress) {
  361.                 arglistsave = arglist;
  362.                 pointer = va_arg(arglist,void *);
  363.             }
  364.  
  365.             done_flag = 0;
  366.  
  367.             if (!widechar) {    /* use case if not explicitly specified */
  368.                 if ((*format == _T('S')) || (*format == _T('C')))
  369. #ifdef _UNICODE
  370.                     --widechar;
  371.                 else
  372.                     ++widechar;
  373. #else  /* _UNICODE */
  374.                     ++widechar;
  375.                 else
  376.                     --widechar;
  377. #endif  /* _UNICODE */
  378.             }
  379.  
  380.             /* switch to lowercase to allow %E,%G, and to
  381.                keep the switch table small */
  382.  
  383.             comchr = *format | (_T('a') - _T('A'));
  384.  
  385.             if (_T('n') != comchr)
  386.                 if (_T('c') != comchr && LEFT_BRACKET != comchr)
  387.                     ch = EAT_WHITE();
  388.                 else
  389.                     ch = INC();
  390.  
  391.  
  392.             if (!widthset || width) {
  393.  
  394.                 switch(comchr) {
  395.  
  396.                     case _T('c'):
  397.                 /*  case _T('C'):  */
  398.                         if (!widthset) {
  399.                             ++widthset;
  400.                             ++width;
  401.                         }
  402.                         if (widechar>0)
  403.                             fl_wchar_arg++;
  404.                         scanptr = cbrackset;
  405.                         --reject; /* set reject to 255 */
  406.                         goto scanit2;
  407.  
  408.                     case _T('s'):
  409.                 /*  case _T('S'):  */
  410.                         if (widechar>0)
  411.                             fl_wchar_arg++;
  412.                         scanptr = sbrackset;
  413.                         --reject; /* set reject to 255 */
  414.                         goto scanit2;
  415.  
  416.                     case LEFT_BRACKET :   /* scanset */
  417.                         if (widechar>0)
  418.                             fl_wchar_arg++;
  419.                         scanptr = (_TCHAR *)(++format);
  420.  
  421.                         if (_T('^') == *scanptr) {
  422.                             ++scanptr;
  423.                             --reject; /* set reject to 255 */
  424.                         }
  425.  
  426.  
  427. scanit2:
  428. #ifdef _UNICODE
  429.                         memset(table, 0, ASCII*256);
  430. #else  /* _UNICODE */
  431.                         memset(table, 0, ASCII);
  432. #endif  /* _UNICODE */
  433.  
  434.  
  435.                         if (LEFT_BRACKET == comchr)
  436.                             if (_T(']') == *scanptr) {
  437.                                 prevchar = _T(']');
  438.                                 ++scanptr;
  439.  
  440.                                 table[ _T(']') >> 3] = 1 << (_T(']') & 7);
  441.  
  442.                             }
  443.  
  444.                         while (_T(']') != *scanptr) {
  445.  
  446.                             rngch = *scanptr++;
  447.  
  448.                             if (_T('-') != rngch ||
  449.                                  !prevchar ||           /* first char */
  450.                                  _T(']') == *scanptr) /* last char */
  451.  
  452.                                 table[(prevchar = rngch) >> 3] |= 1 << (rngch & 7);
  453.  
  454.                             else {  /* handle a-z type set */
  455.  
  456.                                 rngch = *scanptr++; /* get end of range */
  457.  
  458.                                 if (prevchar < rngch)  /* %[a-z] */
  459.                                     last = rngch;
  460.                                 else {              /* %[z-a] */
  461.                                     last = prevchar;
  462.                                     prevchar = rngch;
  463.                                 }
  464.                                 for (rngch = prevchar; rngch <= last; ++rngch)
  465.                                     table[rngch >> 3] |= 1 << (rngch & 7);
  466.  
  467.                                 prevchar = 0;
  468.  
  469.                             }
  470.                         }
  471.  
  472.  
  473.                         if (!*scanptr)
  474.                             goto error_return;      /* trunc'd format string */
  475.  
  476.                         /* scanset completed.  Now read string */
  477.  
  478.                         if (LEFT_BRACKET == comchr)
  479.                             format = scanptr;
  480.  
  481.                         start = pointer;
  482.  
  483.                         /*
  484.                          * execute the format directive. that is, scan input
  485.                          * characters until the directive is fulfilled, eof
  486.                          * is reached, or a non-matching character is
  487.                          * encountered.
  488.                          *
  489.                          * it is important not to get the next character
  490.                          * unless that character needs to be tested! other-
  491.                          * wise, reads from line-buffered devices (e.g.,
  492.                          * scanf()) would require an extra, spurious, newline
  493.                          * if the first newline completes the current format
  494.                          * directive.
  495.                          */
  496.                         UN_INC(ch);
  497.  
  498.                         while ( !widthset || width-- ) {
  499.  
  500.                             ch = INC();
  501.                             if (
  502. #ifndef _UNICODE
  503. #ifndef CPRFLAG
  504.                               (EOF != ch) &&
  505. #endif  /* CPRFLAG */
  506.                               ((table[ch >> 3] ^ reject) & (1 << (ch & 7)))
  507. #else  /* _UNICODE */
  508.                               (WEOF != ch) &&
  509.                          /*     ((ch>>3 >= ASCII) ? reject : */
  510.                               ((table[ch >> 3] ^ reject) &
  511.                                         (1 << (ch & 7)))         /* ) */
  512. #endif  /* _UNICODE */
  513.                             ) {
  514.                                 if (!suppress) {
  515. #ifndef _UNICODE
  516.                                     if (fl_wchar_arg) {
  517.                                         char temp[2];
  518.                                         temp[0] = (char) ch;
  519.                                         if (isleadbyte(ch))
  520.                                             temp[1] = (char) INC();
  521.                                         mbtowc(&wctemp, temp, MB_CUR_MAX);
  522.                                         *(wchar_t UNALIGNED *)pointer =
  523.                                           wctemp;
  524.                                         /* do nothing if mbtowc fails */
  525.                                         pointer = (wchar_t *)pointer + 1;
  526.                                     } else
  527. #else  /* _UNICODE */
  528.                                     if (fl_wchar_arg) {
  529.                                         *(wchar_t UNALIGNED *)pointer = ch;
  530.                                         pointer = (wchar_t *)pointer + 1;
  531.                                     } else
  532. #endif  /* _UNICODE */
  533.                                     {
  534. #ifndef _UNICODE
  535.                                     *(char *)pointer = (char)ch;
  536.                                     pointer = (char *)pointer + 1;
  537. #else  /* _UNICODE */
  538.                                     int temp;
  539.                                     /* convert wide to multibyte */
  540.                                     temp = wctomb((char *)pointer, ch);
  541.                                     /* do nothing if wctomb fails */
  542.                                     pointer = (char *)pointer + temp;
  543. #endif  /* _UNICODE */
  544.                                     }
  545.                                 } /* suppress */
  546.                                 else {
  547.                                     /* just indicate a match */
  548.                                     start = (_TCHAR *)start + 1;
  549.                                 }
  550.                             }
  551.                             else  {
  552.                                 UN_INC(ch);
  553.                                 break;
  554.                             }
  555.                         }
  556.  
  557.                         /* make sure something has been matched and, if
  558.                            assignment is not suppressed, null-terminate
  559.                            output string if comchr != c */
  560.  
  561.                         if (start != pointer) {
  562.                             if (!suppress) {
  563.                                 ++count;
  564.                                 if ('c' != comchr) /* null-terminate strings */
  565.                                     if (fl_wchar_arg)
  566.                                         *(wchar_t UNALIGNED *)pointer = L'\0';
  567.                                     else
  568.                                     *(char *)pointer = '\0';
  569.                             } else /*NULL*/;
  570.                         }
  571.                         else
  572.                             goto error_return;
  573.  
  574.                         break;
  575.  
  576.                     case _T('i') :      /* could be d, o, or x */
  577.  
  578.                         comchr = _T('d'); /* use as default */
  579.  
  580.                     case _T('x'):
  581.  
  582.                         if (_T('-') == ch) {
  583.                             ++negative;
  584.  
  585.                             goto x_incwidth;
  586.  
  587.                         } else if (_T('+') == ch) {
  588. x_incwidth:
  589.                             if (!--width && widthset)
  590.                                 ++done_flag;
  591.                             else
  592.                                 ch = INC();
  593.                         }
  594.  
  595.                         if (_T('0') == ch) {
  596.  
  597.                             if (_T('x') == (_TCHAR)(ch = INC()) || _T('X') == (_TCHAR)ch) {
  598.                                 ch = INC();
  599.                                 comchr = _T('x');
  600.                             } else {
  601.                                 ++started;
  602.                                 if (_T('x') != comchr)
  603.                                     comchr = _T('o');
  604.                                 else {
  605.                                     /* scanning a hex number that starts */
  606.                                     /* with a 0. push back the character */
  607.                                     /* currently in ch and restore the 0 */
  608.                                     UN_INC(ch);
  609.                                     ch = _T('0');
  610.                                 }
  611.                             }
  612.                         }
  613.                         goto getnum;
  614.  
  615.                         /* NOTREACHED */
  616.  
  617.                     case _T('p') :
  618.                         /* force %hp to be treated as %p */
  619.                         longone = 1;
  620.  
  621.                     case _T('o') :
  622.                     case _T('u') :
  623.                     case _T('d') :
  624.  
  625.                         if (_T('-') == ch) {
  626.                             ++negative;
  627.  
  628.                             goto d_incwidth;
  629.  
  630.                         } else if (_T('+') == ch) {
  631. d_incwidth:
  632.                             if (!--width && widthset)
  633.                                 ++done_flag;
  634.                             else
  635.                                 ch = INC();
  636.                         }
  637.  
  638. getnum:
  639. #if _INTEGRAL_MAX_BITS >= 64   
  640.                         if ( integer64 ) {
  641.  
  642.                             while (!done_flag) {
  643.  
  644.                                 if (_T('x') == comchr)
  645.  
  646.                                     if (_ISXDIGIT(ch)) {
  647.                                         num64 <<= 4;
  648.                                         ch = HEXTODEC(ch);
  649.                                     }
  650.                                     else
  651.                                         ++done_flag;
  652.  
  653.                                 else if (_ISDIGIT(ch))
  654.  
  655.                                     if (_T('o') == comchr)
  656.                                         if (_T('8') > ch)
  657.                                                 num64 <<= 3;
  658.                                         else {
  659.                                                 ++done_flag;
  660.                                         }
  661.                                     else /* _T('d') == comchr */
  662.                                         num64 = MUL10(num64);
  663.  
  664.                                 else
  665.                                     ++done_flag;
  666.  
  667.                                 if (!done_flag) {
  668.                                     ++started;
  669.                                     num64 += ch - _T('0');
  670.  
  671.                                     if (widthset && !--width)
  672.                                         ++done_flag;
  673.                                     else
  674.                                         ch = INC();
  675.                                 } else
  676.                                     UN_INC(ch);
  677.  
  678.                             } /* end of WHILE loop */
  679.  
  680.                             if (negative)
  681.                                 num64 = (unsigned __int64 )(-(__int64)num64);
  682.                         }
  683.                         else {
  684. #endif  /* _INTEGRAL_MAX_BITS >= 64    */
  685.                             while (!done_flag) {
  686.  
  687.                                 if (_T('x') == comchr || _T('p') == comchr)
  688.  
  689.                                     if (_ISXDIGIT(ch)) {
  690.                                         number = (number << 4);
  691.                                         ch = HEXTODEC(ch);
  692.                                     }
  693.                                     else
  694.                                         ++done_flag;
  695.  
  696.                                 else if (_ISDIGIT(ch))
  697.  
  698.                                     if (_T('o') == comchr)
  699.                                         if (_T('8') > ch)
  700.                                             number = (number << 3);
  701.                                         else {
  702.                                             ++done_flag;
  703.                                         }
  704.                                     else /* _T('d') == comchr */
  705.                                         number = MUL10(number);
  706.  
  707.                                 else
  708.                                     ++done_flag;
  709.  
  710.                                 if (!done_flag) {
  711.                                     ++started;
  712.                                     number += ch - _T('0');
  713.  
  714.                                     if (widthset && !--width)
  715.                                         ++done_flag;
  716.                                     else
  717.                                         ch = INC();
  718.                                 } else
  719.                                     UN_INC(ch);
  720.  
  721.                             } /* end of WHILE loop */
  722.  
  723.                             if (negative)
  724.                                 number = (unsigned long)(-(long)number);
  725. #if _INTEGRAL_MAX_BITS >= 64   
  726.                         }
  727. #endif  /* _INTEGRAL_MAX_BITS >= 64    */
  728.                         if (_T('F')==comchr) /* expected ':' in long pointer */
  729.                             started = 0;
  730.  
  731.                         if (started)
  732.                             if (!suppress) {
  733.  
  734.                                 ++count;
  735. assign_num:
  736. #if _INTEGRAL_MAX_BITS >= 64   
  737.                                 if ( integer64 )
  738.                                     *(__int64 UNALIGNED *)pointer = (unsigned __int64)num64;
  739.                                 else
  740. #endif  /* _INTEGRAL_MAX_BITS >= 64    */
  741.                                 if (longone)
  742.                                     *(long UNALIGNED *)pointer = (unsigned long)number;
  743.                                 else
  744.                                     *(short UNALIGNED *)pointer = (unsigned short)number;
  745.  
  746.                             } else /*NULL*/;
  747.                         else
  748.                             goto error_return;
  749.  
  750.                         break;
  751.  
  752.                     case _T('n') :      /* char count, don't inc return value */
  753.                         number = charcount;
  754.                         if(!suppress)
  755.                             goto assign_num; /* found in number code above */
  756.                         break;
  757.  
  758.  
  759.                     case _T('e') :
  760.                  /* case _T('E') : */
  761.                     case _T('f') :
  762.                     case _T('g') : /* scan a float */
  763.                  /* case _T('G') : */
  764.  
  765. #ifndef _UNICODE
  766.                         scanptr = floatstring;
  767.  
  768.                         if (_T('-') == ch) {
  769.                             *scanptr++ = _T('-');
  770.                             goto f_incwidth;
  771.  
  772.                         } else if (_T('+') == ch) {
  773. f_incwidth:
  774.                             --width;
  775.                             ch = INC();
  776.                         }
  777.  
  778.                         if (!widthset || width > CVTBUFSIZE)              /* must watch width */
  779.                             width = CVTBUFSIZE;
  780.  
  781.  
  782.                         /* now get integral part */
  783.  
  784.                         while (_ISDIGIT(ch) && width--) {
  785.                             ++started;
  786.                             *scanptr++ = (char)ch;
  787.                             ch = INC();
  788.                         }
  789.  
  790.                         /* now check for decimal */
  791.  
  792.                         if (*___decimal_point == (char)ch && width--) {
  793.                             ch = INC();
  794.                             *scanptr++ = *___decimal_point;
  795.  
  796.                             while (_ISDIGIT(ch) && width--) {
  797.                                 ++started;
  798.                                 *scanptr++ = (char)ch;
  799.                                 ch = INC();
  800.                             }
  801.                         }
  802.  
  803.                         /* now check for exponent */
  804.  
  805.                         if (started && (_T('e') == ch || _T('E') == ch) && width--) {
  806.                             *scanptr++ = 'e';
  807.  
  808.                             if (_T('-') == (ch = INC())) {
  809.  
  810.                                 *scanptr++ = '-';
  811.                                 goto f_incwidth2;
  812.  
  813.                             } else if (_T('+') == ch) {
  814. f_incwidth2:
  815.                                 if (!width--)
  816.                                     ++width;
  817.                                 else
  818.                                     ch = INC();
  819.                             }
  820.  
  821.  
  822.                             while (_ISDIGIT(ch) && width--) {
  823.                                 ++started;
  824.                                 *scanptr++ = (char)ch;
  825.                                 ch = INC();
  826.                             }
  827.  
  828.                         }
  829.  
  830.                         UN_INC(ch);
  831.  
  832.                         if (started)
  833.                             if (!suppress) {
  834.                                 ++count;
  835.                                 *scanptr = '\0';
  836.                                 _fassign( longone-1, pointer , floatstring);
  837.                             } else /*NULL */;
  838.                         else
  839.                             goto error_return;
  840.  
  841. #else  /* _UNICODE */
  842.                         wptr = floatstring;
  843.  
  844.                         if (L'-' == ch) {
  845.                             *wptr++ = L'-';
  846.                             goto f_incwidthw;
  847.  
  848.                         } else if (L'+' == ch) {
  849. f_incwidthw:
  850.                             --width;
  851.                             ch = INC();
  852.                         }
  853.  
  854.                         if (!widthset || width > CVTBUFSIZE)
  855.                             width = CVTBUFSIZE;
  856.  
  857.  
  858.                         /* now get integral part */
  859.  
  860.                         while (_ISDIGIT(ch) && width--) {
  861.                             ++started;
  862.                             *wptr++ = ch;
  863.                             ch = INC();
  864.                         }
  865.  
  866.                         /* now check for decimal */
  867.  
  868.                         /* convert decimal point to wide-char */
  869.                         /* assume result is single wide-char */
  870.                         mbtowc (&wdecimal, ___decimal_point, MB_CUR_MAX);
  871.  
  872.                         if (wdecimal == ch && width--) {
  873.                             ch = INC();
  874.                             *wptr++ = wdecimal;
  875.  
  876.                             while (_ISDIGIT(ch) && width--) {
  877.                                 ++started;
  878.                                 *wptr++ = ch;
  879.                                 ch = INC();
  880.                             }
  881.                         }
  882.  
  883.                         /* now check for exponent */
  884.  
  885.                         if (started && (L'e' == ch || L'E' == ch) && width--) {
  886.                             *wptr++ = L'e';
  887.  
  888.                             if (L'-' == (ch = INC())) {
  889.  
  890.                                 *wptr++ = L'-';
  891.                                 goto f_incwidth2w;
  892.  
  893.                             } else if (L'+' == ch) {
  894. f_incwidth2w:
  895.                                 if (!width--)
  896.                                     ++width;
  897.                                 else
  898.                                     ch = INC();
  899.                             }
  900.  
  901.  
  902.                             while (_ISDIGIT(ch) && width--) {
  903.                                 ++started;
  904.                                 *wptr++ = ch;
  905.                                 ch = INC();
  906.                             }
  907.  
  908.                         }
  909.  
  910.                         UN_INC(ch);
  911.  
  912.                         if (started)
  913.                             if (!suppress) {
  914.                                 ++count;
  915.                                 *wptr = '\0';
  916.                                 {
  917.                                 /* convert floatstring to char string */
  918.                                 /* and do the conversion */
  919.                                 size_t cfslength;
  920.                                 char *cfloatstring;
  921.                                 cfslength =(wptr-floatstring+1)*sizeof(wchar_t);
  922.                                 cfloatstring = (char *)_malloc_crt (cfslength);
  923.                                 wcstombs (cfloatstring, floatstring, cfslength);
  924.                                 _fassign( longone-1, pointer , cfloatstring);
  925.                                 _free_crt (cfloatstring);
  926.                                 }
  927.                             } else /*NULL */;
  928.                         else
  929.                             goto error_return;
  930.  
  931. #endif  /* _UNICODE */
  932.                         break;
  933.  
  934.  
  935.                     default:    /* either found '%' or something else */
  936.  
  937.                         if ((int)*format != (int)ch) {
  938.                             UN_INC(ch);
  939.                             goto error_return;
  940.                             }
  941.                         else
  942.                             match--; /* % found, compensate for inc below */
  943.  
  944.                         if (!suppress)
  945.                             arglist = arglistsave;
  946.  
  947.                 } /* SWITCH */
  948.  
  949.                 match++;        /* matched a format field - set flag */
  950.  
  951.             } /* WHILE (width) */
  952.  
  953.             else {  /* zero-width field in format string */
  954.                 UN_INC(ch);  /* check for input error */
  955.                 goto error_return;
  956.             }
  957.  
  958.             ++format;  /* skip to next char */
  959.  
  960.         } else  /*  ('%' != *format) */
  961.             {
  962.  
  963.             if ((int)*format++ != (int)(ch = INC()))
  964.                 {
  965.                 UN_INC(ch);
  966.                 goto error_return;
  967.                 }
  968. #ifndef _UNICODE
  969.             if (isleadbyte(ch))
  970.                 {
  971.                 int ch2;
  972.                 if ((int)*format++ != (ch2=INC()))
  973.                     {
  974.                     UN_INC(ch2);
  975.                     UN_INC(ch);
  976.                     goto error_return;
  977.                     }
  978.  
  979.                     --charcount; /* only count as one character read */
  980.                 }
  981. #endif  /* _UNICODE */
  982.             }
  983.  
  984. #ifndef CPRFLAG
  985.         if ( (EOF == ch) && ((*format != '%') || (*(format + 1) != 'n')) )
  986.             break;
  987. #endif  /* CPRFLAG */
  988.  
  989.     }  /* WHILE (*format) */
  990.  
  991. error_return:
  992.  
  993. #ifndef CPRFLAG
  994.     if (EOF == ch)
  995.         /* If any fields were matched or assigned, return count */
  996.         return ( (count || match) ? count : EOF);
  997.     else
  998. #endif  /* CPRFLAG */
  999.         return count;
  1000.  
  1001. }
  1002.  
  1003. /* _hextodec() returns a value of 0-15 and expects a char 0-9, a-f, A-F */
  1004. /* _inc() is the one place where we put the actual getc code. */
  1005. /* _whiteout() returns the first non-blank character, as defined by isspace() */
  1006.  
  1007. #ifndef _UNICODE
  1008. static int __cdecl _hextodec (
  1009.     int chr
  1010.     )
  1011. {
  1012.     return _ISDIGIT(chr) ? chr : (chr & ~(_T('a') - _T('A'))) - _T('A') + 10 + _T('0');
  1013. }
  1014. #else  /* _UNICODE */
  1015. static _TCHAR __cdecl _hextodec (
  1016.     _TCHAR chr
  1017.     )
  1018. {
  1019.     if (_ISDIGIT(chr))
  1020.         return chr;
  1021.     if (_istlower(chr))
  1022.         return (_TCHAR)(chr - _T('a') + 10 + _T('0'));
  1023.     else
  1024.         return (_TCHAR)(chr - _T('A') + 10 + _T('0'));
  1025. }
  1026. #endif  /* _UNICODE */
  1027.  
  1028.  
  1029. #ifdef CPRFLAG
  1030.  
  1031. static int __cdecl _inc (
  1032.     void
  1033.     )
  1034. {
  1035.     return(_getche_lk());
  1036. }
  1037.  
  1038. static int __cdecl _whiteout (
  1039.     REG1 int *counter
  1040.     )
  1041. {
  1042.     REG2 int ch;
  1043.  
  1044.     while((_istspace)(ch = (++*counter, _inc())));
  1045.     return ch;
  1046. }
  1047.  
  1048. #elif defined (_UNICODE)
  1049.  
  1050. /*
  1051.  * Manipulate wide-chars in a file.
  1052.  * A wide-char is hard-coded to be two chars for efficiency.
  1053.  */
  1054.  
  1055. static wchar_t __cdecl _inc (
  1056.     REG1 FILE *fileptr
  1057.     )
  1058. {
  1059.     return(_getwc_lk(fileptr));
  1060. }
  1061.  
  1062. static void __cdecl _un_inc (
  1063.     wchar_t chr,
  1064.     FILE *fileptr
  1065.     )
  1066. {
  1067.     if (WEOF != chr)
  1068.         _ungetwc_lk(chr, fileptr);
  1069. }
  1070.  
  1071. static wchar_t __cdecl _whiteout (
  1072.     REG1 int *counter,
  1073.     REG3 FILE *fileptr
  1074.     )
  1075. {
  1076.     REG2 wchar_t ch;
  1077.  
  1078.     while((iswspace)(ch = (++*counter, _inc(fileptr))));
  1079.     return ch;
  1080. }
  1081.  
  1082. #else  /* defined (_UNICODE) */
  1083.  
  1084. static int __cdecl _inc (
  1085.     REG1 FILE *fileptr
  1086.     )
  1087. {
  1088.     return(_getc_lk(fileptr));
  1089. }
  1090.  
  1091. static void __cdecl _un_inc (
  1092.     int chr,
  1093.     FILE *fileptr
  1094.     )
  1095. {
  1096.     if (EOF != chr)
  1097.         _ungetc_lk(chr, fileptr);
  1098. }
  1099.  
  1100. static int __cdecl _whiteout (
  1101.     REG1 int *counter,
  1102.     REG3 FILE *fileptr
  1103.     )
  1104. {
  1105.     REG2 int ch;
  1106.  
  1107.     while((_istspace)(ch = (++*counter, _inc(fileptr))));
  1108.     return ch;
  1109. }
  1110.  
  1111. #endif  /* defined (_UNICODE) */
  1112.  
  1113.  
  1114. #else  /* _WIN32 */
  1115.  
  1116. #if defined (_M_MPPC) || defined (_M_M68K)
  1117.  
  1118.  
  1119. #define ALLOW_RANGE /* allow "%[a-z]"-style scansets */
  1120.  
  1121. /* temporary work-around for compiler without 64-bit support */
  1122.  
  1123. #ifndef _INTEGRAL_MAX_BITS
  1124. #define _INTEGRAL_MAX_BITS  64
  1125. #endif  /* _INTEGRAL_MAX_BITS */
  1126.  
  1127. #include <cruntime.h>
  1128. #include <stdio.h>
  1129. #include <dbgint.h>
  1130. #include <ctype.h>
  1131. #include <cvt.h>
  1132. #include <conio.h>
  1133. #include <stdarg.h>
  1134. #include <string.h>
  1135. #include <internal.h>
  1136. #include <fltintrn.h>
  1137. #include <mtdll.h>
  1138. #include <stdlib.h>
  1139. #include <nlsint.h>
  1140. #include <tchar.h>
  1141.  
  1142. #define HEXTODEC(chr)   _hextodec(chr)
  1143. #define LEFT_BRACKET    ('[' | ('a' - 'A')) /* 'lowercase' version */
  1144.  
  1145. #ifdef _UNICODE
  1146. static wchar_t __cdecl _hextodec(wchar_t);
  1147. #else  /* _UNICODE */
  1148. static int __cdecl _hextodec(int);
  1149. #endif  /* _UNICODE */
  1150.  
  1151. /*
  1152.  * Note: CPRFLAG and _UNICODE cases are currently mutually exclusive.
  1153.  */
  1154.  
  1155. #ifdef CPRFLAG
  1156.  
  1157. #define INC()           (++charcount, _inc())
  1158. #define UN_INC(chr)     (--charcount, _ungetch_lk(chr))
  1159. #define EAT_WHITE()     _whiteout(&charcount)
  1160.  
  1161. static int __cdecl _inc(void);
  1162. static int __cdecl _whiteout(int *);
  1163.  
  1164. #else  /* CPRFLAG */
  1165.  
  1166. #define INC()           (++charcount, _inc(stream))
  1167. #define UN_INC(chr)     (--charcount, _un_inc(chr, stream))
  1168. #define EAT_WHITE()     _whiteout(&charcount, stream)
  1169.  
  1170. #ifndef _UNICODE
  1171. static int __cdecl _inc(FILE *);
  1172. static void __cdecl _un_inc(int, FILE *);
  1173. static int __cdecl _whiteout(int *, FILE *);
  1174. #else  /* _UNICODE */
  1175. static wchar_t __cdecl _inc(FILE *);
  1176. static void __cdecl _un_inc(wchar_t, FILE *);
  1177. static wchar_t __cdecl _whiteout(int *, FILE *);
  1178. #endif  /* _UNICODE */
  1179.  
  1180. #endif  /* CPRFLAG */
  1181.  
  1182.  
  1183. #ifdef _UNICODE
  1184. static int __cdecl _winput(FILE *, const unsigned char *, va_list);
  1185. #endif  /* _UNICODE */
  1186.  
  1187. #ifdef CPRFLAG
  1188. static int __cdecl input(const unsigned char *, va_list);
  1189.  
  1190.  
  1191. /***
  1192. *int _cscanf(format, arglist) - read formatted input direct from console
  1193. *
  1194. *Purpose:
  1195. *   Reads formatted data like scanf, but uses console I/O functions.
  1196. *
  1197. *Entry:
  1198. *   char *format - format string to determine data formats
  1199. *   arglist - list of POINTERS to where to put data
  1200. *
  1201. *Exit:
  1202. *   returns number of successfully matched data items (from input)
  1203. *
  1204. *Exceptions:
  1205. *
  1206. *******************************************************************************/
  1207.  
  1208.  
  1209. int __cdecl _cscanf (
  1210.     const char *format,
  1211.     ...
  1212.     )
  1213. {
  1214.     va_list arglist;
  1215.  
  1216.     va_start(arglist, format);
  1217.  
  1218.     _ASSERTE(format != NULL);
  1219.  
  1220.     return input(format,arglist);   /* get the input */
  1221. }
  1222.  
  1223. #endif  /* CPRFLAG */
  1224.  
  1225.  
  1226. #define ASCII       32           /* # of bytes needed to hold 256 bits */
  1227.  
  1228. #define SCAN_SHORT     0         /* also for FLOAT */
  1229. #define SCAN_LONG      1         /* also for DOUBLE */
  1230. #define SCAN_L_DOUBLE  2         /* only for LONG DOUBLE */
  1231.  
  1232. #define SCAN_NEAR    0
  1233. #define SCAN_FAR     1
  1234.  
  1235.  
  1236. static char sbrackset[] = " \t-\n]"; /* use range-style list, cl68 swaps \n to \r*/
  1237.  
  1238.  
  1239. static char cbrackset[] = "]";
  1240.  
  1241.  
  1242.  
  1243. /***
  1244. *int _input(stream, format, arglist), static int input(format, arglist)
  1245. *
  1246. *Purpose:
  1247. *   get input items (data items or literal matches) from the input stream
  1248. *   and assign them if appropriate to the items thru the arglist. this
  1249. *   function is intended for internal library use only, not for the user
  1250. *
  1251. *   The _input entry point is for the normal scanf() functions
  1252. *   The input entry point is used when compiling for _cscanf() [CPRFLAF
  1253. *   defined] and is a static function called only by _cscanf() -- reads from
  1254. *   console.
  1255. *
  1256. *Entry:
  1257. *   FILE *stream - file to read from
  1258. *   char *format - format string to determine the data to read
  1259. *   arglist - list of pointer to data items
  1260. *
  1261. *Exit:
  1262. *   returns number of items assigned and fills in data items
  1263. *   returns EOF if error or EOF found on stream before 1st data item matched
  1264. *
  1265. *Exceptions:
  1266. *
  1267. *******************************************************************************/
  1268.  
  1269. #ifdef CPRFLAG
  1270.  
  1271. static int __cdecl input (
  1272.     const unsigned char *format,
  1273.     va_list arglist
  1274.     )
  1275. #elif defined (_UNICODE)
  1276.  
  1277. static int __cdecl _winput (
  1278.     FILE *stream,
  1279.     const unsigned char *format,
  1280.     va_list arglist
  1281.     )
  1282. #else  /* defined (_UNICODE) */
  1283.  
  1284. int __cdecl _input (
  1285.     FILE *stream,
  1286.     const unsigned char *format,
  1287.     va_list arglist
  1288.     )
  1289. #endif  /* defined (_UNICODE) */
  1290.  
  1291. {
  1292.     char table[ASCII];                  /* which chars allowed for %[], %s   */
  1293. #ifndef _UNICODE
  1294.     char floatstring[CVTBUFSIZE + 1];   /* ASCII buffer for floats           */
  1295. #else  /* _UNICODE */
  1296.     wchar_t floatstring[CVTBUFSIZE + 1];
  1297. #endif  /* _UNICODE */
  1298.  
  1299.     unsigned long number;               /* temp hold-value                   */
  1300.     unsigned __int64 num64;             /* temp for 64-bit integers          */
  1301.     void *pointer;                      /* points to user data receptacle    */
  1302.     void *start;                        /* indicate non-empty string         */
  1303.  
  1304.     unsigned char *scanptr;             /* for building "table" data         */
  1305.  
  1306. #ifdef _UNICODE
  1307. REG2 wchar_t ch;
  1308. #else  /* _UNICODE */
  1309. REG2 int ch;
  1310. #endif  /* _UNICODE */
  1311.     int charcount;                      /* total number of chars read        */
  1312. REG1 int comchr;                        /* holds designator type             */
  1313.     int count;                          /* return value.  # of assignments   */
  1314.  
  1315.     int started;                        /* indicate good number              */
  1316.     int width;                          /* width of field                    */
  1317.     int widthset;                       /* user has specified width          */
  1318.  
  1319. /* Neither coerceshort nor farone are need for the 386 */
  1320.  
  1321.     unsigned char rngch;                /* used while scanning range         */
  1322.  
  1323.     char done_flag;                     /* general purpose loop monitor      */
  1324.     unsigned char last;                 /* also for %[a-z]                   */
  1325.     char longone;                       /* 0 = SHORT, 1 = LONG, 2 = L_DOUBLE */
  1326.     int integer64;                      /* 1 for 64-bit integer, 0 otherwise */
  1327.     char negative;                      /* flag for '-' detected             */
  1328.     unsigned char prevchar;             /* for %[a-z]                        */
  1329.     char reject;                        /* %[^ABC] instead of %[ABC]         */
  1330.     char suppress;                      /* don't assign anything             */
  1331.     char match;                         /* flag: !0 if any fields matched    */
  1332.     va_list arglistsave;                /* save arglist value                */
  1333.  
  1334.     char fl_wchar_arg;                  /* flags wide char/string argument   */
  1335. #ifdef _UNICODE
  1336.     wchar_t wdecimal;                   /* wide version of decimal point     */
  1337.     wchar_t *wptr;                      /* pointer traverses wide floatstring*/
  1338. #endif  /* _UNICODE */
  1339.  
  1340.     int _tflag = 0;
  1341.  
  1342.     _ASSERTE(format != NULL);
  1343.  
  1344. #ifndef CPRFLAG
  1345.     _ASSERTE(stream != NULL);
  1346. #endif  /* CPRFLAG */
  1347.  
  1348.     /*
  1349.     count = # fields assigned
  1350.     charcount = # chars read
  1351.     match = flag indicating if any fields were matched
  1352.  
  1353.     [Note that we need both count and match.  For example, a field
  1354.     may match a format but have assignments suppressed.  In this case,
  1355.     match will get set, but 'count' will still equal 0.  We need to
  1356.     distinguish 'match vs no-match' when terminating due to EOF.]
  1357.     */
  1358.  
  1359.     count = charcount = match = 0;
  1360.  
  1361.     while (*format) {
  1362.  
  1363.         if (isspace((int)*format)) {
  1364.  
  1365.             UN_INC(EAT_WHITE()); /* put first non-space char back */
  1366.  
  1367.             while ((isspace)(*++format)); /* NULL */
  1368.             /* careful: isspace macro may evaluate argument more than once! */
  1369.  
  1370.         }
  1371.  
  1372.         if ('%' == *format) {
  1373.  
  1374.             number = width = widthset = started = done_flag =
  1375.  
  1376.             /* ints are the same size as longs and all pointers are 'near' for
  1377.                the 386 */
  1378.  
  1379.             suppress = negative = reject = prevchar = 0;
  1380.             longone = 1;
  1381.  
  1382.             integer64 = 0;
  1383.  
  1384.             fl_wchar_arg = 0;
  1385.  
  1386.             while (!done_flag) {
  1387.  
  1388.                 comchr = *++format;
  1389.                 if (isdigit(comchr)) {
  1390.                     ++widthset;
  1391.                     width = MUL10(width) + (comchr - '0');
  1392.                 } else
  1393.                     switch (comchr) {
  1394.                         case 'F':
  1395.                         case 'N':   /* no way to push NEAR in large model */
  1396.                             break;  /* NEAR is default in small model */
  1397.                         case 'h':
  1398.                             /* set longone to 0 */
  1399.                             --longone;
  1400.                             break;
  1401.  
  1402.             case _T('I'):
  1403.                 if ( (*(format + 1) == _T('6')) &&
  1404.                      (*(format + 2) == _T('4')) )
  1405.                 {
  1406.                     format += 2;
  1407.                     ++integer64;
  1408.                     num64 = 0;
  1409.                     break;
  1410.                 }
  1411.                 goto DEFAULT_LABEL;
  1412.  
  1413.             case 'L':
  1414.                             ++longone;
  1415.                                     /* NOBREAK */
  1416.                         case 'l':
  1417.                             ++longone;
  1418.                             break;
  1419.                         case '*':
  1420.                             ++suppress;
  1421.                             break;
  1422.  
  1423.                         default:
  1424. DEFAULT_LABEL:
  1425.                             ++done_flag;
  1426.                             break;
  1427.                     }
  1428.             }
  1429.  
  1430.             if (!suppress) {
  1431.                 arglistsave = arglist;
  1432.                 pointer = va_arg(arglist,void *);
  1433.             }
  1434.  
  1435.             done_flag = 0;
  1436.  
  1437.             /* switch to lowercase to allow %E,%G, and to
  1438.                keep the switch table small */
  1439.  
  1440.             comchr = *format | ('a' - 'A');
  1441.  
  1442.             /*
  1443.              *  Generic string handling support:  %tc, %ts accept
  1444.              *  either chars or wide-chars depending on _tflag.
  1445.              *  _tflag == 1 means wide-chars.
  1446.              */
  1447.             if (comchr == 't') {
  1448.                 if (_tflag == 1)
  1449.                     comchr = 'w';
  1450.                 else
  1451.                     comchr = *(++format);
  1452.             }
  1453.  
  1454.             if ('n' != comchr)
  1455.                 if ('w' == comchr) {
  1456.                     fl_wchar_arg = 1;
  1457.                     comchr = *++format;
  1458.                     if (comchr == 'c')
  1459.                         ch = INC();
  1460.                     else if (comchr == 's')
  1461.                         ch = EAT_WHITE();
  1462.                     else
  1463.                         goto error_return; /* not 'wc' or 'ws' */
  1464.                 } else
  1465.                 if ('c' != comchr && LEFT_BRACKET != comchr)
  1466.                     ch = EAT_WHITE();
  1467.                 else
  1468.                     ch = INC();
  1469.  
  1470.             if (!widthset || width) {
  1471.  
  1472.                 switch(comchr) {
  1473.  
  1474.                     case 'c':
  1475.                         if (!widthset) {
  1476.                             ++widthset;
  1477.                             ++width;
  1478.                         }
  1479.                         scanptr = cbrackset;
  1480.                         --reject; /* set reject to 255 */
  1481.                         goto scanit2;
  1482.  
  1483.                     case 's':
  1484.                         scanptr = sbrackset;
  1485.                         --reject; /* set reject to 255 */
  1486.                         goto scanit2;
  1487.  
  1488.                     case LEFT_BRACKET :   /* scanset */
  1489.                         scanptr = (char *)(++format);
  1490.  
  1491.                         if ('^' == *scanptr) {
  1492.                             ++scanptr;
  1493.                             --reject; /* set reject to 255 */
  1494.                         }
  1495.  
  1496.  
  1497. scanit2:
  1498.                         memset(table, 0, ASCII);
  1499.  
  1500.  
  1501.                         if (LEFT_BRACKET == comchr)
  1502.                             if (']' == *scanptr) {
  1503.                                 prevchar = ']';
  1504.                                 ++scanptr;
  1505.  
  1506.                                 table[ ']' >> 3] = 1 << (']' & 7);
  1507.  
  1508.                             }
  1509.  
  1510.                         while (']' != *scanptr) {
  1511.  
  1512.                             rngch = *scanptr++;
  1513.  
  1514.                             if ('-' != rngch ||
  1515.                                  !prevchar ||           /* first char */
  1516.                                  ']' == *scanptr) /* last char */
  1517.  
  1518.                                 table[(prevchar = rngch) >> 3] |= 1 << (rngch & 7);
  1519.  
  1520.                             else {  /* handle a-z type set */
  1521.  
  1522.                                 rngch = *scanptr++; /* get end of range */
  1523.  
  1524.                                 if (prevchar < rngch)  /* %[a-z] */
  1525.                                     last = rngch;
  1526.                                 else {              /* %[z-a] */
  1527.                                     last = prevchar;
  1528.                                     prevchar = rngch;
  1529.                                 }
  1530.                                 for (rngch = prevchar; rngch <= last; ++rngch)
  1531.                                     table[rngch >> 3] |= 1 << (rngch & 7);
  1532.  
  1533.                                 prevchar = 0;
  1534.  
  1535.                             }
  1536.                         }
  1537.  
  1538.  
  1539.                         if (!*scanptr)
  1540.                             goto error_return;      /* trunc'd format string */
  1541.  
  1542.                         /* scanset completed.  Now read string */
  1543.  
  1544.                         if (LEFT_BRACKET == comchr)
  1545.                             format = scanptr;
  1546.  
  1547.                         start = pointer;
  1548.  
  1549.                         /*
  1550.                          * execute the format directive. that is, scan input
  1551.                          * characters until the directive is fulfilled, eof
  1552.                          * is reached, or a non-matching character is
  1553.                          * encountered.
  1554.                          *
  1555.                          * it is important not to get the next character
  1556.                          * unless that character needs to be tested! other-
  1557.                          * wise, reads from line-buffered devices (e.g.,
  1558.                          * scanf()) would require an extra, spurious, newline
  1559.                          * if the first newline completes the current format
  1560.                          * directive.
  1561.                          */
  1562.                         UN_INC(ch);
  1563.  
  1564.                         while ( !widthset || width-- ) {
  1565.  
  1566.                             ch = INC();
  1567.                             if (
  1568. #ifndef _UNICODE
  1569. #ifndef CPRFLAG
  1570.                               (EOF != ch) &&
  1571. #endif  /* CPRFLAG */
  1572.                               ((table[ch >> 3] ^ reject) & (1 << (ch & 7)))
  1573. #else  /* _UNICODE */
  1574.                               (WEOF != ch) &&
  1575.                               ((ch>>3 >= ASCII) ? reject :
  1576.                               ((table[ch >> 3] ^ reject) &
  1577.                                         (1 << (ch & 7))))
  1578. #endif  /* _UNICODE */
  1579.                             ) {
  1580.                                 if (!suppress) {
  1581. #ifndef _UNICODE
  1582.                                     if (fl_wchar_arg) {
  1583.                                         char temp[2];
  1584.                                         temp[0] = (char) ch;
  1585.                                         if (isleadbyte(ch))
  1586.                                             temp[1] = (char) INC();
  1587.                                         mbtowc((wchar_t *)pointer, temp,
  1588.                                             MB_CUR_MAX);
  1589.                                         /* do nothing if mbtowc fails */
  1590.                                         pointer = (wchar_t *)pointer + 1;
  1591.                                     } else
  1592. #else  /* _UNICODE */
  1593.                                     if (fl_wchar_arg) {
  1594.                                         *(wchar_t *)pointer = ch;
  1595.                                         pointer = (wchar_t *)pointer + 1;
  1596.                                     } else
  1597. #endif  /* _UNICODE */
  1598.                                     {
  1599. #ifndef _UNICODE
  1600.                                     *(char *)pointer = (char)ch;
  1601.                                     pointer = (char *)pointer + 1;
  1602. #else  /* _UNICODE */
  1603.                                     int temp;
  1604.                                     /* convert wide to multibyte */
  1605.                                     temp = wctomb((char *)pointer, ch);
  1606.                                     /* do nothing if wctomb fails */
  1607.                                     pointer = (char *)pointer + temp;
  1608. #endif  /* _UNICODE */
  1609.                                     }
  1610.                                 } /* suppress */
  1611.                                 else {
  1612.                                     /* just indicate a match */
  1613.                                     start = (char *)start + 1;
  1614.                                 }
  1615.                             }
  1616.                             else  {
  1617.                                 UN_INC(ch);
  1618.                                 break;
  1619.                             }
  1620.                         }
  1621.  
  1622.                         /* make sure something has been matched and, if
  1623.                            assignment is not suppressed, null-terminate
  1624.                            output string if comchr != c */
  1625.  
  1626.                         if (start != pointer) {
  1627.                             if (!suppress) {
  1628.                                 ++count;
  1629.                                 if ('c' != comchr) /* null-terminate strings */
  1630.                                     if (fl_wchar_arg)
  1631.                                         *(wchar_t *)pointer = L'\0';
  1632.                                     else
  1633.                                     *(char *)pointer = '\0';
  1634.                             } else /*NULL*/;
  1635.                         }
  1636.                         else
  1637.                             goto error_return;
  1638.  
  1639.                         break;
  1640.  
  1641.                     case 'i':   /* could be d, o, or x */
  1642.  
  1643.                         comchr = 'd'; /* use as default */
  1644.  
  1645.                     case 'x':
  1646.  
  1647.                         if (_T('-') == ch) {
  1648.                             ++negative;
  1649.  
  1650.                             goto x_incwidth;
  1651.  
  1652.                         } else if (_T('+') == ch) {
  1653. x_incwidth:
  1654.                             if (!--width && widthset)
  1655.                                 ++done_flag;
  1656.                             else
  1657.                                 ch = INC();
  1658.                         }
  1659.  
  1660.                         if (_T('0') == ch) {
  1661.  
  1662. #ifdef _UNICODE
  1663.                             if (L'x' == (ch = INC()) || L'X' == ch) {
  1664. #else  /* _UNICODE */
  1665.                             if ('x' == ((char)(ch = INC())) || 'X' == (char)ch){
  1666. #endif  /* _UNICODE */
  1667.                                 ch = INC();
  1668.                                 comchr = 'x';
  1669.                             } else {
  1670.                                 ++started;
  1671.                                 if ('x' != comchr)
  1672.                                     comchr = 'o';
  1673.                                 else {
  1674.                                     /* scanning a hex number that starts */
  1675.                                     /* with a 0. push back the character */
  1676.                                     /* currently in ch and restore the 0 */
  1677.                                     UN_INC(ch);
  1678.                                     ch = _T('0');
  1679.                                 }
  1680.                             }
  1681.                         }
  1682.                         goto getnum;
  1683.  
  1684.                         /* NOTREACHED */
  1685.  
  1686.                     case 'p':
  1687.                         /* force %hp to be treated as %p */
  1688.                         longone = 1;
  1689.  
  1690.                     case 'o':
  1691.                     case 'u':
  1692.                     case 'd':
  1693.  
  1694.                         if (_T('-') == ch) {
  1695.                             ++negative;
  1696.  
  1697.                             goto d_incwidth;
  1698.  
  1699.                         } else if (_T('+') == ch) {
  1700. d_incwidth:
  1701.                             if (!--width && widthset)
  1702.                                 ++done_flag;
  1703.                             else
  1704.                                 ch = INC();
  1705.                         }
  1706.  
  1707. getnum:
  1708.                         if ( integer64 ) {
  1709.  
  1710.                             while (!done_flag) {
  1711.  
  1712.                                 if (_T('x') == comchr)
  1713.  
  1714. #ifdef _UNICODE
  1715.                                     if (iswxdigit(ch)) {
  1716. #else  /* _UNICODE */
  1717.                                     if (isxdigit(ch)) {
  1718. #endif  /* _UNICODE */
  1719.                                         num64 = (num64 << 4);
  1720.                                             ch = HEXTODEC(ch);
  1721.                                     }
  1722.                                     else
  1723.                                         ++done_flag;
  1724.  
  1725. #ifdef _UNICODE
  1726.                                 else if (iswdigit(ch))
  1727. #else  /* _UNICODE */
  1728.                                 else if (isdigit(ch))
  1729. #endif  /* _UNICODE */
  1730.  
  1731.                                     if (_T('o') == comchr)
  1732.                                         if (_T('8') > ch)
  1733.                                             num64 = (num64 << 3);
  1734.                                         else {
  1735.                                             ++done_flag;
  1736.                                         }
  1737.                                     else /* _T('d') == comchr */
  1738.                                             num64 = MUL10(num64);
  1739.  
  1740.                                 else
  1741.                                     ++done_flag;
  1742.  
  1743.                                 if (!done_flag) {
  1744.                                     ++started;
  1745.                                     num64 += ch - _T('0');
  1746.  
  1747.                                     if (widthset && !--width)
  1748.                                             ++done_flag;
  1749.                                     else
  1750.                                             ch = INC();
  1751.                                 } else
  1752.                                     UN_INC(ch);
  1753.  
  1754.                             } /* end of WHILE loop */
  1755.  
  1756.                             if (negative)
  1757.                                     num64 = (unsigned __int64 )(-(__int64)num64);
  1758.                         }
  1759.                         else {
  1760.  
  1761.                             while (!done_flag) {
  1762.  
  1763.                                 if ('x' == comchr || 'p' == comchr)
  1764.  
  1765. #ifdef _UNICODE
  1766.                                     if (iswxdigit(ch)) {
  1767. #else  /* _UNICODE */
  1768.                                     if (isxdigit(ch)) {
  1769. #endif  /* _UNICODE */
  1770.                                         number = (number << 4);
  1771.                                         ch = HEXTODEC(ch);
  1772.                                     }
  1773.                                     else
  1774.                                         ++done_flag;
  1775.  
  1776. #ifdef _UNICODE
  1777.                                 else if (iswdigit(ch))
  1778. #else  /* _UNICODE */
  1779.                                 else if (isdigit(ch))
  1780. #endif  /* _UNICODE */
  1781.  
  1782.                                     if ('o' == comchr)
  1783.                                         if (_T('8') > ch)
  1784.                                             number = (number << 3);
  1785.                                         else {
  1786.                                             ++done_flag;
  1787.                                         }
  1788.                                     else /* 'd' == comchr */
  1789.                                         number = MUL10(number);
  1790.  
  1791.                                 else
  1792.                                     ++done_flag;
  1793.  
  1794.                                 if (!done_flag) {
  1795.                                     ++started;
  1796.                                     number += ch - _T('0');
  1797.  
  1798.                                     if (widthset && !--width)
  1799.                                         ++done_flag;
  1800.                                     else
  1801.                                         ch = INC();
  1802.                                 } else
  1803.                                      UN_INC(ch);
  1804.  
  1805.                             } /* end of WHILE loop */
  1806.  
  1807.                             if (negative)
  1808.                                 number = (unsigned long)-(long)number;
  1809.                         }
  1810.  
  1811.                         if ('F' == comchr)  /* expected a ':' in long pointer */
  1812.                             started = 0;
  1813.  
  1814.                         if (started)
  1815.                             if (!suppress) {
  1816.  
  1817.                                 ++count;
  1818. assign_num:
  1819.                                 if ( integer64 )
  1820.                                     *(__int64 UNALIGNED *)pointer = (unsigned __int64)num64;
  1821.                                 else if (longone)
  1822.                                     *(long *)pointer = (unsigned long)number;
  1823.                                 else
  1824.                                     *(short *)pointer = (unsigned short)number;
  1825.  
  1826.                             } else /*NULL*/;
  1827.                         else
  1828.                             goto error_return;
  1829.  
  1830.                         break;
  1831.  
  1832.                     case 'n':   /* char count, don't inc return value */
  1833.                         number = charcount;
  1834.                         goto assign_num; /* found in number code above */
  1835.  
  1836.  
  1837.                     case 'e':
  1838.                     case 'f':
  1839.                     case 'g': /* scan a float */
  1840.  
  1841. #ifndef _UNICODE
  1842.                         scanptr = floatstring;
  1843.  
  1844.                         if ('-' == ch) {
  1845.                             *scanptr++ = '-';
  1846.                             goto f_incwidth;
  1847.  
  1848.                         } else if ('+' == ch) {
  1849. f_incwidth:
  1850.                             --width;
  1851.                             ch = INC();
  1852.                         }
  1853.  
  1854.                         if (!widthset || width > CVTBUFSIZE)              /* must watch width */
  1855.                             width = CVTBUFSIZE;
  1856.  
  1857.  
  1858.                         /* now get integral part */
  1859.  
  1860.                         while (isdigit(ch) && width--) {
  1861.                             ++started;
  1862.                             *scanptr++ = (char)ch;
  1863.                             ch = INC();
  1864.                         }
  1865.  
  1866.                         /* now check for decimal */
  1867.  
  1868.                         if (*___decimal_point == (char)ch && width--) {
  1869.                             ch = INC();
  1870.                             *scanptr++ = *___decimal_point;
  1871.  
  1872.                             while (isdigit(ch) && width--) {
  1873.                                 ++started;
  1874.                                 *scanptr++ = (char)ch;
  1875.                                 ch = INC();
  1876.                             }
  1877.                         }
  1878.  
  1879.                         /* now check for exponent */
  1880.  
  1881.                         if (started && ('e' == (char)ch || 'E' == (char)ch) && width--) {
  1882.                             *scanptr++ = 'e';
  1883.  
  1884.                             if ('-' == (ch = INC())) {
  1885.  
  1886.                                 *scanptr++ = '-';
  1887.                                 goto f_incwidth2;
  1888.  
  1889.                             } else if ('+' == ch) {
  1890. f_incwidth2:
  1891.                                 if (!width--)
  1892.                                     ++width;
  1893.                                 else
  1894.                                     ch = INC();
  1895.                             }
  1896.  
  1897.  
  1898.                             while (isdigit(ch) && width--) {
  1899.                                 ++started;
  1900.                                 *scanptr++ = (char)ch;
  1901.                                 ch = INC();
  1902.                             }
  1903.  
  1904.                         }
  1905.  
  1906.                         UN_INC(ch);
  1907.  
  1908.                         if (started)
  1909.                             if (!suppress) {
  1910.                                 ++count;
  1911.                                 *scanptr = '\0';
  1912.                                 _fassign( longone-1, pointer , floatstring);
  1913.                             } else /*NULL */;
  1914.                         else
  1915.                             goto error_return;
  1916.  
  1917. #else  /* _UNICODE */
  1918.                         wptr = floatstring;
  1919.  
  1920.                         if (L'-' == ch) {
  1921.                             *wptr++ = L'-';
  1922.                             goto f_incwidthw;
  1923.  
  1924.                         } else if (L'+' == ch) {
  1925. f_incwidthw:
  1926.                             --width;
  1927.                             ch = INC();
  1928.                         }
  1929.  
  1930.                         if (!widthset || width > CVTBUFSIZE)
  1931.                             width = CVTBUFSIZE;
  1932.  
  1933.  
  1934.                         /* now get integral part */
  1935.  
  1936.                         while (iswdigit(ch) && width--) {
  1937.                             ++started;
  1938.                             *wptr++ = ch;
  1939.                             ch = INC();
  1940.                         }
  1941.  
  1942.                         /* now check for decimal */
  1943.  
  1944.                         /* convert decimal point to wide-char */
  1945.                         /* assume result is single wide-char */
  1946.                         mbtowc (&wdecimal, ___decimal_point, MB_CUR_MAX);
  1947.  
  1948.                         if (wdecimal == ch && width--) {
  1949.                             ch = INC();
  1950.                             *wptr++ = wdecimal;
  1951.  
  1952.                             while (iswdigit(ch) && width--) {
  1953.                                 ++started;
  1954.                                 *wptr++ = ch;
  1955.                                 ch = INC();
  1956.                             }
  1957.                         }
  1958.  
  1959.                         /* now check for exponent */
  1960.  
  1961.                         if (started && (L'e' == ch || L'E' == ch) && width--) {
  1962.                             *wptr++ = L'e';
  1963.  
  1964.                             if (L'-' == (ch = INC())) {
  1965.  
  1966.                                 *wptr++ = L'-';
  1967.                                 goto f_incwidth2w;
  1968.  
  1969.                             } else if (L'+' == ch) {
  1970. f_incwidth2w:
  1971.                                 if (!width--)
  1972.                                     ++width;
  1973.                                 else
  1974.                                     ch = INC();
  1975.                             }
  1976.  
  1977.  
  1978.                             while (iswdigit(ch) && width--) {
  1979.                                 ++started;
  1980.                                 *wptr++ = ch;
  1981.                                 ch = INC();
  1982.                             }
  1983.  
  1984.                         }
  1985.  
  1986.                         UN_INC(ch);
  1987.  
  1988.                         if (started)
  1989.                             if (!suppress) {
  1990.                                 ++count;
  1991.                                 *wptr = '\0';
  1992.                                 {
  1993.                                 /* convert floatstring to char string */
  1994.                                 /* and do the conversion */
  1995.                                 size_t cfslength;
  1996.                                 char *cfloatstring;
  1997.                                 cfslength =(wptr-floatstring+1)*sizeof(wchar_t);
  1998.                                 cfloatstring = (char *)malloc (cfslength);
  1999.                                 wcstombs (cfloatstring, floatstring, cfslength);
  2000.                                 _fassign( longone-1, pointer , cfloatstring);
  2001.                                 free (cfloatstring);
  2002.                                 }
  2003.                             } else /*NULL */;
  2004.                         else
  2005.                             goto error_return;
  2006.  
  2007. #endif  /* _UNICODE */
  2008.                         break;
  2009.  
  2010.  
  2011.                     default:    /* either found '%' or something else */
  2012.  
  2013.                         if ((int)*format != (int)ch) {
  2014.                             UN_INC(ch);
  2015.                             goto error_return;
  2016.                             }
  2017.                         else
  2018.                             match--; /* % found, compensate for inc below */
  2019.  
  2020.                         if (!suppress)
  2021.                             arglist = arglistsave;
  2022.  
  2023.                 } /* SWITCH */
  2024.  
  2025.                 match++;        /* matched a format field - set flag */
  2026.  
  2027.             } /* WHILE (width) */
  2028.  
  2029.             else {  /* zero-width field in format string */
  2030.                 UN_INC(ch);  /* check for input error */
  2031.                 goto error_return;
  2032.             }
  2033.  
  2034.             ++format;  /* skip to next char */
  2035.  
  2036.         } else  /*  ('%' != *format) */
  2037.             {
  2038.  
  2039.             if ((int)*format++ != (int)(ch = INC()))
  2040.                 {
  2041.                 UN_INC(ch);
  2042.                 goto error_return;
  2043.                 }
  2044. #ifndef _UNICODE
  2045.             if (isleadbyte(ch))
  2046.                 {
  2047.                 int ch2;
  2048.                 if ((int)*format++ != (ch2=INC()))
  2049.                     {
  2050.                     UN_INC(ch2);
  2051.                     UN_INC(ch);
  2052.                     goto error_return;
  2053.                     }
  2054.  
  2055.                     --charcount; /* only count as one character read */
  2056.                 }
  2057. #endif  /* _UNICODE */
  2058.             }
  2059.  
  2060. #ifndef CPRFLAG
  2061.         if ( (EOF == ch) && ((*format != '%') || (*(format + 1) != 'n')) )
  2062.             break;
  2063. #endif  /* CPRFLAG */
  2064.  
  2065.     }  /* WHILE (*format) */
  2066.  
  2067. error_return:
  2068.  
  2069. #ifndef CPRFLAG
  2070.     if (EOF == ch)
  2071.         /* If any fields were matched or assigned, return count */
  2072.         return ( (count || match) ? count : EOF);
  2073.     else
  2074. #endif  /* CPRFLAG */
  2075.         return count;
  2076.  
  2077. }
  2078.  
  2079. /* _hextodec() returns a value of 0-15 and expects a char 0-9, a-f, A-F */
  2080. /* _inc() is the one place where we put the actual getc code. */
  2081. /* _whiteout() returns the first non-blank character, as defined by isspace() */
  2082.  
  2083. #ifndef _UNICODE
  2084. static int __cdecl _hextodec (
  2085.     int chr
  2086.     )
  2087. {
  2088.     return isdigit(chr) ? chr : (chr & ~('a' - 'A')) - 'A' + 10 + '0';
  2089. }
  2090. #else  /* _UNICODE */
  2091. static wchar_t __cdecl _hextodec (
  2092.     wchar_t chr
  2093.     )
  2094. {
  2095.     if (iswdigit(chr))
  2096.         return chr;
  2097.     if (iswlower(chr))
  2098.         return (wchar_t)(chr - L'a' + 10 + L'0');
  2099.     else
  2100.         return (wchar_t)(chr - L'A' + 10 + L'0');
  2101. }
  2102. #endif  /* _UNICODE */
  2103.  
  2104.  
  2105. #ifdef CPRFLAG
  2106.  
  2107. static int __cdecl _inc (
  2108.     void
  2109.     )
  2110. {
  2111.     return(_getche_lk());
  2112. }
  2113.  
  2114. static int __cdecl _whiteout (
  2115.     REG1 int *counter
  2116.     )
  2117. {
  2118.     REG2 int ch;
  2119.  
  2120.     while((isspace)(ch = (++*counter, _inc())));
  2121.     return ch;
  2122. }
  2123.  
  2124. #elif defined (_UNICODE)
  2125.  
  2126. /*
  2127.  * Manipulate wide-chars in a file.
  2128.  * A wide-char is hard-coded to be two chars for efficiency.
  2129.  */
  2130.  
  2131. static wchar_t __cdecl _inc (
  2132.     REG1 FILE *fileptr
  2133.     )
  2134. {
  2135.     wchar_t c1, c2;
  2136.  
  2137.     c1 = (wchar_t)_getc_lk(fileptr);
  2138.     c2 = (wchar_t)_getc_lk(fileptr);
  2139.     return (wchar_t)((feof(fileptr) || ferror(fileptr)) ? WEOF : c2<<8 | c1);
  2140. }
  2141.  
  2142. static void __cdecl _un_inc (
  2143.     wchar_t chr,
  2144.     FILE *fileptr
  2145.     )
  2146. {
  2147.     if (WEOF != chr) {
  2148.         _ungetc_lk((int)(chr >> 8), fileptr);
  2149.         _ungetc_lk((int)(chr & 0xff), fileptr);
  2150.     }
  2151. }
  2152.  
  2153. static wchar_t __cdecl _whiteout (
  2154.     REG1 int *counter,
  2155.     REG3 FILE *fileptr
  2156.     )
  2157. {
  2158.     REG2 wchar_t ch;
  2159.  
  2160.     while((iswspace)(ch = (++*counter, _inc(fileptr))));
  2161.     return ch;
  2162. }
  2163.  
  2164. #else  /* defined (_UNICODE) */
  2165.  
  2166. static int __cdecl _inc (
  2167.     REG1 FILE *fileptr
  2168.     )
  2169. {
  2170.     return(_getc_lk(fileptr));
  2171. }
  2172.  
  2173. static void __cdecl _un_inc (
  2174.     int chr,
  2175.     FILE *fileptr
  2176.     )
  2177. {
  2178.     if (EOF != chr)
  2179.         _ungetc_lk(chr, fileptr);
  2180. }
  2181.  
  2182. static int __cdecl _whiteout (
  2183.     REG1 int *counter,
  2184.     REG3 FILE *fileptr
  2185.     )
  2186. {
  2187.     REG2 int ch;
  2188.  
  2189.     while((isspace)(ch = (++*counter, _inc(fileptr))));
  2190.     return ch;
  2191. }
  2192.  
  2193. #endif  /* defined (_UNICODE) */
  2194.  
  2195.  
  2196. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  2197.  
  2198. #endif  /* _WIN32 */
  2199.