diff options
Diffstat (limited to 'src/stdio')
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) +*/ |