+ Directives can be:
+ - one or more whitespaces, matching any number of whitespaces in the input;
+ - printing characters, matching the input verbatim;
+ - conversion specifications, which convert an input sequence into a value as
+ defined by the individual specifier, and store that value in a memory
+ location pointed to by the next pointer on the argument stack. Details are
+ documented below. If there is an insufficient number of pointers on the
+ argument stack, behaviour is undefined. Additional arguments not required
+ by any conversion specifications are evaluated, but otherwise ignored.
+
+ (The standard specifies the format string is allowed to contain multibyte
+ character sequences as long as it starts and ends in initial shift state,
+ but this is not yet supported by this implementation, which interprets the
+ format string as sequence of char.)
+ TODO: Add multibyte support to scanf() functions.
+
+ A conversion specifier consists of:
+ - Optional assignment-suppressing character ('*') that makes the conversion
+ read input as usual, but does not assign the conversion result.
+ - Optional maximum field width as decimal integer.
+ - Optional length modifier specifying the size of the argument (one of "hh",
+ "ll", or one of the characters "hljztL").
+ - Conversion specifier character specifying the type of conversion to be
+ applied (and the type of the next argument from the argument stack). One
+ of the characters "diouxXaAeEfFgGcs[pn%".
+
+ LENGTH MODIFIERS
+ hh For "diouxXn" conversions, the next pointer from the argument stack is
+ assumed to point to a variable of of char width.
+ h For "diouxXn" conversions, the next pointer from the argument stack is
+ assumed to point to a variable of short int width.
+ l For "diouxXn" conversions, the next pointer from the argument stack is
+ assumed to point to a variable of long int width.
+ For "aAeEfFgG" conversions, it is assumed to point to a variable of type
+ double.
+ For "cs[" conversions, it is assumed to point to a variable of type
+ wchar_t.
+ ll For "diouxXn" conversions, the next pointer from the argument stack is
+ assumed to point to a variable of long long int width.
+ j For "diouxXn" conversions, the next pointer from the argument stack is
+ assumed to point to a variable of intmax_t width.
+ z For "diouxXn" conversions, the next pointer from the argument stack is
+ assumed to point to a variable of size_t width.
+ t For "diouxXn" conversions, the next pointer from the argument stack is
+ assumed to point to a variable of ptrdiff_t width.
+ L For "aAeEfFgG" conversions, the next pointer from the argument stack is
+ assumed to point to a variable of type long double.
+ Length modifiers appearing for any conversions not mentioned above will have
+ undefined behaviour.
+ If a length modifier appears with any conversion specifier other than as
+ specified above, the behavior is undefined.
+
+ CONVERSION SPECIFIERS
+ d Matches an (optionally signed) decimal integer of the format expected
+ by strtol() with base 10. The next pointer from the argument stack is
+ assumed to point to a signed integer.
+ i Matches an (optionally signed) integer of the format expected by
+ strtol() with base 0. The next pointer from the argument stack is
+ assumed to point to a signed integer.
+ o Matches an (optionally signed) octal integer of the format expected by
+ strtoul() with base 8. The next pointer from the argument stack is
+ assumed to point to an unsigned integer.
+ u Matches an (optionally signed) decimal integer of the format expected
+ by strtoul() with base 10. The next pointer from the argument stack is
+ assumed to point to an unsigned integer.
+ x Matches an (optionally signed) hexadecimal integer of the format
+ expected by strtoul() with base 16. The next pointer from the argument
+ stack is assumed to point to an unsigned integer.
+ aefg Matches an (optionally signed) floating point number, infinity, or not-
+ a-number-value of the format expected by strtod(). The next pointer
+ from the argument stack is assumed to point to a float.
+ c Matches a number of characters as specified by the field width (default
+ 1). The next pointer from the argument stack is assumed to point to a
+ character array large enough to hold that many characters.
+ If the 'l' length modifier is given, the input is assumed to match a
+ sequence of multibyte characters (starting in the initial shift state),
+ which will be converted to a wide character sequence as by successive
+ calls to mbrtowc() with a mbstate_t object initialized to zero prior to
+ the first conversion. The next pointer from the argument stack is
+ assumed to point to a wchar_t array large enough to hold that many
+ characters.
+ In either case, note that no '\0' character is added to terminate the
+ sequence.
+ s Matches a sequence of non-white-space characters. The next pointer from
+ the argument stack is assumed to point to a character array large
+ enough to hold the sequence including terminating '\0' character.
+ If the 'l' length modifier is given, the input is assumed to match a
+ sequence of multibyte characters (starting in the initial shift state),
+ which will be converted to a wide character sequence as by a call to
+ mbrtowc() with a mbstate_t object initialized to zero prior to the
+ first conversion. The next pointer from the argument stack is assumed
+ to point to a wchar_t array large enough to hold the sequence including
+ terminating '\0' character.
+ [ Matches a nonempty sequence consisting of any of those characters
+ specified between itself and a corresponding closing bracket (']').
+ If the first character in the list is a circumflex ('^'), this matches
+ a nonempty sequence consisting of any characters NOT specified. If the
+ closing bracket appears as the first character in the scanset ("[]" or
+ "[^]", it is assumed to belong to the scanset, which then ends with the
+ NEXT closing bracket.
+ If there is a '-' character in the scanset which is not the first after
+ the opening bracket (or the circumflex, see above) or the last in the
+ scanset, behaviour is implementation-defined. This implementation
+ handles this character like any other.
+
+ The extend of the input field is determined byte-by-byte for the above
+ conversions ('c', 's', '['), with no special provisions being made for
+ multibyte characters. The resulting field is nevertheless a multibyte
+ sequence begining in intial shift state.
+
+ p Matches a sequence of characters as produced by the printf() "%p"
+ conversion. The next pointer from the argument stack is assumed to
+ point to a void pointer, which will be filled with the same location
+ as the pointer used in the printf() statement. Note that behaviour is
+ undefined if the input value is not the result of an earlier printf()
+ call.
+ n Does not read input. The next pointer from the argument stack is
+ assumed to point to a signed integer, into which the number of
+ characters read from input so far by this call to fscanf() is stored.
+ This does not affect the return value of fscanf(). The behaviour,
+ should an assignment-supressing character of field width be given,
+ is undefined.
+ This can be used to test the success of literal matches and suppressed
+ assignments.
+ % Matches a single, verbatim '%' character.
+
+ A, E, F, G and X are valid, and equivalent to their lowercase counterparts.
+
+ All conversions except [, c, or n imply that whitespace characters from the
+ input stream are consumed until a non-whitespace character is encountered.
+ Such whitespaces do not count against a maximum field width.
+
+ Conversions push at most one character back into the input stream. That
+ implies that some character sequences converted by the strtol() and strtod()
+ function families are not converted identically by the scnaf() function
+ family.
+
+ Returns the number of input items successfully assigned. This can be zero if
+ an early mismatch occurs. Returns EOF if an input failure occurs before the
+ first conversion.
+*/
+int fscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+
+/* Equivalent to fprintf( stdout, format, ... ). */
+int printf( const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+
+/* Equivalent to fscanf( stdin, format, ... ). */
+int scanf( const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+
+/* Equivalent to fprintf( stdout, format, ... ), except that the result is
+ written into the buffer pointed to by s, instead of stdout, and that any
+ characters beyond the (n-1)th are discarded. The (n)th character is
+ replaced by a '\0' character in this case.
+ Returns the number of characters that would have been written (not counting
+ the terminating '\0' character) if n had been sufficiently large, if
+ successful, and a negative number if an encoding error ocurred.
+*/
+int snprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+
+/* Equivalent to fprintf( stdout, format, ... ), except that the result is
+ written into the buffer pointed to by s, instead of stdout.
+*/
+int sprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+
+/* Equivalent to fscanf( stdin, format, ... ), except that the input is read
+ from the buffer pointed to by s, instead of stdin.
+*/
+int sscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+
+/* Equivalent to fprintf( stream, format, ... ), except that the argument stack
+ is passed as va_list parameter. Note that va_list is not declared by
+ <stdio.h>.
+*/
+int vfprintf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+
+/* Equivalent to fscanf( stream, format, ... ), except that the argument stack
+ is passed as va_list parameter. Note that va_list is not declared by
+ <stdio.h>.
+*/
+int vfscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+
+/* Equivalent to fprintf( stdout, format, ... ), except that the argument stack
+ is passed as va_list parameter. Note that va_list is not declared by
+ <stdio.h>.
+*/
+int vprintf( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+
+/* Equivalent to fscanf( stdin, format, ... ), except that the argument stack
+ is passed as va_list parameter. Note that va_list is not declared by
+ <stdio.h>.
+*/
+int vscanf( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+
+/* Equivalent to snprintf( s, n, format, ... ), except that the argument stack
+ is passed as va_list parameter. Note that va_list is not declared by
+ <stdio.h>.
+ */
+int vsnprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+
+/* Equivalent to fprintf( stdout, format, ... ), except that the argument stack
+ is passed as va_list parameter, and the result is written to the buffer
+ pointed to by s, instead of stdout. Note that va_list is not declared by
+ <stdio.h>.
+*/
+int vsprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+
+/* Equivalent to fscanf( stdin, format, ... ), except that the argument stack
+ is passed as va_list parameter, and the input is read from the buffer
+ pointed to by s, instead of stdin. Note that va_list is not declared by
+ <stdio.h>.
+*/
+int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+
+/* Character input/output functions */
+
+/* Retrieve the next character from given stream.
+ Returns the character, EOF otherwise.
+ If end-of-file is reached, the EOF indicator of the stream is set.
+ If a read error occurs, the error indicator of the stream is set.
+*/
+int fgetc( FILE * stream ) _PDCLIB_nothrow;
+
+/* Read at most n-1 characters from given stream into the array s, stopping at
+ \n or EOF. Terminate the read string with \n. If EOF is encountered before
+ any characters are read, leave the contents of s unchanged.
+ Returns s if successful, NULL otherwise.
+ If a read error occurs, the error indicator of the stream is set. In this
+ case, the contents of s are indeterminate.
+*/
+char * fgets( char * _PDCLIB_restrict s, int n, FILE * _PDCLIB_restrict stream ) _PDCLIB_nothrow;
+
+/* Write the value c (cast to unsigned char) to the given stream.
+ Returns c if successful, EOF otherwise.
+ If a write error occurs, sets the error indicator of the stream is set.
+*/
+int fputc( int c, FILE * stream ) _PDCLIB_nothrow;
+
+/* Write the string s (not including the terminating \0) to the given stream.
+ Returns a value >=0 if successful, EOF otherwise.
+ This implementation does set the error indicator of the stream if a write
+ error occurs.
+*/
+int fputs( const char * _PDCLIB_restrict s, FILE * _PDCLIB_restrict stream ) _PDCLIB_nothrow;
+
+/* Equivalent to fgetc( stream ), but may be overloaded by a macro that
+ evaluates its parameter more than once.
+*/
+int getc( FILE * stream ) _PDCLIB_nothrow;
+
+/* Equivalent to fgetc( stdin ). */
+int getchar( void ) _PDCLIB_nothrow;
+
+#if _PDCLIB_C_MAX(1999)
+/* Read characters from given stream into the array s, stopping at \n or EOF.
+ The string read is terminated with \0. Returns s if successful. If EOF is
+ encountered before any characters are read, the contents of s are unchanged,
+ and NULL is returned. If a read error occurs, the contents of s are indeter-
+ minate, and NULL is returned.
+
+ This function is dangerous and has been a great source of security
+ vulnerabilities. Do not use it. It was removed by C11.
+*/
+char * gets( char * s ) _PDCLIB_DEPRECATED _PDCLIB_nothrow;
+#endif
+
+/* Equivalent to fputc( c, stream ), but may be overloaded by a macro that
+ evaluates its parameter more than once.
+*/
+int putc( int c, FILE * stream ) _PDCLIB_nothrow;
+
+/* Equivalent to fputc( c, stdout ), but may be overloaded by a macro that
+ evaluates its parameter more than once.
+*/
+int putchar( int c ) _PDCLIB_nothrow;
+
+/* Write the string s (not including the terminating \0) to stdout, and append
+ a newline to the output. Returns a value >= 0 when successful, EOF if a
+ write error occurred.
+*/
+int puts( const char * s ) _PDCLIB_nothrow;
+
+/* Push the value c (cast to unsigned char) back onto the given (input) stream.
+ A character pushed back in this way will be delivered by subsequent read
+ operations (and skipped by subsequent file positioning operations) as if it
+ has not been read. The external representation of the stream is unaffected
+ by this pushback (it is a buffer operation). One character of pushback is
+ guaranteed, further pushbacks may fail. EOF as value for c does not change
+ the input stream and results in failure of the function.
+ For text files, the file position indicator is indeterminate until all
+ pushed-back characters are read. For binary files, the file position
+ indicator is decremented by each successful call of ungetc(). If the file
+ position indicator for a binary file was zero before the call of ungetc(),
+ behaviour is undefined. (Older versions of the library allowed such a call.)
+ Returns the pushed-back character if successful, EOF if it fails.
+*/
+int ungetc( int c, FILE * stream ) _PDCLIB_nothrow;
+
+/* Direct input/output functions */
+
+/* Read up to nmemb elements of given size from given stream into the buffer
+ pointed to by ptr. Returns the number of elements successfully read, which
+ may be less than nmemb if a read error or EOF is encountered. If a read
+ error is encountered, the value of the file position indicator is
+ indeterminate. If a partial element is read, its value is indeterminate.
+ If size or nmemb are zero, the function does nothing and returns zero.
+*/
+size_t fread( void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, FILE * _PDCLIB_restrict stream ) _PDCLIB_nothrow;
+
+/* Write up to nmemb elements of given size from buffer pointed to by ptr to
+ the given stream. Returns the number of elements successfully written, which
+ will be less than nmemb only if a write error is encountered. If a write
+ error is encountered, the value of the file position indicator is
+ indeterminate. If size or nmemb are zero, the function does nothing and
+ returns zero.
+*/
+size_t fwrite( const void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, FILE * _PDCLIB_restrict stream ) _PDCLIB_nothrow;
+
+/* File positioning functions */
+
+/* Store the current position indicator (and, where appropriate, the current
+ mbstate_t status object) for the given stream into the given pos object. The
+ actual contents of the object are unspecified, but it can be used as second
+ parameter to fsetpos() to reposition the stream to the exact position and
+ parse state at the time fgetpos() was called.
+ Returns zero if successful, nonzero otherwise.
+ TODO: Implementation-defined errno setting for fgetpos().
+*/
+int fgetpos( FILE * _PDCLIB_restrict stream, fpos_t * _PDCLIB_restrict pos ) _PDCLIB_nothrow;
+
+/* Set the position indicator for the given stream to the given offset from:
+ - the beginning of the file if whence is SEEK_SET,
+ - the current value of the position indicator if whence is SEEK_CUR,
+ - end-of-file if whence is SEEK_END.
+ On text streams, non-zero offsets are only allowed with SEEK_SET, and must
+ have been returned by ftell() for the same file.
+ Any characters buffered by ungetc() are dropped, the end-of-file indicator
+ for the stream is cleared. If the given stream is an update stream, the next
+ operation after a successful fseek() may be either input or output.
+ Returns zero if successful, nonzero otherwise. If a read/write error occurs,
+ the error indicator for the given stream is set.
+*/
+int fseek( FILE * stream, long int offset, int whence ) _PDCLIB_nothrow;
+
+/* Set the position indicator (and, where appropriate the mbstate_t status
+ object) for the given stream to the given pos object (created by an earlier
+ call to fgetpos() on the same file).
+ Any characters buffered by ungetc() are dropped, the end-of-file indicator
+ for the stream is cleared. If the given stream is an update stream, the next
+ operation after a successful fsetpos() may be either input or output.
+ Returns zero if successful, nonzero otherwise. If a read/write error occurs,
+ the error indicator for the given stream is set.
+ TODO: Implementation-defined errno setting for fsetpos().
+*/
+int fsetpos( FILE * stream, const fpos_t * pos ) _PDCLIB_nothrow;
+
+/* Return the current offset of the given stream from the beginning of the
+ associated file. For text streams, the exact value returned is unspecified
+ (and may not be equal to the number of characters), but may be used in
+ subsequent calls to fseek().
+ Returns -1L if unsuccessful.
+ TODO: Implementation-defined errno setting for ftell().
+*/
+long int ftell( FILE * stream ) _PDCLIB_nothrow;
+
+/* Equivalent to (void)fseek( stream, 0L, SEEK_SET ), except that the error
+ indicator for the stream is also cleared.
+*/
+void rewind( FILE * stream ) _PDCLIB_nothrow;
+
+/* Error-handling functions */
+
+/* Clear the end-of-file and error indicators for the given stream. */
+void clearerr( FILE * stream ) _PDCLIB_nothrow;
+
+/* Return zero if the end-of-file indicator for the given stream is not set,
+ nonzero otherwise.
+*/
+int feof( FILE * stream ) _PDCLIB_nothrow;
+
+/* Return zero if the error indicator for the given stream is not set, nonzero
+ otherwise.
+*/
+int ferror( FILE * stream ) _PDCLIB_nothrow;
+
+/* If s is neither a NULL pointer nor an empty string, print the string to
+ stderr (with appended colon (':') and a space) first. In any case, print an
+ error message depending on the current value of errno (being the same as if
+ strerror( errno ) had been called).
+*/
+void perror( const char * s ) _PDCLIB_nothrow;
+
+/* Unlocked I/O
+ *
+ * Since threading was introduced in C11, FILE objects have had implicit locks
+ * to prevent data races and inconsistent output.
+ *
+ * PDCLib provides these functions from POSIX as an extension in order to enable
+ * users to access the underlying unlocked functions.
+ *
+ * For each function defined in C11 where an _unlocked variant is defined below,
+ * the behaviour of the _unlocked variant is the same except that it will not
+ * take the lock associated with the stream.
+ *
+ * flockfile, ftrylockfile and funlockfile can be used to manually manipulate
+ * the stream locks. The behaviour of the _unlocked functions if called when the
+ * stream isn't locked by the calling thread is implementation defined.
+ */
+#if _PDCLIB_POSIX_MIN(200112L) || _PDCLIB_BSD_SOURCE || _PDCLIB_SVID_SOURCE
+void flockfile(FILE *file) _PDCLIB_nothrow;
+int ftrylockfile(FILE *file) _PDCLIB_nothrow;
+void funlockfile(FILE *file) _PDCLIB_nothrow;
+
+int getc_unlocked(FILE *stream) _PDCLIB_nothrow;
+int getchar_unlocked(void) _PDCLIB_nothrow;
+int putc_unlocked(int c, FILE *stream) _PDCLIB_nothrow;
+int putchar_unlocked(int c) _PDCLIB_nothrow;
+#endif
+
+#if _PDCLIB_BSD_SOURCE || _PDCLIB_SVID_SOURCE
+void clearerr_unlocked(FILE *stream) _PDCLIB_nothrow;
+int feof_unlocked(FILE *stream) _PDCLIB_nothrow;
+int ferror_unlocked(FILE *stream) _PDCLIB_nothrow;
+int fflush_unlocked(FILE *stream) _PDCLIB_nothrow;
+int fgetc_unlocked(FILE *stream) _PDCLIB_nothrow;
+int fputc_unlocked(int c, FILE *stream) _PDCLIB_nothrow;
+size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *stream) _PDCLIB_nothrow;
+size_t fwrite_unlocked(const void *ptr, size_t size, size_t n, FILE *stream) _PDCLIB_nothrow;
+#endif
+
+#if _PDCLIB_GNU_SOURCE
+char *fgets_unlocked(char *s, int n, FILE *stream) _PDCLIB_nothrow;
+int fputs_unlocked(const char *s, FILE *stream) _PDCLIB_nothrow;
+#endif
+
+#if _PDCLIB_EXTENSIONS
+int _vcbprintf(
+ void *p,
+ _PDCLIB_size_t ( *cb ) ( void *p, const char *buf, _PDCLIB_size_t size ),
+ const char *format,
+ _PDCLIB_va_list arg );
+
+int _cbprintf(
+ void *p,
+ size_t ( *cb ) ( void *p, const char *buf, size_t size ),
+ const char *format,
+ ... );
+
+int fgetpos_unlocked( FILE * _PDCLIB_restrict stream, fpos_t * _PDCLIB_restrict pos ) _PDCLIB_nothrow;
+int fsetpos_unlocked( FILE * stream, const fpos_t * pos ) _PDCLIB_nothrow;
+long int ftell_unlocked( FILE * stream ) _PDCLIB_nothrow;
+int fseek_unlocked( FILE * stream, long int offset, int whence ) _PDCLIB_nothrow;
+void rewind_unlocked( FILE * stream ) _PDCLIB_nothrow;
+
+int puts_unlocked( const char * s ) _PDCLIB_nothrow;
+int ungetc_unlocked( int c, FILE * stream ) _PDCLIB_nothrow;
+
+
+int printf_unlocked( const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+int vprintf_unlocked( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+int fprintf_unlocked( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+int vfprintf_unlocked( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+int scanf_unlocked( const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+int vscanf_unlocked( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+int fscanf_unlocked( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... ) _PDCLIB_nothrow;
+int vfscanf_unlocked( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
+
+
+// Todo: remove prefix?
+_PDCLIB_uint_fast64_t _PDCLIB_ftell64( FILE * stream ) _PDCLIB_nothrow;
+_PDCLIB_uint_fast64_t _PDCLIB_ftell64_unlocked( FILE * stream ) _PDCLIB_nothrow;
+#endif