# NAME

vsscanf(3) - sscanf(3) with a va_list parameter

# SYNOPSIS

        #include <slack/std.h>
        #ifndef HAVE_VSSCANF
        #include <slack/vsscanf.h>
        #endif

        int vsscanf(const char *str, const char *format, va_list args);

# DESCRIPTION

Similar to sscanf(3) with the variable argument list specified directly as for vprintf(3).

Note that this may not be identical in behaviour to the sscanf(3) on your system because this was implemented from scratch for systems that lack vsscanf(3). So your sscanf(3) and this vsscanf(3) share no common code. Your sscanf(3) may support extensions that vsscanf(3) does not support. vsscanf(3) complies with all of the relevant ISO C requirements for sscanf(3) except:

- `format` may not be a multi-byte character string; and

- Scanning a pointer (`"%p"`) may not exactly match the format that your printf(3) uses to print pointers on your system. This version accepts pointers as a hexadecimal number, with or without a preceding `0x`.

# MT-Level

MT-Safe if and only if no thread calls setlocale(3). Since locales are inherently non-threadsafe as they are currently defined, this shouldn't be a problem. Just call `setlocale(LC_ALL, "")` once after program initialisation and never again (at least not after creating any threads). If it is a problem, just change `localeconv()->decimal_point[0]` in the source to `'.'`, and it will be MT-Safe at the expense of losing locale support.

# EXAMPLE

        #include <slack/std.h>
        #ifndef HAVE_VSSCANF
        #include <slack/vsscanf.h>
        #endif

        int fdscanf(int fd, const char *format, ...)
        {
            va_list args;
            char buf[BUFSIZ];
            ssize_t bytes;
            int rc;

            if ((bytes = read(fd, buf, BUFSIZ)) <= 0)
                return bytes;

            buf[bytes] = '\0';

            va_start(args, format);
            rc = vsscanf(buf, format, args);
            va_end(args);

            return rc;
        }

        int main()
        {
            int rc, a = 0, b = 0;

            rc = fdscanf(STDIN_FILENO, "%d %d", &a, &b);
            printf("rc = %d a = %d b = %d\n", rc, a, b);

            return (rc == 2) ? EXIT_SUCCESS : EXIT_FAILURE;
        }

# NOTE

gcc(1) warns that:

        warning: ANSI C does not support the `L' length modifier
        warning: use of `l' length character with `e' type character

However, the ANSI C standard (Section 7.9.6.2) states that:

"Finally, the conversion specifiers `e`, `f`, and `g` shall be preceded by `l` if the corresponding argument is a pointer to double rather than a pointer to `float`, or by `L` if it is a pointer to long double."

I have chosen to disregard the gcc(1) warnings in favour of the standard. If you see the above warnings when compiling the unit tests for vsscanf(3), just ignore them.

# SEE ALSO

libslack(3), sscanf(3)

# AUTHOR

20210220 raf <raf@raf.org>