*scanf routines and updates to other input routines v.0.21 alpha for TIGCC
Copyright (C) 2002-2003 Kevin Kofler

These routines are free software; you can redistribute and/or modify them
under the terms of the TIGCCLIB license, as stated in License.txt.

These files are distributed in the hope that they will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the license
documents for more details.

Please take that disclaimer of warranties seriously: THIS IS AN ALPHA VERSION,
AND MAY THEREFORE CONTAIN BUGS. Please report any bugs you encounter to
Kevin@tigcc.ticalc.org.

Also, all documentation below is PRELIMINARY, and MAY CONTAIN ERRORS, including,
but not limited to, typos, mismatch between documented behavior and actual
behavior and/or unintentionally omitted details.


To use those routines:
* Make sure you are using a current version of TIGCC. TIGCC 0.94 (release, SP1-4)
  is known to work. TIGCC 0.94 beta 18-22 will probably work too. TIGCC 0.93 will
  NOT work though, and NEITHER will the first 0.94 betas. Moreover, if your
  version of TIGCC is newer than 0.94 SP4, make sure you are using the
  current version of my routines. (TIGCC versions released after this package
  might also have those routines built-in into tigcc.a.)
* Add "scanf.h" to your project and include it. Do NOT attempt to define
  the prototypes yourself: the user-visible functions are all macros which
  wrap around internal routines.
* Add "scanf.a" to your project. (Alternatively, you might also add the
  individual source files, but in that case, make sure you include only the
  source files you need. When using the .a file, ld takes care of that for you.)


The following *scanf macros are available: (The function prototypes are fake.)
short sscanf(const char *buffer, const char *format, ...);
short fscanf(FILE *file, const char *format, ...);
short scanf(const char *format, ...);
short vsscanf(const char *buffer, const char *format, va_list arglist);
short vfscanf(FILE *file, const char *format, va_list arglist);
short vscanf(const char *format, va_list arglist);
short vcbscanf(vcbscanf_get_Callback_t getfun,
               vcbscanf_unget_Callback_t ungetfun, void *param,
               const char *format, va_list arglist);


short sscanf(const char *buffer, const char *format, ...);
Scans the string "buffer" for the formats in the format string "format" and
assigns the input to pointers passed as varargs.
Returns:
* the number of pointers filled in (the number of matches done) if it is non-0
* 0 if no pointers were filled in because of a format matching error
* EOF (-1) if the input ended before any pointers were filled in
Formats accepted:
* any non-whitespace character other than '%': matches a literal character,
  assigns nothing
* whitespace characters: match any whitespace characters, even if they are
                         a different kind of whitespace, assign nothing
* '%%': matches a literal '%', assigns nothing
* Any formats of the type '%' + flags + width + type (or '%' + width + flags +
  type, the order isn't actually checked, you can even put the flags in the
  middle of the width):
Flags accepted:
* '*': skip the matched data (don't assign it to a pointer, and don't count it)
* 'h': if an integer type follows, it will be a short integer, otherwise the
       flag is ignored. (This is the default if neither 'h' nor 'l' are
       specified.)
* 'l': if an integer type follows, it will be a long integer, otherwise the
       flag is ignored
WARNING: "%h" or "%l" alone is NOT accepted. Always write "%li", "%ld", ...
         explicitely.
Width: Maximum number of bytes to read in for data matching. The maximum is
       65535. Any larger number will be truncated modulo 65536. If the width is
       0 or omitted, the default width for the format is used.
Types accepted:
* 'u': matches an unsigned decimal integer
       default width: 65536
       required pointer: 'unsigned short *' for '%hu',
                         'unsigned long *' for '%lu'
       automatically skips leading whitespace
* 'd': matches a signed decimal integer (both [-] and [(-)] are accepted)
       default width: 65536
       required pointer: 'short *' for '%hd', 'long *' for '%ld'
       automatically skips leading whitespace
* 'o': matches an unsigned octal integer
       default width: 65536
       required pointer: 'unsigned short *' for '%ho',
                         'unsigned long *' for '%lo'
       automatically skips leading whitespace
* 'x' or 'X': matches an unsigned hexadecimal integer (0-9 and both a-f and A-F
              are accepted)
              default width: 65536
              required pointer: 'unsigned short *' for '%hx', '%hX',
                                'unsigned long *' for '%lx', '%lX'
              automatically skips leading whitespace
* 'p': same as '%lx' (even if '%hp' or just '%p' is specified)
* 'i': matches an integer in C syntax: may contain a negative sign ([-] or
       [(-)]), is hexadecimal if started with 0x, octal if started with 0, and
       decimal otherwise
       default width: 65536
       required pointer: 'short *' or 'unsigned short *' for '%hi'
                         'long *' or 'unsigned long *' for '%li'
       automatically skips leading whitespace
* 'f', 'g', 'e' or 'E': matches a floating-point number. (This number will be
                        parsed by push_parse_text (through atof), so it has to
                        use the calculator '-' and 'E'.)
                        default AND MAXIMUM width: 29. This limitation is
                        because we need to allocate a buffer for 'atof' on the
                        stack, and I didn't want to waste too much stack space.
                        required pointer: 'float *'
                        automatically skips leading whitespace
* 's': matches a non-whitespace string, and null-terminates it when copying
       it to the buffer (so make sure you have a buffer of size width+1)
       default width: 65536
       required pointer: 'char *'
       automatically skips leading whitespace
* 'c': matches a fixed number of characters (the given width). Does NOT
       null-terminate the string when copying it to the buffer.
       default width: 1 (NOT the maximum width like for the other formats)
       required pointer: 'char *'
       does NOT skip leading whitespace (put a space before '%c' if you want
       to skip it)
* '[': matches a regexp-style set of characters:
       - ']' terminates the set unless it immediately follows the leading '['
         or the leading '[^'
       - if '^' is the first character, matches the characters which are NOT in
         the set
       - '-' specifies a range of characters (as in '0-9') unless it
         immediately precedes the terminating ']'
       - any other characters (including ']' right at the beginning or '-'
         right at the end): match the corresponding literal characters
       copies characters until either the input ends, or the specified width
       is reached, or a character which is not in the specified set (when using
       '^': which IS in the specified set) is encountered
       null-terminates the copied string (so make sure you have a buffer of size
       width+1)
       default width: 65536
       required pointer: 'char *'
       does NOT skip leading whitespace (put a space before '%[' if you want
       to skip it)
* 'n': does not read anything from the input, but assigns the number of
       characters already read in to the given pointer
       default width: N/A (the width is ignored, and NO characters are read in)
       required pointer: 'short *'
       does NOT skip any whitespace in the input

short fscanf(FILE *file, const char *format, ...);
Works like sscanf, but reads the input from the file "file" rather than from
a buffer of type char *.

short scanf(const char *format, ...);
Works like sscanf, but reads the input from the keyboard rather than from a
buffer of type char *. [ENTER] is interpreted as EOF.
The input is echoed on the screen. NO newline will be output at the end of the
input, no matter whether it resulted from the user pressing [ENTER] or from a
format matching error.
WARNING: If BUFFERED_SCANF is not defined, this function does NOT provide any
         editing facilities, NOT EVEN BACKSPACE. Using a buffered input routine
         such as getsn and sscanf is strongly recommended for any practical use.
         This is what is done automatically when using #define BUFFERED_SCANF.

short vsscanf(const char *buffer, const char *format, va_list arglist);
short vfscanf(FILE *file, const char *format, va_list arglist);
short vscanf(const char *format, va_list arglist);
These function-like macros work like sscanf, fscanf and scanf, respectively, but
they take their arguments as an indirect pointer (va_list) rather than as direct
varargs.

short vcbscanf(vcbscanf_get_Callback_t getfun,
               vcbscanf_unget_Callback_t ungetfun, void *param,
               const char *format, va_list arglist);
This works similarly to vcbprintf, but with *scanf instead of *printf.


Other input routines:

char *gets (char *string); 
This replaces the implementation currently (as of TIGCC 0.94) in TIGCCLIB.
It adds:
* a cursor (a simple underscore)
* backspace key handling
* support for the CHAR menu
Contrary to the macro in TIGCCLIB, it is implemented as a true function.

char *getsn(char *string, unsigned long maxlen);
Same as above, but with a maximum length specified. This is essentially the
same as InputStr from the TIGCC FAQ, but with parts optimized in assembly
and shared with gets and fgetchar (and scanf and vscanf through fgetchar or
through getsn itself).
The maximum length is the total size of the buffer. In other words, the
null-terminator is included in the maximum length.

short fgetchar(void);
This replaces the implementation currently (as of TIGCC 0.94) in TIGCCLIB.
It adds:
* a cursor (a simple underscore)
* support for the CHAR menu
Contrary to the macro in TIGCCLIB, it is implemented as a true function.
WARNING: There is NO global input buffer, so fgetchar is NOT buffered.
         fgetchar will return KEY_BACKSPACE for backspace, it is up to you to do
         do something useful with that value.


HISTORY:
========

0.10 alpha (2002-09-22): first release
0.11 alpha (2002-12-20): fixed console scanf callback:
                         * no longer taking the address of a nested function, as
                           it is not supported for HW2 by TIGCC
                         * handling [ESC] in the CHAR menu correctly
0.20 alpha (2003-07-31): * added an improved fgetchar with CHAR menu support
                         * rewrote the console scanf callback to use fgetchar
                         * added improved getsn and gets functions which allow
                           backspace and the CHAR menu
                         * scanf no longer outputs a newline at the end, for
                           consistency with the other TIGCCLIB stdio functions
                         * made vcbscanf user-visible
                         * added BUFFERED_SCANF #define option
0.21 alpha (2003-08-01): * put contents of assembly files into .text rather than
                           .data
                         * converted gets and getsn to assembly
                         * made getsn always null-terminate the string
                         * don't bother null-filling the end of the string in
                           getsn, fgets doesn't do this either
                         * don't immediately quit getsn if the buffer is full,
                           allow the user to press BACKSPACE or ENTER