diff options
Diffstat (limited to 'newlib/libc/stdio/swscanf.c')
-rw-r--r-- | newlib/libc/stdio/swscanf.c | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/newlib/libc/stdio/swscanf.c b/newlib/libc/stdio/swscanf.c new file mode 100644 index 0000000..e4e251f --- /dev/null +++ b/newlib/libc/stdio/swscanf.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<swscanf>>, <<fwscanf>>, <<wscanf>>---scan and format wide character input + +INDEX + wscanf +INDEX + _wscanf_r +INDEX + fwscanf +INDEX + _fwscanf_r +INDEX + swscanf +INDEX + _swscanf_r + +ANSI_SYNOPSIS + #include <stdio.h> + + int wscanf(const wchar_t *<[format]>, ...); + int fwscanf(FILE *<[fd]>, const wchar_t *<[format]>, ...); + int swscanf(const wchar_t *<[str]>, const wchar_t *<[format]>, ...); + + int _wscanf_r(struct _reent *<[ptr]>, const wchar_t *<[format]>, ...); + int _fwscanf_r(struct _reent *<[ptr]>, FILE *<[fd]>, + const wchar_t *<[format]>, ...); + int _swscanf_r(struct _reent *<[ptr]>, const wchar_t *<[str]>, + const wchar_t *<[format]>, ...); + + +TRAD_SYNOPSIS + #include <stdio.h> + + int wscanf(<[format]> [, <[arg]>, ...]) + wchar_t *<[format]>; + + int fwscanf(<[fd]>, <[format]> [, <[arg]>, ...]); + FILE *<[fd]>; + wchar_t *<[format]>; + + int swscanf(<[str]>, <[format]> [, <[arg]>, ...]); + wchar_t *<[str]>; + wchar_t *<[format]>; + + int _wscanf_r(<[ptr]>, <[format]> [, <[arg]>, ...]) + struct _reent *<[ptr]>; + wchar_t *<[format]>; + + int _fwscanf_r(<[ptr]>, <[fd]>, <[format]> [, <[arg]>, ...]); + struct _reent *<[ptr]>; + FILE *<[fd]>; + wchar_t *<[format]>; + + int _swscanf_r(<[ptr]>, <[str]>, <[format]> [, <[arg]>, ...]); + struct _reent *<[ptr]>; + wchar_t *<[str]>; + wchar_t *<[format]>; + + +DESCRIPTION + <<wscanf>> scans a series of input fields from standard input, + one wide character at a time. Each field is interpreted according to + a format specifier passed to <<wscanf>> in the format string at + <<*<[format]>>>. <<wscanf>> stores the interpreted input from + each field at the address passed to it as the corresponding argument + following <[format]>. You must supply the same number of + format specifiers and address arguments as there are input fields. + + There must be sufficient address arguments for the given format + specifiers; if not the results are unpredictable and likely + disasterous. Excess address arguments are merely ignored. + + <<wscanf>> often produces unexpected results if the input diverges from + an expected pattern. Since the combination of <<gets>> or <<fgets>> + followed by <<swscanf>> is safe and easy, that is the preferred way + to be certain that a program is synchronized with input at the end + of a line. + + <<fwscanf>> and <<swscanf>> are identical to <<wscanf>>, other than the + source of input: <<fwscanf>> reads from a file, and <<swscanf>> + from a string. + + The routines <<_wscanf_r>>, <<_fwscanf_r>>, and <<_swscanf_r>> are reentrant + versions of <<wscanf>>, <<fwscanf>>, and <<swscanf>> that take an additional + first argument pointing to a reentrancy structure. + + The string at <<*<[format]>>> is a wide character sequence composed + of zero or more directives. Directives are composed of + one or more whitespace characters, non-whitespace characters, + and format specifications. + + Whitespace characters are blank (<< >>), tab (<<\t>>), or + newline (<<\n>>). + When <<wscanf>> encounters a whitespace character in the format string + it will read (but not store) all consecutive whitespace characters + up to the next non-whitespace character in the input. + + Non-whitespace characters are all other ASCII characters except the + percent sign (<<%>>). When <<wscanf>> encounters a non-whitespace + character in the format string it will read, but not store + a matching non-whitespace character. + + Format specifications tell <<wscanf>> to read and convert characters + from the input field into specific types of values, and store then + in the locations specified by the address arguments. + + Trailing whitespace is left unread unless explicitly + matched in the format string. + + The format specifiers must begin with a percent sign (<<%>>) + and have the following form: + +. %[*][<[width]>][<[size]>]<[type]> + + Each format specification begins with the percent character (<<%>>). + The other fields are: + o+ + o * + an optional marker; if present, it suppresses interpretation and + assignment of this input field. + + o <[width]> + an optional maximum field width: a decimal integer, + which controls the maximum number of characters that + will be read before converting the current input field. If the + input field has fewer than <[width]> characters, <<wscanf>> + reads all the characters in the field, and then + proceeds with the next field and its format specification. + + If a whitespace or a non-convertable wide character occurs + before <[width]> character are read, the characters up + to that character are read, converted, and stored. + Then <<wscanf>> proceeds to the next format specification. + + o size + <<h>>, <<j>>, <<l>>, <<L>>, <<t>>, and <<z>> are optional size + characters which override the default way that <<wscanf>> + interprets the data type of the corresponding argument. + + +.Modifier Type(s) +. hh d, i, o, u, x, n convert input to char, +. store in char object +. +. h d, i, o, u, x, n convert input to short, +. store in short object +. +. h e, f, c, s, p no effect +. +. j d, i, o, u, x, n convert input to intmax_t, +. store in intmax_t object +. +. j all others no effect +. +. l d, i, o, u, x, n convert input to long, +. store in long object +. +. l e, f, g convert input to double +. store in a double object +. +. l c, s, [ the input is stored in a wchar_t object +. +. l p no effect +. +. ll d, i, o, u, x, n convert to long long, +. store in long long +. +. L d, i, o, u, x, n convert to long long, +. store in long long +. +. L e, f, g, E, G convert to long double, +. store in long double +. +. L all others no effect +. +. t d, i, o, u, x, n convert input to ptrdiff_t, +. store in ptrdiff_t object +. +. t all others no effect +. +. z d, i, o, u, x, n convert input to size_t, +. store in size_t object +. +. z all others no effect +. + + + o <[type]> + + A character to specify what kind of conversion + <<wscanf>> performs. Here is a table of the conversion + characters: + + o+ + o % + No conversion is done; the percent character (<<%>>) is stored. + + o c + Scans one wide character. Corresponding <[arg]>: <<(char *arg)>>. + Otherwise, if an <<l>> specifier is present, the corresponding + <[arg]> is a <<(wchar_t *arg)>>. + + o s + Reads a character string into the array supplied. + Corresponding <[arg]>: <<(char arg[])>>. + If an <<l>> specifier is present, the corresponding <[arg]> is a <<(wchar_t *arg)>>. + + o [<[pattern]>] + Reads a non-empty character string into memory + starting at <[arg]>. This area must be large + enough to accept the sequence and a + terminating null character which will be added + automatically. (<[pattern]> is discussed in the paragraph following + this table). Corresponding <[arg]>: <<(char *arg)>>. + + o d + Reads a decimal integer into the corresponding <[arg]>: <<(int *arg)>>. + + o o + Reads an octal integer into the corresponding <[arg]>: <<(int *arg)>>. + + o u + Reads an unsigned decimal integer into the corresponding + <[arg]>: <<(unsigned int *arg)>>. + + o x,X + Read a hexadecimal integer into the corresponding <[arg]>: + <<(int *arg)>>. + + o e, f, g + Read a floating-point number into the corresponding <[arg]>: + <<(float *arg)>>. + + o E, F, G + Read a floating-point number into the corresponding <[arg]>: + <<(double *arg)>>. + + o i + Reads a decimal, octal or hexadecimal integer into the + corresponding <[arg]>: <<(int *arg)>>. + + o n + Stores the number of characters read in the corresponding + <[arg]>: <<(int *arg)>>. + + o p + Stores a scanned pointer. ANSI C leaves the details + to each implementation; this implementation treats + <<%p>> exactly the same as <<%U>>. Corresponding + <[arg]>: <<(void **arg)>>. + o- + + A <[pattern]> of characters surrounded by square brackets can be used + instead of the <<s>> type character. <[pattern]> is a set of + characters which define a search set of possible characters making up + the <<wscanf>> input field. If the first character in the brackets is a + caret (<<^>>), the search set is inverted to include all ASCII characters + except those between the brackets. There is no range facility as is + defined in the corresponding non-wide character scanf functions. + Ranges are not part of the POSIX standard. + + Here are some <[pattern]> examples: + o+ + o %[abcd] + matches wide wide character strings containing only + <<a>>, <<b>>, <<c>>, and <<d>>. + + o %[^abcd] + matches wide character strings containing any characters except + <<a>>, <<b>>, <<c>>, or <<d>>. + + o %[A-DW-Z] + Note: No wide character ranges, so this expression matches wide + character strings containing <<A>>, <<->>, <<D>>, <<W>>, <<Z>>. + + Floating point numbers (for field types <<e>>, <<f>>, <<g>>, <<E>>, + <<F>>, <<G>>) must correspond to the following general form: + +. [+/-] ddddd[.]ddd [E|e[+|-]ddd] + + where objects inclosed in square brackets are optional, and <<ddd>> + represents decimal, octal, or hexadecimal digits. + o- + +RETURNS + <<wscanf>> returns the number of input fields successfully + scanned, converted and stored; the return value does + not include scanned fields which were not stored. + + If <<wscanf>> attempts to read at end-of-file, the return + value is <<EOF>>. + + If no fields were stored, the return value is <<0>>. + + <<wscanf>> might stop scanning a particular field before + reaching the normal field end character, or may + terminate entirely. + + <<wscanf>> stops scanning and storing the current field + and moves to the next input field (if any) + in any of the following situations: + + O+ + o The assignment suppressing character (<<*>>) appears + after the <<%>> in the format specification; the current + input field is scanned but not stored. + + o <[width]> characters have been read (<[width]> is a + width specification, a positive decimal integer). + + o The next wide character read cannot be converted + under the the current format (for example, + if a <<Z>> is read when the format is decimal). + + o The next wide character in the input field does not appear + in the search set (or does appear in the inverted search set). + O- + + When <<wscanf>> stops scanning the current input field for one of + these reasons, the next character is considered unread and + used as the first character of the following input field, or the + first character in a subsequent read operation on the input. + + <<wscanf>> will terminate under the following circumstances: + + O+ + o The next wide character in the input field conflicts + with a corresponding non-whitespace character in the + format string. + + o The next wide character in the input field is <<WEOF>>. + + o The format string has been exhausted. + O- + + When the format string contains a wide character sequence that is + not part of a format specification, the same wide character + sequence must appear in the input; <<wscanf>> will + scan but not store the matched characters. If a + conflict occurs, the first conflicting wide character remains in the + input as if it had never been read. + +PORTABILITY +<<wscanf>> is C99, POSIX-1.2008. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <_ansi.h> +#include <reent.h> +#include <stdio.h> +#include <wchar.h> +#include <stdarg.h> +#include "local.h" + +#ifndef _REENT_ONLY + +int +swscanf (_CONST wchar_t *str, _CONST wchar_t *fmt, ...) +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SRD | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._r = wcslen (str) * sizeof (wchar_t); + f._read = __seofread; + f._ub._base = NULL; + f._lb._base = NULL; + f._file = -1; /* No file. */ + va_start (ap, fmt); + ret = __ssvfwscanf_r (_REENT, &f, fmt, ap); + va_end (ap); + return ret; +} + +#endif /* !_REENT_ONLY */ + +int +_swscanf_r (struct _reent *ptr, _CONST wchar_t *str, _CONST wchar_t *fmt, ...) +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SRD | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._r = wcslen (str) * sizeof (wchar_t); + f._read = __seofread; + f._ub._base = NULL; + f._lb._base = NULL; + f._file = -1; /* No file. */ + va_start (ap, fmt); + ret = __ssvfwscanf_r (ptr, &f, fmt, ap); + va_end (ap); + return ret; +} |