From b1ddaa81f28b8bbc62d6d50526e0935b173099eb Mon Sep 17 00:00:00 2001 From: Patryk Niedźwiedziński Date: Sat, 17 Apr 2021 10:28:11 +0200 Subject: Init --- stdio/clearerr.c | 23 +++ stdio/dirstream.c | 321 +++++++++++++++++++++++++++++++++++++ stdio/dtoa.c | 25 +++ stdio/fbufsize.c | 27 ++++ stdio/fclose.c | 59 +++++++ stdio/fclose_s.c | 33 ++++ stdio/fdopen.c | 50 ++++++ stdio/feof.c | 26 +++ stdio/ferror.c | 29 ++++ stdio/fflush.c | 91 +++++++++++ stdio/fflush.internal.h | 21 +++ stdio/fgetc.c | 33 ++++ stdio/fgetpos.c | 29 ++++ stdio/fgets.c | 46 ++++++ stdio/fgetwc.c | 51 ++++++ stdio/fgetws.c | 41 +++++ stdio/fileno.c | 31 ++++ stdio/flbf.c | 27 ++++ stdio/flockfile.c | 38 +++++ stdio/flushers.c | 21 +++ stdio/flushlbf.c | 33 ++++ stdio/fmemopen.c | 64 ++++++++ stdio/fopen.c | 74 +++++++++ stdio/fopenflags.c | 47 ++++++ stdio/fpending.c | 26 +++ stdio/fprintf.c | 28 ++++ stdio/fpurge.c | 26 +++ stdio/fputc.c | 38 +++++ stdio/fputs.c | 39 +++++ stdio/fputwc.c | 40 +++++ stdio/fputws.c | 44 +++++ stdio/fread.c | 99 ++++++++++++ stdio/freadable.c | 28 ++++ stdio/freading.c | 27 ++++ stdio/freopen.c | 60 +++++++ stdio/fscanf.c | 44 +++++ stdio/fseek.c | 36 +++++ stdio/fseeko.c | 83 ++++++++++ stdio/fsetlocking.c | 26 +++ stdio/fsetpos.c | 24 +++ stdio/ftell.c | 29 ++++ stdio/ftello.c | 54 +++++++ stdio/fwritable.c | 28 ++++ stdio/fwrite.c | 89 ++++++++++ stdio/fwriting.c | 27 ++++ stdio/get_current_dir_name.c | 38 +++++ stdio/getc.c | 27 ++++ stdio/getchar.c | 27 ++++ stdio/getdelim.c | 79 +++++++++ stdio/getline.c | 37 +++++ stdio/gets.c | 24 +++ stdio/getwc.c | 27 ++++ stdio/getwchar.c | 27 ++++ stdio/internal.h | 19 +++ stdio/mkostemp.c | 23 +++ stdio/mkostemps.c | 26 +++ stdio/mkostempsm.c | 81 ++++++++++ stdio/mkstemp.c | 23 +++ stdio/mkstemps.c | 23 +++ stdio/mktemp.c | 39 +++++ stdio/pclose.c | 43 +++++ stdio/popen.c | 57 +++++++ stdio/printf.c | 71 ++++++++ stdio/putc.c | 29 ++++ stdio/putchar.c | 26 +++ stdio/puts.c | 38 +++++ stdio/putwc.c | 28 ++++ stdio/putwchar.c | 27 ++++ stdio/rewind.c | 31 ++++ stdio/scanf.c | 33 ++++ stdio/setbuf.c | 27 ++++ stdio/setbuffer.c | 33 ++++ stdio/setlinebuf.c | 27 ++++ stdio/setvbuf.c | 42 +++++ stdio/spawn.c | 115 +++++++++++++ stdio/spawn.h | 50 ++++++ stdio/spawna.c | 107 +++++++++++++ stdio/spawna.internal.h | 19 +++ stdio/spawnf.c | 85 ++++++++++ stdio/spawnp.c | 37 +++++ stdio/stdbuf.c | 22 +++ stdio/stderr-init.S | 38 +++++ stdio/stderr.c | 36 +++++ stdio/stdin-init.S | 34 ++++ stdio/stdin.c | 36 +++++ stdio/stdio.h | 129 +++++++++++++++ stdio/stdio.mk | 66 ++++++++ stdio/stdio_ext.h | 25 +++ stdio/stdout-init.S | 36 +++++ stdio/stdout.c | 45 ++++++ stdio/system.c | 76 +++++++++ stdio/systemexec.c | 38 +++++ stdio/temp.h | 20 +++ stdio/tmpfile.c | 44 +++++ stdio/ungetc.c | 36 +++++ stdio/ungetwc.c | 47 ++++++ stdio/unlocked.h | 36 +++++ stdio/unlocked/clearerr_unlocked.S | 29 ++++ stdio/unlocked/feof_unlocked.S | 29 ++++ stdio/unlocked/ferror_unlocked.S | 29 ++++ stdio/unlocked/fflush_unlocked.S | 29 ++++ stdio/unlocked/fgetc_unlocked.S | 29 ++++ stdio/unlocked/fgets_unlocked.S | 29 ++++ stdio/unlocked/fgetwc_unlocked.S | 29 ++++ stdio/unlocked/fgetws_unlocked.S | 29 ++++ stdio/unlocked/fileno_unlocked.S | 29 ++++ stdio/unlocked/fputc_unlocked.S | 29 ++++ stdio/unlocked/fputs_unlocked.S | 29 ++++ stdio/unlocked/fputwc_unlocked.S | 29 ++++ stdio/unlocked/fputws_unlocked.S | 29 ++++ stdio/unlocked/fread_unlocked.S | 29 ++++ stdio/unlocked/fwrite_unlocked.S | 29 ++++ stdio/unlocked/getc_unlocked.S | 29 ++++ stdio/unlocked/getchar_unlocked.S | 29 ++++ stdio/unlocked/getwc_unlocked.S | 29 ++++ stdio/unlocked/getwchar_unlocked.S | 29 ++++ stdio/unlocked/putc_unlocked.S | 29 ++++ stdio/unlocked/putchar_unlocked.S | 29 ++++ stdio/unlocked/putwc_unlocked.S | 29 ++++ stdio/unlocked/putwchar_unlocked.S | 30 ++++ stdio/vfprintf.c | 41 +++++ stdio/vfscanf.c | 28 ++++ stdio/vprintf.c | 23 +++ stdio/vscanf.c | 28 ++++ 124 files changed, 5132 insertions(+) create mode 100644 stdio/clearerr.c create mode 100644 stdio/dirstream.c create mode 100644 stdio/dtoa.c create mode 100644 stdio/fbufsize.c create mode 100644 stdio/fclose.c create mode 100644 stdio/fclose_s.c create mode 100644 stdio/fdopen.c create mode 100644 stdio/feof.c create mode 100644 stdio/ferror.c create mode 100644 stdio/fflush.c create mode 100644 stdio/fflush.internal.h create mode 100644 stdio/fgetc.c create mode 100644 stdio/fgetpos.c create mode 100644 stdio/fgets.c create mode 100644 stdio/fgetwc.c create mode 100644 stdio/fgetws.c create mode 100644 stdio/fileno.c create mode 100644 stdio/flbf.c create mode 100644 stdio/flockfile.c create mode 100644 stdio/flushers.c create mode 100644 stdio/flushlbf.c create mode 100644 stdio/fmemopen.c create mode 100644 stdio/fopen.c create mode 100644 stdio/fopenflags.c create mode 100644 stdio/fpending.c create mode 100644 stdio/fprintf.c create mode 100644 stdio/fpurge.c create mode 100644 stdio/fputc.c create mode 100644 stdio/fputs.c create mode 100644 stdio/fputwc.c create mode 100644 stdio/fputws.c create mode 100644 stdio/fread.c create mode 100644 stdio/freadable.c create mode 100644 stdio/freading.c create mode 100644 stdio/freopen.c create mode 100644 stdio/fscanf.c create mode 100644 stdio/fseek.c create mode 100644 stdio/fseeko.c create mode 100644 stdio/fsetlocking.c create mode 100644 stdio/fsetpos.c create mode 100644 stdio/ftell.c create mode 100644 stdio/ftello.c create mode 100644 stdio/fwritable.c create mode 100644 stdio/fwrite.c create mode 100644 stdio/fwriting.c create mode 100644 stdio/get_current_dir_name.c create mode 100644 stdio/getc.c create mode 100644 stdio/getchar.c create mode 100644 stdio/getdelim.c create mode 100644 stdio/getline.c create mode 100644 stdio/gets.c create mode 100644 stdio/getwc.c create mode 100644 stdio/getwchar.c create mode 100644 stdio/internal.h create mode 100644 stdio/mkostemp.c create mode 100644 stdio/mkostemps.c create mode 100644 stdio/mkostempsm.c create mode 100644 stdio/mkstemp.c create mode 100644 stdio/mkstemps.c create mode 100644 stdio/mktemp.c create mode 100644 stdio/pclose.c create mode 100644 stdio/popen.c create mode 100644 stdio/printf.c create mode 100644 stdio/putc.c create mode 100644 stdio/putchar.c create mode 100644 stdio/puts.c create mode 100644 stdio/putwc.c create mode 100644 stdio/putwchar.c create mode 100644 stdio/rewind.c create mode 100644 stdio/scanf.c create mode 100644 stdio/setbuf.c create mode 100644 stdio/setbuffer.c create mode 100644 stdio/setlinebuf.c create mode 100644 stdio/setvbuf.c create mode 100644 stdio/spawn.c create mode 100644 stdio/spawn.h create mode 100644 stdio/spawna.c create mode 100644 stdio/spawna.internal.h create mode 100644 stdio/spawnf.c create mode 100644 stdio/spawnp.c create mode 100644 stdio/stdbuf.c create mode 100644 stdio/stderr-init.S create mode 100644 stdio/stderr.c create mode 100644 stdio/stdin-init.S create mode 100644 stdio/stdin.c create mode 100644 stdio/stdio.h create mode 100644 stdio/stdio.mk create mode 100644 stdio/stdio_ext.h create mode 100644 stdio/stdout-init.S create mode 100644 stdio/stdout.c create mode 100644 stdio/system.c create mode 100644 stdio/systemexec.c create mode 100644 stdio/temp.h create mode 100644 stdio/tmpfile.c create mode 100644 stdio/ungetc.c create mode 100644 stdio/ungetwc.c create mode 100644 stdio/unlocked.h create mode 100644 stdio/unlocked/clearerr_unlocked.S create mode 100644 stdio/unlocked/feof_unlocked.S create mode 100644 stdio/unlocked/ferror_unlocked.S create mode 100644 stdio/unlocked/fflush_unlocked.S create mode 100644 stdio/unlocked/fgetc_unlocked.S create mode 100644 stdio/unlocked/fgets_unlocked.S create mode 100644 stdio/unlocked/fgetwc_unlocked.S create mode 100644 stdio/unlocked/fgetws_unlocked.S create mode 100644 stdio/unlocked/fileno_unlocked.S create mode 100644 stdio/unlocked/fputc_unlocked.S create mode 100644 stdio/unlocked/fputs_unlocked.S create mode 100644 stdio/unlocked/fputwc_unlocked.S create mode 100644 stdio/unlocked/fputws_unlocked.S create mode 100644 stdio/unlocked/fread_unlocked.S create mode 100644 stdio/unlocked/fwrite_unlocked.S create mode 100644 stdio/unlocked/getc_unlocked.S create mode 100644 stdio/unlocked/getchar_unlocked.S create mode 100644 stdio/unlocked/getwc_unlocked.S create mode 100644 stdio/unlocked/getwchar_unlocked.S create mode 100644 stdio/unlocked/putc_unlocked.S create mode 100644 stdio/unlocked/putchar_unlocked.S create mode 100644 stdio/unlocked/putwc_unlocked.S create mode 100644 stdio/unlocked/putwchar_unlocked.S create mode 100644 stdio/vfprintf.c create mode 100644 stdio/vfscanf.c create mode 100644 stdio/vprintf.c create mode 100644 stdio/vscanf.c (limited to 'stdio') diff --git a/stdio/clearerr.c b/stdio/clearerr.c new file mode 100644 index 0000000..db30cda --- /dev/null +++ b/stdio/clearerr.c @@ -0,0 +1,23 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +void clearerr(FILE *f) { + f->state = 0; +} diff --git a/stdio/dirstream.c b/stdio/dirstream.c new file mode 100644 index 0000000..77940a0 --- /dev/null +++ b/stdio/dirstream.c @@ -0,0 +1,321 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" +#include "libc/calls/internal.h" +#include "libc/calls/struct/dirent.h" +#include "libc/dce.h" +#include "libc/macros.internal.h" +#include "libc/mem/mem.h" +#include "libc/nt/enum/fileflagandattributes.h" +#include "libc/nt/enum/filetype.h" +#include "libc/nt/files.h" +#include "libc/nt/runtime.h" +#include "libc/nt/struct/win32finddata.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/dt.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/errfuns.h" + +/** + * @fileoverview Directory Streams for Linux+Mac+Windows+FreeBSD+OpenBSD. + * + * System interfaces for listing the contents of file system directories + * are famously incompatible across platforms. Most native projects that + * have been around a long time implement wrappers for this. Normally it + * will only be for DOS or Windows support. So this is the first time it + * has been done for five platforms, having a remarkably tiny footprint. + */ + +/** + * Directory stream object. + */ +struct dirstream { + int64_t fd; + int64_t tell; + struct dirent ent; + union { + struct { + unsigned buf_pos; + unsigned buf_end; + char buf[BUFSIZ]; + }; + struct { + bool isdone; + struct NtWin32FindData windata; + }; + }; +}; + +/** + * FreeBSD getdents() and XNU getdirentries() ABI. + */ +struct dirent_bsd { + uint32_t d_fileno; + uint16_t d_reclen; + uint8_t d_type; + uint8_t d_namlen; + char d_name[256]; +}; + +/** + * OpenBSD getdents() ABI. + */ +struct dirent_openbsd { + uint64_t d_fileno; + int64_t d_off; + uint16_t d_reclen; + uint8_t d_type; + uint8_t d_namlen; + uint8_t __zomg[4]; + char d_name[256]; +}; + +/** + * NetBSD getdents(). + */ +struct dirent_netbsd { + uint64_t d_fileno; + uint16_t d_reclen; + uint16_t d_namlen; + uint8_t d_type; + char d_name[512]; +}; + +static textwindows DIR *opendir_nt_impl(char16_t name[PATH_MAX], size_t len) { + DIR *res; + if (len + 2 + 1 <= PATH_MAX) { + if (name[len - 1] != u'\\') name[len++] = u'\\'; + name[len++] = u'*'; + name[len] = u'\0'; + if ((res = calloc(1, sizeof(DIR)))) { + if ((res->fd = FindFirstFile(name, &res->windata)) != -1) { + return res; + } else { + __winerr(); + } + free(res); + } + } else { + enametoolong(); + } + return NULL; +} + +static textwindows noinline DIR *opendir_nt(const char *path) { + int len; + char16_t name[PATH_MAX]; + if ((len = __mkntpath(path, name)) == -1) return NULL; + return opendir_nt_impl(name, len); +} + +static textwindows noinline DIR *fdopendir_nt(int fd) { + DIR *res; + char16_t name[PATH_MAX]; + if (__isfdkind(fd, kFdFile)) { + if ((res = opendir_nt_impl( + name, GetFinalPathNameByHandle( + g_fds.p[fd].handle, name, ARRAYLEN(name), + kNtFileNameNormalized | kNtVolumeNameDos)))) { + close(fd); + return res; + } + } else { + ebadf(); + } + return NULL; +} + +static textwindows noinline struct dirent *readdir_nt(DIR *dir) { + if (!dir->isdone) { + memset(&dir->ent, 0, sizeof(dir->ent)); + dir->ent.d_ino = 0; + dir->ent.d_off = dir->tell++; + dir->ent.d_reclen = sizeof(dir->ent) + + tprecode16to8(dir->ent.d_name, sizeof(dir->ent.d_name), + dir->windata.cFileName) + .ax + + 1; + switch (dir->windata.dwFileType) { + case kNtFileTypeDisk: + dir->ent.d_type = DT_BLK; + break; + case kNtFileTypeChar: + dir->ent.d_type = DT_CHR; + break; + case kNtFileTypePipe: + dir->ent.d_type = DT_FIFO; + break; + default: + if (dir->windata.dwFileAttributes & kNtFileAttributeDirectory) { + dir->ent.d_type = DT_DIR; + } else { + dir->ent.d_type = DT_REG; + } + break; + } + dir->isdone = !FindNextFile(dir->fd, &dir->windata); + return &dir->ent; + } else { + return NULL; + } +} + +/** + * Opens directory, e.g. + * + * DIR *d; + * struct dirent *e; + * CHECK((d = opendir(path))); + * while ((e = readdir(d))) { + * printf("%s/%s\n", path, e->d_name); + * } + * LOGIFNEG1(closedir(d)); + * + * @returns newly allocated DIR object, or NULL w/ errno + * @errors ENOENT, ENOTDIR, EACCES, EMFILE, ENFILE, ENOMEM + * @see glob() + */ +DIR *opendir(const char *name) { + int fd; + DIR *res; + if (!IsWindows()) { + res = NULL; + if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) != -1) { + if (!(res = fdopendir(fd))) close(fd); + } + return res; + } else { + return opendir_nt(name); + } +} + +/** + * Creates directory object for file descriptor. + * + * @param fd gets owned by this function, if it succeeds + * @return new directory object, which must be freed by closedir(), + * or NULL w/ errno + * @errors ENOMEM and fd is closed + */ +DIR *fdopendir(int fd) { + DIR *dir; + if (!IsWindows()) { + if (!(dir = calloc(1, sizeof(*dir)))) return NULL; + dir->fd = fd; + return dir; + } else { + return fdopendir_nt(fd); + } +} + +/** + * Reads next entry from directory stream. + * + * This API doesn't define any particular ordering. + * + * @param dir is the object opendir() or fdopendir() returned + * @return next entry or NULL on end or error, which can be + * differentiated by setting errno to 0 beforehand + */ +struct dirent *readdir(DIR *dir) { + int rc; + long basep; + struct dirent *ent; + struct dirent_bsd *bsd; + struct dirent_netbsd *nbsd; + struct dirent_openbsd *obsd; + if (!IsWindows()) { + if (dir->buf_pos >= dir->buf_end) { + basep = dir->tell; /* TODO(jart): what does xnu do */ + rc = getdents(dir->fd, dir->buf, sizeof(dir->buf) - 256, &basep); + if (!rc || rc == -1) return NULL; + dir->buf_pos = 0; + dir->buf_end = rc; + } + if (IsLinux()) { + ent = (struct dirent *)(dir->buf + dir->buf_pos); + dir->buf_pos += ent->d_reclen; + dir->tell = ent->d_off; + } else if (IsOpenbsd()) { + obsd = (struct dirent_openbsd *)(dir->buf + dir->buf_pos); + dir->buf_pos += obsd->d_reclen; + ent = &dir->ent; + ent->d_ino = obsd->d_fileno; + ent->d_off = obsd->d_off; + ent->d_reclen = obsd->d_reclen; + ent->d_type = obsd->d_type; + memcpy(ent->d_name, obsd->d_name, obsd->d_namlen + 1); + } else if (IsNetbsd()) { + nbsd = (struct dirent_netbsd *)(dir->buf + dir->buf_pos); + dir->buf_pos += nbsd->d_reclen; + ent = &dir->ent; + ent->d_ino = nbsd->d_fileno; + ent->d_off = dir->tell++; + ent->d_reclen = nbsd->d_reclen; + ent->d_type = nbsd->d_type; + memcpy(ent->d_name, nbsd->d_name, MAX(256, nbsd->d_namlen + 1)); + } else { + bsd = (struct dirent_bsd *)(dir->buf + dir->buf_pos); + dir->buf_pos += bsd->d_reclen; + ent = &dir->ent; + ent->d_ino = bsd->d_fileno; + ent->d_off = IsXnu() ? (dir->tell = basep) : dir->tell++; + ent->d_reclen = bsd->d_reclen; + ent->d_type = bsd->d_type; + memcpy(ent->d_name, bsd->d_name, bsd->d_namlen + 1); + } + return ent; + } else { + return readdir_nt(dir); + } +} + +/** + * Closes directory object returned by opendir(). + * @return 0 on success or -1 w/ errno + */ +int closedir(DIR *dir) { + int rc; + if (dir) { + if (!IsWindows()) { + rc = close(dir->fd); + } else { + rc = FindClose(dir->fd) ? 0 : __winerr(); + } + free(dir); + } else { + rc = 0; + } + return rc; +} + +/** + * Returns offset into directory data. + */ +long telldir(DIR *dir) { + return dir->tell; +} + +/** + * Returns file descriptor associated with DIR object. + */ +int dirfd(DIR *dir) { + if (IsWindows()) return eopnotsupp(); + return dir->fd; +} diff --git a/stdio/dtoa.c b/stdio/dtoa.c new file mode 100644 index 0000000..f58202d --- /dev/null +++ b/stdio/dtoa.c @@ -0,0 +1,25 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/fmts.h" +#include "third_party/gdtoa/gdtoa.h" + +char *__fmt_dtoa(double d0, int mode, int ndigits, int *decpt, int *sign, + char **rve) { + return dtoa(d0, mode, ndigits, decpt, sign, rve); +} diff --git a/stdio/fbufsize.c b/stdio/fbufsize.c new file mode 100644 index 0000000..254276b --- /dev/null +++ b/stdio/fbufsize.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/stdio/stdio_ext.h" + +/** + * Returns capacity of stdio stream buffer. + */ +size_t __fbufsize(FILE *f) { + return f->size; +} diff --git a/stdio/fclose.c b/stdio/fclose.c new file mode 100644 index 0000000..cd75a50 --- /dev/null +++ b/stdio/fclose.c @@ -0,0 +1,59 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/mem/mem.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" + +/** + * Closes standard i/o stream and its underlying thing. + * + * @param f is the file object, which is always free if it's heap, + * otherwise its resources are released and fields updated + * @return 0 on success or -1 on error, which can be a trick for + * differentiating between EOF and real errors during previous + * i/o calls, without needing to call ferror() + * @see fclose_s() + */ +int fclose(FILE *f) { + int rc; + if (!f) return 0; + __fflush_unregister(f); + fflush(f); + if (!f->nofree) { + free_s(&f->buf); + } + f->state = EOF; + if (f->noclose) { + f->fd = -1; + } else if (close_s(&f->fd) == -1) { + f->state = errno; + } + if (f->state == EOF) { + rc = 0; + } else { + errno = f->state; + rc = EOF; + } + free_s(&f); + return rc; +} diff --git a/stdio/fclose_s.c b/stdio/fclose_s.c new file mode 100644 index 0000000..7fa0b41 --- /dev/null +++ b/stdio/fclose_s.c @@ -0,0 +1,33 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" +#include "libc/stdio/stdio.h" + +/** + * Closes standard i/o stream and its underlying thing. + * + * @param f is the heap file object pointer, to close+free+clear + * @return 0 on success or -1 on error, which can be a trick for + * differentiating between EOF and real errors during previous + * i/o calls, without needing to call ferror() + */ +int fclose_s(FILE **fp) { + FILE *f = NULL; + return fclose(lockxchg(fp, &f)); +} diff --git a/stdio/fdopen.c b/stdio/fdopen.c new file mode 100644 index 0000000..0f786fa --- /dev/null +++ b/stdio/fdopen.c @@ -0,0 +1,50 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/mem/mem.h" +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/errfuns.h" + +/** + * Allocates stream object for already-opened file descriptor. + * + * @param fd existing file descriptor or -1 for plain old buffer + * @param mode is passed to fopenflags() + * @return new stream or NULL w/ errno + * @error ENOMEM + */ +FILE *fdopen(int fd, const char *mode) { + FILE *f; + if ((f = calloc(1, sizeof(FILE)))) { + f->fd = fd; + f->bufmode = ischardev(fd) ? _IOLBF : _IOFBF; + f->iomode = fopenflags(mode); + f->size = BUFSIZ; + if ((f->buf = malloc(f->size))) { + if ((f->iomode & O_ACCMODE) != O_RDONLY) { + __fflush_register(f); + } + return f; + } + free(f); + } + return NULL; +} diff --git a/stdio/feof.c b/stdio/feof.c new file mode 100644 index 0000000..6016fc8 --- /dev/null +++ b/stdio/feof.c @@ -0,0 +1,26 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Returns true if stream is in end-of-file state. + */ +int feof(FILE *f) { + return f->state == -1; +} diff --git a/stdio/ferror.c b/stdio/ferror.c new file mode 100644 index 0000000..241cb25 --- /dev/null +++ b/stdio/ferror.c @@ -0,0 +1,29 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Returns nonzero if stream is in error state. + * + * @note EOF doesn't count + * @see feof() + */ +errno_t ferror(FILE *f) { + return f->state > 0 ? f->state : 0; +} diff --git a/stdio/fflush.c b/stdio/fflush.c new file mode 100644 index 0000000..99a758d --- /dev/null +++ b/stdio/fflush.c @@ -0,0 +1,91 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/alg/arraylist.internal.h" +#include "libc/bits/bits.h" +#include "libc/bits/pushpop.h" +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/macros.internal.h" +#include "libc/mem/mem.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/fflush.internal.h" +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/o.h" + +/** + * Blocks until data from stream buffer is written out. + * + * @param f is the stream handle + * @return is 0 on success or -1 on error + */ +int fflush(FILE *f) { + size_t i; + ssize_t rc; + if (!f) { + for (i = __fflush.handles.i; i; --i) { + if ((f = __fflush.handles.p[i - 1])) { + if (fflush(f) == -1) return -1; + } + } + } else if (f->fd != -1) { + while (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) { + if ((rc = write(f->fd, f->buf, f->beg)) == -1) { + f->state = errno; + return -1; + } + if (rc != f->beg) abort(); + f->beg = 0; + } + } else if (f->beg && f->beg < f->size) { + f->buf[f->beg] = 0; + } + return 0; +} + +textstartup int __fflush_register(FILE *f) { + size_t i; + struct StdioFlush *sf; + sf = &__fflush; + if (!sf->handles.p) { + sf->handles.p = &sf->handles_initmem[0]; + pushmov(&sf->handles.n, ARRAYLEN(sf->handles_initmem)); + __cxa_atexit(fflush, NULL, NULL); + } + for (i = sf->handles.i; i; --i) { + if (!sf->handles.p[i - 1]) { + sf->handles.p[i - 1] = f; + return 0; + } + } + return append(&sf->handles, &f); +} + +void __fflush_unregister(FILE *f) { + size_t i; + struct StdioFlush *sf; + sf = &__fflush; + sf = pushpop(sf); + for (i = sf->handles.i; i; --i) { + if (sf->handles.p[i - 1] == f) { + pushmov(&sf->handles.p[i - 1], NULL); + return; + } + } +} diff --git a/stdio/fflush.internal.h b/stdio/fflush.internal.h new file mode 100644 index 0000000..d49156d --- /dev/null +++ b/stdio/fflush.internal.h @@ -0,0 +1,21 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_ +#define COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_ +#include "libc/stdio/stdio.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +struct StdioFlushHandles { + size_t i, n; + FILE **p; +}; + +struct StdioFlush { + struct StdioFlushHandles handles; + FILE *handles_initmem[8]; +}; + +extern struct StdioFlush __fflush hidden; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_FFLUSH_H_ */ diff --git a/stdio/fgetc.c b/stdio/fgetc.c new file mode 100644 index 0000000..034b967 --- /dev/null +++ b/stdio/fgetc.c @@ -0,0 +1,33 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Reads byte from stream. + * @return byte in range 0..255, or -1 w/ errno + */ +int fgetc(FILE *f) { + unsigned char b; + if (f->beg < f->end) { + return f->buf[f->beg++] & 0xff; + } else { + if (!fread(&b, 1, 1, f)) return -1; + return b; + } +} diff --git a/stdio/fgetpos.c b/stdio/fgetpos.c new file mode 100644 index 0000000..cd7d4a3 --- /dev/null +++ b/stdio/fgetpos.c @@ -0,0 +1,29 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +int fgetpos(FILE *stream, fpos_t *pos) { + long res; + if ((res = ftell(stream)) != -1) { + *pos = res; + return 0; + } else { + return -1; + } +} diff --git a/stdio/fgets.c b/stdio/fgets.c new file mode 100644 index 0000000..195880e --- /dev/null +++ b/stdio/fgets.c @@ -0,0 +1,46 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/errno.h" +#include "libc/stdio/stdio.h" + +/** + * Reads content from stream. + * + * This function is similar to getline() except it'll truncate lines + * exceeding size. The line ending marker is included and may be removed + * using chomp(). + */ +char *fgets(char *s, int size, FILE *f) { + int c; + char *p; + p = s; + if (size > 0) { + while (--size > 0) { + if ((c = getc(f)) == -1) { + if (ferror(f) == EINTR) continue; + break; + } + *p++ = c & 0xff; + if (c == '\n') break; + } + *p = '\0'; + } + return p > s ? s : NULL; +} diff --git a/stdio/fgetwc.c b/stdio/fgetwc.c new file mode 100644 index 0000000..6411236 --- /dev/null +++ b/stdio/fgetwc.c @@ -0,0 +1,51 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" +#include "libc/str/thompike.h" +#include "libc/str/tpdecodecb.internal.h" + +/** + * Reads UTF-8 character from stream. + * @return wide character or -1 on EOF or error + */ +wint_t fgetwc(FILE *f) { + int c, n; + wint_t b, x, y; + if (f->beg < f->end) { + b = f->buf[f->beg++] & 0xff; + } else if ((c = fgetc(f)) != -1) { + b = c; + } else { + return -1; + } + if (b < 0300) return b; + n = ThomPikeLen(b); + x = ThomPikeByte(b); + while (--n) { + if ((c = fgetc(f)) == -1) return -1; + y = c; + if (ThomPikeCont(y)) { + x = ThomPikeMerge(x, y); + } else { + ungetc(y, f); + return b; + } + } + return x; +} diff --git a/stdio/fgetws.c b/stdio/fgetws.c new file mode 100644 index 0000000..3fdd3b3 --- /dev/null +++ b/stdio/fgetws.c @@ -0,0 +1,41 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/errno.h" +#include "libc/stdio/stdio.h" + +/** + * Reads UTF-8 content from stream into UTF-32 buffer. + */ +wchar_t *fgetws(wchar_t *s, int size, FILE *f) { + wint_t c; + wchar_t *p = s; + if (size > 0) { + while (--size > 0) { + if ((c = fgetwc(f)) == -1) { + if (ferror(f) == EINTR) continue; + break; + } + *p++ = c; + if (c == '\n') break; + } + *p = '\0'; + } + return (intptr_t)p > (intptr_t)s ? s : NULL; +} diff --git a/stdio/fileno.c b/stdio/fileno.c new file mode 100644 index 0000000..a16d858 --- /dev/null +++ b/stdio/fileno.c @@ -0,0 +1,31 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" +#include "libc/sysv/errfuns.h" + +/** + * Returns file descriptor associated with stream. + */ +int fileno(FILE *f) { + if (f->fd != -1) { + return f->fd; + } else { + return ebadf(); + } +} diff --git a/stdio/flbf.c b/stdio/flbf.c new file mode 100644 index 0000000..661e09a --- /dev/null +++ b/stdio/flbf.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/stdio_ext.h" + +/** + * Returns nonzero if stream is line buffered. + */ +int __flbf(FILE *f) { + return f->bufmode == _IOLBF; +} diff --git a/stdio/flockfile.c b/stdio/flockfile.c new file mode 100644 index 0000000..fd6e8e6 --- /dev/null +++ b/stdio/flockfile.c @@ -0,0 +1,38 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Does nothing since Cosmopolitan currently doesn't support threads. + */ +void flockfile(FILE *f) { +} + +/** + * Does nothing since Cosmopolitan currently doesn't support threads. + */ +void funlockfile(FILE *f) { +} + +/** + * Does nothing since Cosmopolitan currently doesn't support threads. + */ +int ftrylockfile(FILE *f) { + return 0; +} diff --git a/stdio/flushers.c b/stdio/flushers.c new file mode 100644 index 0000000..3b7c976 --- /dev/null +++ b/stdio/flushers.c @@ -0,0 +1,21 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/fflush.internal.h" + +struct StdioFlush __fflush; diff --git a/stdio/flushlbf.c b/stdio/flushlbf.c new file mode 100644 index 0000000..a714b25 --- /dev/null +++ b/stdio/flushlbf.c @@ -0,0 +1,33 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/fflush.internal.h" +#include "libc/stdio/stdio_ext.h" + +/** + * Flushes all line-buffered streams. + */ +void _flushlbf(void) { + int i; + for (i = 0; i < __fflush.handles.i; ++i) { + if (__fflush.handles.p[i]->bufmode == _IOLBF) { + fflush(__fflush.handles.p[i]); + } + } +} diff --git a/stdio/fmemopen.c b/stdio/fmemopen.c new file mode 100644 index 0000000..6aac757 --- /dev/null +++ b/stdio/fmemopen.c @@ -0,0 +1,64 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/mem/mem.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/errfuns.h" + +/** + * Opens buffer as stream. + * + * @param buf becomes owned by this function, and is allocated if NULL + * @return new stream or NULL w/ errno + */ +FILE *fmemopen(void *buf, size_t size, const char *mode) { + FILE *f; + char *p; + unsigned flags; + if (size && size > 0x7ffff000) { + einval(); + return NULL; + } + if (!(f = calloc(1, sizeof(FILE)))) { + return NULL; + } + if (buf) { + f->nofree = true; + } else { + if (!size) size = BUFSIZ; + if (!(buf = calloc(1, size))) { + free(f); + return NULL; + } + } + f->fd = -1; + f->buf = buf; + f->end = size; + f->size = size; + f->iomode = fopenflags(mode); + if (f->iomode & O_APPEND) { + if ((p = memchr(buf, '\0', size))) { + f->beg = p - (char *)buf; + } else { + f->beg = f->end; + } + } + return f; +} diff --git a/stdio/fopen.c b/stdio/fopen.c new file mode 100644 index 0000000..a5e0b05 --- /dev/null +++ b/stdio/fopen.c @@ -0,0 +1,74 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/mem/mem.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/o.h" + +static const char *fixpathname(const char *pathname, int flags) { + if ((flags & O_ACCMODE) == O_RDONLY && strcmp(pathname, "-") == 0) { + return "/dev/stdin"; + } else if ((flags & O_ACCMODE) == O_WRONLY && strcmp(pathname, "-") == 0) { + return "/dev/stdout"; + } else { + return pathname; + } +} + +static int openpathname(const char *pathname, int flags, bool *out_noclose) { + if ((flags & O_ACCMODE) == O_RDONLY && strcmp(pathname, "/dev/stdin") == 0) { + *out_noclose = true; + return fileno(stdin); + } else if ((flags & O_ACCMODE) == O_WRONLY && + strcmp(pathname, "/dev/stdout") == 0) { + *out_noclose = true; + return fileno(stdout); + } else { + *out_noclose = false; + return open(pathname, flags, 0666); + } +} + +/** + * Opens file as stream object. + * + * @param pathname is a utf-8 ideally relative filename + * @param mode is the string mode/flag DSL see fopenflags() + * @return new object to be free'd by fclose() or NULL w/ errno + * @note microsoft unilaterally deprecated this function lool + */ +FILE *fopen(const char *pathname, const char *mode) { + FILE *f; + bool noclose; + int fd, flags; + flags = fopenflags(mode); + pathname = fixpathname(pathname, flags); + if ((fd = openpathname(pathname, flags, &noclose)) != -1) { + if ((f = fdopen(fd, mode)) != NULL) { + f->noclose = noclose; + return f; + } else { + if (!noclose) close(fd); + return NULL; + } + } else { + return NULL; + } +} diff --git a/stdio/fopenflags.c b/stdio/fopenflags.c new file mode 100644 index 0000000..268ea61 --- /dev/null +++ b/stdio/fopenflags.c @@ -0,0 +1,47 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/o.h" + +/** + * Turns stdio flags description string into bitmask. + */ +int fopenflags(const char *mode) { + unsigned omode, flags; + omode = flags = 0; + do { + if (*mode == 'r') { + omode = O_RDONLY; + } else if (*mode == 'w') { + omode = O_WRONLY; + flags |= O_CREAT | O_TRUNC; + } else if (*mode == 'a') { + omode = O_WRONLY; + flags |= O_CREAT | O_APPEND; + } else if (*mode == '+') { + omode = O_RDWR; + } else if (*mode == 'x') { + flags |= O_EXCL; + } else if (*mode == 'e') { + flags |= O_CLOEXEC; + } + } while (*mode++); + return omode | flags; +} diff --git a/stdio/fpending.c b/stdio/fpending.c new file mode 100644 index 0000000..1d54071 --- /dev/null +++ b/stdio/fpending.c @@ -0,0 +1,26 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio_ext.h" + +/** + * Returns number of pending output bytes. + */ +size_t __fpending(FILE *f) { + return f->end - f->beg; +} diff --git a/stdio/fprintf.c b/stdio/fprintf.c new file mode 100644 index 0000000..10223fb --- /dev/null +++ b/stdio/fprintf.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +int(fprintf)(FILE *f, const char *fmt, ...) { + int rc; + va_list va; + va_start(va, fmt); + rc = (vfprintf)(f, fmt, va); + va_end(va); + return rc; +} diff --git a/stdio/fpurge.c b/stdio/fpurge.c new file mode 100644 index 0000000..ae87dd1 --- /dev/null +++ b/stdio/fpurge.c @@ -0,0 +1,26 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio_ext.h" + +/** + * Discards contents of stream buffer. + */ +void __fpurge(FILE *f) { + f->beg = f->end = 0; +} diff --git a/stdio/fputc.c b/stdio/fputc.c new file mode 100644 index 0000000..635294f --- /dev/null +++ b/stdio/fputc.c @@ -0,0 +1,38 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/stdio.h" + +/** + * Writes byte to stream. + * + * @param c is byte to buffer or write, which is masked + * @return c as unsigned char if written or -1 w/ errno + */ +int fputc(int c, FILE *f) { + unsigned char b; + if (c != '\n' && f->beg < f->size && f->bufmode != _IONBF) { + f->buf[f->beg++] = c; + return c & 0xff; + } else { + b = c; + if (!fwrite(&b, 1, 1, f)) return -1; + return b; + } +} diff --git a/stdio/fputs.c b/stdio/fputs.c new file mode 100644 index 0000000..149b03c --- /dev/null +++ b/stdio/fputs.c @@ -0,0 +1,39 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" + +/** + * Writes string to stream. + * + * Writing stops at the NUL-terminator, which isn't included in output. + * This function blocks until the full string is written, unless an + * unrecoverable error happens. + * + * @param s is a NUL-terminated string that's non-NULL + * @param f is an open stream + * @return bytes written, or -1 w/ errno + */ +int fputs(const char *s, FILE *f) { + size_t n, r; + n = strlen(s); + r = fwrite(s, 1, n, f); + if (!r && n) return -1; + return r; +} diff --git a/stdio/fputwc.c b/stdio/fputwc.c new file mode 100644 index 0000000..3bb23e7 --- /dev/null +++ b/stdio/fputwc.c @@ -0,0 +1,40 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" +#include "libc/str/tpenc.h" + +/** + * Writes wide character to stream. + * + * @return wc if written or -1 w/ errno + */ +wint_t fputwc(wchar_t wc, FILE *f) { + uint64_t w; + if (wc != -1) { + w = tpenc(wc); + do { + if (fputc(w, f) == -1) { + return -1; + } + } while ((w >>= 8)); + return wc; + } else { + return -1; + } +} diff --git a/stdio/fputws.c b/stdio/fputws.c new file mode 100644 index 0000000..b31fb17 --- /dev/null +++ b/stdio/fputws.c @@ -0,0 +1,44 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/errno.h" +#include "libc/stdio/stdio.h" + +/** + * Writes wide character string to stream. + * + * Writing stops at the NUL-terminator, which isn't included in output. + * This function blocks until the full string is written, unless an + * unrecoverable error happens. + * + * @param s is a NUL-terminated string that's non-NULL + * @param f is an open stream + * @return strlen(s) or -1 w/ errno on error + */ +int fputws(const wchar_t *s, FILE *f) { + int res = 0; + while (*s) { + if (fputwc(*s++, f) == -1) { + if (ferror(f) == EINTR) continue; + if (feof(f)) errno = f->state = EPIPE; + return -1; + } + ++res; + } + return ++res; +} diff --git a/stdio/fread.c b/stdio/fread.c new file mode 100644 index 0000000..52fea4d --- /dev/null +++ b/stdio/fread.c @@ -0,0 +1,99 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/calls/struct/iovec.h" +#include "libc/errno.h" +#include "libc/fmt/conv.h" +#include "libc/macros.internal.h" +#include "libc/runtime/runtime.h" +#include "libc/sock/sock.h" +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" +#include "libc/str/internal.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/errfuns.h" + +/** + * Reads data from stream. + * + * @param stride specifies the size of individual items + * @param count is the number of strides to fetch + * @return count on success, [0,count) on eof, or 0 on error or count==0 + */ +size_t fread(void *buf, size_t stride, size_t count, FILE *f) { + char *p; + ssize_t rc; + size_t n, m; + struct iovec iov[2]; + if ((f->iomode & O_ACCMODE) == O_WRONLY) { + f->state = errno = EBADF; + return 0; + } + if (f->beg > f->end) { + f->state = errno = EINVAL; + return 0; + } + p = buf; + n = stride * count; + m = f->end - f->beg; + memcpy(p, f->buf + f->beg, MIN(n, m)); + if (n < m) { + f->beg += n; + return count; + } + if (n == m) { + f->beg = f->end = 0; + return count; + } + if (f->fd == -1) { + f->beg = 0; + f->end = 0; + f->state = -1; + return m / stride; + } + iov[0].iov_base = p + m; + iov[0].iov_len = n - m; + if (f->bufmode != _IONBF && n < f->size) { + iov[1].iov_base = f->buf; + if (f->size > PUSHBACK) { + iov[1].iov_len = f->size - PUSHBACK; + } else { + iov[1].iov_len = f->size; + } + } else { + iov[1].iov_base = NULL; + iov[1].iov_len = 0; + } + if ((rc = readv(f->fd, iov, 2)) == -1) { + f->state = errno; + return 0; + } + n = rc; + f->beg = 0; + f->end = 0; + if (n > iov[0].iov_len) { + f->end += n - iov[0].iov_len; + return count; + } else { + n = (m + n) / stride; + if (n < count) f->state = -1; + return n; + } +} diff --git a/stdio/freadable.c b/stdio/freadable.c new file mode 100644 index 0000000..23281cb --- /dev/null +++ b/stdio/freadable.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio_ext.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns nonzero if stream allows reading. + */ +int __freadable(FILE *f) { + return (f->iomode & O_ACCMODE) == O_RDONLY || + (f->iomode & O_ACCMODE) == O_RDWR; +} diff --git a/stdio/freading.c b/stdio/freading.c new file mode 100644 index 0000000..07f2f22 --- /dev/null +++ b/stdio/freading.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio_ext.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns nonzero if stream is read only. + */ +int __freading(FILE *f) { + return (f->iomode & O_ACCMODE) == O_RDONLY; +} diff --git a/stdio/freopen.c b/stdio/freopen.c new file mode 100644 index 0000000..2f83742 --- /dev/null +++ b/stdio/freopen.c @@ -0,0 +1,60 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/f.h" +#include "libc/sysv/consts/fd.h" +#include "libc/sysv/consts/o.h" + +/** + * Overwrites existing stream. + * + * This function can be used in two ways. The first is sort of a + * mutating assignment. The second behavior, if pathname is NULL, is + * just changing the mode of an already open file descriptor. + * + * @param pathname is the file to open or NULL + * @param mode is the mode string flags, see fopenflags() + * @param stream is the existing allocated stream memory, which is + * flushed and closed if already open + * @return stream object if successful, or NULL w/ errno + */ +FILE *freopen(const char *pathname, const char *mode, FILE *stream) { + int fd; + unsigned flags; + flags = fopenflags(mode); + fflush(stream); + if (pathname) { + /* open new stream, overwriting existing alloc */ + if ((fd = open(pathname, flags, 0666)) != -1) { + dup3(fd, stream->fd, flags & O_CLOEXEC); + close(fd); + stream->iomode = flags; + stream->beg = 0; + stream->end = 0; + return stream; + } else { + return NULL; + } + } else { + fcntl(stream->fd, F_SETFD, !!(flags & O_CLOEXEC)); + fcntl(stream->fd, F_SETFL, flags & ~O_CLOEXEC); + return stream; + } +} diff --git a/stdio/fscanf.c b/stdio/fscanf.c new file mode 100644 index 0000000..a713b7b --- /dev/null +++ b/stdio/fscanf.c @@ -0,0 +1,44 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/fmt.h" +#include "libc/stdio/stdio.h" + +/** + * Decodes data from stream. + * + * To read a line of data from a well-formed trustworthy file: + * + * int x, y; + * char text[256]; + * fscanf(f, "%d %d %s\n", &x, &y, text); + * + * Please note that this function is brittle by default, which makes it + * a good fit for yolo coding. With some toil it can be used in a way + * that makes it reasonably hardened although getline() may be better. + * + * @see libc/fmt/vcscanf.c + */ +int(fscanf)(FILE *stream, const char *fmt, ...) { + int rc; + va_list va; + va_start(va, fmt); + rc = (vcscanf)((int (*)(void *))fgetc, (void *)ungetc, stream, fmt, va); + va_end(va); + return rc; +} diff --git a/stdio/fseek.c b/stdio/fseek.c new file mode 100644 index 0000000..f9c92c7 --- /dev/null +++ b/stdio/fseek.c @@ -0,0 +1,36 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Repositions open file stream. + * + * This function flushes the buffer (unless it's currently in the EOF + * state) and then calls lseek() on the underlying file. If the stream + * is in the EOF state, this function can be used to restore it without + * needing to reopen the file. + * + * @param f is a non-null stream handle + * @param offset is the byte delta + * @param whence can be SEET_SET, SEEK_CUR, or SEEK_END + * @returns 0 on success or -1 on error + */ +int fseek(FILE *f, long offset, int whence) { + return fseeko(f, offset, whence); +} diff --git a/stdio/fseeko.c b/stdio/fseeko.c new file mode 100644 index 0000000..67dd330 --- /dev/null +++ b/stdio/fseeko.c @@ -0,0 +1,83 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/o.h" + +/** + * Repositions open file stream. + * + * This function flushes the buffer (unless it's currently in the EOF + * state) and then calls lseek() on the underlying file. If the stream + * is in the EOF state, this function can be used to restore it without + * needing to reopen the file. + * + * @param f is a non-null stream handle + * @param offset is the byte delta + * @param whence can be SEET_SET, SEEK_CUR, or SEEK_END + * @returns 0 on success or -1 on error + */ +int fseeko(FILE *f, int64_t offset, int whence) { + ssize_t rc; + int64_t pos; + if (f->fd != -1) { + if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) { + if ((rc = write(f->fd, f->buf, f->beg)) == -1) { + f->state = errno; + return -1; + } + if (rc != f->beg) abort(); + f->beg = 0; + } + if (whence == SEEK_CUR && f->beg < f->end) { + offset -= f->end - f->beg; + } + if (lseek(f->fd, offset, whence) != -1) { + f->beg = 0; + f->end = 0; + return 0; + } else { + f->state = errno == ESPIPE ? EBADF : errno; + return -1; + } + } else { + switch (whence) { + case SEEK_SET: + pos = offset; + break; + case SEEK_CUR: + pos = f->beg + offset; + break; + case SEEK_END: + pos = f->end + offset; + break; + default: + pos = -1; + break; + } + if (0 <= pos && pos <= f->end) { + f->beg = pos; + return 0; + } else { + f->state = errno = EINVAL; + return -1; + } + } +} diff --git a/stdio/fsetlocking.c b/stdio/fsetlocking.c new file mode 100644 index 0000000..2dd880e --- /dev/null +++ b/stdio/fsetlocking.c @@ -0,0 +1,26 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio_ext.h" + +/** + * Does nothing and returns `FSETLOCKING_BYCALLER`. + */ +int __fsetlocking(FILE *f, int type) { + return FSETLOCKING_BYCALLER; +} diff --git a/stdio/fsetpos.c b/stdio/fsetpos.c new file mode 100644 index 0000000..899ab69 --- /dev/null +++ b/stdio/fsetpos.c @@ -0,0 +1,24 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" +#include "libc/calls/calls.h" + +int fsetpos(FILE *stream, const fpos_t *pos) { + return fseek(stream, *pos, SEEK_SET); +} diff --git a/stdio/ftell.c b/stdio/ftell.c new file mode 100644 index 0000000..1f843ea --- /dev/null +++ b/stdio/ftell.c @@ -0,0 +1,29 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Returns current position of stream. + * + * @param stream is a non-null stream handle + * @returns current byte offset from beginning, or -1 w/ errno + */ +long ftell(FILE *f) { + return ftello(f); +} diff --git a/stdio/ftello.c b/stdio/ftello.c new file mode 100644 index 0000000..7c6148a --- /dev/null +++ b/stdio/ftello.c @@ -0,0 +1,54 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns current position of stream. + * + * @param stream is a non-null stream handle + * @returns current byte offset from beginning, or -1 w/ errno + */ +int64_t ftello(FILE *f) { + ssize_t rc; + int64_t pos; + uint32_t skew; + if (f->fd != -1) { + if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) { + if ((rc = write(f->fd, f->buf, f->beg)) == -1) { + f->state = errno; + return -1; + } + if (rc != f->beg) abort(); + f->beg = 0; + } + if ((pos = lseek(f->fd, 0, SEEK_CUR)) != -1) { + if (f->beg < f->end) pos -= f->end - f->beg; + return pos; + } else { + f->state = errno == ESPIPE ? EBADF : errno; + return -1; + } + } else { + return f->beg; + } +} diff --git a/stdio/fwritable.c b/stdio/fwritable.c new file mode 100644 index 0000000..04562f4 --- /dev/null +++ b/stdio/fwritable.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio_ext.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns nonzero if stream allows reading. + */ +int __fwritable(FILE *f) { + return (f->iomode & O_ACCMODE) == O_WRONLY || + (f->iomode & O_ACCMODE) == O_RDWR; +} diff --git a/stdio/fwrite.c b/stdio/fwrite.c new file mode 100644 index 0000000..30f1000 --- /dev/null +++ b/stdio/fwrite.c @@ -0,0 +1,89 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/calls/struct/iovec.h" +#include "libc/errno.h" +#include "libc/fmt/conv.h" +#include "libc/macros.internal.h" +#include "libc/runtime/runtime.h" +#include "libc/sock/sock.h" +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/o.h" + +/** + * Writes data to stream. + * + * @param stride specifies the size of individual items + * @param count is the number of strides to write + * @return count on success, [0,count) on EOF, 0 on error or count==0 + */ +size_t fwrite(const void *data, size_t stride, size_t count, FILE *f) { + ldiv_t d; + ssize_t rc; + size_t n, m; + const char *p; + struct iovec iov[2]; + if ((f->iomode & O_ACCMODE) == O_RDONLY) { + f->state = errno = EBADF; + return 0; + } + n = stride * count; + m = f->size - f->beg; + if (n <= m && f->bufmode != _IONBF) { + memcpy(f->buf + f->beg, data, n); + f->beg += n; + if (f->fd != -1 && f->bufmode == _IOLBF && + (p = memrchr(f->buf, '\n', f->beg))) { + n = p + 1 - f->buf; + if ((rc = write(f->fd, f->buf, n)) == -1) { + if (errno == EINTR || errno == EAGAIN) return count; + f->state = errno; + return 0; + } + n = rc; + memmove(f->buf, f->buf + n, f->beg - n); + f->beg -= n; + } + return count; + } + if (f->fd == -1) { + n = MIN(n, m); + d = ldiv(n, stride); + n -= d.rem; + memcpy(f->buf + f->beg, data, n); + f->beg += n; + f->state = -1; + return d.quot; + } + iov[0].iov_base = f->buf; + iov[0].iov_len = f->beg; + iov[1].iov_base = data; + iov[1].iov_len = n; + n += f->beg; + if ((rc = writev(f->fd, iov, 2)) == -1) { + f->state = errno; + return 0; + } + m = rc; + if (n != m) abort(); + f->beg = 0; + return count; +} diff --git a/stdio/fwriting.c b/stdio/fwriting.c new file mode 100644 index 0000000..1820949 --- /dev/null +++ b/stdio/fwriting.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio_ext.h" +#include "libc/sysv/consts/o.h" + +/** + * Returns nonzero if stream is write only. + */ +int __fwriting(FILE *f) { + return (f->iomode & O_ACCMODE) == O_WRONLY; +} diff --git a/stdio/get_current_dir_name.c b/stdio/get_current_dir_name.c new file mode 100644 index 0000000..f9fdd0b --- /dev/null +++ b/stdio/get_current_dir_name.c @@ -0,0 +1,38 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/safemacros.internal.h" +#include "libc/calls/calls.h" +#include "libc/mem/mem.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/errfuns.h" + +/** + * Returns current working directory. + * + * If the PWD environment variable is set, that'll be returned (since + * it's faster than issuing a system call). + * + * @return pointer that must be free()'d, or NULL w/ errno + */ +nodiscard char *get_current_dir_name(void) { + char *buf, *res; + if (!(buf = malloc(PATH_MAX))) return NULL; + if (!(res = (getcwd)(buf, PATH_MAX))) free(buf); + return res; +} diff --git a/stdio/getc.c b/stdio/getc.c new file mode 100644 index 0000000..71082bc --- /dev/null +++ b/stdio/getc.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Reads byte from stream. + * @return byte in range 0..255, or -1 w/ errno + */ +int(getc)(FILE *f) { + return fgetc(f); +} diff --git a/stdio/getchar.c b/stdio/getchar.c new file mode 100644 index 0000000..db56d6b --- /dev/null +++ b/stdio/getchar.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Reads byte from stream. + * @return byte in range 0..255, or -1 w/ errno + */ +int getchar(void) { + return fgetc(stdin); +} diff --git a/stdio/getdelim.c b/stdio/getdelim.c new file mode 100644 index 0000000..dfdadf2 --- /dev/null +++ b/stdio/getdelim.c @@ -0,0 +1,79 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/macros.internal.h" +#include "libc/mem/mem.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/o.h" + +/** + * Reads string from stream. + * + * @param s is the caller's buffer (in/out) which is extended or + * allocated automatically, also NUL-terminated is guaranteed + * @param n is the capacity of s (in/out) + * @param delim is the stop char (and NUL is implicitly too) + * @return number of bytes read, including delim, excluding NUL, or -1 + * w/ errno on EOF or error; see ferror() and feof() + * @note this function can't punt EINTR to caller + * @see getline(), gettok_r() + */ +ssize_t getdelim(char **s, size_t *n, int delim, FILE *f) { + char *p; + ssize_t rc; + size_t i, m; + if ((f->iomode & O_ACCMODE) == O_WRONLY) { + f->state = errno = EBADF; + return -1; + } + if (f->beg > f->end || f->bufmode == _IONBF) { + f->state = errno = EINVAL; + return -1; + } + if (!*s) *n = 0; + for (i = 0;; i += m) { + m = f->end - f->beg; + if ((p = memchr(f->buf + f->beg, delim, m))) m = p + 1 - (f->buf + f->beg); + if (i + m + 1 > *n && !(*s = realloc(*s, (*n = i + m + 1)))) abort(); + memcpy(*s + i, f->buf + f->beg, m); + (*s)[i + m] = '\0'; + if ((f->beg += m) == f->end) f->beg = f->end = 0; + if (p) { + return i + m; + } else if (f->fd == -1) { + break; + } else if ((rc = read(f->fd, f->buf, f->size)) != -1) { + if (!rc) break; + f->end = rc; + } else if (errno != EINTR) { + f->state = errno; + return -1; + } + } + f->state = -1; + if (i + m) { + return i + m; + } else { + return -1; + } +} diff --git a/stdio/getline.c b/stdio/getline.c new file mode 100644 index 0000000..4a5c259 --- /dev/null +++ b/stdio/getline.c @@ -0,0 +1,37 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Reads line from stream. + * + * This function delegates to getdelim(), which provides further + * documentation. Concerning lines, please note the \n or \r\n are + * included in results, and can be removed with chomp(). + * + * @param line is the caller's buffer (in/out) which is extended + * automatically. *line may be NULL but only if *n is 0; + * NUL-termination is guaranteed FTMP + * @return number of bytes read, including delim, excluding NUL, or -1 + * w/ errno on EOF or error; see ferror() and feof() + * @see xgetline(), getdelim(), gettok_r() + */ +ssize_t getline(char **line, size_t *n, FILE *f) { + return getdelim(line, n, '\n', f); +} diff --git a/stdio/gets.c b/stdio/gets.c new file mode 100644 index 0000000..d62e623 --- /dev/null +++ b/stdio/gets.c @@ -0,0 +1,24 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/limits.h" +#include "libc/stdio/stdio.h" + +compatfn char *gets(char *s) { + return fgets(s, INT_MAX, stdin); +} diff --git a/stdio/getwc.c b/stdio/getwc.c new file mode 100644 index 0000000..2ec4cc1 --- /dev/null +++ b/stdio/getwc.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Reads UTF-8 character from stream. + * @return wide character or -1 on EOF or error + */ +wint_t(getwc)(FILE *f) { + return fgetwc(f); +} diff --git a/stdio/getwchar.c b/stdio/getwchar.c new file mode 100644 index 0000000..a455dbc --- /dev/null +++ b/stdio/getwchar.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Reads UTF-8 character from stream. + * @return wide character or -1 on EOF or error + */ +wint_t getwchar(void) { + return fgetwc(stdin); +} diff --git a/stdio/internal.h b/stdio/internal.h new file mode 100644 index 0000000..ba8de1e --- /dev/null +++ b/stdio/internal.h @@ -0,0 +1,19 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_INTERNAL_H_ +#define COSMOPOLITAN_LIBC_STDIO_INTERNAL_H_ +#include "libc/stdio/stdio.h" + +#define PUSHBACK 12 + +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +extern char g_stdinbuf[BUFSIZ]; +extern char g_stdoutbuf[BUFSIZ]; +extern char g_stderrbuf[BUFSIZ]; + +int __fflush_register(FILE *) hidden; +void __fflush_unregister(FILE *) hidden; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_INTERNAL_H_ */ diff --git a/stdio/mkostemp.c b/stdio/mkostemp.c new file mode 100644 index 0000000..7d4bd03 --- /dev/null +++ b/stdio/mkostemp.c @@ -0,0 +1,23 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/temp.h" + +int mkostemp(char *template, unsigned flags) { + return mkostempsm(template, 0, flags, 0600); +} diff --git a/stdio/mkostemps.c b/stdio/mkostemps.c new file mode 100644 index 0000000..2159770 --- /dev/null +++ b/stdio/mkostemps.c @@ -0,0 +1,26 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/temp.h" + +/** + * Delegates to mkotempsm() w/ owner-only non-execute access. + */ +nodiscard int mkostemps(char *template, int suffixlen, unsigned flags) { + return mkostempsm(template, suffixlen, flags, 0600); +} diff --git a/stdio/mkostempsm.c b/stdio/mkostempsm.c new file mode 100644 index 0000000..f42e46f --- /dev/null +++ b/stdio/mkostempsm.c @@ -0,0 +1,81 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/rand/lcg.internal.h" +#include "libc/rand/rand.h" +#include "libc/stdio/temp.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/errfuns.h" + +#define RESEED 1024 +#define ATTEMPTS 10 +#define WILDCARD "XXXXXX" + +int mkostempsmi(char *tpl, int slen, unsigned flags, uint64_t *rando, int mode, + int openit(const char *file, int flags, ...)) { + size_t len = strlen(tpl); + size_t wildlen = strlen(WILDCARD); + if (len < wildlen || slen > len - wildlen) { + return einval(); + } + char *ss = tpl + len - wildlen - slen; + assert(memcmp(ss, WILDCARD, wildlen) == 0); + flags = (flags & ~(flags & O_ACCMODE)) | O_RDWR | O_CREAT | O_EXCL; + unsigned attempts = ATTEMPTS; + do { + char *p = ss; + uint32_t num = KnuthLinearCongruentialGenerator(rando) >> 32; + for (unsigned i = 0; i < wildlen; ++i) { + p[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[num & 31]; + num >>= 5; + } + int fd; + if ((fd = openit(tpl, flags, 0600)) != -1) return fd; + } while (--attempts && errno == EEXIST); + memcpy(ss, WILDCARD, wildlen); + return -1; +} + +static uint64_t g_mkostemps_rand; +static uint64_t g_mkostemps_reseed; + +/** + * Opens unique temporary file. + * + * The substring XXXXXX is replaced with a pseudorandom number that's + * seeded automatically and grants 30 bits of randomness to each value. + * Retries are made in the unlikely event of collisions. + * + * @param template is a pathname relative to current directory by default, + * that needs to have "XXXXXX" at the end of the string + * @param suffixlen may be nonzero to permit characters after the XXXXXX + * @param flags can have O_APPEND, O_CLOEXEC, etc. + * @param mode is conventionally 0600, for owner-only non-exec access + * @return exclusive open file descriptor for generated pathname, + * or -1 w/ errno + * @see kTmpPath + */ +nodiscard int mkostempsm(char *template, int suffixlen, unsigned flags, + int mode) { + if (g_mkostemps_reseed++ % RESEED == 0) g_mkostemps_rand = rand64(); + return mkostempsmi(template, suffixlen, flags, &g_mkostemps_rand, mode, open); +} diff --git a/stdio/mkstemp.c b/stdio/mkstemp.c new file mode 100644 index 0000000..881c3b4 --- /dev/null +++ b/stdio/mkstemp.c @@ -0,0 +1,23 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/temp.h" + +int mkstemp(char *template) { + return mkostempsm(template, 0, 0, 0600); +} diff --git a/stdio/mkstemps.c b/stdio/mkstemps.c new file mode 100644 index 0000000..d785d93 --- /dev/null +++ b/stdio/mkstemps.c @@ -0,0 +1,23 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/temp.h" + +int mkstemps(char *template, int suffixlen) { + return mkostempsm(template, suffixlen, 0, 0600); +} diff --git a/stdio/mktemp.c b/stdio/mktemp.c new file mode 100644 index 0000000..fb72216 --- /dev/null +++ b/stdio/mktemp.c @@ -0,0 +1,39 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/temp.h" +#include "libc/sysv/errfuns.h" + +/** + * Generates unique filename. + * + * This function is usually frowned upon, since it's been known to + * create nasty opportunities for race conditions. Our implementation + * reflects that; consider using mkostemps(). + */ +char *mktemp(char *template) { + int fd; + if ((fd = mkostemps(template, 0, 0)) != -1) { + close(fd); + unlink(template); + } else { + template[0] = '\0'; + } + return template; +} diff --git a/stdio/pclose.c b/stdio/pclose.c new file mode 100644 index 0000000..911855a --- /dev/null +++ b/stdio/pclose.c @@ -0,0 +1,43 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/errfuns.h" + +/** + * Closes stream created by popen(). + * @return termination status of subprocess, or -1 w/ ECHILD + */ +int pclose(FILE *f) { + int ws, pid; + pid = f->pid; + fclose(f); + assert(pid); + if (!pid) return 0; +TryAgain: + if (wait4(pid, &ws, 0, 0) != -1) { + return ws; + } else if (errno == EINTR) { + goto TryAgain; + } else { + return echild(); + } +} diff --git a/stdio/popen.c b/stdio/popen.c new file mode 100644 index 0000000..50abc39 --- /dev/null +++ b/stdio/popen.c @@ -0,0 +1,57 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/paths.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/f.h" +#include "libc/sysv/consts/fd.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/errfuns.h" + +/** + * Spawns subprocess and returns pipe stream. + * @see pclose() + */ +FILE *popen(const char *cmdline, const char *mode) { + FILE *f; + int dir, flags, pipefds[2]; + flags = fopenflags(mode); + if ((flags & O_ACCMODE) == O_RDONLY) { + dir = 0; + } else if ((flags & O_ACCMODE) == O_WRONLY) { + dir = 1; + } else { + errno = EINVAL; + return NULL; + } + if (pipe(pipefds) == -1) return NULL; + fcntl(pipefds[dir], F_SETFD, FD_CLOEXEC); + if (!(f = fdopen(pipefds[dir], mode))) abort(); + if ((f->pid = vfork()) == -1) abort(); + if (!f->pid) { + dup2(pipefds[!dir], !dir); + systemexec(cmdline); + _exit(127); + } + close(pipefds[!dir]); + return f; +} diff --git a/stdio/printf.c b/stdio/printf.c new file mode 100644 index 0000000..8c64c6d --- /dev/null +++ b/stdio/printf.c @@ -0,0 +1,71 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Formats and writes string to stdout. + * + * Cosmopolitan supports most of the standard formatting behaviors + * described by `man 3 printf`, in addition to the following: + * + * - `%jd`, `%jx`, etc. are {,u}intmax_t which in Cosmopolitan is 128-bit. + * + * - `%'d` or `%,d` may be used to insert thousands separators. The prior is + * consistent with C; the latter is consistent with Python. + * + * - `%m` inserts strerror(errno) into the formatted output. This is + * consistent with glibc, musl, and uclibc. + * + * - `%n` inserts "\n" on non-Windows and "\r\n" on Windows. This is the + * same behavior as Java. It's incompatible with glibc's behavior, + * since that's problematic according to Android's security team. + * + * - `%hs` converts UTF-16/UCS-2 → UTF-8, which can be helpful on Windows. + * Formatting (e.g. %-10hs) will use monospace display width rather + * than string length or codepoint count. + * + * - `%ls` (or `%Ls`) converts UTF-32 → UTF-8. Formatting (e.g. %-10ls) + * will use monospace display width rather than string length. + * + * - The `%#s` and `%#c` alternate forms display values using the + * standard IBM standard 256-letter alphabet. Using `%#.*s` to specify + * length will allow true binary (i.e. with NULs) to be formatted. + * + * - The `%'s` and `%'c` alternate forms are Cosmopolitan extensions for + * escaping string literals for C/C++ and Python. The outer quotation + * marks can be added automatically using ``%`s``. If constexpr format + * strings are used, we can avoid linking cescapec() too. + * + * - The backtick modifier (``%`s`` and ``%`c``) and repr() directive + * (`%r`) both ask the formatting machine to represent values as real + * code rather than using arbitrary traditions for displaying values. + * This means it implies the quoting modifier, wraps the value with + * {,u,L}['"] quotes, displays NULL as "NULL" rather than "(null)". + * + * @see __fmt() for intuitive reference documentation + * @see {,v}{,s{,n},{,{,x}as},f,d}printf + */ +int(printf)(const char* fmt, ...) { + int rc; + va_list va; + va_start(va, fmt); + rc = (vfprintf)(stdout, fmt, va); + va_end(va); + return rc; +} diff --git a/stdio/putc.c b/stdio/putc.c new file mode 100644 index 0000000..559519a --- /dev/null +++ b/stdio/putc.c @@ -0,0 +1,29 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Writes byte to stream. + * + * @param c is byte to buffer or write, which is masked + * @return c as unsigned char if written or -1 w/ errno + */ +int(putc)(int c, FILE *f) { + return fputc(c, f); +} diff --git a/stdio/putchar.c b/stdio/putchar.c new file mode 100644 index 0000000..55b7c3c --- /dev/null +++ b/stdio/putchar.c @@ -0,0 +1,26 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Writes byte to stdout. + * + * @return c (as unsigned char) if written or -1 w/ errno + */ +int putchar(int c) { return fputc(c, stdout); } diff --git a/stdio/puts.c b/stdio/puts.c new file mode 100644 index 0000000..044420e --- /dev/null +++ b/stdio/puts.c @@ -0,0 +1,38 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Writes string w/ trailing newline to stdout. + */ +int puts(const char *s) { + FILE *f; + size_t n, r; + f = stdout; + if ((n = strlen(s))) { + r = fwrite(s, 1, n, f); + if (!r) return -1; + if (r < n) return r; + } + if (fputc('\n', f) == -1) { + if (feof(f)) return n; + return -1; + } + return n + 1; +} diff --git a/stdio/putwc.c b/stdio/putwc.c new file mode 100644 index 0000000..fad85ca --- /dev/null +++ b/stdio/putwc.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Writes wide character to stream. + * + * @return wc if written or -1 w/ errno + */ +wint_t(putwc)(wchar_t wc, FILE *f) { + return fputwc(wc, f); +} diff --git a/stdio/putwchar.c b/stdio/putwchar.c new file mode 100644 index 0000000..8fe5cf0 --- /dev/null +++ b/stdio/putwchar.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +/** + * Writes wide character to stdout. + * @return wc if written or -1 w/ errno + */ +wint_t putwchar(wchar_t wc) { + return fputwc(wc, stdout); +} diff --git a/stdio/rewind.c b/stdio/rewind.c new file mode 100644 index 0000000..03aa3f5 --- /dev/null +++ b/stdio/rewind.c @@ -0,0 +1,31 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/stdio.h" + +/** + * Moves standard i/o stream to beginning of file. + * + * Like fseek(), this function can be used to restore a stream from the + * EOF state, without reopening it. + */ +void rewind(FILE *f) { + fseek(f, 0, SEEK_SET); + f->state = 0; +} diff --git a/stdio/scanf.c b/stdio/scanf.c new file mode 100644 index 0000000..e2b19b2 --- /dev/null +++ b/stdio/scanf.c @@ -0,0 +1,33 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/fmt.h" +#include "libc/stdio/stdio.h" + +/** + * Standard input decoder. + * @see libc/fmt/vcscanf.h + */ +int(scanf)(const char *fmt, ...) { + int rc; + va_list va; + va_start(va, fmt); + rc = (vcscanf)((int (*)(void *))fgetc, NULL, stdin, fmt, va); + va_end(va); + return rc; +} diff --git a/stdio/setbuf.c b/stdio/setbuf.c new file mode 100644 index 0000000..4396f15 --- /dev/null +++ b/stdio/setbuf.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/stdio.h" + +/** + * Sets buffer on stdio stream. + */ +void setbuf(FILE *f, char *buf) { + setvbuf(f, buf, buf ? _IOFBF : _IONBF, BUFSIZ); +} diff --git a/stdio/setbuffer.c b/stdio/setbuffer.c new file mode 100644 index 0000000..94220dc --- /dev/null +++ b/stdio/setbuffer.c @@ -0,0 +1,33 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/errfuns.h" + +/** + * Sets buffer on stdio stream. + * + * @param buf may optionally be non-NULL to set the stream's underlying + * buffer, which the stream will own, but won't free + * @param size is ignored if buf is NULL + */ +void setbuffer(FILE *f, char *buf, size_t size) { + setvbuf(f, buf, buf ? _IOFBF : _IONBF, size); +} diff --git a/stdio/setlinebuf.c b/stdio/setlinebuf.c new file mode 100644 index 0000000..fa6bc64 --- /dev/null +++ b/stdio/setlinebuf.c @@ -0,0 +1,27 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/stdio/stdio.h" + +/** + * Puts stream in line-buffering mode. + */ +void setlinebuf(FILE *f) { + setvbuf(f, NULL, _IOLBF, 0); +} diff --git a/stdio/setvbuf.c b/stdio/setvbuf.c new file mode 100644 index 0000000..4149bdd --- /dev/null +++ b/stdio/setvbuf.c @@ -0,0 +1,42 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" +#include "libc/sysv/errfuns.h" + +/** + * Tunes buffering settings for an stdio stream. + * + * @param mode may be _IOFBF, _IOLBF, or _IONBF + * @param buf may optionally be non-NULL to set the stream's underlying + * buffer, which the stream will own, but won't free, otherwise the + * existing buffer is used + * @param size is ignored if buf is NULL + * @return 0 on success or -1 on error + */ +int setvbuf(FILE *f, char *buf, int mode, size_t size) { + if (buf) { + if (!size) size = BUFSIZ; + if (!f->nofree && f->buf != buf) free_s(&f->buf); + f->buf = buf; + f->size = size; + f->nofree = true; + } + f->bufmode = mode; + return 0; +} diff --git a/stdio/spawn.c b/stdio/spawn.c new file mode 100644 index 0000000..5dc3980 --- /dev/null +++ b/stdio/spawn.c @@ -0,0 +1,115 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/calls/scheduler.h" +#include "libc/calls/sigbits.h" +#include "libc/calls/struct/sigaction.h" +#include "libc/errno.h" +#include "libc/fmt/fmt.h" +#include "libc/stdio/spawn.h" +#include "libc/stdio/spawna.internal.h" +#include "libc/str/str.h" + +/** + * Spawns process the POSIX way. + * + * @param pid is non-NULL and will be set to child pid in parent + * @param path of executable that is not PATH searched + * @return 0 on success or error number on failure + */ +int posix_spawn(int *pid, const char *path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[]) { + unsigned mode; + sigset_t allsigs; + struct sigaction dfl; + char *p, *q, opath[PATH_MAX]; + int s, fd, newfd, oflag, tempfd; + if (!(*pid = vfork())) { + if (attrp) { + if (attrp->posix_attr_flags & POSIX_SPAWN_SETPGROUP) { + if (setpgid(0, attrp->posix_attr_pgroup)) _exit(127); + } + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGMASK) { + sigprocmask(SIG_SETMASK, &attrp->posix_attr_sigmask, NULL); + } + if (attrp->posix_attr_flags & POSIX_SPAWN_RESETIDS) { + setuid(getuid()); + setgid(getgid()); + } + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGDEF) { + dfl.sa_handler = SIG_DFL; + dfl.sa_flags = 0; + sigfillset(&allsigs); + for (s = 0; sigismember(&allsigs, s); s++) { + if (sigismember(&attrp->posix_attr_sigdefault, s)) { + if (sigaction(s, &dfl, NULL) == -1) _exit(127); + } + } + } + } + if (file_actions) { + for (p = *file_actions; *p; p = strchr(p, ')') + 1) { + if (!strncmp(p, "close(", 6)) { + if (sscanf(p + 6, "%d)", &fd) != 1) _exit(127); + if (close(fd) == -1) _exit(127); + } else if (!strncmp(p, "dup2(", 5)) { + if (sscanf(p + 5, "%d,%d)", &fd, &newfd) != 2) _exit(127); + if (dup2(fd, newfd) == -1) _exit(127); + } else if (!strncmp(p, "open(", 5)) { + if (sscanf(p + 5, "%d,", &fd) != 1) _exit(127); + p = strchr(p, ',') + 1; + q = strchr(p, '*'); + if (!q || q - p + 1 > PATH_MAX) _exit(127); + strncpy(opath, p, q - p); + opath[q - p] = '\0'; + if (sscanf(q + 1, "%o,%o)", &oflag, &mode) != 2) _exit(127); + if (close(fd) == -1 && errno != EBADF) _exit(127); + tempfd = open(opath, oflag, mode); + if (tempfd == -1) _exit(127); + if (tempfd != fd) { + if (dup2(tempfd, fd) == -1) _exit(127); + if (close(tempfd) == -1) _exit(127); + } + } else { + _exit(127); + } + } + } + if (attrp) { + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSCHEDULER) { + if (sched_setscheduler(0, attrp->posix_attr_schedpolicy, + &attrp->posix_attr_schedparam) == -1) { + _exit(127); + } + } + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSCHEDPARAM) { + if (sched_setparam(0, &attrp->posix_attr_schedparam) == -1) { + _exit(127); + } + } + } + execve(path, argv, envp); + _exit(127); + } else { + if (*pid == -1) return errno; + return 0; + } +} diff --git a/stdio/spawn.h b/stdio/spawn.h new file mode 100644 index 0000000..7fe335c --- /dev/null +++ b/stdio/spawn.h @@ -0,0 +1,50 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_SPAWN_H_ +#define COSMOPOLITAN_LIBC_STDIO_SPAWN_H_ +#include "libc/calls/struct/sched_param.h" +#include "libc/calls/struct/sigset.h" + +#define POSIX_SPAWN_RESETIDS 0x01 +#define POSIX_SPAWN_SETPGROUP 0x02 +#define POSIX_SPAWN_SETSIGDEF 0x04 +#define POSIX_SPAWN_SETSIGMASK 0x08 +#define POSIX_SPAWN_SETSCHEDPARAM 0x10 +#define POSIX_SPAWN_SETSCHEDULER 0x20 + +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +typedef char *posix_spawn_file_actions_t; +typedef struct _posix_spawnattr posix_spawnattr_t; + +int posix_spawn(int *, const char *, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *, char *const[], char *const[]); +int posix_spawnp(int *, const char *, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *, char *const[], char *const[]); + +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int); +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *, int, + const char *, int, unsigned); + +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_destroy(posix_spawnattr_t *); +int posix_spawnattr_getflags(const posix_spawnattr_t *, short *); +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_getpgroup(const posix_spawnattr_t *, int *); +int posix_spawnattr_setpgroup(posix_spawnattr_t *, int); +int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *, int *); +int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int); +int posix_spawnattr_getschedparam(const posix_spawnattr_t *, + struct sched_param *); +int posix_spawnattr_setschedparam(posix_spawnattr_t *, + const struct sched_param *); +int posix_spawnattr_getsigmask(const posix_spawnattr_t *, sigset_t *); +int posix_spawnattr_setsigmask(posix_spawnattr_t *, const sigset_t *); +int posix_spawnattr_getdefault(const posix_spawnattr_t *, sigset_t *); +int posix_spawnattr_setsigdefault(posix_spawnattr_t *, const sigset_t *); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_SPAWN_H_ */ diff --git a/stdio/spawna.c b/stdio/spawna.c new file mode 100644 index 0000000..125738e --- /dev/null +++ b/stdio/spawna.c @@ -0,0 +1,107 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/calls/scheduler.h" +#include "libc/calls/sigbits.h" +#include "libc/stdio/spawn.h" +#include "libc/stdio/spawna.internal.h" + +/** + * Initialize object with default values. + */ +int posix_spawnattr_init(posix_spawnattr_t *attr) { + attr->posix_attr_flags = 0; + attr->posix_attr_pgroup = 0; + sigprocmask(0, NULL, &attr->posix_attr_sigmask); + sigemptyset(&attr->posix_attr_sigdefault); + attr->posix_attr_schedpolicy = sched_getscheduler(0); + sched_getparam(0, &attr->posix_attr_schedparam); + return 0; +} + +int posix_spawnattr_destroy(posix_spawnattr_t *attr) { + return 0; +} + +int posix_spawnattr_getflags(const posix_spawnattr_t *attr, short *flags) { + *flags = attr->posix_attr_flags; + return 0; +} + +int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) { + attr->posix_attr_flags = flags; + return 0; +} + +int posix_spawnattr_getpgroup(const posix_spawnattr_t *attr, int *pgroup) { + *pgroup = attr->posix_attr_pgroup; + return 0; +} + +int posix_spawnattr_setpgroup(posix_spawnattr_t *attr, int pgroup) { + attr->posix_attr_pgroup = pgroup; + return 0; +} + +int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *attr, + int *schedpolicy) { + *schedpolicy = attr->posix_attr_schedpolicy; + return 0; +} + +int posix_spawnattr_setschedpolicy(posix_spawnattr_t *attr, int schedpolicy) { + attr->posix_attr_schedpolicy = schedpolicy; + return 0; +} + +int posix_spawnattr_getschedparam(const posix_spawnattr_t *attr, + struct sched_param *schedparam) { + *schedparam = attr->posix_attr_schedparam; + return 0; +} + +int posix_spawnattr_setschedparam(posix_spawnattr_t *attr, + const struct sched_param *schedparam) { + attr->posix_attr_schedparam = *schedparam; + return 0; +} + +int posix_spawnattr_getsigmask(const posix_spawnattr_t *attr, + sigset_t *sigmask) { + *sigmask = attr->posix_attr_sigmask; + return 0; +} + +int posix_spawnattr_setsigmask(posix_spawnattr_t *attr, + const sigset_t *sigmask) { + attr->posix_attr_sigmask = *sigmask; + return 0; +} + +int posix_spawnattr_getsigdefault(const posix_spawnattr_t *attr, + sigset_t *sigdefault) { + *sigdefault = attr->posix_attr_sigdefault; + return 0; +} + +int posix_spawnattr_setsigdefault(posix_spawnattr_t *attr, + const sigset_t *sigdefault) { + attr->posix_attr_sigdefault = *sigdefault; + return 0; +} diff --git a/stdio/spawna.internal.h b/stdio/spawna.internal.h new file mode 100644 index 0000000..2635aca --- /dev/null +++ b/stdio/spawna.internal.h @@ -0,0 +1,19 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_SPAWNA_INTERNAL_H_ +#define COSMOPOLITAN_LIBC_STDIO_SPAWNA_INTERNAL_H_ +#include "libc/calls/struct/sched_param.h" +#include "libc/calls/struct/sigset.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +struct _posix_spawnattr { + int16_t posix_attr_flags; + int32_t posix_attr_pgroup; + sigset_t posix_attr_sigmask; + sigset_t posix_attr_sigdefault; + int32_t posix_attr_schedpolicy; + struct sched_param posix_attr_schedparam; +}; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_SPAWNA_INTERNAL_H_ */ diff --git a/stdio/spawnf.c b/stdio/spawnf.c new file mode 100644 index 0000000..3e893b1 --- /dev/null +++ b/stdio/spawnf.c @@ -0,0 +1,85 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/errno.h" +#include "libc/fmt/fmt.h" +#include "libc/mem/mem.h" +#include "libc/stdio/spawn.h" +#include "libc/str/str.h" + +/** + * Creates object with no actions. + */ +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *file_actions) { + *file_actions = malloc(sizeof(char)); + if (!*file_actions) return ENOMEM; + strcpy(*file_actions, ""); + return 0; +} + +/** + * Frees object storage and make invalid. + */ +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *file_actions) { + free(*file_actions); + *file_actions = NULL; + return 0; +} + +/** + * Adds new action string to object. + */ +static int add_to_file_actions(posix_spawn_file_actions_t *file_actions, + char *new_action) { + *file_actions = + realloc(*file_actions, strlen(*file_actions) + strlen(new_action) + 1); + if (!*file_actions) return ENOMEM; + strcat(*file_actions, new_action); + return 0; +} + +/** + * Add a close action to object. + */ +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions, + int fildes) { + char temp[100]; + sprintf(temp, "close(%d)", fildes); + return add_to_file_actions(file_actions, temp); +} + +/** + * Add a dup2 action to object. + */ +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions, + int fildes, int newfildes) { + char temp[100]; + sprintf(temp, "dup2(%d,%d)", fildes, newfildes); + return add_to_file_actions(file_actions, temp); +} + +/** + * Add an open action to object. + */ +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *file_actions, + int fildes, const char *path, int oflag, + unsigned mode) { + char temp[100]; + sprintf(temp, "open(%d,%s*%o,%o)", fildes, path, oflag, mode); + return add_to_file_actions(file_actions, temp); +} diff --git a/stdio/spawnp.c b/stdio/spawnp.c new file mode 100644 index 0000000..2191b3c --- /dev/null +++ b/stdio/spawnp.c @@ -0,0 +1,37 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/stdio/spawn.h" + +/** + * Spawns process the POSIX way w/ PATH search. + * + * @param pid is non-NULL and will be set to child pid in parent + * @param path of executable is PATH searched unless it contains a slash + * @return 0 on success or error number on failure + */ +int posix_spawnp(int *pid, const char *path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[]) { + char pathbuf[PATH_MAX]; + if (!(path = commandv(path, pathbuf))) return errno; + return posix_spawn(pid, path, file_actions, attrp, argv, envp); +} diff --git a/stdio/stdbuf.c b/stdio/stdbuf.c new file mode 100644 index 0000000..67d68cf --- /dev/null +++ b/stdio/stdbuf.c @@ -0,0 +1,22 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/internal.h" + +char g_stdoutbuf[BUFSIZ] hidden; +char g_stderrbuf[BUFSIZ] hidden; diff --git a/stdio/stderr-init.S b/stdio/stderr-init.S new file mode 100644 index 0000000..30acd05 --- /dev/null +++ b/stdio/stderr-init.S @@ -0,0 +1,38 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/sysv/consts/o.h" +#include "libc/dce.h" +#include "libc/calls/calls.h" +#include "libc/sysv/consts/fileno.h" +#include "libc/macros.internal.h" +.source __FILE__ + + .init.start 400,_init_stderr + ezlea __stderr,ax + push $_IOLBF + pop (%rax) #→ f.fd + push STDERR_FILENO + pop 12(%rax) + mov O_WRONLY,%edx + mov %edx,4(%rax) #→ f.iomode + ezlea __stderr_buf,cx + mov %rcx,24(%rax) #→ f.buf + movl $BUFSIZ,32(%rax) #→ f.size + mov %rax,stderr(%rip) + .init.end 400,_init_stderr,globl,hidden diff --git a/stdio/stderr.c b/stdio/stderr.c new file mode 100644 index 0000000..9529789 --- /dev/null +++ b/stdio/stderr.c @@ -0,0 +1,36 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" + +STATIC_YOINK("_init_stderr"); + +/** + * Pointer to standard error stream. + */ +FILE *stderr; + +hidden FILE __stderr; +hidden unsigned char __stderr_buf[BUFSIZ]; + +static textstartup void __stderr_init() { + __fflush_register(stderr); +} + +const void *const __stderr_ctor[] initarray = {__stderr_init}; diff --git a/stdio/stdin-init.S b/stdio/stdin-init.S new file mode 100644 index 0000000..4609537 --- /dev/null +++ b/stdio/stdin-init.S @@ -0,0 +1,34 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/sysv/consts/o.h" +#include "libc/dce.h" +#include "libc/calls/calls.h" +#include "libc/sysv/consts/fileno.h" +#include "libc/macros.internal.h" +.source __FILE__ + + .init.start 400,_init_stdin + ezlea __stdin,ax + mov O_RDONLY,%edx + mov %edx,4(%rax) #→ f.iomode + ezlea __stdin_buf,cx + mov %rcx,24(%rax) #→ f.buf + movl $BUFSIZ,32(%rax) #→ f.size + mov %rax,stdin(%rip) + .init.end 400,_init_stdin,globl,hidden diff --git a/stdio/stdin.c b/stdio/stdin.c new file mode 100644 index 0000000..716a0b6 --- /dev/null +++ b/stdio/stdin.c @@ -0,0 +1,36 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" + +STATIC_YOINK("_init_stdin"); + +/** + * Pointer to standard input stream. + */ +FILE *stdin; + +hidden FILE __stdin; +hidden unsigned char __stdin_buf[BUFSIZ]; + +static textstartup void __stdin_init() { + __fflush_register(stdin); +} + +const void *const __stdin_ctor[] initarray = {__stdin_init}; diff --git a/stdio/stdio.h b/stdio/stdio.h new file mode 100644 index 0000000..268913b --- /dev/null +++ b/stdio/stdio.h @@ -0,0 +1,129 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_STDIO_H_ +#define COSMOPOLITAN_LIBC_STDIO_STDIO_H_ +#include "libc/fmt/pflink.h" +#include "libc/runtime/symbolic.h" + +#define FILENAME_MAX PATH_MAX + +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +/*───────────────────────────────────────────────────────────────────────────│─╗ +│ cosmopolitan § standard i/o ─╬─│┼ +╚────────────────────────────────────────────────────────────────────────────│*/ + +typedef struct FILE { + uint8_t bufmode; /* 0x00 _IOFBF, etc. (ignored if fd=-1) */ + bool noclose; /* 0x01 for fake dup() */ + uint32_t iomode; /* 0x04 O_RDONLY, etc. (ignored if fd=-1) */ + int32_t state; /* 0x08 0=OK, -1=EOF, >0=errno */ + int fd; /* 0x0c ≥0=fd, -1=closed|buffer */ + uint32_t beg; /* 0x10 */ + uint32_t end; /* 0x14 */ + char *buf; /* 0x18 */ + uint32_t size; /* 0x20 */ + uint32_t nofree; /* 0x24 */ + int pid; /* 0x28 */ +} FILE; + +extern FILE *stdin; +extern FILE *stdout; +extern FILE *stderr; + +errno_t ferror(FILE *) paramsnonnull(); +void clearerr(FILE *) paramsnonnull(); +int feof(FILE *) paramsnonnull(); +int getc(FILE *) paramsnonnull(); +int putc(int, FILE *) paramsnonnull(); +int fflush(FILE *); +int fgetc(FILE *) paramsnonnull(); +int ungetc(int, FILE *) paramsnonnull(); +int fileno(FILE *) paramsnonnull() nosideeffect; +int fputc(int, FILE *) paramsnonnull(); +int fputs(const char *, FILE *) paramsnonnull(); +int fputws(const wchar_t *, FILE *) paramsnonnull(); +char *fgets(char *, int, FILE *) paramsnonnull(); +wchar_t *fgetws(wchar_t *, int, FILE *) paramsnonnull(); +wint_t putwc(wchar_t, FILE *) paramsnonnull(); +wint_t fputwc(wchar_t, FILE *) paramsnonnull(); +wint_t putwchar(wchar_t); +wint_t getwchar(void); +wint_t getwc(FILE *) paramsnonnull(); +wint_t fgetwc(FILE *) paramsnonnull(); +wint_t ungetwc(wint_t, FILE *) paramsnonnull(); +int getchar(void); +int putchar(int); +int puts(const char *) paramsnonnull(); +ssize_t getline(char **, size_t *, FILE *) paramsnonnull(); +ssize_t getdelim(char **, size_t *, int, FILE *) paramsnonnull(); +FILE *fopen(const char *, const char *) paramsnonnull() nodiscard; +FILE *fdopen(int, const char *) paramsnonnull() nodiscard; +FILE *fmemopen(void *, size_t, const char *) paramsnonnull((3)) nodiscard; +FILE *freopen(const char *, const char *, FILE *) paramsnonnull((2, 3)); +size_t fread(void *, size_t, size_t, FILE *) paramsnonnull((4)); +size_t fwrite(const void *, size_t, size_t, FILE *) paramsnonnull((4)); +int fclose(FILE *); +int fclose_s(FILE **) paramsnonnull(); +int fseek(FILE *, long, int) paramsnonnull(); +long ftell(FILE *) paramsnonnull(); +int fseeko(FILE *, int64_t, int) paramsnonnull(); +int64_t ftello(FILE *) paramsnonnull(); +void rewind(FILE *) paramsnonnull(); +int fopenflags(const char *) paramsnonnull(); +void setbuf(FILE *, char *); +void setbuffer(FILE *, char *, size_t); +int setvbuf(FILE *, char *, int, size_t); +FILE *popen(const char *, const char *); +int pclose(FILE *); + +typedef uint64_t fpos_t; +compatfn char *gets(char *) paramsnonnull(); +compatfn int fgetpos(FILE *, fpos_t *) paramsnonnull(); +compatfn int fsetpos(FILE *, const fpos_t *) paramsnonnull(); + +int system(const char *); +int systemexec(const char *); + +/*───────────────────────────────────────────────────────────────────────────│─╗ +│ cosmopolitan § standard i/o » formatting ─╬─│┼ +╚────────────────────────────────────────────────────────────────────────────│*/ + +int printf(const char *, ...) printfesque(1) + paramsnonnull((1)) nothrow nocallback; +int vprintf(const char *, va_list) paramsnonnull() nothrow nocallback; +int fprintf(FILE *, const char *, ...) printfesque(2) + paramsnonnull((1, 2)) nothrow nocallback; +int vfprintf(FILE *, const char *, va_list) paramsnonnull() nothrow nocallback; +int scanf(const char *, ...) scanfesque(1); +int vscanf(const char *, va_list); +int fscanf(FILE *, const char *, ...) scanfesque(2); +int vfscanf(FILE *, const char *, va_list); + +/*───────────────────────────────────────────────────────────────────────────│─╗ +│ cosmopolitan § standard i/o » optimizations ─╬─│┼ +╚────────────────────────────────────────────────────────────────────────────│*/ + +#define getc(f) fgetc(f) +#define getwc(f) fgetwc(f) +#define putc(c, f) fputc(c, f) +#define putwc(c, f) fputwc(c, f) + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define printf(FMT, ...) (printf)(PFLINK(FMT), ##__VA_ARGS__) +#define vprintf(FMT, VA) (vprintf)(PFLINK(FMT), VA) +#define fprintf(F, FMT, ...) (fprintf)(F, PFLINK(FMT), ##__VA_ARGS__) +#define vfprintf(F, FMT, VA) (vfprintf)(F, PFLINK(FMT), VA) +#define vscanf(FMT, VA) (vscanf)(SFLINK(FMT), VA) +#define scanf(FMT, ...) (scanf)(SFLINK(FMT), ##__VA_ARGS__) +#define fscanf(F, FMT, ...) (fscanf)(F, SFLINK(FMT), ##__VA_ARGS__) +#define vfscanf(F, FMT, VA) (vfscanf)(F, SFLINK(FMT), VA) +#endif + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ + +#define stdin SYMBOLIC(stdin) +#define stdout SYMBOLIC(stdout) +#define stderr SYMBOLIC(stderr) + +#endif /* COSMOPOLITAN_LIBC_STDIO_STDIO_H_ */ diff --git a/stdio/stdio.mk b/stdio/stdio.mk new file mode 100644 index 0000000..a54636e --- /dev/null +++ b/stdio/stdio.mk @@ -0,0 +1,66 @@ +#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ +#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ + +PKGS += LIBC_STDIO + +LIBC_STDIO_ARTIFACTS += LIBC_STDIO_A +LIBC_STDIO = $(LIBC_STDIO_A_DEPS) $(LIBC_STDIO_A) +LIBC_STDIO_A = o/$(MODE)/libc/stdio/stdio.a +LIBC_STDIO_A_FILES := $(wildcard libc/stdio/*) $(wildcard libc/stdio/unlocked/*) +LIBC_STDIO_A_HDRS = $(filter %.h,$(LIBC_STDIO_A_FILES)) +LIBC_STDIO_A_SRCS_S = $(filter %.S,$(LIBC_STDIO_A_FILES)) +LIBC_STDIO_A_SRCS_C = $(filter %.c,$(LIBC_STDIO_A_FILES)) + +LIBC_STDIO_A_SRCS = \ + $(LIBC_STDIO_A_SRCS_S) \ + $(LIBC_STDIO_A_SRCS_C) + +LIBC_STDIO_A_OBJS = \ + $(LIBC_STDIO_A_SRCS_S:%.S=o/$(MODE)/%.o) \ + $(LIBC_STDIO_A_SRCS_C:%.c=o/$(MODE)/%.o) + +LIBC_STDIO_A_CHECKS = \ + $(LIBC_STDIO_A).pkg \ + $(LIBC_STDIO_A_HDRS:%=o/$(MODE)/%.ok) + +LIBC_STDIO_A_DIRECTDEPS = \ + LIBC_ALG \ + LIBC_BITS \ + LIBC_CALLS \ + LIBC_FMT \ + LIBC_INTRIN \ + LIBC_MEM \ + LIBC_NEXGEN32E \ + LIBC_NT_KERNEL32 \ + LIBC_RAND \ + LIBC_RUNTIME \ + LIBC_STR \ + LIBC_STUBS \ + LIBC_SYSV \ + LIBC_SYSV_CALLS \ + THIRD_PARTY_GDTOA + +LIBC_STDIO_A_DEPS := \ + $(call uniq,$(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x)))) + +$(LIBC_STDIO_A):libc/stdio/ \ + $(LIBC_STDIO_A).pkg \ + $(LIBC_STDIO_A_OBJS) + +$(LIBC_STDIO_A).pkg: \ + $(LIBC_STDIO_A_OBJS) \ + $(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x)_A).pkg) + +o/$(MODE)/libc/stdio/fputc.o: \ + OVERRIDE_CFLAGS += \ + -O3 + +LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x))) +LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS)) +LIBC_STDIO_HDRS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_HDRS)) +LIBC_STDIO_CHECKS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_CHECKS)) +LIBC_STDIO_OBJS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_OBJS)) +$(LIBC_STDIO_OBJS): $(BUILD_FILES) libc/stdio/stdio.mk + +.PHONY: o/$(MODE)/libc/stdio +o/$(MODE)/libc/stdio: $(LIBC_STDIO_CHECKS) diff --git a/stdio/stdio_ext.h b/stdio/stdio_ext.h new file mode 100644 index 0000000..ea8b671 --- /dev/null +++ b/stdio/stdio_ext.h @@ -0,0 +1,25 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_ +#define COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_ +#include "libc/stdio/stdio.h" + +#define FSETLOCKING_QUERY 0 +#define FSETLOCKING_INTERNAL 1 +#define FSETLOCKING_BYCALLER 2 + +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +size_t __fbufsize(FILE *); +size_t __fpending(FILE *); +int __flbf(FILE *); +int __freadable(FILE *); +int __fwritable(FILE *); +int __freading(FILE *); +int __fwriting(FILE *); +int __fsetlocking(FILE *, int); +void _flushlbf(void); +void __fpurge(FILE *); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_STDIO_EXT_H_ */ diff --git a/stdio/stdout-init.S b/stdio/stdout-init.S new file mode 100644 index 0000000..da9efdb --- /dev/null +++ b/stdio/stdout-init.S @@ -0,0 +1,36 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/sysv/consts/o.h" +#include "libc/dce.h" +#include "libc/calls/calls.h" +#include "libc/sysv/consts/fileno.h" +#include "libc/macros.internal.h" +.source __FILE__ + + .init.start 400,_init_stdout + ezlea __stdout,ax + push STDOUT_FILENO + pop 12(%rax) #→ f.fd + mov O_WRONLY,%edx + mov %edx,4(%rax) #→ f.iomode + ezlea __stdout_buf,cx + mov %rcx,24(%rax) #→ f.buf + movl $BUFSIZ,32(%rax) #→ f.size + mov %rax,stdout(%rip) + .init.end 400,_init_stdout,globl,hidden diff --git a/stdio/stdout.c b/stdio/stdout.c new file mode 100644 index 0000000..41227ad --- /dev/null +++ b/stdio/stdout.c @@ -0,0 +1,45 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/pushpop.h" +#include "libc/calls/calls.h" +#include "libc/dce.h" +#include "libc/stdio/internal.h" +#include "libc/stdio/stdio.h" + +STATIC_YOINK("_init_stdout"); + +/** + * Pointer to standard output stream. + */ +FILE *stdout; + +hidden FILE __stdout; +hidden unsigned char __stdout_buf[BUFSIZ]; + +static textstartup void __stdout_init() { + struct FILE *sf; + sf = stdout; + asm("" : "+r"(sf)); + if (IsWindows() || ischardev(pushpop(sf->fd))) { + sf->bufmode = _IOLBF; + } + __fflush_register(sf); +} + +const void *const __stdout_ctor[] initarray = {__stdout_init}; diff --git a/stdio/system.c b/stdio/system.c new file mode 100644 index 0000000..ef58b0f --- /dev/null +++ b/stdio/system.c @@ -0,0 +1,76 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/weaken.h" +#include "libc/calls/calls.h" +#include "libc/calls/sigbits.h" +#include "libc/calls/struct/sigaction.h" +#include "libc/dce.h" +#include "libc/errno.h" +#include "libc/paths.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/ok.h" +#include "libc/sysv/consts/sig.h" + +/** + * Launches program with system command interpreter. + * + * @param cmdline is an interpreted Turing-complete command + * @return -1 if child process couldn't be created, otherwise a wait + * status that can be accessed using macros like WEXITSTATUS(s) + */ +int system(const char *cmdline) { + int pid, wstatus; + sigset_t chldmask, savemask; + struct sigaction ignore, saveint, savequit; + if (!cmdline) { + if (IsWindows()) return 1; + if (access(_PATH_BSHELL, X_OK) == 0) return 1; + return 0; + } + ignore.sa_flags = 0; + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + sigaction(SIGINT, &ignore, &saveint); + sigaction(SIGQUIT, &ignore, &savequit); + sigemptyset(&chldmask); + sigaddset(&chldmask, SIGCHLD); + sigprocmask(SIG_BLOCK, &chldmask, &savemask); + if (!(pid = fork())) { + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); + systemexec(cmdline); + _exit(127); + } else if (pid != -1) { + while (wait4(pid, &wstatus, 0, NULL) == -1) { + if (errno != EINTR) { + wstatus = -1; + break; + } + } + } else { + wstatus = -1; + } + sigaction(SIGINT, &saveint, NULL); + sigaction(SIGQUIT, &savequit, NULL); + sigprocmask(SIG_SETMASK, &savemask, NULL); + return wstatus; +} diff --git a/stdio/systemexec.c b/stdio/systemexec.c new file mode 100644 index 0000000..cb9b3fd --- /dev/null +++ b/stdio/systemexec.c @@ -0,0 +1,38 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/dce.h" +#include "libc/paths.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" + +/** + * Executes system command replacing current process. + * @vforksafe + */ +int systemexec(const char *cmdline) { + char comspec[128]; + const char *prog, *arg; + strcpy(comspec, kNtSystemDirectory); + strcat(comspec, "cmd.exe"); + prog = !IsWindows() ? _PATH_BSHELL : comspec; + arg = !IsWindows() ? "-c" : "/C"; + return execv(prog, (char *const[]){prog, arg, cmdline, NULL}); +} diff --git a/stdio/temp.h b/stdio/temp.h new file mode 100644 index 0000000..9b6113f --- /dev/null +++ b/stdio/temp.h @@ -0,0 +1,20 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_TEMP_H_ +#define COSMOPOLITAN_LIBC_STDIO_TEMP_H_ +#include "libc/stdio/stdio.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +nodiscard FILE *tmpfile(void); +nodiscard int mkstemp(char *); +nodiscard int mkostemp(char *, unsigned); +nodiscard int mkstemps(char *, int); +nodiscard int mkostemps(char *, int, unsigned); +nodiscard int mkostempsm(char *, int, unsigned, int); +compatfn char *mktemp(char *); + +int mkostempsmi(char *, int, unsigned, uint64_t *, int, + int (*)(const char *, int, ...)) hidden nodiscard; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_TEMP_H_ */ diff --git a/stdio/tmpfile.c b/stdio/tmpfile.c new file mode 100644 index 0000000..b2197e4 --- /dev/null +++ b/stdio/tmpfile.c @@ -0,0 +1,44 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/safemacros.internal.h" +#include "libc/calls/calls.h" +#include "libc/fmt/fmt.h" +#include "libc/macros.internal.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/stdio/temp.h" +#include "libc/str/str.h" + +/** + * Creates a temporary file. + * + * @see mkostempsm(), kTmpPath + */ +FILE *tmpfile(void) { + int fd; + char *tmp, *sep, tpl[PATH_MAX]; + tmp = firstnonnull(getenv("TMPDIR"), kTmpPath); + sep = !isempty(tmp) && !endswith(tmp, "/") ? "/" : ""; + if (snprintf(tpl, PATH_MAX, "%s%stmp.XXXXXX", tmp, sep) < PATH_MAX) { + if ((fd = mkostemps(tpl, 0, 0)) != -1) { + return fdopen(fd, "w+"); + } + } + return NULL; +} diff --git a/stdio/ungetc.c b/stdio/ungetc.c new file mode 100644 index 0000000..91a28e2 --- /dev/null +++ b/stdio/ungetc.c @@ -0,0 +1,36 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" + +/** + * Pushes byte back to stream. + */ +int ungetc(int c, FILE *f) { + if (c == -1) return -1; + if (f->beg) { + f->buf[--f->beg] = c; + } else if (f->end < f->size) { + memmove(f->buf + 1, f->buf, f->end++); + f->buf[0] = c; + } else { + return -1; + } + return c & 0xff; +} diff --git a/stdio/ungetwc.c b/stdio/ungetwc.c new file mode 100644 index 0000000..be1fce4 --- /dev/null +++ b/stdio/ungetwc.c @@ -0,0 +1,47 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" +#include "libc/str/tpenc.h" + +/** + * Pushes wide character back to stream. + */ +wint_t ungetwc(wint_t c, FILE *f) { + char b[6]; + unsigned n; + uint64_t w; + if (c == -1) return -1; + n = 0; + w = tpenc(c); + do { + b[n++] = w; + } while ((w >>= 8)); + if (f->beg >= n) { + f->beg -= n; + memcpy(f->buf + f->beg, b, n); + } else if (f->beg + f->end + n <= f->size) { + memmove(f->buf + f->beg + n, f->buf + f->beg, f->end - f->beg); + memcpy(f->buf + f->beg, b, n); + f->end += n; + } else { + return -1; + } + return c; +} diff --git a/stdio/unlocked.h b/stdio/unlocked.h new file mode 100644 index 0000000..8686466 --- /dev/null +++ b/stdio/unlocked.h @@ -0,0 +1,36 @@ +#ifndef COSMOPOLITAN_LIBC_STDIO_UNLOCKED_H_ +#define COSMOPOLITAN_LIBC_STDIO_UNLOCKED_H_ +#include "libc/stdio/stdio.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +void flockfile(FILE *); +void funlockfile(FILE *); +int ftrylockfile(FILE *); +int getc_unlocked(FILE *) paramsnonnull(); +int getchar_unlocked(void); +int putc_unlocked(int, FILE *) paramsnonnull(); +int putchar_unlocked(int); +void clearerr_unlocked(FILE *); +int feof_unlocked(FILE *); +int ferror_unlocked(FILE *); +int fileno_unlocked(FILE *); +int fflush_unlocked(FILE *); +int fgetc_unlocked(FILE *); +int fputc_unlocked(int, FILE *); +size_t fread_unlocked(void *, size_t, size_t, FILE *); +size_t fwrite_unlocked(const void *, size_t, size_t, FILE *); +char *fgets_unlocked(char *, int, FILE *); +int fputs_unlocked(const char *, FILE *); +wint_t getwc_unlocked(FILE *); +wint_t getwchar_unlocked(void); +wint_t fgetwc_unlocked(FILE *); +wint_t fputwc_unlocked(wchar_t, FILE *); +wint_t putwc_unlocked(wchar_t, FILE *); +wint_t putwchar_unlocked(wchar_t); +wchar_t *fgetws_unlocked(wchar_t *, int, FILE *); +int fputws_unlocked(const wchar_t *, FILE *); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_STDIO_UNLOCKED_H_ */ diff --git a/stdio/unlocked/clearerr_unlocked.S b/stdio/unlocked/clearerr_unlocked.S new file mode 100644 index 0000000..a1da354 --- /dev/null +++ b/stdio/unlocked/clearerr_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +clearerr_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call clearerr + pop %rbp + ret + .endfn clearerr_unlocked,globl diff --git a/stdio/unlocked/feof_unlocked.S b/stdio/unlocked/feof_unlocked.S new file mode 100644 index 0000000..a3a80c1 --- /dev/null +++ b/stdio/unlocked/feof_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +feof_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call feof + pop %rbp + ret + .endfn feof_unlocked,globl diff --git a/stdio/unlocked/ferror_unlocked.S b/stdio/unlocked/ferror_unlocked.S new file mode 100644 index 0000000..e6598fb --- /dev/null +++ b/stdio/unlocked/ferror_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +ferror_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call ferror + pop %rbp + ret + .endfn ferror_unlocked,globl diff --git a/stdio/unlocked/fflush_unlocked.S b/stdio/unlocked/fflush_unlocked.S new file mode 100644 index 0000000..280d080 --- /dev/null +++ b/stdio/unlocked/fflush_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fflush_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fflush + pop %rbp + ret + .endfn fflush_unlocked,globl diff --git a/stdio/unlocked/fgetc_unlocked.S b/stdio/unlocked/fgetc_unlocked.S new file mode 100644 index 0000000..f4c77bc --- /dev/null +++ b/stdio/unlocked/fgetc_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fgetc_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fgetc + pop %rbp + ret + .endfn fgetc_unlocked,globl diff --git a/stdio/unlocked/fgets_unlocked.S b/stdio/unlocked/fgets_unlocked.S new file mode 100644 index 0000000..7521d8c --- /dev/null +++ b/stdio/unlocked/fgets_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fgets_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fgets + pop %rbp + ret + .endfn fgets_unlocked,globl diff --git a/stdio/unlocked/fgetwc_unlocked.S b/stdio/unlocked/fgetwc_unlocked.S new file mode 100644 index 0000000..52bbb7a --- /dev/null +++ b/stdio/unlocked/fgetwc_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fgetwc_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fgetwc + pop %rbp + ret + .endfn fgetwc_unlocked,globl diff --git a/stdio/unlocked/fgetws_unlocked.S b/stdio/unlocked/fgetws_unlocked.S new file mode 100644 index 0000000..02b1dd7 --- /dev/null +++ b/stdio/unlocked/fgetws_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fgetws_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fgetws + pop %rbp + ret + .endfn fgetws_unlocked,globl diff --git a/stdio/unlocked/fileno_unlocked.S b/stdio/unlocked/fileno_unlocked.S new file mode 100644 index 0000000..f90be61 --- /dev/null +++ b/stdio/unlocked/fileno_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fileno_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fileno + pop %rbp + ret + .endfn fileno_unlocked,globl diff --git a/stdio/unlocked/fputc_unlocked.S b/stdio/unlocked/fputc_unlocked.S new file mode 100644 index 0000000..7c35788 --- /dev/null +++ b/stdio/unlocked/fputc_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fputc_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fputc + pop %rbp + ret + .endfn fputc_unlocked,globl diff --git a/stdio/unlocked/fputs_unlocked.S b/stdio/unlocked/fputs_unlocked.S new file mode 100644 index 0000000..2adf210 --- /dev/null +++ b/stdio/unlocked/fputs_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fputs_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fputs + pop %rbp + ret + .endfn fputs_unlocked,globl diff --git a/stdio/unlocked/fputwc_unlocked.S b/stdio/unlocked/fputwc_unlocked.S new file mode 100644 index 0000000..1b505fa --- /dev/null +++ b/stdio/unlocked/fputwc_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fputwc_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fputwc + pop %rbp + ret + .endfn fputwc_unlocked,globl diff --git a/stdio/unlocked/fputws_unlocked.S b/stdio/unlocked/fputws_unlocked.S new file mode 100644 index 0000000..611be6a --- /dev/null +++ b/stdio/unlocked/fputws_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fputws_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fputws + pop %rbp + ret + .endfn fputws_unlocked,globl diff --git a/stdio/unlocked/fread_unlocked.S b/stdio/unlocked/fread_unlocked.S new file mode 100644 index 0000000..3cbb061 --- /dev/null +++ b/stdio/unlocked/fread_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fread_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fread + pop %rbp + ret + .endfn fread_unlocked,globl diff --git a/stdio/unlocked/fwrite_unlocked.S b/stdio/unlocked/fwrite_unlocked.S new file mode 100644 index 0000000..d296e28 --- /dev/null +++ b/stdio/unlocked/fwrite_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +fwrite_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fwrite + pop %rbp + ret + .endfn fwrite_unlocked,globl diff --git a/stdio/unlocked/getc_unlocked.S b/stdio/unlocked/getc_unlocked.S new file mode 100644 index 0000000..1d6e9c7 --- /dev/null +++ b/stdio/unlocked/getc_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +getc_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call getc + pop %rbp + ret + .endfn getc_unlocked,globl diff --git a/stdio/unlocked/getchar_unlocked.S b/stdio/unlocked/getchar_unlocked.S new file mode 100644 index 0000000..ebb6b76 --- /dev/null +++ b/stdio/unlocked/getchar_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +getchar_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call getchar + pop %rbp + ret + .endfn getchar_unlocked,globl diff --git a/stdio/unlocked/getwc_unlocked.S b/stdio/unlocked/getwc_unlocked.S new file mode 100644 index 0000000..a024387 --- /dev/null +++ b/stdio/unlocked/getwc_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +getwc_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fgetwc_unlocked + pop %rbp + ret + .endfn getwc_unlocked,globl diff --git a/stdio/unlocked/getwchar_unlocked.S b/stdio/unlocked/getwchar_unlocked.S new file mode 100644 index 0000000..bb6710a --- /dev/null +++ b/stdio/unlocked/getwchar_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +getwchar_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call getwchar + pop %rbp + ret + .endfn getwchar_unlocked,globl diff --git a/stdio/unlocked/putc_unlocked.S b/stdio/unlocked/putc_unlocked.S new file mode 100644 index 0000000..842d740 --- /dev/null +++ b/stdio/unlocked/putc_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +putc_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call putc + pop %rbp + ret + .endfn putc_unlocked,globl diff --git a/stdio/unlocked/putchar_unlocked.S b/stdio/unlocked/putchar_unlocked.S new file mode 100644 index 0000000..df0b807 --- /dev/null +++ b/stdio/unlocked/putchar_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +putchar_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call putchar + pop %rbp + ret + .endfn putchar_unlocked,globl diff --git a/stdio/unlocked/putwc_unlocked.S b/stdio/unlocked/putwc_unlocked.S new file mode 100644 index 0000000..3890a2d --- /dev/null +++ b/stdio/unlocked/putwc_unlocked.S @@ -0,0 +1,29 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +putwc_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call fputwc_unlocked + pop %rbp + ret + .endfn putwc_unlocked,globl diff --git a/stdio/unlocked/putwchar_unlocked.S b/stdio/unlocked/putwchar_unlocked.S new file mode 100644 index 0000000..5e7f38e --- /dev/null +++ b/stdio/unlocked/putwchar_unlocked.S @@ -0,0 +1,30 @@ + +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +.source __FILE__ + +putwchar_unlocked: + push %rbp + mov %rsp,%rbp + .profilable # note: no consensus for threads exists in abis + call putwchar + pop %rbp + ret + .endfn putwchar_unlocked,globl diff --git a/stdio/vfprintf.c b/stdio/vfprintf.c new file mode 100644 index 0000000..cd2c0a2 --- /dev/null +++ b/stdio/vfprintf.c @@ -0,0 +1,41 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/fmt.h" +#include "libc/limits.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/errfuns.h" + +struct state { + FILE *f; + int n; +}; + +static noinstrument int vfprintfputchar(int c, struct state *st) { + st->n++; + return fputc(c, st->f); +} + +int(vfprintf)(FILE *f, const char *fmt, va_list va) { + struct state st[1] = {{f, 0}}; + if (__fmt(vfprintfputchar, st, fmt, va) != -1) { + return st->n; + } else { + return -1; + } +} diff --git a/stdio/vfscanf.c b/stdio/vfscanf.c new file mode 100644 index 0000000..536c554 --- /dev/null +++ b/stdio/vfscanf.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/fmt.h" +#include "libc/stdio/stdio.h" + +/** + * Stream decoder. + * @see libc/fmt/vcscanf.h + */ +int(vfscanf)(FILE *stream, const char *fmt, va_list ap) { + return (vcscanf)((void *)fgetc, (void *)ungetc, stream, fmt, ap); +} diff --git a/stdio/vprintf.c b/stdio/vprintf.c new file mode 100644 index 0000000..0599232 --- /dev/null +++ b/stdio/vprintf.c @@ -0,0 +1,23 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/stdio/stdio.h" + +int(vprintf)(const char* fmt, va_list va) { + return (vfprintf)(stdout, fmt, va); +} diff --git a/stdio/vscanf.c b/stdio/vscanf.c new file mode 100644 index 0000000..acb01a2 --- /dev/null +++ b/stdio/vscanf.c @@ -0,0 +1,28 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/fmt.h" +#include "libc/stdio/stdio.h" + +/** + * String decoder. + * @see libc/fmt/vcscanf.h + */ +int(vscanf)(const char *fmt, va_list ap) { + return (vcscanf)((int (*)(void *))fgetc, (void *)ungetc, stdin, fmt, ap); +} -- cgit 1.4.1