summaryrefslogtreecommitdiff
path: root/src/stdio
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdio')
-rw-r--r--src/stdio/BUFSIZ.c15
-rw-r--r--src/stdio/EOF.c12
-rw-r--r--src/stdio/FILE.c15
-rw-r--r--src/stdio/FILENAME_MAX.c12
-rw-r--r--src/stdio/FOPEN_MAX.c16
-rw-r--r--src/stdio/L_tmpnam.c11
-rw-r--r--src/stdio/NULL.ref3
-rw-r--r--src/stdio/SEEK_CUR.c12
-rw-r--r--src/stdio/SEEK_END.c12
-rw-r--r--src/stdio/SEEK_SET.c12
-rw-r--r--src/stdio/TMP_MAX.c12
-rw-r--r--src/stdio/_IOFBF.c12
-rw-r--r--src/stdio/_IOLBF.c12
-rw-r--r--src/stdio/_IONBF.c12
-rw-r--r--src/stdio/_stdio.c2
-rw-r--r--src/stdio/clearerr.c20
-rw-r--r--src/stdio/fclose.c50
-rw-r--r--src/stdio/feof.c29
-rw-r--r--src/stdio/ferror.c21
-rw-r--r--src/stdio/fflush.c44
-rw-r--r--src/stdio/fgetc.c24
-rw-r--r--src/stdio/fgetpos.c23
-rw-r--r--src/stdio/fgets.c52
-rw-r--r--src/stdio/fopen.c59
-rw-r--r--src/stdio/fpos_t.c12
-rw-r--r--src/stdio/fprintf.c30
-rw-r--r--src/stdio/fputc.c42
-rw-r--r--src/stdio/fputs.c28
-rw-r--r--src/stdio/fread.c39
-rw-r--r--src/stdio/freopen.c53
-rw-r--r--src/stdio/fscanf.c30
-rw-r--r--src/stdio/fseek.c35
-rw-r--r--src/stdio/fsetpos.c21
-rw-r--r--src/stdio/ftell.c26
-rw-r--r--src/stdio/fwrite.c36
-rw-r--r--src/stdio/getc.c19
-rw-r--r--src/stdio/getchar.c18
-rw-r--r--src/stdio/gets.c28
-rw-r--r--src/stdio/perror.c29
-rw-r--r--src/stdio/printf.c111
-rw-r--r--src/stdio/putc.c19
-rw-r--r--src/stdio/putchar.c19
-rw-r--r--src/stdio/puts.c27
-rw-r--r--src/stdio/remove.c37
-rw-r--r--src/stdio/rename.c30
-rw-r--r--src/stdio/rewind.c16
-rw-r--r--src/stdio/scanf.c31
-rw-r--r--src/stdio/setbuf.c24
-rw-r--r--src/stdio/setvbuf.c48
-rw-r--r--src/stdio/size_t.ref3
-rw-r--r--src/stdio/snprintf.c9
-rw-r--r--src/stdio/sprintf.c31
-rw-r--r--src/stdio/sscanf.c31
-rw-r--r--src/stdio/stderr.c12
-rw-r--r--src/stdio/stdin.c12
-rw-r--r--src/stdio/stdout.c12
-rw-r--r--src/stdio/tmpfile.c33
-rw-r--r--src/stdio/tmpnam.c43
-rw-r--r--src/stdio/ungetc.c37
-rw-r--r--src/stdio/va_list.ref3
-rw-r--r--src/stdio/vfprintf.c30
-rw-r--r--src/stdio/vfscanf.c9
-rw-r--r--src/stdio/vprintf.c30
-rw-r--r--src/stdio/vscanf.c10
-rw-r--r--src/stdio/vsnprintf.c10
-rw-r--r--src/stdio/vsprintf.c30
-rw-r--r--src/stdio/vsscanf.c10
67 files changed, 1655 insertions, 0 deletions
diff --git a/src/stdio/BUFSIZ.c b/src/stdio/BUFSIZ.c
new file mode 100644
index 00000000..c1b315c4
--- /dev/null
+++ b/src/stdio/BUFSIZ.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#define BUFSIZ (4096)
+
+/** default buffer size **/
+
+/***
+is the buffer size used when buffering is adjusted with FUNCTION(setbuf).
+***/
+
+/*
+VALUE_MIN(256)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/EOF.c b/src/stdio/EOF.c
new file mode 100644
index 00000000..84f560a1
--- /dev/null
+++ b/src/stdio/EOF.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define EOF (-1)
+
+/** end-of-file **/
+
+/***
+is a sentinal value used to indicated that a TYPEDEF(FILE) stream has reached
+the end of file.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/FILE.c b/src/stdio/FILE.c
new file mode 100644
index 00000000..854bbcee
--- /dev/null
+++ b/src/stdio/FILE.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+typedef struct __FILE FILE;
+
+/** buffered I/O stream **/
+
+/***
+is used to hold information about buffered input and output streams. The
+structure holds information including the current file position indicator,
+a pointer to its buffer, an error indicator, and an end-of-file indicator.
+No standard defines the members of THIS(). User programs should not attempt
+to access or modify its members directly.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/FILENAME_MAX.c b/src/stdio/FILENAME_MAX.c
new file mode 100644
index 00000000..4acdbcfb
--- /dev/null
+++ b/src/stdio/FILENAME_MAX.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define FILENAME_MAX (255)
+
+/** maximum filename length **/
+
+/***
+is size of the longest array of TYPE(char) that the implementation guarantees
+can be used as a file name.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/FOPEN_MAX.c b/src/stdio/FOPEN_MAX.c
new file mode 100644
index 00000000..2cfc1fb0
--- /dev/null
+++ b/src/stdio/FOPEN_MAX.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#define FOPEN_MAX (8)
+
+/** maximum open FILE streams **/
+
+/***
+is the minimum number of TYPEDEF(FILE) streams that the implementation
+guarantees can be opened at the same time.
+***/
+
+/*
+VALUE_MIN(8)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/L_tmpnam.c b/src/stdio/L_tmpnam.c
new file mode 100644
index 00000000..d35cb988
--- /dev/null
+++ b/src/stdio/L_tmpnam.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#define L_tmpnam (255)
+
+/** temporary file name length **/
+
+/***
+is the maximum length of a temporary filename returned by FUNCTION(tmpnam).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/NULL.ref b/src/stdio/NULL.ref
new file mode 100644
index 00000000..d1bb9ab5
--- /dev/null
+++ b/src/stdio/NULL.ref
@@ -0,0 +1,3 @@
+#include <stdio.h>
+REFERENCE(stddef/NULL.c)
+STDC(1)
diff --git a/src/stdio/SEEK_CUR.c b/src/stdio/SEEK_CUR.c
new file mode 100644
index 00000000..558d57ef
--- /dev/null
+++ b/src/stdio/SEEK_CUR.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define SEEK_CUR (1)
+
+/** seek forward **/
+
+/***
+is used as the ARGUMENT(whence) argument to FUNCTION(fseek) to indicate that
+seeking should begin at the current file position and move forward.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/SEEK_END.c b/src/stdio/SEEK_END.c
new file mode 100644
index 00000000..856d2074
--- /dev/null
+++ b/src/stdio/SEEK_END.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define SEEK_END (2)
+
+/** seek from end **/
+
+/***
+is used as the ARGUMENT(whence) argument to FUNCTION(fseek) to indicate that
+seeking should begin at the end of the file and move backward.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/SEEK_SET.c b/src/stdio/SEEK_SET.c
new file mode 100644
index 00000000..213c3c33
--- /dev/null
+++ b/src/stdio/SEEK_SET.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define SEEK_SET (3)
+
+/** seek from beginning **/
+
+/***
+is used as the ARGUMENT(whence) argument to FUNCTION(fseek) to indicate that
+seeking should begin at the start of the file and move forward.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/TMP_MAX.c b/src/stdio/TMP_MAX.c
new file mode 100644
index 00000000..af429fd3
--- /dev/null
+++ b/src/stdio/TMP_MAX.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define TMP_MAX (10000)
+
+/** maximum temporary file names **/
+
+/***
+is the minimum number of unique file names FUNCTION(tmpnam) is guaranteed to
+be able to generate.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/_IOFBF.c b/src/stdio/_IOFBF.c
new file mode 100644
index 00000000..659b787d
--- /dev/null
+++ b/src/stdio/_IOFBF.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define _IOFBF (1)
+
+/** full buffering **/
+
+/***
+is used as the ARGUMENT(mode) in calls to FUNCTION(setvbuf) to indicate that
+a stream should be fully buffered.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/_IOLBF.c b/src/stdio/_IOLBF.c
new file mode 100644
index 00000000..8f84ae97
--- /dev/null
+++ b/src/stdio/_IOLBF.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define _IOLBF (2)
+
+/** line buffering **/
+
+/***
+is used as the ARGUMENT(mode) in calls to FUNCTION(setvbuf) to indicate that
+a stream should be line buffered.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/_IONBF.c b/src/stdio/_IONBF.c
new file mode 100644
index 00000000..aa88cb9b
--- /dev/null
+++ b/src/stdio/_IONBF.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#define _IONBF (3)
+
+/** no buffering **/
+
+/***
+is used as the ARGUMENT(mode) in calls to FUNCTION(setvbuf) to indicate that
+a stream should be unbuffered.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/_stdio.c b/src/stdio/_stdio.c
new file mode 100644
index 00000000..05851eeb
--- /dev/null
+++ b/src/stdio/_stdio.c
@@ -0,0 +1,2 @@
+#include "stdio.h"
+FILE *stdin, *stdout, *stderr;
diff --git a/src/stdio/clearerr.c b/src/stdio/clearerr.c
new file mode 100644
index 00000000..9b817a97
--- /dev/null
+++ b/src/stdio/clearerr.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+
+/** reset file stream error indicator **/
+void clearerr(FILE * stream)
+{
+ flockfile(stream);
+ if (stream != NULL) {
+ stream->eof = 0;
+ stream->err = 0;
+ }
+ funlockfile(stream);
+}
+
+/***
+clears the error and end-of-file indicators of ARGUMENT(stream).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fclose.c b/src/stdio/fclose.c
new file mode 100644
index 00000000..e8cd037e
--- /dev/null
+++ b/src/stdio/fclose.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include "stdlib.h"
+#include "nonstd/io.h"
+
+#ifdef _POSIX_SOURCE
+#include "unistd.h"
+#else
+#define close(fd) -1
+#endif
+
+/** close a file stream **/
+int fclose(FILE *stream)
+{
+ flockfile(stream);
+ if (fflush(stream) == EOF) {
+ /* set errno */
+ return EOF;
+ }
+
+ if (stream->mem.buf) {
+ if (stream->mem.allocated) {
+ free(stream->mem.buf);
+ }
+ } else if (close(stream->fd) == -1) {
+ /* set errno */
+ return EOF;
+ }
+
+ /*
+ if (!(stream->flags & FF_USERBUF) && stream->buf != NULL) {
+ free(stream->buf);
+ }
+ */
+
+ funlockfile(stream);
+ /*
+ RETURN_SUCCESS(0);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return 0;
+}
+
+/***
+function closes ARGUMENT(stream) and its associated file. Any
+unwritten data is flushed before closing. Any unread data is discarded. If the
+buffer was automatically allocated, it is freed.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/feof.c b/src/stdio/feof.c
new file mode 100644
index 00000000..26c9a5a8
--- /dev/null
+++ b/src/stdio/feof.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+#include "nonstd/assert.h"
+
+/** test for end-of-file **/
+int feof(FILE *stream)
+{
+ ASSERT_NONNULL(stream);
+ flockfile(stream);
+
+ if (stream->eof) {
+ return 1;
+ }
+ /* TODO */
+ /* system level test */
+ funlockfile(stream);
+ /*
+ RETURN(0, the end-of-file indicator is not set);
+ RETURN(NONZERO, the end-of-file indicator is set);
+ */
+ return stream->eof;
+}
+
+/***
+tests for the end-of-file indicator of ARGUMENT(stream).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/ferror.c b/src/stdio/ferror.c
new file mode 100644
index 00000000..609f7640
--- /dev/null
+++ b/src/stdio/ferror.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include "nonstd/assert.h"
+#include "nonstd/io.h"
+
+/** tests the file stream error indicator **/
+int ferror(FILE *stream)
+{
+ ASSERT_NONNULL(stream);
+ /*
+ RETURN(0, the error indicator is not set);
+ RETURN(NONZERO, the error indicator is set);
+ */
+ return stream->err;
+}
+
+/***
+tests the error indicator of ARGUMENT(stream).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fflush.c b/src/stdio/fflush.c
new file mode 100644
index 00000000..c7514d10
--- /dev/null
+++ b/src/stdio/fflush.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+#include "nonstd/internal.h"
+
+/** flush buffered writes **/
+int fflush(FILE *stream)
+{
+ flockfile(stream);
+ if (stream == NULL) {
+ FILE *p;
+ for (p = __libc(FILE_TAIL); p != NULL; p = p->prev) {
+ fflush(p);
+ }
+ }
+
+ /*
+ if (fsync(stream->fd) != 0) {
+ stream->err = 1;
+ return EOF;
+ }
+ */
+
+ funlockfile(stream);
+ /*
+ RETURN_SUCCESS(0);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return 0;
+}
+
+/***
+function flushes any buffered write operations on ARGUMENT(stream) to
+the underlying file.
+
+If ARGUMENT(stream) is CONSTANT(NULL), THIS() will flush all open streams.
+***/
+
+/*
+UNDEFINED(ARGUMENT(stream) is not an output stream)
+UNDEFINED(ARGUMENT(stream) is an update stream in which the most recent operation was input)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fgetc.c b/src/stdio/fgetc.c
new file mode 100644
index 00000000..8c682c39
--- /dev/null
+++ b/src/stdio/fgetc.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+
+/** read a character from a file stream **/
+int fgetc(FILE *stream)
+{
+ flockfile(stream);
+ char c = getc_unlocked(stream);
+ funlockfile(stream);
+ /*
+ RETURN_SUCCESS(the next character);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return c;
+}
+
+/***
+reads the next character from ARGUMENT(stream) as an
+TYPE(unsigned char) converted to an TYPE(int). The file position indicator
+of ARGUMENT(stream) is advanced.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fgetpos.c b/src/stdio/fgetpos.c
new file mode 100644
index 00000000..177519d1
--- /dev/null
+++ b/src/stdio/fgetpos.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+
+/** get the file stream position indicator **/
+int fgetpos(FILE * restrict stream, fpos_t * restrict pos)
+{
+ flockfile(stream);
+ *pos = stream->pos;
+ funlockfile(stream);
+ return 0;
+}
+
+/***
+stores the current value of the file position indicator
+for ARGUMENT(stream) into the TYPEDEF(fpos_t) at ARGUMENT(pos).
+***/
+
+/*
+UNSPECIFIED(The information stored in TYPEDEF(fpos_t))
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fgets.c b/src/stdio/fgets.c
new file mode 100644
index 00000000..df110de2
--- /dev/null
+++ b/src/stdio/fgets.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+
+/** read a string of characters from a file stream **/
+char * fgets(char * restrict s, int n, FILE * restrict stream)
+{
+ flockfile(stream);
+
+ int i = 0;
+ if (feof(stream)) {
+ return NULL;
+ }
+
+ while (i < n-1) {
+ s[i] = fgetc(stream);
+ if (s[i] == '\n') {
+ s[i+1] = '\0';
+ i = n;
+ } else if (s[i] == EOF && feof(stream)) {
+ s[i] = '\0';
+ i = n;
+ }
+ i++;
+ }
+
+ funlockfile(stream);
+ /*
+ RETURN_SUCCESS(ARGUMENT(s));
+ RETURN_FAILURE(CONSTANT(NULL));
+ */
+ return s;
+}
+
+/***
+reads a string of characters from ARGUMENT(stream). Up to
+ARGUMENT(n)-1 characters will be read into the array at ARGUMENT(s).
+
+If a newline is read, it will be appended to ARGUMENT(s) and THIS() will return.
+
+If end-of-file is reached, THIS() will return.
+
+A CHAR(\0) will be written immediately after the final character is read.
+
+If end-of-file is reached before any characters are read, the contents of
+ARGUMENT(s) will be unchanged.
+
+If an error occurs, the contents of ARGUMENT(s) are indeterminite.
+***/
+
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c
new file mode 100644
index 00000000..935885d9
--- /dev/null
+++ b/src/stdio/fopen.c
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include "stdlib.h"
+#include "nonstd/internal.h"
+#include "nonstd/io.h"
+
+/** open a file stream **/
+FILE * fopen(const char * restrict filename, const char * restrict mode)
+{
+ FILE *f = calloc(1, sizeof(*f));
+ f->fd = -1;
+ if (freopen(filename, mode, f) == NULL) {
+ free(f);
+ return NULL;
+ }
+
+ if (__libc(FILE_TAIL)) {
+ f->prev = __libc(FILE_TAIL);
+ f->prev->next = f;
+ }
+
+ /* __libc(FILE_TAIL) = f; */
+
+ /*
+ RETURN_SUCCESS(a pointer to the new file stream);
+ RETURN_FAILURE(CONSTANT(NULL));
+ */
+ return f;
+}
+
+/***
+opens a file stream associated with the file ARGUMENT(filename).
+
+The type of file and allowed operations are determined by ARGUMENT(mode):
+
+FLAG(LITERAL(r), text file; read-only)
+FLAG(LITERAL(w), text file; write-only; truncate to 0 bytes)
+FLAG(LITERAL(a), text file; append)
+FLAG(LITERAL(rb), binary file; read-only)
+FLAG(LITERAL(wb), binary file; write-only; truncate to 0 bytes)
+FLAG(LITERAL(ab), binary file; append)
+FLAG(LITERAL(r+), text file; update (read and write))
+FLAG(LITERAL(w+), text file; update (read and write); truncate to 0 bytes)
+FLAG(LITERAL(a+), text file; update (read and write); append data to end of file)
+FLAG(LITERAL(r+b), binary file; update (read and write))
+FLAG(LITERAL(rb+), binary file; update (read and write))
+FLAG(LITERAL(w+b), binary file; update (read and write); truncate to 0 bytes)
+FLAG(LITERAL(wb+), binary file; update (read and write); truncate to 0 bytes)
+FLAG(LITERAL(a+b), binary file; update (read and write); append data to end of file)
+FLAG(LITERAL(ab+), binary file; update (read and write); append data to end of file)
+
+File streams are opened in fully buffered mode if and only if
+ARGUMENT(filename) is not an interactive device.
+
+The error and end-of-file indicators are cleared.
+***/
+
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fpos_t.c b/src/stdio/fpos_t.c
new file mode 100644
index 00000000..40d304cf
--- /dev/null
+++ b/src/stdio/fpos_t.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+typedef struct __fpos_t * fpos_t;
+
+/** file position **/
+
+/***
+is used to record information about individual positions within a TYPEDEF(FILE)
+stream.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fprintf.c b/src/stdio/fprintf.c
new file mode 100644
index 00000000..053277d7
--- /dev/null
+++ b/src/stdio/fprintf.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/io.h"
+#include "nonstd/internal.h"
+
+/** write formatted output to a file stream **/
+int fprintf(FILE * restrict stream, const char * restrict format, ...)
+{
+ int ret = 0;
+ va_list ap;
+ struct io_options opt = {0};
+ opt.fnname = "fprintf";
+ opt.stream = stream;
+ va_start(ap, format);
+ ret = __printf(&opt, format, ap);
+ va_end(ap);
+ /*
+ RETURN_SUCCESS(the number of characters written);
+ RETURN_FAILURE(NEGATIVE());
+ */
+ return ret;
+}
+
+/***
+writes a formatted string to ARGUMENT(stream). The format of ARGUMENT(format)
+and the variadic arguments is the same as that for FUNCTION(printf).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fputc.c b/src/stdio/fputc.c
new file mode 100644
index 00000000..eb249b77
--- /dev/null
+++ b/src/stdio/fputc.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+
+#ifdef _POSIX_SOURCE
+#include "unistd.h"
+#else
+#define write(fd, buf, size) -1
+#endif
+
+/** write a character to a file stream **/
+int fputc(int c, FILE *stream)
+{
+ unsigned char ch = (unsigned char)c;
+ flockfile(stream);
+
+ if (!stream) {
+ return EOF;
+ }
+
+ if (write(stream->fd, &ch, sizeof(ch)) != 1) {
+ /* error */
+ return EOF;
+ }
+
+ funlockfile(stream);
+ /*
+ RETURN_SUCCESS(ARGUMENT(c));
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return ch;
+}
+
+/***
+writes the character ARGUMENT(c) (converted to an TYPE(unsigned char)) to
+ARGUMENT(stream). The character is written at the current
+file position indicator, which is advanced. If ARGUMENT(stream) does not support
+seeking or was opened in append mode, the character is written to the end of
+the stream.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fputs.c b/src/stdio/fputs.c
new file mode 100644
index 00000000..b33d3b59
--- /dev/null
+++ b/src/stdio/fputs.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+
+/** write a string to a file stream **/
+int fputs(const char * restrict s, FILE * restrict stream)
+{
+ flockfile(stream);
+ while (*s) {
+ if (fputc(*s++, stream) == EOF) {
+ return EOF;
+ }
+ }
+ funlockfile(stream);
+
+ /*
+ RETURN_SUCCESS(NONNEGATIVE());
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return 1;
+}
+
+/***
+writes the string ARGUMENT(s) to ARGUMENT(stream), not including
+the terminating CHAR(\0) character.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fread.c b/src/stdio/fread.c
new file mode 100644
index 00000000..692e3e18
--- /dev/null
+++ b/src/stdio/fread.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+
+/** read directly from a file stream **/
+size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream)
+{
+ unsigned char *buf = ptr;
+ size_t n = 0;
+ flockfile(stream);
+ while (nmemb) {
+ size_t i;
+ for (i = 0; i < size; i++) {
+ int c = fgetc(stream);
+ if (c == EOF) {
+ /* an error */
+ } else {
+ buf[i] = (char)c;
+ }
+ }
+ nmemb--;
+ buf += size;
+ n++;
+ }
+ funlockfile(stream);
+ /*
+ RETURN_SUCCESS(the number of elements read);
+ */
+ return n;
+}
+
+/***
+reads up to ARGUMENT(nmemb) elements of ARGUMENT(size) bytes each
+from ARGUMENT(stream) into the array at ARGUMENT(ptr).
+
+The file position indicate is advanced by the number of bytes read.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c
new file mode 100644
index 00000000..cddf296a
--- /dev/null
+++ b/src/stdio/freopen.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include "errno.h"
+#include "nonstd/io.h"
+
+#ifdef _POSIX_SOURCE
+#include "fcntl.h"
+#else
+#define open(fname, flags, mode) (filename ? -1 : -1)
+#endif
+
+/** reopen a file stream with a new file **/
+FILE * freopen(const char * restrict filename, const char * restrict mode, FILE * restrict stream)
+{
+ flockfile(stream);
+ (void)mode;
+
+ int openmode = 0; /* modetoflag(mode); */
+ if (openmode == 0) {
+ #ifdef EINVAL
+ errno = EINVAL;
+ #endif
+ return NULL;
+ }
+
+ int fd = open(filename, openmode, 0);
+ if (fd == -1) {
+ /* set errno */
+ return NULL;
+ }
+
+ stream->fd = fd;
+ stream->nlocks = 0;
+
+ /*
+ RETURN_SUCCESS(ARGUMENT(stream));
+ RETURN_FAILURE(CONSTANT(NULL));
+ */
+ return stream;
+}
+
+/***
+changes the file associated with ARGUMENT(stream) to
+ARGUMENT(filename). The meaning of ARGUMENT(mode) is the same as with
+FUNCTION(fopen).
+
+Whatever file is currently associated with ARGUMENT(stream) is closed,
+ignoring any errors.
+
+The error and end-of-file indicators are cleared.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fscanf.c b/src/stdio/fscanf.c
new file mode 100644
index 00000000..adbb753c
--- /dev/null
+++ b/src/stdio/fscanf.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/internal.h"
+#include "nonstd/io.h"
+
+/** read formatted input from a file stream **/
+int fscanf(FILE * restrict stream, const char * restrict format, ...)
+{
+ int ret = 0;
+ va_list ap;
+ struct io_options opt = {0};
+ opt.fnname = "fscanf";
+ opt.stream = stream;
+ va_start(ap, format);
+ ret = __scanf(&opt, format, ap);
+ va_end(ap);
+ /*
+ RETURN_SUCCESS(the number of input items assigned);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return ret;
+}
+
+/***
+reads formatted input from ARGUMENT(stream). The format of ARGUMENT(format) at
+the variadic arguments is the same as that for FUNCTION(scanf).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c
new file mode 100644
index 00000000..2cee57a1
--- /dev/null
+++ b/src/stdio/fseek.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+/** set the file position indicator **/
+int fseek(FILE *stream, long int offset, int whence)
+{
+ (void)stream; (void)offset;
+
+ if (whence == SEEK_CUR) {
+ } else if (whence == SEEK_END) {
+ } else if (whence == SEEK_SET) {
+ }
+
+ return 1;
+}
+
+/***
+sets the file position indicator for ARGUMENT(stream).
+
+How the indicator is set is determined by ARGUMENT(whence):
+
+FLAG(CONSTANT(SEEK_SET), The indicator is set to the beginning of the file plus ARGUMENT(offset))
+FLAG(CONSTANT(SEEK_CUR), The indicator is advanced from its current position by ARGUMENT(offset), which may be negative)
+FLAG(CONSTANT(SEEK_END), The indicator is set to the end of the file minus ARGUMENT(offset))
+
+A successful call to fn(fseek) clears the end-of-file indicator and discards
+any characters pushed with fn(ungetc).
+***/
+
+/*
+UNDEFINED(Specifying CONSTANT(SEEK_END) for ARGUMENT(whence) on a binary file)
+UNDEFINED(Specifying a value for ARGUMENT(offset) other than 0 or a previous return value of FUNCTION(ftell) on a text file)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fsetpos.c b/src/stdio/fsetpos.c
new file mode 100644
index 00000000..8ec7cdd8
--- /dev/null
+++ b/src/stdio/fsetpos.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+/** set the file position indicator **/
+int fsetpos(FILE *stream, const fpos_t *pos)
+{
+ (void)stream; (void)pos;
+ /* TODO */
+ return 1;
+}
+
+/***
+sets the file position indicator of ARGUMENT(stream) to
+ARGUMENT(pos), which must have been previously obtained by a call to
+FUNCTION(fgetpos).
+
+A successful call to THIS() clears the end-of-file indicator and discards
+any characters pushed back with FUNCTION(ungetc).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/ftell.c b/src/stdio/ftell.c
new file mode 100644
index 00000000..796a468c
--- /dev/null
+++ b/src/stdio/ftell.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+/** get the file position indicator **/
+long int ftell(FILE *stream)
+{
+ (void)stream;
+ /* TODO */
+ /*
+ RETURN_SUCCESS(the current file position);
+ RETURN_FAILURE(LITERAL(-1L));
+ */
+ return -1L;
+}
+
+/***
+obtains the current value of the file position indicitor of ARGUMENT(stream).
+
+For binary streams, the indicator is the current byte position.
+***/
+
+/*
+UNSPECIFIED(The meaning of the file position indicator for text streams)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/fwrite.c b/src/stdio/fwrite.c
new file mode 100644
index 00000000..047ee892
--- /dev/null
+++ b/src/stdio/fwrite.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+
+/** write directly to a file stream **/
+size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream)
+{
+ unsigned char *buf = (unsigned char *)ptr;
+ size_t n = 0;
+ while (nmemb) {
+ size_t i;
+ for (i = 0; i < size; i++) {
+ int c = fputc(buf[i], stream);
+ if (c == EOF) {
+ /* an error */
+ } else {
+ n++;
+ }
+ }
+ nmemb--;
+ buf += size;
+ }
+ /*
+ RETURN_SUCCESS(the number of elements written);
+ */
+ return n;
+}
+
+/***
+writes ARGUMENT(nmemb) elements of ARGUMENT(size) bytes each from
+the array ARGUMENT(ptr) to ARGUMENT(stream).
+
+The file position inidicate is advanced by the number of bytes successfully
+written.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/getc.c b/src/stdio/getc.c
new file mode 100644
index 00000000..11a75d4e
--- /dev/null
+++ b/src/stdio/getc.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+
+/** read a character from a file stream **/
+int getc(FILE *stream)
+{
+ /*
+ RETURN_SUCCESS(the next character);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return fgetc(stream);
+}
+
+/***
+is the equivalent of FUNCTION(fgetc) except that if it is
+defined as a macro, it may evaluate ARGUMENT(stream) more than once.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/getchar.c b/src/stdio/getchar.c
new file mode 100644
index 00000000..3bd12654
--- /dev/null
+++ b/src/stdio/getchar.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+/** read a character from stdin **/
+int getchar(void)
+{
+ /*
+ RETURN_SUCCESS(the next character);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return getc(stdin);
+}
+
+/***
+reads the next character from ARGUMENT(stdin).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/gets.c b/src/stdio/gets.c
new file mode 100644
index 00000000..fbe16cd2
--- /dev/null
+++ b/src/stdio/gets.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include "limits.h"
+
+/** read a line from stdin **/
+char * gets(char *s)
+{
+ /*
+ RETURN_SUCCESS(ARGUMENT(s));
+ RETURN_FAILURE(CONSTANT(NULL));
+ */
+ return fgets(s, INT_MAX, stdin);
+}
+
+/***
+does no bounds checking, is marked obsolete in ISO/IEC 9899:1999, and
+has been removed from ISO/IEC 9899:2011. It is a security risk and should not be used.
+
+The THIS() function reads a line of input from IDENTIFIER(stdin) into the array
+ARGUMENT(s). Input characters are read until a newline or end-of-file is reached. The
+newline will not be appended to ARGUMENT(s). A CHAR(\0) character will be written
+after the last character read into the array.
+
+If end-of-file is reached before any characters are read, the contents of ARGUMENT(s)
+remain unchanged.
+***/
+/*
+STDC(1,201112)
+*/
diff --git a/src/stdio/perror.c b/src/stdio/perror.c
new file mode 100644
index 00000000..2aae8470
--- /dev/null
+++ b/src/stdio/perror.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include "string.h"
+#include "errno.h"
+
+/** print an error message **/
+void perror(const char *s)
+{
+ if (s != NULL && *s != '\0') {
+ fprintf(stderr, "%s: ", s);
+ }
+ fprintf(stderr, "%s\n", strerror(errno));
+}
+
+/***
+writes an error message to IDENTIFIER(stderr).
+
+If ARGUMENT(s) is CONSTANT(NULL), the error message is a string representation of the
+current value of IDENTIFIER(errno).
+
+If ARGUMENT(s) is not CONSTANT(NULL), the error message will be preceded by the string
+pointed to by ARGUMENT(s), a colon (CHAR(:)), and a space.
+***/
+
+/*
+POSIX_(L_C_MESSAGES)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/printf.c b/src/stdio/printf.c
new file mode 100644
index 00000000..57684158
--- /dev/null
+++ b/src/stdio/printf.c
@@ -0,0 +1,111 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/internal.h"
+#include "nonstd/io.h"
+
+/** write formatted output **/
+int printf(const char *format, ...)
+{
+
+ int ret = 0;
+ va_list ap;
+ struct io_options opt = {0};
+ opt.fnname = "printf";
+ opt.stream = stdout;
+ va_start(ap, format);
+ ret = __printf(&opt, format, ap);
+ va_end(ap);
+
+ /*
+ RETURN_SUCCESS(the number of characters written);
+ RETURN_FAILURE(NEGATIVE);
+ */
+ return ret;
+}
+
+/***
+writes a formatted string to IDENTIFIER(stdout).
+
+The argument ARGUMENT(format) controls the output. It points to a
+NUL-terminated multibyte character string. Characters other than CHAR(%)
+are output unmodified. The CHAR(%) begins a conversion specifier, which is
+made up of the following:
+
+__(Zero or more CONCEPT(flags, flags))
+__(An optional CONCEPT(fieldwidth, field width) <!-- TODO: describe -->)
+__(An optional CONCEPT(precision, precision) <!-- TODO: describe -->)
+__(An optional CONCEPT(typewidth, type width) <!-- TODO: describe -->)
+__(The CONCEPT(typespec, type specifier) <!-- TODO: describe -->)
+
+CONCEPT_DEFINITION(flags, Flags)
+The following flags modify output as indicated:
+
+FLAG(CHAR(-), Left-justify this field (the default is right-justification))
+FLAG(CHAR(+), Always include a plus or minus sign for signed values (the default is only to display a sign for negative values))
+FLAG(SPACE, TODO: I am not entirely clear on this myself)
+FLAG(CHAR(#), TODO: Or this one)
+FLAG(CHAR(0), Include leading zeros unless TODO)
+
+CONCEPT_DEFINITION(fieldwidth, Field Width)
+If the provided value has fewer characters than specified here, it will be
+padded with spaces or zeroes to fill the desired width. The width is specified
+as a decimal integer or a CHAR(*). If CHAR(*) is specified, the width will
+be taken from the next argument as an TYPE(int).
+
+CONCEPT_DEFINITION(precision, Precision)
+The maximum number of digits in CHAR(d), CHAR(i), CHAR(o), CHAR(u),
+CHAR(x), and CHAR(X) conversions; or, the number of digits after the
+decimal for CHAR(e), CHAR(E), and CHAR(f) converions; or, the maximum
+number of significant digits for CHAR(g) and CHAR(G) conversions; or, the
+maximum number of characters from a string in CHAR(s) conversions. The
+precision is specified by a CHAR(.) followed by a decimal integer, a
+CHAR(*), or nothing. If CHAR(*) is specified, the precision will be taken
+from the next argument as an TYPE(int). If nothing is specified, it is
+the same as specifying CHAR(0).
+
+CONCEPT_DEFINITION(typewidth, Type Width)
+The following type widths can be applied to ensure accurate type conversions
+following normal argument type promotions:
+FLAG(CHAR(h), `Converts the next argument to TYPE(short int) or
+ TYPE(unsigned short int) for CHAR(d), CHAR(i), CHAR(o),
+ CHAR(u), CHAR(x), and CHAR(X) conversions.')
+FLAG(CHAR(h), `Specifies that pointer at an CHAR(n) conversion is a
+ TYPE(short int).')
+FLAG(CHAR(l), `Converts the next argument to TYPE(long int) or
+ TYPE(unsigned long int) for CHAR(d), CHAR(i), CHAR(o),
+ CHAR(u), CHAR(x), and CHAR(X) conversions.')
+FLAG(CHAR(l), `Specifies that pointer at an CHAR(n) conversion is a
+ TYPE(long int).')
+FLAG(CHAR(L), `Converts the next argument to TYPE(long double) for
+ CHAR(e), CHAR(E), CHAR(f), CHAR(g), and CHAR(G) conversions.')
+
+CONCEPT_DEFINITION(typespec, Type Specifier)
+The final character of the conversion specifier indicates the type of value
+to be output:
+
+FLAG(CHAR(d), `Converts an TYPE(int) to a signed decimal number.')
+FLAG(CHAR(i), `Same as CHAR(d).')
+FLAG(CHAR(o), `Converts an TYPE(unsigned int) to octal notation.')
+FLAG(CHAR(u), `Converts an TYPE(unsigned int) to decimal notation.')
+FLAG(CHAR(x), `Converts an TYPE(unsigned int) to hexadecimal notation using lowercase letters.')
+FLAG(CHAR(X), `Converts an TYPE(unsigned int) to hexadecimal notation using uppercase letters.')
+FLAG(CHAR(f), `Converts a TYPE(double) to decimal notation.')
+FLAG(CHAR(e), `Converts a TYPE(double) to scientific notation with a lowercase CHAR(e).')
+FLAG(CHAR(E), `Converts a TYPE(double) to scientific notation with an uppercase CHAR(E).')
+FLAG(CHAR(g), `FIXME: Same as CHAR(f) or CHAR(e) depending on precision.')
+FLAG(CHAR(G), `FIXME: Same as CHAR(f) or CHAR(E) depending on precision.')
+FLAG(CHAR(c), `Converts a TYPE(unsigned char) to a character.')
+FLAG(CHAR(s), `Converts a pointer to an array of TYPE(char) to a NUL-terminated string.')
+FLAG(CHAR(p), `Converts a TYPE(void *) to an implementation-defined format.')
+FLAG(CHAR(n), `Causes the function to write the total number of characters output so far to an TYPE(int) pointed at by the next argument.')
+FLAG(CHAR(%), `Outputs a literal CHAR(%).')
+***/
+
+/*
+IMPLEMENTATION(`The format of CHAR(p) conversions', `STRING(0x%0ARGUMENT(n)x), where ARGUMENT(n) is the number of hexadecimal digits in a canonical address on the platform of execution.')
+UNDEFINED(`Precision with a conversion specifier other than CHAR(d), CHAR(i), CHAR(o), CHAR(u), CHAR(x), CHAR(X), CHAR(e), CHAR(E), CHAR(f), CHAR(g), CHAR(G), or CHAR(s)')
+UNDEFINED(TODO: Using h or l for !(diouxXn) or L for !(eEfgG))
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/putc.c b/src/stdio/putc.c
new file mode 100644
index 00000000..c3509ee2
--- /dev/null
+++ b/src/stdio/putc.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+
+/** write a character to a file stream **/
+int putc(int c, FILE *stream)
+{
+ /*
+ RETURN_SUCCESS(ARGUMENT(c));
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return fputc(c, stream);
+}
+
+/***
+is equivalent of FUNCTION(fputc), except that if it is defined
+as a macro, it may evaluate ARGUMENT(stream) more than once.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/putchar.c b/src/stdio/putchar.c
new file mode 100644
index 00000000..cb12ec0c
--- /dev/null
+++ b/src/stdio/putchar.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+
+/** write a character to stdout **/
+int putchar(int c)
+{
+ /*
+ RETURN_SUCCESS(c);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return putc(c, stdout);
+}
+
+/***
+writes the character ARGUMENT(c) (converted to an TYPE(unsigned char)) to
+IDENTIFIER(stdout).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/puts.c b/src/stdio/puts.c
new file mode 100644
index 00000000..7aeb8d83
--- /dev/null
+++ b/src/stdio/puts.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+/** write a string to stoud **/
+int puts(const char *s)
+{
+ if (fputs(s, stdout) == EOF) {
+ return EOF;
+ }
+
+ if (putc('\n', stdout) == EOF) {
+ return EOF;
+ }
+
+ /*
+ RETURN_SUCCESS(NONNEGATIVE());
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return 1;
+}
+
+/***
+function writes the string pointed to by ARGUMENT(s) to IDENTIFIER(stdout),
+followed by a newline. The terminated CHAR(\0) is not written.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/remove.c b/src/stdio/remove.c
new file mode 100644
index 00000000..2a10e443
--- /dev/null
+++ b/src/stdio/remove.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+
+#ifdef _POSIX_SOURCE
+#include "sys/types.h"
+#include "sys/stat.h"
+#include "unistd.h"
+#else
+ struct stat { int st_mode; };
+#define stat(f, b) (void)f
+#define S_ISDIR(m) (m = 0)
+#define rmdir(f) (-1)
+#define unlink(f) (-1)
+#endif
+
+/** delete a file **/
+
+int remove(const char *filename)
+{
+ struct stat st;
+ stat(filename, &st);
+ if (S_ISDIR(st.st_mode)) {
+ return rmdir(filename);
+ }
+ return unlink(filename);
+}
+
+/***
+function removes the file ARGUMENT(filename) so the future attempts to
+open that file will fail unless creating a new file.
+***/
+
+/*
+IMPLEMENTATION(Whether the file is removed if it is open)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/rename.c b/src/stdio/rename.c
new file mode 100644
index 00000000..068cd73d
--- /dev/null
+++ b/src/stdio/rename.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "errno.h"
+#include "nonstd/syscall.h"
+
+/** rename a file **/
+int rename(const char *old, const char *new)
+{
+ SYSCALL_NUMBER(sc, "rename", -1);
+ int err = 0;
+
+ err = __syscall(sc, old, new);
+ if (err < 0) {
+ errno = -err;
+ return -1;
+ }
+
+ return 0;
+}
+
+/***
+renames a file from its original name ARGUMENT(old) to
+ARGUMENT(new).
+***/
+
+/*
+IMPLEMENTATION(Behavior if ARGUMENT(new) exists prior to THIS() being called)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/rewind.c b/src/stdio/rewind.c
new file mode 100644
index 00000000..73be1f57
--- /dev/null
+++ b/src/stdio/rewind.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+/** reset file position indicator **/
+void rewind(FILE *stream)
+{
+ fseek(stream, 0L, SEEK_SET);
+ clearerr(stream);
+}
+
+/***
+sets the file position indicator of ARGUMENT(stream) to the
+beginning of the file. The error indicator will be cleared.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/scanf.c b/src/stdio/scanf.c
new file mode 100644
index 00000000..5fbe51ec
--- /dev/null
+++ b/src/stdio/scanf.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/internal.h"
+#include "nonstd/io.h"
+
+/** read formatted input **/
+int scanf(const char * restrict format, ...)
+{
+ int ret = 0;
+ va_list ap;
+ struct io_options opt = {0};
+ opt.fnname = "scanf";
+ opt.stream = stdout;
+ va_start(ap, format);
+ ret = __scanf(&opt, format, ap);
+ va_end(ap);
+ /*
+ RETURN_SUCCESS(the number of input items assigned);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return ret;
+}
+
+/***
+reads formatted input from macro(stdin).
+
+FIXME: scanf format goes here
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/setbuf.c b/src/stdio/setbuf.c
new file mode 100644
index 00000000..351db3d3
--- /dev/null
+++ b/src/stdio/setbuf.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+/** specify file stream buffer **/
+void setbuf(FILE * restrict stream, char * restrict buf)
+{
+ if (buf) {
+ setvbuf(stream, buf, _IOFBF, BUFSIZ);
+ } else {
+ setvbuf(stream, NULL, _IONBF, 0);
+ }
+}
+
+/***
+sets the buffer for ARGUMENT(stream) to ARGUMENT(buf). The buffer must hold
+at least CONSTANT(BUFSIZ) characters. It is the equivalent of:
+ LITERAL(setvbuf(stream, buf, _IOFBF, BUFSIZ);)
+
+If ARGUMENT(buf) is CONSTANT(NULL), ARGUMENT(stream) will become unbuffered. It is the
+equivalent of:
+ LITERAL(setvbuf(stream, NULL, _IONBF, 0);)
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/setvbuf.c b/src/stdio/setvbuf.c
new file mode 100644
index 00000000..0db67cda
--- /dev/null
+++ b/src/stdio/setvbuf.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include "stdlib.h"
+#include "nonstd/io.h"
+
+/** specify file stream buffering options **/
+int setvbuf(FILE *stream, char *buf, int mode, size_t size)
+{
+ if (stream == NULL
+ || !stream->isopen
+ || stream->buftype != UNSET
+ || (mode != _IOFBF && mode != _IOLBF && mode != _IONBF))
+ {
+ return 1;
+ }
+
+ stream->buffering = mode;
+ stream->bsize = size;
+
+ if (buf != NULL) {
+ stream->buf = buf;
+ stream->buftype = SUPPLIED;
+ } else if (mode != _IONBF) {
+ stream->buf = calloc(size, sizeof(char));
+ stream->buftype = ALLOCED;
+ }
+
+ return 0;
+}
+
+/***
+function sets the type of buffering for a file stream, along
+with the size and location of the buffer. It must be called before any other
+operations are performed.
+
+The type of buffering is specified by ARGUMENT(mode):
+FLAG(CONSTANT(_IOFBF), fully buffered)
+FLAG(CONSTANT(_IOLBF), line buffered)
+FLAG(CONSTANT(_IONBF), unbuffered)
+
+If ARGUMENT(buf) is CONSTANT(NULL), THIS() will automatically allocate an
+appropriate buffer. If ARGUMENT(buf) is not CONSTANT(NULL), it must point to
+an array of at least ARGUMENT(size) characters.
+
+The ARGUMENT(size) argument specifies the size of the buffer.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/size_t.ref b/src/stdio/size_t.ref
new file mode 100644
index 00000000..5b9b0797
--- /dev/null
+++ b/src/stdio/size_t.ref
@@ -0,0 +1,3 @@
+#include <stdio.h>
+REFERENCE(stddef/size_t.c)
+STDC(1)
diff --git a/src/stdio/snprintf.c b/src/stdio/snprintf.c
new file mode 100644
index 00000000..bc6df080
--- /dev/null
+++ b/src/stdio/snprintf.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int snprintf(char * restrict s, size_t n, const char * restrict format, ...)
+{
+}
+
+/*
+STDC(199901)
+*/
diff --git a/src/stdio/sprintf.c b/src/stdio/sprintf.c
new file mode 100644
index 00000000..babd4ba3
--- /dev/null
+++ b/src/stdio/sprintf.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/io.h"
+#include "nonstd/internal.h"
+
+/** write formatted output to a string **/
+int sprintf(char * restrict s, const char * restrict format, ...)
+{
+ int ret = 0;
+ va_list ap;
+ struct io_options opt = {0};
+ opt.fnname = "sprintf";
+ opt.string = s;
+ opt.maxlen = (size_t)-1;
+ va_start(ap, format);
+ ret = __printf(&opt, format, ap);
+ va_end(ap);
+ /*
+ RETURN_SUCCESS(the number of characters written to the array, not counting the terminating null);
+ */
+ return ret;
+}
+
+/***
+writes a formatted string to the buffer at ARGUMENT(s). The format of
+ARGUMENT(format) and the variadic arguments is the same as that for
+FUNCTION(printf).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/sscanf.c b/src/stdio/sscanf.c
new file mode 100644
index 00000000..f6637476
--- /dev/null
+++ b/src/stdio/sscanf.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/io.h"
+#include "nonstd/internal.h"
+
+/** read formatted input from a string **/
+int sscanf(const char * restrict s, const char * restrict format, ...)
+{
+ int ret = 0;
+ va_list ap;
+ struct io_options opt = {0};
+ opt.fnname = "sscanf";
+ opt.string = (char *)s;
+ va_start(ap, format);
+ ret = __scanf(&opt, format, ap);
+ va_end(ap);
+ /*
+ RETURN_SUCCESS(the number of input items assigned);
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return ret;
+}
+
+/***
+reads formatted input from the string ARGUMENT(s). The format of
+ARGUMENT(format) at the variadic arguments is the same as that for
+FUNCTION(scanf).
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/stderr.c b/src/stdio/stderr.c
new file mode 100644
index 00000000..0a2a6a2e
--- /dev/null
+++ b/src/stdio/stderr.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+ extern FILE *stderr;
+#define stderr stderr
+
+/** standard error **/
+
+/***
+is the standard error stream.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/stdin.c b/src/stdio/stdin.c
new file mode 100644
index 00000000..ba24de75
--- /dev/null
+++ b/src/stdio/stdin.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+ extern FILE *stdin;
+#define stdin stdin
+
+/** standard input **/
+
+/***
+is the standard input stream.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/stdout.c b/src/stdio/stdout.c
new file mode 100644
index 00000000..9a822f8f
--- /dev/null
+++ b/src/stdio/stdout.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+ extern FILE *stdout;
+#define stdout stdout
+
+/** standard output **/
+
+/***
+is the standard output stream.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/tmpfile.c b/src/stdio/tmpfile.c
new file mode 100644
index 00000000..7143b491
--- /dev/null
+++ b/src/stdio/tmpfile.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+/* open a temporary file stream */
+FILE * tmpfile(void)
+{
+ char *path = "FIXME: A temporary file name *not* calling tmpnam()";
+ FILE *f = fopen(path, "w+");
+ if (f) {
+ /* FIXME: set flag for temporary in FILE struct */
+ } else {
+ /* FIXME: set errno */
+ }
+
+ /*
+ RETURN_SUCCESS(a pointer to the temporary file stream);
+ RETURN_FAILURE(CONSTANT(NULL));
+ */
+ return f;
+}
+
+/***
+creates a temporary binary file stream for update (as
+when ARGUMENT(mode) is specified as LITERAL("wb+") to FUNCTION(fopen)).
+The file stream will be automatically removed when closed by FUNCTION(fclose)
+or when the program exits.
+***/
+
+/*
+IMPLEMENTATION(Whether the temporary file is removed if the program terminates abnormally)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/tmpnam.c b/src/stdio/tmpnam.c
new file mode 100644
index 00000000..b4b5d932
--- /dev/null
+++ b/src/stdio/tmpnam.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+/** generate a temporary file name **/
+char * tmpnam(char *s)
+{
+ static int ntimescalled = 0;
+ static char path[L_tmpnam];
+
+ if (ntimescalled >= TMP_MAX) {
+ return NULL;
+ }
+ ntimescalled++;
+
+ if (s == NULL) {
+ s = path;
+ }
+
+ /*
+ RETURN_SUCCESS(a pointer to the temporary file name);
+ */
+ return s;
+}
+
+/***
+generates a unique file name that can be used as a
+temporary file. A new file name is generated every time the function is called
+up to CONSTANT(TMP_MAX) times.
+
+If ARGUMENT(s) is CONSTANT(NULL), the temporary name is stored in a static
+internal buffer. This buffer may be overwritten by additional calls to
+THIS().
+
+If ARGUMENT(s) is not CONSTANT(NULL), it should point to a TYPE(char) array of
+at least CONSTANT(L_tmpnam) characters. The temporary name will be copied to
+this array.
+***/
+
+/*
+IMPLEMENTATION(Behavior if THIS() is called more than CONSTANT(TMP_MAX) times)
+*/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/ungetc.c b/src/stdio/ungetc.c
new file mode 100644
index 00000000..1c32ac1f
--- /dev/null
+++ b/src/stdio/ungetc.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include "nonstd/io.h"
+
+/** push a character back into an input stream **/
+int ungetc(int c, FILE *stream)
+{
+ (void)c; (void)stream;
+ /* TODO */
+ /*
+ RETURN_SUCCESS(ARGUMENT(c));
+ RETURN_FAILURE(CONSTANT(EOF));
+ */
+ return EOF;
+}
+
+/***
+pushes the characer ARGUMENT(c) (converted to an
+type(unsigned char)) into the input stream ARGUMENT(stream). Future function calls
+that read input will return the pushed character. Calls to seeking functions
+(e.g. FUNCTION(fseek), FUNCTION(fsetpos), or FUNCTION(rewind)) will discard pushed characters.
+The file associated with ARGUMENT(stream) is unchanged.
+
+At least one character can be pushed back. Multiple calls to THIS() without
+intervening read operations may fail.
+
+If macro(EOF) is specified for ARGUMENT(c), THIS() fails and the input stream
+is unchagned.
+
+A successfull call clears the end-of-file indicator for ARGUMENT(stream). The file
+position indicator is decremented.
+
+Calling THIS() on a binary stream when the file position indicator is zero
+is obsolete in ISO/IEC 9899:1999.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/va_list.ref b/src/stdio/va_list.ref
new file mode 100644
index 00000000..f1fd28ec
--- /dev/null
+++ b/src/stdio/va_list.ref
@@ -0,0 +1,3 @@
+#include <stdio.h>
+REFERENCE(stdarg/va_list.c)
+STDC(1)
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
new file mode 100644
index 00000000..c6a35edc
--- /dev/null
+++ b/src/stdio/vfprintf.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/io.h"
+#include "nonstd/internal.h"
+
+/** write formatted output to a file stream **/
+int vfprintf(FILE * restrict stream, const char * restrict format, va_list arg)
+{
+ int ret = 0;
+ struct io_options opt = {0};
+ opt.fnname = "vfprintf";
+ opt.stream = stream;
+ ret = __printf(&opt, format, arg);
+ /*
+ RETURN_SUCCESS(the number of characters written);
+ RETURN_FAILURE(an error occured);
+ */
+ return ret;
+}
+
+/***
+is equivalent to FUNCTION(fprintf), but with a TYPEDEF(va_list)
+argument instead of variadic arguments. The argument ARGUMENT(arg) must be
+initialized with FUNCTION(va_start) prior to calling THIS(). The THIS()
+function does not call FUNCTION(va_end), so the calling function is
+responsible for this.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/vfscanf.c b/src/stdio/vfscanf.c
new file mode 100644
index 00000000..44ce6ea2
--- /dev/null
+++ b/src/stdio/vfscanf.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int vfscanf(FILE * restrict stream, const char * restrict format, va_list arg)
+{
+}
+
+/*
+STDC(199901)
+*/
diff --git a/src/stdio/vprintf.c b/src/stdio/vprintf.c
new file mode 100644
index 00000000..eb9b4d30
--- /dev/null
+++ b/src/stdio/vprintf.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/io.h"
+#include "nonstd/internal.h"
+
+/** write formatted output **/
+int vprintf(const char * restrict format, va_list arg)
+{
+ int ret = 0;
+ struct io_options opt = {0};
+ opt.fnname = "vfprintf";
+ opt.stream = stdout;
+ ret = __printf(&opt, format, arg);
+ /*
+ RETURN_SUCCESS(the number of characters written);
+ RETURN_FAILURE(NEGATIVE());
+ */
+ return ret;
+}
+
+/***
+is equivalent to FUNCTION(printf), but with a TYPEDEF(va_list)
+argument instead of variadic arguments. The argument ARGUMENT(arg) must be
+initialized with FUNCTION(va_start) prior to calling THIS(). The THIS()
+function does not call FUNCTION(va_end), so the calling function is
+responsible for this.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/vscanf.c b/src/stdio/vscanf.c
new file mode 100644
index 00000000..189ae04f
--- /dev/null
+++ b/src/stdio/vscanf.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+int vscanf(const char * restrict format, va_list arg)
+{
+ return vfscanf(stdin, format, arg);
+}
+
+/*
+STDC(199901)
+*/
diff --git a/src/stdio/vsnprintf.c b/src/stdio/vsnprintf.c
new file mode 100644
index 00000000..7c5a1e03
--- /dev/null
+++ b/src/stdio/vsnprintf.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include "stdarg.h"
+
+int vsnprintf(char * restrict s, size_t n, va_list ap)
+{
+}
+
+/*
+STDC(199901)
+*/
diff --git a/src/stdio/vsprintf.c b/src/stdio/vsprintf.c
new file mode 100644
index 00000000..4a6ec2b8
--- /dev/null
+++ b/src/stdio/vsprintf.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "stdarg.h"
+#include "nonstd/io.h"
+#include "nonstd/internal.h"
+
+/** write formatted output to a string **/
+int vsprintf(char *s, const char *format, va_list arg)
+{
+ int ret = 0;
+ struct io_options opt = {0};
+ opt.fnname = "fprintf";
+ opt.string = s;
+ opt.maxlen = (size_t)-1;
+ ret = __printf(&opt, format, arg);
+ /*
+ RETURN_SUCCESS(the number of characters written, not including the final CHAR(\0));
+ */
+ return ret;
+}
+
+/***
+is equivalent to fn(sprintf), but with a TYPEDEF(va_list)
+argument instead of variadic arguments. The argument ARGUMENT(arg) must be
+initialized with FUNCTION(va_start) prior to calling THIS(). The
+THIS() function does not call FUNCTION(va_end), so the calling function is
+responsible for this.
+***/
+/*
+STDC(1)
+*/
diff --git a/src/stdio/vsscanf.c b/src/stdio/vsscanf.c
new file mode 100644
index 00000000..534f30ea
--- /dev/null
+++ b/src/stdio/vsscanf.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include "stdarg.h"
+
+int vsscanf(const char * restrict s, const char * restrict format, va_list arg)
+{
+}
+
+/*
+STDC(199901)
+*/