mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
61
libc/fmt/bing.c
Normal file
61
libc/fmt/bing.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/bing.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Turns binary octet into unicode glyph representation.
|
||||
*
|
||||
* Cosmopolitan displays RADIX-256 numbers using these digits:
|
||||
*
|
||||
* 0123456789abcdef
|
||||
* 0 ☺☻♥♦♣♠•◘○◙♂♀♪♫☼
|
||||
* 1►◄↕‼¶§▬↨↑↓→←∟↔▲▼
|
||||
* 2 !"#$%&'()*+,-./
|
||||
* 30123456789:;<=>?
|
||||
* 4@ABCDEFGHIJKLMNO
|
||||
* 5PQRSTUVWXYZ[\]^_
|
||||
* 6`abcdefghijklmno
|
||||
* 7pqrstuvwxyz{|}~⌂
|
||||
* 8ÇüéâäàåçêëèïîìÄÅ
|
||||
* 9ÉæÆôöòûùÿÖÜ¢£¥€ƒ
|
||||
* aáíóúñѪº¿⌐¬½¼¡«»
|
||||
* b░▒▓│┤╡╢╖╕╣║╗╝╜╛┐
|
||||
* c└┴┬├─┼╞╟╚╔╩╦╠═╬╧
|
||||
* d╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀
|
||||
* eαßΓπΣσμτΦΘΩδ∞φε∩
|
||||
* f≡±≥≤⌠⌡÷≈°∙·√ⁿ²■λ
|
||||
*
|
||||
* IBM designed these glyphs for the PC to map onto the display bytes at
|
||||
* (char *)0xb8000. Because IBM authorized buyers of its PCs to inspect
|
||||
* and/or modify this region of memory, it became widely understood by
|
||||
* many developers as a quick way to visualize arbitrary data that's so
|
||||
* superior to hexdump -- a use-case that's lived on longer than the CGA
|
||||
* graphics card for which it was designed.
|
||||
*
|
||||
* @param b is binary octet to pictorally represent
|
||||
* @param intent controls canonical multimappings: ∅␀ ,\n◙,ε∊∈€, λ,etc.
|
||||
* @see unbing() for inverse
|
||||
*/
|
||||
int bing(int b, int intent) {
|
||||
assert(0 <= b && b < 256);
|
||||
return kCp437[b & 0xff]; /* TODO(jart): multimappings */
|
||||
}
|
16
libc/fmt/bing.h
Normal file
16
libc/fmt/bing.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_BING_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_BING_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int bing(int, int) nosideeffect;
|
||||
int unbing(int) nosideeffect;
|
||||
void *unbingbuf(void *, size_t, const char16_t *, int);
|
||||
void *unbingstr(const char16_t *) paramsnonnull() mallocesque;
|
||||
void *unhexbuf(void *, size_t, const char *);
|
||||
void *unhexstr(const char *) mallocesque;
|
||||
short *bingblit(int ys, int xs, unsigned char[ys][xs], int, int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_BING_H_ */
|
48
libc/fmt/fmt.h
Normal file
48
libc/fmt/fmt.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_FMT_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_FMT_H_
|
||||
#include "libc/fmt/pflink.h"
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § string formatting ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#if __SIZEOF_POINTER__ == 8
|
||||
#define POINTER_XDIGITS 12 /* math.log(2**48-1,16) */
|
||||
#else
|
||||
#define POINTER_XDIGITS 8
|
||||
#endif
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int snprintf(char *, size_t, const char *, ...) printfesque(3)
|
||||
paramsnonnull((3)) nothrow nocallback;
|
||||
int vsnprintf(char *, size_t, const char *, va_list)
|
||||
paramsnonnull((3)) nothrow nocallback;
|
||||
int sprintf(char *, const char *, ...) printfesque(2)
|
||||
paramsnonnull((2)) nothrow nocallback frownedupon(snprintf);
|
||||
int vsprintf(char *, const char *, va_list)
|
||||
paramsnonnull((2)) nothrow nocallback frownedupon(vsnprintf);
|
||||
int sscanf(const char *, const char *, ...) scanfesque(2);
|
||||
int vsscanf(const char *, const char *, va_list);
|
||||
int vcscanf(int callback(void *), void *, const char *, va_list);
|
||||
char *strerror(int) returnsnonnull nothrow nocallback;
|
||||
int strerror_r(int, char *, size_t) nothrow nocallback;
|
||||
int palandprintf(void *, void *, const char *, va_list) hidden;
|
||||
char *itoa(int, char *, int) compatfn;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § string formatting » optimizations ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define sprintf(BUF, FMT, ...) (sprintf)(BUF, PFLINK(FMT), ##__VA_ARGS__)
|
||||
#define vsprintf(BUF, FMT, VA) (vsprintf)(BUF, PFLINK(FMT), VA)
|
||||
#define snprintf(B, Z, F, ...) (snprintf)(B, Z, PFLINK(F), ##__VA_ARGS__)
|
||||
#define vsnprintf(BUF, SIZE, FMT, VA) (vsnprintf)(BUF, SIZE, PFLINK(FMT), VA)
|
||||
#define sscanf(STR, FMT, ...) (sscanf)(STR, SFLINK(FMT), ##__VA_ARGS__)
|
||||
#define vsscanf(STR, FMT, VA) (vsscanf)(STR, SFLINK(FMT), VA)
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_FMT_H_ */
|
67
libc/fmt/fmt.mk
Normal file
67
libc/fmt/fmt.mk
Normal file
|
@ -0,0 +1,67 @@
|
|||
#-*-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───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Cosmopolitan String Formatting
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This package provides incredible domain-specific languages for
|
||||
# encoding and decoding strings.
|
||||
|
||||
PKGS += LIBC_FMT
|
||||
|
||||
LIBC_FMT_ARTIFACTS += LIBC_FMT_A
|
||||
LIBC_FMT = $(LIBC_FMT_A_DEPS) $(LIBC_FMT_A)
|
||||
LIBC_FMT_A = o/$(MODE)/libc/fmt/fmt.a
|
||||
LIBC_FMT_A_FILES := $(wildcard libc/fmt/*)
|
||||
LIBC_FMT_A_HDRS = $(filter %.h,$(LIBC_FMT_A_FILES))
|
||||
LIBC_FMT_A_SRCS_S = $(filter %.S,$(LIBC_FMT_A_FILES))
|
||||
LIBC_FMT_A_SRCS_C = $(filter %.c,$(LIBC_FMT_A_FILES))
|
||||
|
||||
LIBC_FMT_A_SRCS = \
|
||||
$(LIBC_FMT_A_SRCS_S) \
|
||||
$(LIBC_FMT_A_SRCS_C)
|
||||
|
||||
LIBC_FMT_A_OBJS = \
|
||||
$(LIBC_FMT_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_FMT_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_FMT_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_FMT_A_CHECKS = \
|
||||
$(LIBC_FMT_A).pkg \
|
||||
$(LIBC_FMT_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_FMT_A_DIRECTDEPS = \
|
||||
LIBC_STUBS \
|
||||
LIBC_STR \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_SYSV
|
||||
|
||||
LIBC_FMT_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_FMT_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_FMT_A): libc/fmt/ \
|
||||
$(LIBC_FMT_A).pkg \
|
||||
$(LIBC_FMT_A_OBJS)
|
||||
|
||||
$(LIBC_FMT_A).pkg: \
|
||||
$(LIBC_FMT_A_OBJS) \
|
||||
$(foreach x,$(LIBC_FMT_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(LIBC_FMT_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fno-jump-tables
|
||||
|
||||
LIBC_FMT_LIBS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)))
|
||||
LIBC_FMT_SRCS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_FMT_HDRS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_FMT_CHECKS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_FMT_OBJS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_OBJS))
|
||||
$(LIBC_FMT_OBJS): $(BUILD_FILES) libc/fmt/fmt.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/fmt
|
||||
o/$(MODE)/libc/fmt: $(LIBC_FMT_CHECKS)
|
32
libc/fmt/itoa.c
Normal file
32
libc/fmt/itoa.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
|
||||
STATIC_YOINK("ntoa");
|
||||
|
||||
compatfn char *itoa(int value, char *str, int radix) {
|
||||
(sprintf)(
|
||||
str,
|
||||
VEIL("r",
|
||||
radix == 16 ? "%x" : radix == 8 ? "%d" : radix == 2 ? "%b" : "%d"),
|
||||
value);
|
||||
return str;
|
||||
}
|
311
libc/fmt/kerrnonames.S
Normal file
311
libc/fmt/kerrnonames.S
Normal file
|
@ -0,0 +1,311 @@
|
|||
/*-*- mode:asm; 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/notice.inc"
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Embeds ASCII names for errno constants into binary.
|
||||
/
|
||||
/ @see libc/sysv/consts.sh
|
||||
.section .rodata,"aS",@progbits
|
||||
kErrnoNames:
|
||||
/ <SORTED-ORDER-C>
|
||||
.asciz "2BIG"
|
||||
.asciz "ACCES"
|
||||
.asciz "ADDRINUSE"
|
||||
.asciz "ADDRNOTAVAIL"
|
||||
.asciz "ADV"
|
||||
.asciz "AFNOSUPPORT"
|
||||
.asciz "AGAIN"
|
||||
.asciz "ALREADY"
|
||||
.asciz "BADE"
|
||||
.asciz "BADF"
|
||||
.asciz "BADFD"
|
||||
.asciz "BADMSG"
|
||||
.asciz "BADR"
|
||||
.asciz "BADRQC"
|
||||
.asciz "BADSLT"
|
||||
.asciz "BFONT"
|
||||
.asciz "BUSY"
|
||||
.asciz "CANCELED"
|
||||
.asciz "CHILD"
|
||||
.asciz "CHRNG"
|
||||
.asciz "COMM"
|
||||
.asciz "CONNABORTED"
|
||||
.asciz "CONNREFUSED"
|
||||
.asciz "CONNRESET"
|
||||
.asciz "DEADLK"
|
||||
.asciz "DESTADDRREQ"
|
||||
.asciz "DOM"
|
||||
.asciz "DOTDOT"
|
||||
.asciz "DQUOT"
|
||||
.asciz "EXIST"
|
||||
.asciz "FAULT"
|
||||
.asciz "FBIG"
|
||||
.asciz "HOSTDOWN"
|
||||
.asciz "HOSTUNREACH"
|
||||
.asciz "HWPOISON"
|
||||
.asciz "IDRM"
|
||||
.asciz "ILSEQ"
|
||||
.asciz "INPROGRESS"
|
||||
.asciz "INTR"
|
||||
.asciz "INVAL"
|
||||
.asciz "IO"
|
||||
.asciz "ISCONN"
|
||||
.asciz "ISDIR"
|
||||
.asciz "ISNAM"
|
||||
.asciz "KEYEXPIRED"
|
||||
.asciz "KEYREJECTED"
|
||||
.asciz "KEYREVOKED"
|
||||
.asciz "L2HLT"
|
||||
.asciz "L2NSYNC"
|
||||
.asciz "L3HLT"
|
||||
.asciz "L3RST"
|
||||
.asciz "LIBACC"
|
||||
.asciz "LIBBAD"
|
||||
.asciz "LIBEXEC"
|
||||
.asciz "LIBMAX"
|
||||
.asciz "LIBSCN"
|
||||
.asciz "LNRNG"
|
||||
.asciz "LOOP"
|
||||
.asciz "MEDIUMTYPE"
|
||||
.asciz "MFILE"
|
||||
.asciz "MLINK"
|
||||
.asciz "MSGSIZE"
|
||||
.asciz "MULTIHOP"
|
||||
.asciz "NAMETOOLONG"
|
||||
.asciz "NAVAIL"
|
||||
.asciz "NETDOWN"
|
||||
.asciz "NETRESET"
|
||||
.asciz "NETUNREACH"
|
||||
.asciz "NFILE"
|
||||
.asciz "NOANO"
|
||||
.asciz "NOBUFS"
|
||||
.asciz "NOCSI"
|
||||
.asciz "NODATA"
|
||||
.asciz "NODEV"
|
||||
.asciz "NOENT"
|
||||
.asciz "NOEXEC"
|
||||
.asciz "NOKEY"
|
||||
.asciz "NOLCK"
|
||||
.asciz "NOLINK"
|
||||
.asciz "NOMEDIUM"
|
||||
.asciz "NOMEM"
|
||||
.asciz "NOMSG"
|
||||
.asciz "NONET"
|
||||
.asciz "NOPKG"
|
||||
.asciz "NOPROTOOPT"
|
||||
.asciz "NOSPC"
|
||||
.asciz "NOSR"
|
||||
.asciz "NOSTR"
|
||||
.asciz "NOSYS"
|
||||
.asciz "NOTBLK"
|
||||
.asciz "NOTCONN"
|
||||
.asciz "NOTDIR"
|
||||
.asciz "NOTEMPTY"
|
||||
.asciz "NOTNAM"
|
||||
.asciz "NOTRECOVERABLE"
|
||||
.asciz "NOTSOCK"
|
||||
.asciz "NOTSUP"
|
||||
.asciz "NOTTY"
|
||||
.asciz "NOTUNIQ"
|
||||
.asciz "NXIO"
|
||||
.asciz "OPNOTSUPP"
|
||||
.asciz "OVERFLOW"
|
||||
.asciz "OWNERDEAD"
|
||||
.asciz "PERM"
|
||||
.asciz "PFNOSUPPORT"
|
||||
.asciz "PIPE"
|
||||
.asciz "PROTO"
|
||||
.asciz "PROTONOSUPPORT"
|
||||
.asciz "PROTOTYPE"
|
||||
.asciz "RANGE"
|
||||
.asciz "REMCHG"
|
||||
.asciz "REMOTE"
|
||||
.asciz "REMOTEIO"
|
||||
.asciz "RESTART"
|
||||
.asciz "RFKILL"
|
||||
.asciz "ROFS"
|
||||
.asciz "SHUTDOWN"
|
||||
.asciz "SOCKTNOSUPPORT"
|
||||
.asciz "SPIPE"
|
||||
.asciz "SRCH"
|
||||
.asciz "SRMNT"
|
||||
.asciz "STALE"
|
||||
.asciz "STRPIPE"
|
||||
.asciz "TIME"
|
||||
.asciz "TIMEDOUT"
|
||||
.asciz "TOOMANYREFS"
|
||||
.asciz "TXTBSY"
|
||||
.asciz "UCLEAN"
|
||||
.asciz "UNATCH"
|
||||
.asciz "USERS"
|
||||
.asciz "XDEV"
|
||||
.asciz "XFULL"
|
||||
/ </SORTED-ORDER-C>
|
||||
.byte 0
|
||||
.endobj kErrnoNames,globl,hidden
|
||||
.previous
|
||||
|
||||
/ Pulls errno constants into linkage.
|
||||
/
|
||||
/ @assume linker relocates these in sorted order
|
||||
/ @assume linker invoked as LC_ALL=C ld ...
|
||||
/ @see libc/sysv/systemfive.S
|
||||
/ @see libc/sysv/consts/syscon.h
|
||||
yoink E2BIG
|
||||
yoink EACCES
|
||||
yoink EADDRINUSE
|
||||
yoink EADDRNOTAVAIL
|
||||
yoink EADV
|
||||
yoink EAFNOSUPPORT
|
||||
yoink EAGAIN
|
||||
yoink EALREADY
|
||||
yoink EBADE
|
||||
yoink EBADF
|
||||
yoink EBADFD
|
||||
yoink EBADMSG
|
||||
yoink EBADR
|
||||
yoink EBADRQC
|
||||
yoink EBADSLT
|
||||
yoink EBFONT
|
||||
yoink EBUSY
|
||||
yoink ECANCELED
|
||||
yoink ECHILD
|
||||
yoink ECHRNG
|
||||
yoink ECOMM
|
||||
yoink ECONNABORTED
|
||||
yoink ECONNREFUSED
|
||||
yoink ECONNRESET
|
||||
yoink EDEADLK
|
||||
yoink EDESTADDRREQ
|
||||
yoink EDOM
|
||||
yoink EDOTDOT
|
||||
yoink EDQUOT
|
||||
yoink EEXIST
|
||||
yoink EFAULT
|
||||
yoink EFBIG
|
||||
yoink EHOSTDOWN
|
||||
yoink EHOSTUNREACH
|
||||
yoink EHWPOISON
|
||||
yoink EIDRM
|
||||
yoink EILSEQ
|
||||
yoink EINPROGRESS
|
||||
yoink EINTR
|
||||
yoink EINVAL
|
||||
yoink EIO
|
||||
yoink EISCONN
|
||||
yoink EISDIR
|
||||
yoink EISNAM
|
||||
yoink EKEYEXPIRED
|
||||
yoink EKEYREJECTED
|
||||
yoink EKEYREVOKED
|
||||
yoink EL2HLT
|
||||
yoink EL2NSYNC
|
||||
yoink EL3HLT
|
||||
yoink EL3RST
|
||||
yoink ELIBACC
|
||||
yoink ELIBBAD
|
||||
yoink ELIBEXEC
|
||||
yoink ELIBMAX
|
||||
yoink ELIBSCN
|
||||
yoink ELNRNG
|
||||
yoink ELOOP
|
||||
yoink EMEDIUMTYPE
|
||||
yoink EMFILE
|
||||
yoink EMLINK
|
||||
yoink EMSGSIZE
|
||||
yoink EMULTIHOP
|
||||
yoink ENAMETOOLONG
|
||||
yoink ENAVAIL
|
||||
yoink ENETDOWN
|
||||
yoink ENETRESET
|
||||
yoink ENETUNREACH
|
||||
yoink ENFILE
|
||||
yoink ENOANO
|
||||
yoink ENOBUFS
|
||||
yoink ENOCSI
|
||||
yoink ENODATA
|
||||
yoink ENODEV
|
||||
yoink ENOENT
|
||||
yoink ENOEXEC
|
||||
yoink ENOKEY
|
||||
yoink ENOLCK
|
||||
yoink ENOLINK
|
||||
yoink ENOMEDIUM
|
||||
yoink ENOMEM
|
||||
yoink ENOMSG
|
||||
yoink ENONET
|
||||
yoink ENOPKG
|
||||
yoink ENOPROTOOPT
|
||||
yoink ENOSPC
|
||||
yoink ENOSR
|
||||
yoink ENOSTR
|
||||
yoink ENOSYS
|
||||
yoink ENOTBLK
|
||||
yoink ENOTCONN
|
||||
yoink ENOTDIR
|
||||
yoink ENOTEMPTY
|
||||
yoink ENOTNAM
|
||||
yoink ENOTRECOVERABLE
|
||||
yoink ENOTSOCK
|
||||
yoink ENOTSUP
|
||||
yoink ENOTTY
|
||||
yoink ENOTUNIQ
|
||||
yoink ENXIO
|
||||
yoink EOPNOTSUPP
|
||||
yoink EOVERFLOW
|
||||
yoink EOWNERDEAD
|
||||
yoink EPERM
|
||||
yoink EPFNOSUPPORT
|
||||
yoink EPIPE
|
||||
yoink EPROTO
|
||||
yoink EPROTONOSUPPORT
|
||||
yoink EPROTOTYPE
|
||||
yoink ERANGE
|
||||
yoink EREMCHG
|
||||
yoink EREMOTE
|
||||
yoink EREMOTEIO
|
||||
yoink ERESTART
|
||||
yoink ERFKILL
|
||||
yoink EROFS
|
||||
yoink ESHUTDOWN
|
||||
yoink ESOCKTNOSUPPORT
|
||||
yoink ESPIPE
|
||||
yoink ESRCH
|
||||
yoink ESRMNT
|
||||
yoink ESTALE
|
||||
yoink ESTRPIPE
|
||||
yoink ETIME
|
||||
yoink ETIMEDOUT
|
||||
yoink ETOOMANYREFS
|
||||
yoink ETXTBSY
|
||||
yoink EUCLEAN
|
||||
yoink EUNATCH
|
||||
yoink EUSERS
|
||||
yoink EXDEV
|
||||
yoink EXFULL
|
||||
|
||||
.type kErrnoStart,@object
|
||||
.type kErrnoEnd,@object
|
||||
.globl kErrnoStart, kErrnoEnd, EXFULL, E2BIG
|
||||
.hidden kErrnoStart, kErrnoEnd
|
||||
kErrnoStart = E2BIG
|
||||
kErrnoEnd = EXFULL + 8
|
46
libc/fmt/mbrtowc.c
Normal file
46
libc/fmt/mbrtowc.c
Normal file
|
@ -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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static mbstate_t g_mbrtowc;
|
||||
|
||||
size_t mbrtowc(wchar_t *pwc, const char *src, size_t n, mbstate_t *ps) {
|
||||
/* TODO(jart): Need to fix. */
|
||||
wchar_t t;
|
||||
mbstate_t c;
|
||||
const unsigned char *p;
|
||||
if (!ps) ps = &g_mbrtowc;
|
||||
p = (const unsigned char *)src;
|
||||
c = *ps;
|
||||
if (!p && c) return eilseq();
|
||||
if (!p) return 0;
|
||||
if (!pwc) pwc = &t;
|
||||
if (n) {
|
||||
if (!c) {
|
||||
if (0 <= *p && *p < 0x80) {
|
||||
return !!(*pwc = *p);
|
||||
}
|
||||
abort(); /* TODO(jart) */
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
43
libc/fmt/mbsrtowcs.c
Normal file
43
libc/fmt/mbsrtowcs.c
Normal file
|
@ -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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
size_t mbsrtowcs(wchar_t *dest, const char **src, size_t len, mbstate_t *ps) {
|
||||
/* TODO(jart): Need to fix. */
|
||||
const unsigned char *s = (const void *)*src;
|
||||
size_t wn0 = len;
|
||||
unsigned c = 0;
|
||||
if (!dest) return strlen((const char *)s);
|
||||
for (;;) {
|
||||
if (!len) {
|
||||
*src = (const void *)s;
|
||||
return wn0;
|
||||
}
|
||||
if (!*s) break;
|
||||
c = *s++;
|
||||
*dest++ = c;
|
||||
len--;
|
||||
}
|
||||
*dest = 0;
|
||||
*src = 0;
|
||||
return wn0 - len;
|
||||
}
|
25
libc/fmt/mbstowcs.c
Normal file
25
libc/fmt/mbstowcs.c
Normal file
|
@ -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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
size_t mbstowcs(wchar_t *pwc, const char *s, size_t wn) {
|
||||
return mbsrtowcs(pwc, (void *)&s, wn, 0);
|
||||
}
|
62
libc/fmt/paland.inc
Normal file
62
libc/fmt/paland.inc
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-*- 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│
|
||||
╚══════════════════════════════════════════════════════════════════════════════╝
|
||||
│ @author (c) Marco Paland (info@paland.com) │
|
||||
│ 2014-2019, PALANDesign Hannover, Germany │
|
||||
│ │
|
||||
│ @license The MIT License (MIT) │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining a copy │
|
||||
│ of this software and associated documentation files (the "Software"), to deal│
|
||||
│ in the Software without restriction, including without limitation the rights │
|
||||
│ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell │
|
||||
│ copies of the Software, and to permit persons to whom the Software is │
|
||||
│ furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│ The above copyright notice and this permission notice shall be included in │
|
||||
│ all copies or substantial portions of the Software. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
|
||||
│ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
|
||||
│ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
|
||||
│ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
|
||||
│ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,│
|
||||
│ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN │
|
||||
│ THE SOFTWARE. │
|
||||
└─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
Paland Printf (MIT License)\\n\
|
||||
Copyright 2014-2019 Marco Paland\\n\
|
||||
PALANDesign Hannover, Germany\\n\
|
||||
info@paland.com\"");
|
||||
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/* 'ntoa' conversion buffer size, this must be big enough to hold one
|
||||
converted numeric number including padded zeros (dynamically created
|
||||
on stack) default: 64 byte */
|
||||
#ifndef PRINTF_NTOA_BUFFER_SIZE
|
||||
#define PRINTF_NTOA_BUFFER_SIZE 64
|
||||
#endif
|
||||
|
||||
/* 'ftoa' conversion buffer size, this must be big enough to hold one
|
||||
converted float number including padded zeros (dynamically created on
|
||||
stack) default: 32 byte */
|
||||
#ifndef PRINTF_FTOA_BUFFER_SIZE
|
||||
#define PRINTF_FTOA_BUFFER_SIZE 64
|
||||
#endif
|
||||
|
||||
#define FLAGS_ZEROPAD (1U << 0U)
|
||||
#define FLAGS_LEFT (1U << 1U)
|
||||
#define FLAGS_PLUS (1U << 2U)
|
||||
#define FLAGS_SPACE (1U << 3U)
|
||||
#define FLAGS_HASH (1U << 4U)
|
||||
#define FLAGS_PRECISION (1U << 5U)
|
||||
#define FLAGS_ISSIGNED (1U << 6U)
|
||||
#define FLAGS_NOQUOTE (1U << 7U)
|
||||
#define FLAGS_QUOTE FLAGS_SPACE
|
||||
#define FLAGS_GROUPING FLAGS_NOQUOTE
|
||||
#define FLAGS_REPR FLAGS_PLUS
|
174
libc/fmt/palandftoa.c
Normal file
174
libc/fmt/palandftoa.c
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*-*- 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│
|
||||
╚══════════════════════════════════════════════════════════════════════════════╝
|
||||
│ @author (c) Marco Paland (info@paland.com) │
|
||||
│ 2014-2019, PALANDesign Hannover, Germany │
|
||||
│ │
|
||||
│ @license The MIT License (MIT) │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining a copy │
|
||||
│ of this software and associated documentation files (the "Software"), to deal│
|
||||
│ in the Software without restriction, including without limitation the rights │
|
||||
│ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell │
|
||||
│ copies of the Software, and to permit persons to whom the Software is │
|
||||
│ furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│ The above copyright notice and this permission notice shall be included in │
|
||||
│ all copies or substantial portions of the Software. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
|
||||
│ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
|
||||
│ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
|
||||
│ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
|
||||
│ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,│
|
||||
│ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN │
|
||||
│ THE SOFTWARE. │
|
||||
│ │
|
||||
│ @brief Tiny printf, sprintf and (v)snprintf implementation, optimized for │
|
||||
│ embedded systems with a very limited resources. These routines are │
|
||||
│ thread safe and reentrant! Use this instead of the bloated │
|
||||
│ standard/newlib printf cause these use malloc for printf (and may not │
|
||||
│ be thread safe). │
|
||||
└─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/paland.inc"
|
||||
#include "libc/fmt/palandprintf.h"
|
||||
#include "libc/math.h"
|
||||
|
||||
static const int kPow10[] = {1, 10, 100, 1000, 10000,
|
||||
100000, 1000000, 10000000, 100000000, 1000000000};
|
||||
|
||||
int ftoa(int out(int, void *), void *arg, long double value, unsigned long prec,
|
||||
unsigned long width, unsigned long flags) {
|
||||
long whole, frac;
|
||||
long double tmp, diff;
|
||||
unsigned i, len, count, idx;
|
||||
char buf[PRINTF_FTOA_BUFFER_SIZE];
|
||||
|
||||
len = 0;
|
||||
diff = 0;
|
||||
|
||||
if (isnan(value)) {
|
||||
buf[0] = 'N';
|
||||
buf[1] = 'A';
|
||||
buf[2] = 'N';
|
||||
buf[3] = '\0';
|
||||
len += 3;
|
||||
} else if (isinf(value) ||
|
||||
(/* TODO(jart): need this? */ fabsl(value) > 0x7fffffff)) {
|
||||
buf[0] = 'Y';
|
||||
buf[1] = 'T';
|
||||
buf[2] = 'I';
|
||||
buf[3] = 'N';
|
||||
buf[4] = 'I';
|
||||
buf[5] = 'F';
|
||||
buf[6] = 'N';
|
||||
buf[7] = 'I';
|
||||
buf[8] = '\0';
|
||||
len += 8;
|
||||
} else {
|
||||
|
||||
/* set default precision to 6, if not set explicitly */
|
||||
if (!(flags & FLAGS_PRECISION)) {
|
||||
prec = 6;
|
||||
}
|
||||
|
||||
/* limit precision to 9, cause a prec >= 10 can lead to overflow errors */
|
||||
while (len < PRINTF_FTOA_BUFFER_SIZE && prec > 9) {
|
||||
buf[len++] = '0';
|
||||
prec--;
|
||||
}
|
||||
|
||||
whole = truncl(fabsl(value));
|
||||
tmp = (fabsl(value) - whole) * kPow10[prec];
|
||||
frac = tmp;
|
||||
diff = tmp - frac;
|
||||
|
||||
if (diff > 0.5) {
|
||||
++frac; /* handle rollover, e.g. case 0.99 with prec 1 is 1.0 */
|
||||
if (frac >= kPow10[prec]) {
|
||||
frac = 0;
|
||||
++whole;
|
||||
}
|
||||
} else if (diff < 0.5) {
|
||||
} else if ((frac == 0U) || (frac & 1U)) {
|
||||
++frac; /* if halfway, round up if odd OR if last digit is 0 */
|
||||
}
|
||||
|
||||
if (prec == 0U) {
|
||||
diff = fabsl(value) - whole;
|
||||
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
|
||||
/* exactly 0.5 and ODD, then round up */
|
||||
/* 1.5 -> 2, but 2.5 -> 2 */
|
||||
++whole;
|
||||
}
|
||||
} else {
|
||||
count = prec;
|
||||
/* now do fractional part, as an unsigned number */
|
||||
while (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
--count;
|
||||
buf[len++] = 48 + (frac % 10);
|
||||
if (!(frac /= 10)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* add extra 0s */
|
||||
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
if (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
/* add decimal */
|
||||
buf[len++] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
/* do whole part, number is reversed */
|
||||
while (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
buf[len++] = (char)(48 + (whole % 10));
|
||||
if (!(whole /= 10)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* pad leading zeros */
|
||||
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
|
||||
if (width && (signbit(value) || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
|
||||
width--;
|
||||
}
|
||||
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
if (signbit(value)) {
|
||||
buf[len++] = '-';
|
||||
} else if (flags & FLAGS_PLUS) {
|
||||
buf[len++] = '+'; /* ignore the space if the '+' exists */
|
||||
} else if (flags & FLAGS_SPACE) {
|
||||
buf[len++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/* pad spaces up to given width */
|
||||
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
|
||||
if (len < width) {
|
||||
if (spacepad(out, arg, width - len) == -1) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* reverse string */
|
||||
for (idx = i = 0; i < len; i++) {
|
||||
if (out(buf[len - i - 1U], arg) == -1) return -1;
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* append pad spaces up to given width */
|
||||
if (flags & FLAGS_LEFT) {
|
||||
if (len < width) {
|
||||
if (spacepad(out, arg, width - len) == -1) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
176
libc/fmt/palandntoa.c
Normal file
176
libc/fmt/palandntoa.c
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*-*- 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│
|
||||
╚══════════════════════════════════════════════════════════════════════════════╝
|
||||
│ @author (c) Marco Paland (info@paland.com) │
|
||||
│ 2014-2019, PALANDesign Hannover, Germany │
|
||||
│ │
|
||||
│ @license The MIT License (MIT) │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining a copy │
|
||||
│ of this software and associated documentation files (the "Software"), to deal│
|
||||
│ in the Software without restriction, including without limitation the rights │
|
||||
│ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell │
|
||||
│ copies of the Software, and to permit persons to whom the Software is │
|
||||
│ furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│ The above copyright notice and this permission notice shall be included in │
|
||||
│ all copies or substantial portions of the Software. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
|
||||
│ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
|
||||
│ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
|
||||
│ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
|
||||
│ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,│
|
||||
│ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN │
|
||||
│ THE SOFTWARE. │
|
||||
└─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/fmt/paland.inc"
|
||||
#include "libc/fmt/palandprintf.h"
|
||||
|
||||
static int ntoaformat(int out(int, void *), void *arg, char *buf, unsigned len,
|
||||
bool negative, unsigned log2base, unsigned prec,
|
||||
unsigned width, unsigned flags) {
|
||||
unsigned i, idx;
|
||||
idx = 0;
|
||||
|
||||
/* pad leading zeros */
|
||||
if (!(flags & FLAGS_LEFT)) {
|
||||
if (width && (flags & FLAGS_ZEROPAD) &&
|
||||
(negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
|
||||
width--;
|
||||
}
|
||||
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
while ((flags & FLAGS_ZEROPAD) && (len < width) &&
|
||||
(len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
/* handle hash */
|
||||
if (flags & FLAGS_HASH) {
|
||||
if (!(flags & FLAGS_PRECISION) && len &&
|
||||
((len == prec) || (len == width)) && buf[len - 1] == '0') {
|
||||
len--;
|
||||
if (len && (log2base == 4 || log2base == 1) && buf[len - 1] == '0') {
|
||||
len--;
|
||||
}
|
||||
}
|
||||
if (log2base == 4 && len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
buf[len++] = 'x';
|
||||
} else if (log2base == 1 && len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
buf[len++] = 'b';
|
||||
}
|
||||
if (len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if (len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
if (negative) {
|
||||
buf[len++] = '-';
|
||||
} else if (flags & FLAGS_PLUS) {
|
||||
buf[len++] = '+'; /* ignore the space if the '+' exists */
|
||||
} else if (flags & FLAGS_SPACE) {
|
||||
buf[len++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/* pad spaces up to given width */
|
||||
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
|
||||
if (len < width) {
|
||||
if (spacepad(out, arg, width - len) == -1) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* reverse string */
|
||||
for (i = 0U; i < len; i++) {
|
||||
if (out(buf[len - i - 1], arg) == -1) return -1;
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* append pad spaces up to given width */
|
||||
if (flags & FLAGS_LEFT) {
|
||||
if (idx < width) {
|
||||
if (spacepad(out, arg, width - idx) == -1) return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ntoa2(int out(int, void *), void *arg, uintmax_t value, bool neg,
|
||||
unsigned log2base, unsigned prec, unsigned width,
|
||||
unsigned flags, const char *alphabet) {
|
||||
unsigned len, count, digit;
|
||||
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||
len = 0;
|
||||
if (!value) flags &= ~FLAGS_HASH;
|
||||
if (value || !(flags & FLAGS_PRECISION)) {
|
||||
count = 0;
|
||||
do {
|
||||
assert(len < PRINTF_NTOA_BUFFER_SIZE);
|
||||
if (log2base) {
|
||||
digit = value;
|
||||
digit &= (1u << log2base) - 1;
|
||||
value >>= log2base;
|
||||
} else {
|
||||
value = div10(value, &digit);
|
||||
}
|
||||
if ((flags & FLAGS_GROUPING) && count == 3) {
|
||||
buf[len++] = ',';
|
||||
count = 1;
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
buf[len++] = alphabet[digit];
|
||||
} while (value);
|
||||
}
|
||||
return ntoaformat(out, arg, buf, len, neg, log2base, prec, width, flags);
|
||||
}
|
||||
|
||||
int ntoa(int out(int, void *), void *arg, va_list va, unsigned char signbit,
|
||||
unsigned long log2base, unsigned long precision, unsigned long width,
|
||||
unsigned long flags, const char *alphabet) {
|
||||
bool negative;
|
||||
uintmax_t value, sign;
|
||||
|
||||
/* ignore '0' flag when precision is given */
|
||||
if (flags & FLAGS_PRECISION) {
|
||||
flags &= ~FLAGS_ZEROPAD;
|
||||
}
|
||||
|
||||
/* no plus / space flag for u, x, X, o, b */
|
||||
if (!(flags & FLAGS_ISSIGNED)) {
|
||||
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
|
||||
}
|
||||
|
||||
if (signbit > 63) {
|
||||
value = va_arg(va, uint128_t);
|
||||
} else {
|
||||
value = va_arg(va, uint64_t);
|
||||
}
|
||||
|
||||
negative = false;
|
||||
sign = (uintmax_t)1 << signbit;
|
||||
if (value > (sign | (sign - 1))) erange();
|
||||
if (flags & FLAGS_ISSIGNED) {
|
||||
if (value != sign) {
|
||||
if (value & sign) {
|
||||
value = ~value + 1;
|
||||
negative = true;
|
||||
}
|
||||
value &= sign - 1;
|
||||
}
|
||||
} else {
|
||||
value &= sign | (sign - 1);
|
||||
}
|
||||
|
||||
if (ntoa2(out, arg, value, negative, log2base, precision, width, flags,
|
||||
alphabet) == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
264
libc/fmt/palandprintf.c
Normal file
264
libc/fmt/palandprintf.c
Normal file
|
@ -0,0 +1,264 @@
|
|||
/*-*- 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│
|
||||
╚══════════════════════════════════════════════════════════════════════════════╝
|
||||
│ @author (c) Marco Paland (info@paland.com) │
|
||||
│ 2014-2019, PALANDesign Hannover, Germany │
|
||||
│ │
|
||||
│ @license The MIT License (MIT) │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining a copy │
|
||||
│ of this software and associated documentation files (the "Software"), to deal│
|
||||
│ in the Software without restriction, including without limitation the rights │
|
||||
│ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell │
|
||||
│ copies of the Software, and to permit persons to whom the Software is │
|
||||
│ furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│ The above copyright notice and this permission notice shall be included in │
|
||||
│ all copies or substantial portions of the Software. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
|
||||
│ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
|
||||
│ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
|
||||
│ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
|
||||
│ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,│
|
||||
│ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN │
|
||||
│ THE SOFTWARE. │
|
||||
│ │
|
||||
│ @brief Tiny printf, sprintf and (v)snprintf implementation, optimized for │
|
||||
│ embedded systems with a very limited resources. These routines are │
|
||||
│ thread safe and reentrant! Use this instead of the bloated │
|
||||
│ standard/newlib printf cause these use malloc for printf (and may not │
|
||||
│ be thread safe). │
|
||||
│ │
|
||||
│ @brief Modified by Justine Tunney to support three different types of │
|
||||
│ UNICODE, 128-bit arithmetic, binary conversion, string escaping, │
|
||||
│ AVX2 character scanning, and possibly a tinier footprint too, so │
|
||||
│ long as extremely wild linker hacks aren't considered cheating. │
|
||||
└─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/paland.inc"
|
||||
#include "libc/fmt/palandprintf.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static unsigned ppatoi(const char **str) {
|
||||
unsigned i;
|
||||
i = 0;
|
||||
while (isdigit(**str)) i = i * 10u + (unsigned)(*((*str)++) - '0');
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements {,v}{,s{,n},{,{,x}as},f,d}printf state machine.
|
||||
* @see libc/stdio/printf.c for documentation
|
||||
*/
|
||||
hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
|
||||
int (*out)(int, void *);
|
||||
unsigned flags, width, precision;
|
||||
int lasterr;
|
||||
|
||||
lasterr = errno;
|
||||
out = fn ? fn : (int (*)(int, void *))missingno;
|
||||
|
||||
while (*format) {
|
||||
/* %[flags][width][.precision][length] */
|
||||
if (*format != '%') {
|
||||
/* no */
|
||||
if (out(*format, arg) == -1) return -1;
|
||||
format++;
|
||||
continue;
|
||||
} else {
|
||||
/* yes, evaluate it */
|
||||
format++;
|
||||
}
|
||||
|
||||
/* evaluate flags */
|
||||
flags = 0;
|
||||
getflag:
|
||||
switch (*format++) {
|
||||
case '0':
|
||||
flags |= FLAGS_ZEROPAD;
|
||||
goto getflag;
|
||||
case '-':
|
||||
flags |= FLAGS_LEFT;
|
||||
goto getflag;
|
||||
case '+':
|
||||
flags |= FLAGS_PLUS;
|
||||
goto getflag;
|
||||
case ' ':
|
||||
flags |= FLAGS_SPACE;
|
||||
goto getflag;
|
||||
case '#':
|
||||
flags |= FLAGS_HASH;
|
||||
goto getflag;
|
||||
case ',':
|
||||
flags |= FLAGS_GROUPING;
|
||||
goto getflag;
|
||||
case '`':
|
||||
flags |= FLAGS_REPR;
|
||||
/* fallthrough */
|
||||
case '\'':
|
||||
flags |= FLAGS_QUOTE;
|
||||
goto getflag;
|
||||
default:
|
||||
format--;
|
||||
break;
|
||||
}
|
||||
|
||||
/* evaluate width field */
|
||||
width = 0;
|
||||
if (isdigit(*format)) {
|
||||
width = ppatoi(&format);
|
||||
} else if (*format == '*') {
|
||||
const int w = va_arg(va, int);
|
||||
if (w < 0) {
|
||||
flags |= FLAGS_LEFT; /* reverse padding */
|
||||
width = -w;
|
||||
} else {
|
||||
width = w;
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
/* evaluate precision field */
|
||||
precision = 0;
|
||||
if (*format == '.') {
|
||||
flags |= FLAGS_PRECISION;
|
||||
format++;
|
||||
if (isdigit(*format)) {
|
||||
precision = ppatoi(&format);
|
||||
} else if (*format == '*') {
|
||||
const int prec = (int)va_arg(va, int);
|
||||
precision = prec > 0 ? prec : 0;
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
/* evaluate length field */
|
||||
unsigned char signbit = 31;
|
||||
switch (*format) {
|
||||
case 'j': /* intmax_t */
|
||||
format++;
|
||||
signbit = sizeof(intmax_t) * 8 - 1;
|
||||
break;
|
||||
case 'l':
|
||||
if (format[1] == 'l') format++;
|
||||
/* fallthrough */
|
||||
case 't': /* ptrdiff_t */
|
||||
case 'Z': /* size_t */
|
||||
case 'z': /* size_t */
|
||||
case 'L': /* long double */
|
||||
format++;
|
||||
signbit = 63;
|
||||
break;
|
||||
case 'h':
|
||||
format++;
|
||||
if (*format == 'h') {
|
||||
format++;
|
||||
signbit = 7;
|
||||
} else {
|
||||
signbit = 15;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* evaluate specifier */
|
||||
void *p;
|
||||
const char *alphabet = "0123456789abcdef";
|
||||
unsigned log2base = 0;
|
||||
wchar_t charbuf[3];
|
||||
int rc;
|
||||
char qchar = '"';
|
||||
switch (*format++) {
|
||||
case 'p':
|
||||
flags |= FLAGS_ZEROPAD;
|
||||
width = POINTER_XDIGITS;
|
||||
log2base = 4;
|
||||
signbit = 47;
|
||||
goto DoNumber;
|
||||
case 'X':
|
||||
alphabet = "0123456789ABCDEF";
|
||||
/* fallthrough */
|
||||
case 'x':
|
||||
log2base = 4;
|
||||
goto DoNumber;
|
||||
case 'b':
|
||||
log2base = 1;
|
||||
goto DoNumber;
|
||||
case 'o':
|
||||
log2base = 3;
|
||||
goto DoNumber;
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= FLAGS_ISSIGNED;
|
||||
/* fallthrough */
|
||||
case 'u': {
|
||||
flags &= ~FLAGS_HASH; /* no hash for dec format */
|
||||
DoNumber:
|
||||
if (weaken(ntoa)(out, arg, va, signbit, log2base, precision, width,
|
||||
flags, alphabet) == -1) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
case 'F': {
|
||||
long double value;
|
||||
if (signbit == 63) {
|
||||
value = va_arg(va, long double);
|
||||
} else {
|
||||
value = va_arg(va, double);
|
||||
}
|
||||
if (weaken(ftoa)(out, arg, value, precision, width, flags) == -1) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
qchar = '\'';
|
||||
p = charbuf;
|
||||
charbuf[0] = (wchar_t)va_arg(va, int); /* @assume little endian */
|
||||
charbuf[1] = L'\0';
|
||||
goto showstr;
|
||||
|
||||
case 'm':
|
||||
p = weaken(strerror)(lasterr);
|
||||
signbit = 0;
|
||||
goto showstr;
|
||||
|
||||
case 'r':
|
||||
flags |= FLAGS_REPR;
|
||||
/* fallthrough */
|
||||
|
||||
case 'q':
|
||||
flags |= FLAGS_QUOTE;
|
||||
/* fallthrough */
|
||||
|
||||
case 's':
|
||||
p = va_arg(va, void *);
|
||||
showstr:
|
||||
rc = weaken(stoa)(out, arg, p, flags, precision, width, signbit, qchar);
|
||||
if (rc == -1) return -1;
|
||||
break;
|
||||
|
||||
case '%':
|
||||
if (out('%', arg) == -1) return -1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (out(format[-1], arg) == -1) return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
16
libc/fmt/palandprintf.h
Normal file
16
libc/fmt/palandprintf.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_PALANDPRINTF_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_PALANDPRINTF_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int spacepad(int(int, void *), void *, unsigned long) hidden;
|
||||
int ftoa(int(int, void *), void *, long double, unsigned long, unsigned long,
|
||||
unsigned long) hidden;
|
||||
int stoa(int(int, void *), void *, void *, unsigned long, unsigned long,
|
||||
unsigned long, unsigned char, unsigned char) hidden;
|
||||
int ntoa(int(int, void *), void *, va_list, unsigned char, unsigned long,
|
||||
unsigned long, unsigned long, unsigned long, const char *) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_PALANDPRINTF_H_ */
|
60
libc/fmt/pflink.h
Normal file
60
libc/fmt/pflink.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_PFLINK_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_PFLINK_H_
|
||||
#include "libc/dce.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
#ifndef __STRICT_ANSI__
|
||||
|
||||
/**
|
||||
* @fileoverview builtin+preprocessor+linker tricks for printf/scanf.
|
||||
*
|
||||
* Your printf() function only requires that you pay for what you use.
|
||||
* These macros ensure that its code size starts at under 4kb, growing
|
||||
* to about 40kb for a fully-loaded implementation. This works best when
|
||||
* format strings are constexprs that only contain directives.
|
||||
*/
|
||||
|
||||
#define PFLINK(FMT) \
|
||||
({ \
|
||||
if (___PFLINK(FMT, strpbrk, "bxdinupo")) STATIC_YOINK("ntoa"); \
|
||||
if (___PFLINK(FMT, strpbrk, "fFgGaA")) STATIC_YOINK("ftoa"); \
|
||||
if (___PFLINK(FMT, strpbrk, "cmrqs")) { \
|
||||
STATIC_YOINK("stoa"); \
|
||||
if (___PFLINK(FMT, strchr, '#')) STATIC_YOINK("kCp437"); \
|
||||
if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \
|
||||
if (!IsTiny() && (___PFLINK(FMT, strstr, "%*") || \
|
||||
___PFLINK(FMT, strpbrk, "0123456789"))) { \
|
||||
STATIC_YOINK("strnwidth"); \
|
||||
STATIC_YOINK("strnwidth16"); \
|
||||
STATIC_YOINK("wcsnwidth"); \
|
||||
} \
|
||||
} \
|
||||
FMT; \
|
||||
})
|
||||
|
||||
#define SFLINK(FMT) \
|
||||
({ \
|
||||
if (___PFLINK(FMT, strchr, 'm')) { \
|
||||
STATIC_YOINK("malloc"); \
|
||||
STATIC_YOINK("calloc"); \
|
||||
STATIC_YOINK("free_s"); \
|
||||
STATIC_YOINK("grow"); \
|
||||
} \
|
||||
FMT; \
|
||||
})
|
||||
|
||||
#if __GNUC__ + 0 < 4 || defined(__llvm__)
|
||||
#define ___PFLINK(FMT, FN, C) 1
|
||||
#else
|
||||
#define ___PFLINK(FMT, FN, C) \
|
||||
!isconstant(FMT) || ((FMT) && __builtin_##FN(FMT, C) != NULL)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ < 6
|
||||
#pragma GCC diagnostic ignored "-Wformat-security"
|
||||
#endif /* __GNUC__ + 0 < 6 */
|
||||
#else
|
||||
#define PFLINK(FMT) FMT
|
||||
#define SFLINK(FMT) FMT
|
||||
#endif /* __STRICT_ANSI__ */
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_PFLINK_H_ */
|
37
libc/fmt/snprintf.c
Normal file
37
libc/fmt/snprintf.c
Normal file
|
@ -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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
|
||||
/**
|
||||
* Formats string to buffer.
|
||||
*
|
||||
* @return number of bytes written, excluding the NUL terminator; or,
|
||||
* if the output buffer wasn't passed, or was too short, then the
|
||||
* number of characters that *would* have been written is returned
|
||||
* @see libc/fmt/fmt.h for documentation
|
||||
*/
|
||||
int(snprintf)(char* buf, size_t count, const char* fmt, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
rc = (vsnprintf)(buf, count, fmt, va);
|
||||
va_end(va);
|
||||
return rc;
|
||||
}
|
26
libc/fmt/spacepad.c
Normal file
26
libc/fmt/spacepad.c
Normal file
|
@ -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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/palandprintf.h"
|
||||
|
||||
int spacepad(int out(int, void *), void *arg, unsigned long n) {
|
||||
int i, rc;
|
||||
for (rc = i = 0; i < n; ++i) rc |= out(' ', arg);
|
||||
return rc;
|
||||
}
|
30
libc/fmt/sprintf.c
Normal file
30
libc/fmt/sprintf.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
int(sprintf)(char *buf, const char *fmt, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
rc = (vsnprintf)(buf, INT_MAX, fmt, va);
|
||||
va_end(va);
|
||||
return rc;
|
||||
}
|
38
libc/fmt/sscanf.c
Normal file
38
libc/fmt/sscanf.c
Normal file
|
@ -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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/vsscanf.h"
|
||||
|
||||
/**
|
||||
* String decoder.
|
||||
* @see libc/fmt/vcscanf.h (for docs and implementation)
|
||||
*/
|
||||
int(sscanf)(const char *str, const char *fmt, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
if (IsTiny()) {
|
||||
rc = (vsscanf)(str, fmt, va);
|
||||
} else {
|
||||
rc = __vsscanf(str, fmt, va, __vcscanf);
|
||||
}
|
||||
va_end(va);
|
||||
return rc;
|
||||
}
|
180
libc/fmt/stoa.c
Normal file
180
libc/fmt/stoa.c
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/paland.inc"
|
||||
#include "libc/fmt/palandprintf.h"
|
||||
#include "libc/nexgen32e/tinystrlen.h"
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/unicode/unicode.h"
|
||||
|
||||
forceinline unsigned long tpiencode(wint_t wc) {
|
||||
char buf[8];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
tpencode(buf, sizeof(buf), wc, false);
|
||||
return read64le(buf);
|
||||
}
|
||||
|
||||
forceinline int emitwc(int out(int, void *), void *arg, unsigned flags,
|
||||
wint_t wc) {
|
||||
unsigned long pending;
|
||||
if (flags & FLAGS_QUOTE) {
|
||||
if (wc > 127) {
|
||||
pending = tpiencode(wc);
|
||||
} else {
|
||||
pending = cescapec(wc);
|
||||
}
|
||||
} else {
|
||||
pending = tpiencode(wc);
|
||||
}
|
||||
do {
|
||||
if (out(pending & 0xff, arg) == -1) return -1;
|
||||
} while ((pending >>= 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
forceinline int emitquote(int out(int, void *), void *arg, unsigned flags,
|
||||
char ch, unsigned char signbit) {
|
||||
if (flags & FLAGS_REPR) {
|
||||
if (signbit == 63) {
|
||||
if (out('L', arg) == -1) return -1;
|
||||
} else if (signbit == 15) {
|
||||
if (out('u', arg) == -1) return -1;
|
||||
}
|
||||
if (out(ch, arg) == -1) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts string to array.
|
||||
*
|
||||
* This function is used by palandprintf() to implement the %s and %c
|
||||
* directives. The content outputted to the array is always UTF-8, but
|
||||
* the input may be UTF-16 or UTF-32.
|
||||
*/
|
||||
int stoa(int out(int, void *), void *arg, void *data, unsigned long flags,
|
||||
unsigned long precision, unsigned long width, unsigned char signbit,
|
||||
unsigned char qchar) {
|
||||
char *p;
|
||||
wint_t wc;
|
||||
unsigned w, c;
|
||||
bool ignorenul;
|
||||
|
||||
p = data;
|
||||
if (!p) {
|
||||
p = ((flags & FLAGS_REPR) ? "NULL" : "(null)");
|
||||
flags &= ~FLAGS_PRECISION;
|
||||
flags |= FLAGS_NOQUOTE;
|
||||
signbit = 0;
|
||||
} else {
|
||||
if (emitquote(out, arg, flags, qchar, signbit) == -1) return -1;
|
||||
}
|
||||
|
||||
w = precision ? precision : -1;
|
||||
if (width) {
|
||||
if (signbit == 63) {
|
||||
if (weaken(wcsnwidth)) {
|
||||
w = weaken(wcsnwidth)((const wchar_t *)p, w);
|
||||
} else {
|
||||
w = tinywcsnlen((const wchar_t *)p, w);
|
||||
}
|
||||
} else if (signbit == 15) {
|
||||
if (weaken(strnwidth16)) {
|
||||
w = weaken(strnwidth16)((const char16_t *)p, w);
|
||||
} else {
|
||||
w = tinystrnlen16((const char16_t *)p, w);
|
||||
}
|
||||
} else if (weaken(strnwidth)) {
|
||||
w = weaken(strnwidth)(p, w);
|
||||
} else {
|
||||
w = strnlen(p, w);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FLAGS_PRECISION) {
|
||||
w = MIN(w, precision);
|
||||
}
|
||||
|
||||
if (w < width && !(flags & FLAGS_LEFT)) {
|
||||
if (spacepad(out, arg, width - w) == -1) return -1;
|
||||
}
|
||||
|
||||
ignorenul = (flags & FLAGS_PRECISION) && (flags & (FLAGS_HASH | FLAGS_QUOTE));
|
||||
for (; !(flags & FLAGS_PRECISION) || precision; --precision) {
|
||||
if (signbit == 15) {
|
||||
if ((wc = *(const char16_t *)p) || ignorenul) {
|
||||
if ((1 <= wc && wc <= 0xD7FF)) {
|
||||
p += sizeof(char16_t);
|
||||
} else if ((wc & UTF16_MASK) == UTF16_CONT) {
|
||||
p += sizeof(char16_t);
|
||||
continue;
|
||||
} else {
|
||||
char16_t buf[4] = {wc};
|
||||
if (!(flags & FLAGS_PRECISION) || precision > 1) {
|
||||
buf[1] = ((const char16_t *)p)[1];
|
||||
}
|
||||
p += max(1, getutf16((const char16_t *)p, &wc)) * sizeof(char16_t);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (signbit == 63) {
|
||||
wc = *(const wint_t *)p;
|
||||
p += sizeof(wint_t);
|
||||
if (!wc) break;
|
||||
} else if (flags & FLAGS_HASH) {
|
||||
c = *p & 0xff;
|
||||
if (!c && !ignorenul) break;
|
||||
wc = (*weaken(kCp437))[c];
|
||||
p++;
|
||||
} else {
|
||||
if ((wc = *p & 0xff) || ignorenul) {
|
||||
if (1 <= wc && wc <= 0x7f) {
|
||||
++p;
|
||||
} else if (iscont(wc & 0xff)) {
|
||||
++p;
|
||||
continue;
|
||||
} else {
|
||||
char buf[8];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memcpy(buf, p,
|
||||
!(flags & FLAGS_PRECISION) ? 7 : MIN(7, precision - 1));
|
||||
p += max(1, tpdecode(p, &wc));
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (emitwc(out, arg, flags, wc) == -1) return -1;
|
||||
}
|
||||
|
||||
if (w <= width && (flags & FLAGS_LEFT)) {
|
||||
if (spacepad(out, arg, width - w) == -1) return -1;
|
||||
}
|
||||
if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) {
|
||||
if (out(qchar, arg) == -1) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
30
libc/fmt/strerror.c
Normal file
30
libc/fmt/strerror.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:c; indent-tabs-mode:nil; tab-width:2; coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
|
||||
/**
|
||||
* Converts errno value to string non-reentrantly.
|
||||
* @see strerror_r()
|
||||
*/
|
||||
char *strerror(int err) {
|
||||
alignas(1) static char buf[512];
|
||||
strerror_r(err, buf, sizeof(buf));
|
||||
return &buf[0];
|
||||
}
|
68
libc/fmt/strerror_r.c
Normal file
68
libc/fmt/strerror_r.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static const char *geterrname(int code) {
|
||||
extern const char kErrnoNames[];
|
||||
const long *e;
|
||||
const char *s;
|
||||
size_t i;
|
||||
for (i = 0, e = &E2BIG; e <= &EXFULL; ++e, ++i) {
|
||||
if (code == *e && (s = indexdoublenulstring(&kErrnoNames[0], i))) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts errno value to string.
|
||||
* @return 0 on success, or error code
|
||||
*/
|
||||
int strerror_r(int err, char *buf, size_t size) {
|
||||
const char *s;
|
||||
s = (err == -1 || IsTiny()) ? "?" : firstnonnull(geterrname(err), "?");
|
||||
if (!SupportsWindows()) {
|
||||
snprintf(buf, size, "E%s[%d]", s, err);
|
||||
} else {
|
||||
char16_t buf16[100];
|
||||
int winstate, sysvstate;
|
||||
winstate = GetLastError();
|
||||
sysvstate = errno;
|
||||
if (FormatMessage(
|
||||
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, NULL,
|
||||
err, 0, buf16, ARRAYLEN(buf16) - 1, 0) > 0) {
|
||||
chomp(buf16);
|
||||
} else {
|
||||
buf16[0] = u'\0';
|
||||
}
|
||||
snprintf(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
|
||||
sysvstate, winstate, buf16[0] ? " " : "", buf16);
|
||||
}
|
||||
return 0;
|
||||
}
|
28
libc/fmt/typefmt.h
Normal file
28
libc/fmt/typefmt.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_TYPEFMT_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_TYPEFMT_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* Returns printf directive to format scalar type of expression.
|
||||
*
|
||||
* @see TYPE_NAME()
|
||||
*/
|
||||
#define TYPE_FMT(X, DXOB, UXOB) \
|
||||
_Generic((X), long double \
|
||||
: "Lf", double \
|
||||
: "f", float \
|
||||
: "f", char \
|
||||
: "c", signed char \
|
||||
: "hh" DXOB, unsigned char \
|
||||
: "hh" UXOB, short \
|
||||
: "h" DXOB, unsigned short \
|
||||
: "h" UXOB, int \
|
||||
: DXOB, unsigned \
|
||||
: UXOB, long \
|
||||
: "l" DXOB, unsigned long \
|
||||
: "l" UXOB)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_TYPEFMT_H_ */
|
77
libc/fmt/unbing.c
Normal file
77
libc/fmt/unbing.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/fmt/bing.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define ALTCOUNT 21
|
||||
|
||||
static const struct Cp437Multimappings {
|
||||
unsigned char b[ALTCOUNT];
|
||||
char16_t c[ALTCOUNT];
|
||||
} kCp437iMultimappings = {
|
||||
#define ALT(I, C, B) .c[I] = C, .b[I] = B
|
||||
ALT(0, u'\n', '\n'),
|
||||
ALT(1, u'\r', '\r'),
|
||||
ALT(2, u'?', '?'), /* TRIGRAPH */
|
||||
ALT(3, u'\'', '\''), /* CHARACTER LITERAL */
|
||||
ALT(4, u'\"', '\"'), /* STRING LITERAL */
|
||||
ALT(5, u'\\', '\\'), /* ESCAPE LITERAL */
|
||||
ALT(6, u'∅', '\0'), /* EMPTY SET */
|
||||
ALT(7, u'␀', '\0'), /* SYMBOL FOR NULL [sic] */
|
||||
ALT(7, 0x20A7, 0x9E), /* PESETA SIGN */
|
||||
ALT(8, u'Π' /* 03A0: GREEK CAPITAL LETTER PI */, 0xE3),
|
||||
ALT(9, u'∏' /* 220F: N-ARY PRODUCT */, 0xE3),
|
||||
ALT(10, u'∑' /* 2211: N-ARY SUMMATION */, 0xE4),
|
||||
ALT(11, u'µ' /* 03BC: MICRO SIGN */, 0xE6),
|
||||
ALT(12, u'Ω' /* 2126: OHM SIGN */, 0xEA),
|
||||
ALT(13, u'∂' /* 2202: PARTIAL DIFFERENTIAL */, 0xEB),
|
||||
ALT(14, u'ε' /* 03D5: PHI SMALL (CLOSED FORM) */, 0xED),
|
||||
ALT(15, u'ϕ' /* 03D5: PHI SMALL (CLOSED FORM) */, 0xED),
|
||||
ALT(16, u'∈' /* 2208: ELEMENT-OF SIGN */, 0xED),
|
||||
ALT(17, u'∊' /* 220A: SMALL ELEMENT OF */, 0xEE),
|
||||
ALT(18, u'∈' /* 03B5: ELEMENT-OF SIGN */, 0xEE),
|
||||
ALT(19, u'β' /* 03B2: GREEK SMALL BETA */, 0xE1),
|
||||
ALT(20, u'ſ' /* 017F: LATIN SMALL LETTER LONG S */, 0xF4),
|
||||
#undef ALT
|
||||
};
|
||||
|
||||
/**
|
||||
* Turns CP437 unicode glyph into its binary representation.
|
||||
*
|
||||
* @param c is a unicode character
|
||||
* @return byte representation, or -1 if ch wasn't ibm cp437
|
||||
* @see bing()
|
||||
*/
|
||||
int unbing(int c) {
|
||||
int i;
|
||||
for (i = 0; i < 256; ++i) {
|
||||
if (c == kCp437[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ALTCOUNT; ++i) {
|
||||
if (c == kCp437iMultimappings.c[i]) {
|
||||
return kCp437iMultimappings.b[i];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
36
libc/fmt/unhexbuf.c
Normal file
36
libc/fmt/unhexbuf.c
Normal file
|
@ -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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/bing.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
void *unhexbuf(void *buf, size_t size, const char *hexdigs) {
|
||||
size_t i;
|
||||
unsigned char *p;
|
||||
assert(size * 2 == strlen(hexdigs));
|
||||
p = buf;
|
||||
for (i = 0; i < size; ++i) {
|
||||
assert(isxdigit(hexdigs[i / 2 + 0]) && isxdigit(hexdigs[i / 2 + 1]));
|
||||
}
|
||||
for (i = 0; i < size; ++i) {
|
||||
p[i] = hextoint(hexdigs[i * 2 + 0]) * 16 + hextoint(hexdigs[i * 2 + 1]);
|
||||
}
|
||||
return buf;
|
||||
}
|
29
libc/fmt/vcscanf.c
Normal file
29
libc/fmt/vcscanf.c
Normal file
|
@ -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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/vcscanf.h"
|
||||
|
||||
/**
|
||||
* Linkable callback-driven string / file / stream decoder.
|
||||
* @see libc/fmt/vcscanf.h (for docs and implementation)
|
||||
*/
|
||||
int(vcscanf)(int callback(void *), void *arg, const char *fmt, va_list ap) {
|
||||
return __vcscanf(callback, arg, fmt, ap);
|
||||
}
|
294
libc/fmt/vcscanf.h
Normal file
294
libc/fmt/vcscanf.h
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_FMT_VCSSCANF_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_VCSSCANF_H_
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpdecodecb.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* String / file / stream decoder.
|
||||
*
|
||||
* This scanf implementation is able to tokenize strings containing
|
||||
* 8-bit through 128-bit integers (with validation), floating point
|
||||
* numbers, etc. It can also be used to convert UTF-8 to UTF-16/32.
|
||||
*
|
||||
* @param callback supplies UTF-8 characters using -1 sentinel
|
||||
* @param fmt is a computer program embedded inside a c string, written
|
||||
* in a domain-specific programming language that, by design, lacks
|
||||
* Turing-completeness
|
||||
* @param va points to the variadic argument state
|
||||
* @see libc/fmt/pflink.h (dynamic memory is not a requirement)
|
||||
*/
|
||||
forceinline int __vcscanf(int callback(void *), void *arg, const char *fmt,
|
||||
va_list va) {
|
||||
struct FreeMe {
|
||||
struct FreeMe *next;
|
||||
void *ptr;
|
||||
} *freeme = NULL;
|
||||
const unsigned char *p = (const unsigned char *)fmt;
|
||||
unsigned i = 0;
|
||||
int items = 0;
|
||||
int c = callback(arg);
|
||||
while (c != -1) {
|
||||
switch (p[i++]) {
|
||||
case '\0':
|
||||
return items;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\v':
|
||||
while (isspace(c)) c = callback(arg);
|
||||
break;
|
||||
case '%': {
|
||||
uintmax_t number;
|
||||
void *buf;
|
||||
size_t bufsize;
|
||||
unsigned width = 0;
|
||||
unsigned char bits = 32;
|
||||
unsigned char charbytes = sizeof(char);
|
||||
unsigned char diglet;
|
||||
unsigned char base;
|
||||
unsigned char prefix;
|
||||
bool rawmode = false;
|
||||
bool issigned = false;
|
||||
bool ismalloc = false;
|
||||
bool isneg = false;
|
||||
bool thousands = false;
|
||||
bool discard = false;
|
||||
for (;;) {
|
||||
switch (p[i++]) {
|
||||
case '%': /* %% → % */
|
||||
goto NonDirectiveCharacter;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
width *= 10;
|
||||
width += p[i - 1] - '0';
|
||||
break;
|
||||
case '*':
|
||||
discard = true;
|
||||
break;
|
||||
case 'm':
|
||||
ismalloc = true;
|
||||
break;
|
||||
case 'c':
|
||||
rawmode = true;
|
||||
if (!width) width = 1;
|
||||
/* εpsilon transition */
|
||||
case 's':
|
||||
goto DecodeString;
|
||||
case '\'':
|
||||
thousands = true;
|
||||
break;
|
||||
case 'j': /* 128-bit */
|
||||
bits = sizeof(intmax_t) * 8;
|
||||
break;
|
||||
case 'l': /* long */
|
||||
case 'L': /* loooong */
|
||||
charbytes = sizeof(wchar_t);
|
||||
/* fallthrough */
|
||||
case 't': /* ptrdiff_t */
|
||||
case 'Z': /* size_t */
|
||||
case 'z': /* size_t */
|
||||
bits = 64;
|
||||
break;
|
||||
case 'h': /* short and char */
|
||||
charbytes = sizeof(char16_t);
|
||||
bits >>= 1;
|
||||
break;
|
||||
case 'b': /* binary */
|
||||
base = 2;
|
||||
prefix = 'b';
|
||||
goto ConsumeBasePrefix;
|
||||
case 'p': /* pointer (NexGen32e) */
|
||||
bits = 48;
|
||||
/* fallthrough */
|
||||
case 'x':
|
||||
case 'X': /* hexadecimal */
|
||||
base = 16;
|
||||
prefix = 'x';
|
||||
goto ConsumeBasePrefix;
|
||||
case 'o': /* octal */
|
||||
base = 8;
|
||||
goto DecodeNumber;
|
||||
case 'd': /* decimal */
|
||||
case 'n': /* TODO(jart): flexidecimal */
|
||||
issigned = true;
|
||||
if (c == '+' || (isneg = c == '-')) {
|
||||
c = callback(arg);
|
||||
}
|
||||
/* εpsilon transition */
|
||||
case 'u':
|
||||
base = 10;
|
||||
goto DecodeNumber;
|
||||
default:
|
||||
items = einval();
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
ConsumeBasePrefix:
|
||||
if (c == '0') {
|
||||
c = callback(arg);
|
||||
if (c == prefix || c == prefix + ('a' - 'A')) {
|
||||
c = callback(arg);
|
||||
}
|
||||
}
|
||||
DecodeNumber:
|
||||
if (c != -1) {
|
||||
number = 0;
|
||||
do {
|
||||
diglet = kBase36[(unsigned char)c];
|
||||
if (1 <= diglet && diglet <= base) {
|
||||
number *= base;
|
||||
number += diglet - 1;
|
||||
} else if (thousands && diglet == ',') {
|
||||
/* ignore */
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while ((c = callback(arg)) != -1);
|
||||
if (!discard) {
|
||||
uintmax_t bane = (uintmax_t)1 << (bits - 1);
|
||||
if (!(number & ~((bane - 1) | (issigned ? 0 : bane))) ||
|
||||
(issigned && number == bane /* two's complement bane */)) {
|
||||
++items;
|
||||
} else {
|
||||
items = erange();
|
||||
goto Done;
|
||||
}
|
||||
if (issigned && isneg) {
|
||||
number = ~number + 1;
|
||||
}
|
||||
void *out = va_arg(va, void *);
|
||||
switch (bits) {
|
||||
case sizeof(uintmax_t) * CHAR_BIT:
|
||||
*(uintmax_t *)out = number;
|
||||
break;
|
||||
case 48:
|
||||
case 64:
|
||||
*(uint64_t *)out = (uint64_t)number;
|
||||
break;
|
||||
case 32:
|
||||
*(uint32_t *)out = (uint32_t)number;
|
||||
break;
|
||||
case 16:
|
||||
*(uint16_t *)out = (uint16_t)number;
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
*(uint8_t *)out = (uint8_t)number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
DecodeString:
|
||||
bufsize = !width ? 32 : rawmode ? width : width + 1;
|
||||
if (discard) {
|
||||
buf = NULL;
|
||||
} else if (ismalloc) {
|
||||
buf = weaken(malloc)(bufsize * charbytes);
|
||||
struct FreeMe *entry;
|
||||
if (buf && (entry = weaken(calloc)(1, sizeof(struct FreeMe)))) {
|
||||
entry->ptr = buf;
|
||||
entry->next = freeme;
|
||||
freeme = entry;
|
||||
}
|
||||
} else {
|
||||
buf = va_arg(va, void *);
|
||||
}
|
||||
if (buf) {
|
||||
size_t j = 0;
|
||||
for (;;) {
|
||||
if (ismalloc && !width && j + 2 + 1 >= bufsize &&
|
||||
!weaken(grow)(&buf, &bufsize, charbytes, 0)) {
|
||||
width = bufsize - 1;
|
||||
}
|
||||
if (c != -1 && j + !rawmode < bufsize && (rawmode || !isspace(c))) {
|
||||
if (charbytes == 1) {
|
||||
((unsigned char *)buf)[j++] = (unsigned char)c;
|
||||
c = callback(arg);
|
||||
} else if (tpdecodecb((wint_t *)&c, c, (void *)callback, arg) !=
|
||||
-1) {
|
||||
if (charbytes == sizeof(char16_t)) {
|
||||
j += abs(pututf16(&((char16_t *)buf)[j], bufsize - j - 1, c,
|
||||
false));
|
||||
} else {
|
||||
((wchar_t *)buf)[j++] = (wchar_t)c;
|
||||
}
|
||||
c = callback(arg);
|
||||
}
|
||||
} else {
|
||||
if (!rawmode && j < bufsize) {
|
||||
if (charbytes == sizeof(char)) {
|
||||
((unsigned char *)buf)[j] = '\0';
|
||||
} else if (charbytes == sizeof(char16_t)) {
|
||||
((char16_t *)buf)[j] = u'\0';
|
||||
} else if (charbytes == sizeof(wchar_t)) {
|
||||
((wchar_t *)buf)[j] = L'\0';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
++items;
|
||||
if (ismalloc) {
|
||||
*va_arg(va, char **) = buf;
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
if (isspace(c)) break;
|
||||
} while ((c = callback(arg)) != -1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NonDirectiveCharacter:
|
||||
c = (c == p[i - 1]) ? callback(arg) : -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Done:
|
||||
while (freeme) {
|
||||
struct FreeMe *entry = freeme;
|
||||
freeme = entry->next;
|
||||
if (items == -1) {
|
||||
weaken(free_s)((void **)&entry->ptr);
|
||||
}
|
||||
weaken(free_s)((void **)&entry);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_VCSSCANF_H_ */
|
62
libc/fmt/vsnprintf.c
Normal file
62
libc/fmt/vsnprintf.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
struct SprintfStr {
|
||||
char *p;
|
||||
size_t i, n;
|
||||
};
|
||||
|
||||
static int vsnprintfputchar(unsigned char c, struct SprintfStr *str) {
|
||||
if (str->i < str->n) {
|
||||
if (str->p) str->p[str->i] = c;
|
||||
str->i++;
|
||||
} else {
|
||||
if (!IsTrustworthy() && str->i >= INT_MAX) abort();
|
||||
str->i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats string to buffer.
|
||||
*
|
||||
* @param buf stores output and a NUL-terminator is always written,
|
||||
* provided buf!=NULL && size!=0
|
||||
* @param size is byte capacity buf
|
||||
* @return number of bytes written, excluding the NUL terminator; or,
|
||||
* if the output buffer wasn't passed, or was too short, then the
|
||||
* number of characters that *would* have been written is returned
|
||||
* @throw EOVERFLOW when a formatted field exceeds its limit, which can
|
||||
* be checked by setting errno to 0 before calling
|
||||
* @see libc/fmt/fmt.h for further documentation
|
||||
*/
|
||||
int(vsnprintf)(char *buf, size_t size, const char *fmt, va_list va) {
|
||||
struct SprintfStr str = {buf, 0, size};
|
||||
palandprintf(vsnprintfputchar, &str, fmt, va);
|
||||
if (str.p && str.n) {
|
||||
str.p[min(str.i, str.n - 1)] = '\0';
|
||||
}
|
||||
return str.i;
|
||||
}
|
25
libc/fmt/vsprintf.c
Normal file
25
libc/fmt/vsprintf.c
Normal file
|
@ -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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
int(vsprintf)(char *buf, const char *fmt, va_list va) {
|
||||
return (vsnprintf)(buf, INT_MAX, fmt, va);
|
||||
}
|
33
libc/fmt/vsscanf.c
Normal file
33
libc/fmt/vsscanf.c
Normal file
|
@ -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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/vsscanf.h"
|
||||
|
||||
/**
|
||||
* String decoder.
|
||||
*
|
||||
* @see libc/fmt/vcscanf.h (for docs and implementation)
|
||||
* @note to offer the best performance, we assume small codebases
|
||||
* needing vsscanf() won't need sscanf() too; and as such, there's
|
||||
* a small code size penalty to using both
|
||||
*/
|
||||
int(vsscanf)(const char *str, const char *fmt, va_list va) {
|
||||
return __vsscanf(str, fmt, va, IsTiny() ? vcscanf : __vcscanf);
|
||||
}
|
39
libc/fmt/vsscanf.h
Normal file
39
libc/fmt/vsscanf.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTERNAL_VSSCANF_H_
|
||||
#define COSMOPOLITAN_LIBC_INTERNAL_VSSCANF_H_
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/vcscanf.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
struct StringScannerState {
|
||||
const unsigned char *s;
|
||||
size_t i;
|
||||
};
|
||||
|
||||
static inline int vsscanfcb(void *arg) {
|
||||
struct StringScannerState *state = arg;
|
||||
int res;
|
||||
if ((res = state->s[state->i])) {
|
||||
state->i++;
|
||||
} else {
|
||||
res = -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* String decoder builder.
|
||||
*
|
||||
* This macro grants sscanf() and vsscanf() the choice to either link or
|
||||
* inline the full vcscanf() implementation.
|
||||
*
|
||||
* @see libc/fmt/vcscanf.h (for docs and implementation)
|
||||
*/
|
||||
static inline int __vsscanf(const char *str, const char *fmt, va_list ap,
|
||||
int impl(int callback(void *), void *arg,
|
||||
const char *fmt, va_list ap)) {
|
||||
struct StringScannerState state = {(const unsigned char *)str, 0};
|
||||
return impl(vsscanfcb, &state, fmt, ap);
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTERNAL_VSSCANF_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue