Add glob and some finer tuning of documentation

main
Justine Tunney 2020-06-21 00:10:11 -07:00
parent 799e24a87b
commit d51409ccd9
77 changed files with 1321 additions and 736 deletions

View File

@ -231,8 +231,9 @@ HTAGS: o/$(MODE)/hdrs.txt $(HDRS)
@rm -f $@
@ACTION=TAGS TARGET=$@ build/do build/htags -L $< -o $@
loc:; find -name \*.h -or -name \*.c -or -name \*.S | \
$(XARGS) wc -l | grep total | awk '{print $$1}' | summy
loc: o/$(MODE)/tool/build/summy.com
find -name \*.h -or -name \*.c -or -name \*.S | \
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
# UNSPECIFIED PREREQUISITES TUTORIAL
#

13
NOTICE
View File

@ -1,16 +1,3 @@
Cosmopolitan is Free Software licensed under the GPLv2. The build config
**will embed all linked sources inside your binaries** so the compliance
is easy while facilitating trust and transparency similar to JavaScript.
You can audit your source filesystem using ZIP GUIs e.g. WIN10, InfoZip.
If you want to be able to distribute binaries in binary form only, then
please send $1,000 to jtunney@gmail.com on PayPal for a license lasting
1 year. Please be sure to provide your contact information, and details
on whether or not the license is for an individual or a corporation. If
you want your license to last 5 years, send $10,000 to the author above
who is Justine Tunney <jtunney@gmail.com>. Reach out, for more details.
────────────────────────────────────────────────────────────────────────
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

View File

@ -18,17 +18,19 @@ Cosmopolitan provides a native development environment similar to those
currently being offered by RedHat, Google, Apple, Microsoft, etc. We're
different in two ways: (1) we're not a platform therefore we don't have
any commercial interest in making our tooling work better on one rather
than another; and (2) we're only focused on catering towards interfaces
all platforms agree upon. Goal is software that stands the test of time
than another; and (2) we cater primarily towards features having gained
cross-platform agreement. Goal is software that stands the test of time
without the costs and restrictions cross-platform distribution entails.
That makes Cosmopolitan an excellent fit for writing small CLI programs
that do things like heavyweight numerical computations as a subprocess.
that do things like matrix multiplication relu stdio as a subprocess or
perhaps a web server having the minimum surface area that you require.
## Getting Started
Just clone the repository and put your own folder in it. Please choose a
name that's based on a .com or .org domain name registration you control
which is scout's honor but might change to require TXT records in future
which is scout's honor but could change to verify TXT records in future.
We provide a script that makes it easy to start a new package:
@ -37,11 +39,11 @@ We provide a script that makes it easy to start a new package:
make o//com/github/user/project/program.com
o//com/github/user/project/program.com
Please note GNU make is awesome. Little known fact: make is a functional
Please note GNU Make is awesome. Little known fact: make is a functional
programming language. We improved upon it too! In [tool/build/package.c]
which performs strict dependency checking, to correct Google's published
mistakes c. 2006 which was when they switched from using a GNU Make repo
in favor of an inhouse derivative called Blaze which does strictness too
in favor of an inhouse derivative called Blaze which does graph checking
thereby allowing the repository to grow gracefully with any requirements
## Performance
@ -66,18 +68,20 @@ Furthermore Cosmopolitan provides you with Intel's official instruction
length decoder Xed ravaged down to 3kb in size using Tim Patterson code
stunts. So you can absolutely code high-performance lightweight fabless
x86 microprocessors using any hobbyist board without royalties, because
Xed tells us which parts of the encoding space now belong to the people
Xed tells us which parts of the encoding space now belong to the people.
Please see [third_party/xed/x86ild.greg.c] to learn more.
## Integrated Development Environment
Your Cosmopolitan IDE is based on Emacs. When used alongside `make tags`
it can automate certain toilsome problems such as adding an include line
by typing `C-c C-h` with the cursor over a symbol. Please install these:
Your Cosmopolitan IDE is based on whichever editor you love most. Emacs
configs are provided, showing how `make tags` can be used to automate
certain toil, such as adding include lines by typing `C-c C-h` over a
symbol. We recommend trying the following:
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
sudo apt install gdb ragel ctags clang-format-10 # <-recommended
sudo apt install gdb ragel ctags clang-format-10
git clone git@github.com:jart/cosmopolitan.git && cd cosmopolitan
tool/scripts/install-emacs.sh # recommended over apt
tool/scripts/install-emacs.sh # Emacs 26.1 has a bug
tool/scripts/configure-emacs.sh # adds load statements
make tags # index all the symbol
emacs # for power and glory!
@ -95,10 +99,9 @@ should explain how easy it is to do pe+sh+elf+macho+bootloader overlays
enabling gnu ld.bfd to produce a simple portable 12kb .com program file
Please send feedback and concerns to <jtunney@gmail.com> since we would
love to do an even better job. Please also report GPL abuse the address
above as well. We believe this binary structure is novel, and therefore
easily recognizable. So if some goofball isn't bundling the source code
please let us know, so we can reach out and ask if they want a license.
love to do an even better job. Please also let us know if some goofball
is distributing without bundling their source code, so we can reach out
and ask if they would like to purchase a commercial license.
make -j10 -O MODE=tiny CPPFLAGS=-DIM_FEELING_NAUGHTY
o/tiny/tool/viz/bing.com <o/tiny/examples/life.com |
@ -244,6 +247,7 @@ Cosmopolitan is Free Software licensed under the GPLv2. The build config
**will embed all linked sources inside your binaries** so the compliance
is easy while facilitating trust and transparency similar to JavaScript.
You can audit your source filesystem using ZIP GUIs e.g. Win10, InfoZip.
That works easiest by changing the filename extension from .com to .zip.
### Commercial Support
@ -276,9 +280,9 @@ ideas, aside from taking care of low-level build system toil, so coding
can become more beautifully pleasant.
Cosmopolitan is maintained by Justine Tunney, who previously worked on
projects like TensorFlow, [Operation Rosehub], [Nomulus], and Google's
tape backups sre team. She's also helped radical activists by operating
the [Occupy Wall Street] website. Justine Tunney currently isn't on the
projects like [TensorFlow], [Operation Rosehub], [Nomulus], and Google's
tape backups SRE team. She's also helped activists by operating the
[Occupy Wall Street] website. Justine Tunney currently isn't on the
payroll of any company. She's been focusing on Cosmopolitan because she
wants to give back to Free Software which helped her be successful. See
her [LinkedIn] profile for further details on her professional history.
@ -288,6 +292,7 @@ her [LinkedIn] profile for further details on her professional history.
[Nomulus]: https://github.com/google/nomulus
[Occupy Wall Street]: https://www.newyorker.com/magazine/2011/11/28/pre-occupied
[Operation Rosehub]: https://opensource.googleblog.com/2017/03/operation-rosehub.html
[TensorFlow]: https://github.com/tensorflow/tensorflow
[ansitrinsics library]: libc/intrin
[ape/ape.lds]: ape/ape.lds
[dsp/scale/cdecimate2xuint8x8.c]: dsp/scale/cdecimate2xuint8x8.c
@ -297,6 +302,7 @@ her [LinkedIn] profile for further details on her professional history.
[libc/nexgen32e/x86feature.h]: libc/nexgen32e/x86feature.h
[libc/sysv/consts.sh]: libc/sysv/consts.sh
[libc/sysv/syscalls.sh]: libc/sysv/syscalls.sh
[third_party/xed/x86ild.greg.c]: third_party/xed/x86ild.greg.c
[tool/build/package.c]: tool/build/package.c
[tool/emacs/cosmo-stuff.el]: tool/emacs/cosmo-stuff.el
[tool/viz/lib/ycbcr2rgb3.c]: tool/viz/lib/ycbcr2rgb3.c

View File

@ -141,12 +141,37 @@ endif
# ANSI Mode
#
# Folks who want it deserve to get it, good and hard.
# These flags cause GCC to predefine __STRICT_ANSI__. Please be warned
# that Cosmopolitan headers are written to comply with that request if
# it's possible to do so. Consider the following example:
#
# make -j12 -O o//tool/viz/printvideo.i
# clang-format-10 -i o//tool/viz/printvideo.i
# less o//tool/viz/printvideo.i
#
# You'll notice functions like memcpy(), ioctl(), etc. get expanded into
# wild-eyed gnu-style performance hacks. You can turn it off as follows:
#
# make -j12 -O MODE=ansi o/ansi/tool/viz/printvideo.i
# clang-format-10 -i o/ansi/tool/viz/printvideo.i
# less o/ansi/tool/viz/printvideo.i
#
# Here it becomes clear that ANSI mode can help you decouple your source
# from Cosmopolitan, by turning it into plain ordinary textbook C code.
#
# Another potential use case is distributing code to folks using tools
# such as MSVC or XCode. You can run your binary objects through a tool
# like objconv to convert them to COFF or MachO. Then use ANSI mode to
# rollup one header file that'll enable linkage with minimal issues.
#
# Lastly note that in some cases, such as gc(), there simply isn't any
# ANSI workaround available. It's only in cases like that when we'll use
# the __asm__() header workaround, rather than simply removing it. We do
# however try to do that much less often than mainstream C libraries.
ifeq ($(MODE), ansi)
CONFIG_CCFLAGS += \
-std=c11 \
-Og
CONFIG_CFLAGS += -std=c11
CONFIG_CXXFLAGS += -std=c++11
endif

View File

@ -96,4 +96,3 @@ build/bootstrap/%.c.gz: %.rl
%.svgz: %.rl
@$(RAGEL) -V -p $< | $(DOT) -Tsvg | $(GZ) $(ZFLAGS) >$@
$(LIBC__A_SRCS:%=o/$(MODE)/%.zip.o) \

View File

@ -1,37 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/dce.h"
#include "libc/nt/dll.h"
#include "libc/nt/nt/process.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/exit.h"
int main() {
if (IsWindows()) {
/*
* Cosmopolitan imports this automatically if it's referenced the
* normal way. But Microsoft wants us to use loose coupling when
* referencing their internal APIs. Don't think for a moment they
* won't break open source projects that fail to heed the warning.
*/
typeof(NtTerminateProcess) *NtTerminateProcess_ =
GetProcAddress(GetModuleHandle("ntdll.dll"), "NtTerminateProcess");
printf("%ld\n", GetModuleHandle("ntdll.dll"));
printf("%p\n", NtTerminateProcess_);
if (NtTerminateProcess_) {
fflush(stdout);
for (;;) NtTerminateProcess_(-1, 42);
}
} else {
fprintf(stderr, "error: intended for windows\n");
}
return EXIT_FAILURE;
}

View File

@ -13,17 +13,14 @@ void *bsearch_r(const void *, const void *, size_t, size_t,
int cmp(const void *, const void *, void *), void *)
paramsnonnull((1, 2, 5)) nothrow nosideeffect;
void djbsort(size_t n, int32_t[n]);
void qsort(void *items, size_t itemcount, size_t itemsize,
int cmp(const void *, const void *)) paramsnonnull();
void qsort_r(void *items, size_t itemcount, size_t itemsize,
void qsort(void *, size_t, size_t, int (*)(const void *, const void *))
paramsnonnull();
void qsort_r(void *, size_t, size_t,
int cmp(const void *, const void *, void *), void *arg)
paramsnonnull((1, 4));
int tarjan(uint32_t vertex_count, const uint32_t (*edges)[2],
uint32_t edge_count, uint32_t out_sorted[],
uint32_t out_opt_components[], uint32_t *out_opt_componentcount)
paramsnonnull((2, 4)) nocallback nothrow;
void heapsortcar(int32_t (*A)[2], unsigned n)
paramsnonnull() nocallback nothrow;
int tarjan(uint32_t, const uint32_t (*)[2], uint32_t, uint32_t[], uint32_t[],
uint32_t *) paramsnonnull((2, 4)) nocallback nothrow;
void heapsortcar(int32_t (*)[2], unsigned) paramsnonnull() nocallback nothrow;
void *memmem(const void *, size_t, const void *, size_t)
paramsnonnull() nothrow nocallback nosideeffect;
@ -56,16 +53,16 @@ struct critbit0 {
size_t count;
};
bool critbit0_contains(struct critbit0 *t, const char *u) nothrow nosideeffect
bool critbit0_contains(struct critbit0 *, const char *) nothrow nosideeffect
paramsnonnull();
bool critbit0_insert(struct critbit0 *t, const char *u) paramsnonnull();
bool critbit0_delete(struct critbit0 *t, const char *u) nothrow paramsnonnull();
void critbit0_clear(struct critbit0 *t) nothrow paramsnonnull();
char *critbit0_get(struct critbit0 *t, const char *u);
intptr_t critbit0_allprefixed(struct critbit0 *t, const char *prefix,
intptr_t (*callback)(const char *elem, void *arg),
void *arg) paramsnonnull((1, 2, 3)) nothrow;
bool critbit0_emplace(struct critbit0 *t, char *u, size_t ulen) paramsnonnull();
bool critbit0_insert(struct critbit0 *, const char *) paramsnonnull();
bool critbit0_delete(struct critbit0 *, const char *) nothrow paramsnonnull();
void critbit0_clear(struct critbit0 *) nothrow paramsnonnull();
char *critbit0_get(struct critbit0 *, const char *);
intptr_t critbit0_allprefixed(struct critbit0 *, const char *,
intptr_t (*)(const char *, void *), void *)
paramsnonnull((1, 2, 3)) nothrow;
bool critbit0_emplace(struct critbit0 *, char *, size_t) paramsnonnull();
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § algorithms » comparators

View File

@ -76,6 +76,7 @@ static textwindows noinline DIR *opendir$nt(const char *name) {
*
* @returns newly allocated DIR object, or NULL w/ errno
* @errors ENOENT, ENOTDIR, EACCES, EMFILE, ENFILE, ENOMEM
* @see glob()
*/
DIR *opendir(const char *name) {
if (!IsWindows() && !IsXnu()) {

View File

@ -12,7 +12,7 @@ int ioctl(int, uint64_t, void *);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § system calls » input output control » undiamonding
*/
#ifdef __GNUC__
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#include "libc/macros.h"
#include "libc/sysv/consts/termios.h"
@ -46,7 +46,7 @@ forceinline int ioctl$dispatch(int fd, uint64_t request, void *memory) {
return ioctl$default(fd, request, memory);
}
#endif /* GNUC */
#endif /* GNUC && !ANSI */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_IOCTL_H_ */

View File

@ -28,8 +28,9 @@ int unlockpt(int);
int posix_openpt(int) nodiscard;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § teletypewriter » optimizations
cosmopolitan § teletypewriter » undiamonding
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define tcsetattr(FD, OPT, TIO) tcsetattr$dispatch(FD, OPT, TIO)
forceinline int tcsetattr$dispatch(int fd, int opt, const struct termios *tio) {
@ -44,6 +45,7 @@ forceinline int tcgetattr$dispatch(int fd, const struct termios *tio) {
return ioctl(fd, TCGETS, (void *)tio);
}
#endif /* GNUC && !ANSI */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_TERMIOS_H_ */

View File

@ -3,7 +3,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/**
* @fileoverview Types for scoundrels.
* @fileoverview Types we'd prefer hadn't been invented.
*/
#define blkcnt_t int64_t

View File

@ -49,7 +49,7 @@ aes_block_t unrijndael(uint32_t, aes_block_t, const struct Rijndael *);
aligned(64) extern const uint8_t kAesSbox[256];
aligned(64) extern const uint8_t kAesSboxInverse[256];
aes_block_t InvMixColumns(aes_block_t x) hidden;
aes_block_t InvMixColumns(aes_block_t) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -18,12 +18,10 @@ COSMOPOLITAN_C_START_
struct MappedFile;
Elf64_Ehdr *mapelfread(const char *filename, struct MappedFile *mf);
char *getelfstringtable(const Elf64_Ehdr *elf, size_t mapsize);
Elf64_Sym *getelfsymboltable(const Elf64_Ehdr *elf, size_t mapsize,
Elf64_Xword *out_count);
Elf64_Shdr *getelfsectionbyaddress(const Elf64_Ehdr *elf, size_t mapsize,
void *addr);
Elf64_Ehdr *mapelfread(const char *, struct MappedFile *);
char *getelfstringtable(const Elf64_Ehdr *, size_t);
Elf64_Sym *getelfsymboltable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
Elf64_Shdr *getelfsectionbyaddress(const Elf64_Ehdr *, size_t, void *);
forceinline void checkelfaddress(const Elf64_Ehdr *elf, size_t mapsize,
intptr_t addr, size_t addrsize) {
@ -66,8 +64,9 @@ static inline Elf64_Shdr *getelfsectionheaderaddress(const Elf64_Ehdr *elf,
static inline void *getelfsectionaddress(const Elf64_Ehdr *elf, size_t mapsize,
const Elf64_Shdr *shdr) {
intptr_t addr = (intptr_t)elf + (intptr_t)shdr->sh_offset;
intptr_t size = (intptr_t)shdr->sh_size;
intptr_t addr, size;
addr = (intptr_t)elf + (intptr_t)shdr->sh_offset;
size = (intptr_t)shdr->sh_size;
checkelfaddress(elf, mapsize, addr, size);
return (void *)addr;
}
@ -83,13 +82,16 @@ static inline void getelfvirtualaddressrange(const Elf64_Ehdr *elf,
size_t elfsize,
intptr_t *out_start,
intptr_t *out_end) {
intptr_t start = INTPTR_MAX;
intptr_t end = 0;
for (unsigned i = 0; i < elf->e_phnum; ++i) {
Elf64_Phdr *phdr = getelfsegmentheaderaddress(elf, elfsize, i);
unsigned i;
Elf64_Phdr *phdr;
intptr_t start, end, pstart, pend;
start = INTPTR_MAX;
end = 0;
for (i = 0; i < elf->e_phnum; ++i) {
phdr = getelfsegmentheaderaddress(elf, elfsize, i);
if (phdr->p_type != PT_LOAD) continue;
intptr_t pstart = phdr->p_vaddr;
intptr_t pend = phdr->p_vaddr + phdr->p_memsz;
pstart = phdr->p_vaddr;
pend = phdr->p_vaddr + phdr->p_memsz;
if (pstart < start) start = pstart;
if (pend > end) end = pend;
}

View File

@ -23,9 +23,10 @@
Elf64_Shdr *getelfsectionbyaddress(const Elf64_Ehdr *elf, size_t mapsize,
void *addr) {
Elf64_Half i;
Elf64_Shdr *shdr;
if (elf) {
for (i = elf->e_shnum; i > 0; --i) {
Elf64_Shdr *shdr = getelfsectionheaderaddress(elf, mapsize, i - 1);
shdr = getelfsectionheaderaddress(elf, mapsize, i - 1);
if ((intptr_t)addr >= shdr->sh_addr &&
(intptr_t)addr < shdr->sh_addr + shdr->sh_size) {
return shdr;

View File

@ -7,20 +7,15 @@ COSMOPOLITAN_C_START_
cosmopolitan § escaping
*/
unsigned cescapec(int c);
int escapec(char *buf, unsigned size, const char *unescaped, unsigned length)
unsigned cescapec(int);
int escapec(char *, unsigned, const char *, unsigned)
paramsnonnull((3)) nothrow nocallback;
int escapesh(char *buf, unsigned size, const char *unescaped, unsigned length)
paramsnonnull((3));
bool escapedos(char16_t *buffer, unsigned buflen, const char16_t *unquoted,
unsigned len);
int aescapec(char **escaped, const char *unescaped, unsigned length)
paramsnonnull();
int aescapesh(char **escaped, const char *unescaped, unsigned length)
paramsnonnull();
int aescape(char **escaped, size_t size, const char *unescaped, unsigned length,
int impl(char *escaped, unsigned size, const char *unescaped,
unsigned length)) hidden;
int escapesh(char *, unsigned, const char *, unsigned) paramsnonnull((3));
bool escapedos(char16_t *, unsigned, const char16_t *, unsigned);
int aescapec(char **, const char *, unsigned) paramsnonnull();
int aescapesh(char **, const char *, unsigned) paramsnonnull();
int aescape(char **, size_t, const char *, unsigned,
int (*)(char *, unsigned, const char *, unsigned)) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -20,11 +20,6 @@
#include "libc/escape/escape.h"
#include "libc/str/str.h"
asm(".ident\t\"\\n\\n\
NSSM (Public Domain)\\n\
Credit: Iain Patterson\n\
http://iain.cx/\"");
static textwindows bool shouldescapedos(const char16_t c) {
if (c == u'"') return true;
if (c == u'&') return true;
@ -48,6 +43,7 @@ static textwindows bool shouldquotedos(const char16_t c) {
/**
* Escapes command so DOS can run it.
* @see Iain Patterson's NSSM for original code in public domain
*/
textwindows bool escapedos(char16_t *buffer, unsigned buflen,
const char16_t *unquoted, unsigned len) {

View File

@ -170,138 +170,138 @@ kErrnoNames:
/ @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
.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

View File

@ -37,6 +37,12 @@
static const int kPow10[] = {1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000, 1000000000};
/**
* Formats floating point number.
*
* @see xdtoa() for higher precision at the cost of bloat
* @see palandprintf() which is intended caller
*/
int ftoa(int out(int, void *), void *arg, long double value, unsigned long prec,
unsigned long width, unsigned long flags) {
long whole, frac;

View File

@ -56,7 +56,52 @@ static unsigned ppatoi(const char **str) {
/**
* Implements {,v}{,s{,n},{,{,x}as},f,d}printf state machine.
* @see libc/stdio/printf.c for documentation
*
* Type Specifiers
*
* - `%s` char * (thompson-pike unicode)
* - `%ls` wchar_t * (32-bit unicode thompson-pike unicode)
* - `%hs` char16_t * (16-bit unicode thompson-pike unicode)
* - `%b` int (radix 2 binary)
* - `%o` int (radix 8 octal)
* - `%d` int (radix 10 decimal)
* - `%x` int (radix 16 hexadecimal)
* - `%X` int (radix 16 hexadecimal uppercase)
* - `%u` unsigned
* - `%f` double
* - `%Lf` long double
* - `%p` pointer (48-bit hexadecimal)
*
* Length Modifiers
*
* - `%hhd` char (8-bit)
* - `%hd` short (16-bit)
* - `%ld` long (64-bit)
* - `%lu` unsigned long (64-bit)
* - `%lx` unsigned long (64-bit hexadecimal)
* - `%jd` intmax_t (128-bit)
*
* Width Modifiers
*
* - `%08d` fixed columns w/ zero leftpadding
* - `%8d` fixed columns w/ space leftpadding
* - `%*s` variable column string (thompson-pike)
* - `%.*s` variable column data (ignore nul terminator)
*
* Formatting Modifiers
*
* - `%,d` thousands separators
* - `%'s` escaped c string literal
* - `%'c` escaped c character literal
* - `%`s` escaped double quoted c string literal
* - `%`c` escaped double quoted c character literal
* - `%+d` plus leftpad if positive (aligns w/ negatives)
* - `% d` space leftpad if positive (aligns w/ negatives)
* - `%#s` datum (radix 256 null-terminated ibm cp437)
* - `%#x` int (radix 16 hexadecimal w/ 0x prefix if not zero)
*
* @note implementation detail of printf(), snprintf(), etc.
* @see printf() for wordier documentation
*/
hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
int (*out)(int, void *);

View File

@ -50,8 +50,18 @@
#endif
#if defined(__GNUC__) && __GNUC__ < 6
/*
* Compilers don't understand the features we've added to the format
* string DSL, such as c string escaping, therefore we can't use it.
* Ideally compilers should grant us more flexibility to define DSLs
*
* The recommended approach to turning this back on is `CFLAGS=-std=c11`
* which puts the compiler in __STRICT_ANSI__ mode, which Cosmopolitan
* respects by disabling all the esoteric tuning in headers like this.
*/
#pragma GCC diagnostic ignored "-Wformat-security"
#endif /* __GNUC__ + 0 < 6 */
#else
#define PFLINK(FMT) FMT
#define SFLINK(FMT) FMT

View File

@ -25,7 +25,7 @@
* @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
* @see palandprintf() and printf() for detailed documentation
*/
int(snprintf)(char* buf, size_t count, const char* fmt, ...) {
int rc;

View File

@ -20,6 +20,12 @@
#include "libc/fmt/fmt.h"
#include "libc/limits.h"
/**
* Formats string to buffer that's hopefully large enough.
*
* @see palandprintf() and printf() for detailed documentation
* @see snprintf() for same w/ buf size param
*/
int(sprintf)(char *buf, const char *fmt, ...) {
int rc;
va_list va;

View File

@ -74,6 +74,8 @@ forceinline int emitquote(int out(int, void *), void *arg, unsigned flags,
* 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.
*
* @see palandprintf()
*/
int stoa(int out(int, void *), void *arg, void *data, unsigned long flags,
unsigned long precision, unsigned long width, unsigned char signbit,

View File

@ -34,6 +34,9 @@
* 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.
*
* - `%d` parses integer
* - `%ms` parses string allocating buffer assigning pointer
*
* @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

View File

@ -40,7 +40,7 @@ static int vsnprintfputchar(unsigned char c, struct SprintfStr *str) {
}
/**
* Formats string to buffer.
* Formats string to buffer w/ preexisting vararg state.
*
* @param buf stores output and a NUL-terminator is always written,
* provided buf!=NULL && size!=0
@ -50,7 +50,7 @@ static int vsnprintfputchar(unsigned char c, struct SprintfStr *str) {
* 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
* @see palandprintf() and printf() for detailed documentation
*/
int(vsnprintf)(char *buf, size_t size, const char *fmt, va_list va) {
struct SprintfStr str = {buf, 0, size};

View File

@ -20,6 +20,12 @@
#include "libc/fmt/fmt.h"
#include "libc/limits.h"
/**
* Formats string to buffer hopefully large enough w/ vararg state.
*
* @see palandprintf() and printf() for detailed documentation
* @see vsnprintf() for modern alternative w/ buf size param
*/
int(vsprintf)(char *buf, const char *fmt, va_list va) {
return (vsnprintf)(buf, INT_MAX, fmt, va);
}

View File

@ -21,7 +21,7 @@
#include "libc/fmt/vsscanf.h"
/**
* String decoder.
* Decodes string.
*
* @see libc/fmt/vcscanf.h (for docs and implementation)
* @note to offer the best performance, we assume small codebases

View File

@ -1015,8 +1015,9 @@ typedef uint64_t uintmax_t;
/**
* Pulls source of object being compiled into zip.
* @note automates compliance with gpl terms
* @see -DIM_FEELING_NAUGHTY
* @note automates most compliance with gpl terms
* @see libc/zipos/zipcentraldir.S
* @see ape/ape.lds
*/
#ifdef __BASE_FILE__
STATIC_YOINK_SOURCE(__BASE_FILE__);

View File

@ -50,8 +50,7 @@ void exit(int) noreturn;
void quick_exit(int) noreturn;
void _exit(int) libcesque noreturn;
void _Exit(int) libcesque noreturn;
void abort(void) noreturn noinstrument forcealignargpointer;
void abort_(void) asm("abort") noreturn noinstrument privileged;
void abort(void) noreturn noinstrument;
void panic(void) noreturn noinstrument privileged;
void triplf(void) noreturn noinstrument privileged;
int __cxa_atexit(void *, void *, void *) libcesque;

View File

@ -44,7 +44,7 @@ size_t fread(void *buf, size_t stride, size_t count, FILE *f) {
if (i % stride != 0) abort(); /* todo(jart) */
return i / stride;
}
p[i] = (unsigned char)c;
p[i] = c & 0xff;
}
return count;
}

View File

@ -12,13 +12,13 @@ extern unsigned char g_stderrbuf[BUFSIZ];
int fflushregister(FILE *) hidden;
void fflushunregister(FILE *) hidden;
int freadbuf(FILE *f) hidden;
int fwritebuf(FILE *f) hidden;
int fsreadbuf(FILE *f) hidden;
int fswritebuf(FILE *f) hidden;
long fseteof(FILE *f) hidden;
long fseterrno(FILE *f) hidden;
long fseterr(FILE *f, int err) hidden;
int freadbuf(FILE *) hidden;
int fwritebuf(FILE *) hidden;
int fsreadbuf(FILE *) hidden;
int fswritebuf(FILE *) hidden;
long fseteof(FILE *) hidden;
long fseterrno(FILE *) hidden;
long fseterr(FILE *, int) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -59,6 +59,7 @@
* it implies the quoting modifier, wraps the value with {,u,L}['"]
* quotes, displays NULL as "NULL" rather than "(null)", etc.
*
* @see palandprintf() for intuitive reference documentation
* @see {,v}{,s{,n},{,{,x}as},f,d}printf
*/
int(printf)(const char* fmt, ...) {

View File

@ -4,29 +4,29 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int getc_unlocked(FILE *f) paramsnonnull();
int getc_unlocked(FILE *) paramsnonnull();
int getchar_unlocked(void);
int putc_unlocked(int c, FILE *f) paramsnonnull();
int putchar_unlocked(int c);
void clearerr_unlocked(FILE *f);
int feof_unlocked(FILE *f);
int ferror_unlocked(FILE *f);
int fileno_unlocked(FILE *f);
int fflush_unlocked(FILE *f);
int fgetc_unlocked(FILE *f);
int fputc_unlocked(int c, FILE *f);
size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *f);
size_t fwrite_unlocked(const void *ptr, size_t size, size_t n, FILE *f);
char *fgets_unlocked(char *s, int n, FILE *f);
int fputs_unlocked(const char *s, FILE *f);
wint_t getwc_unlocked(FILE *f);
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 *f);
wint_t fputwc_unlocked(wchar_t wc, FILE *f);
wint_t putwc_unlocked(wchar_t wc, FILE *f);
wint_t putwchar_unlocked(wchar_t wc);
wchar_t *fgetws_unlocked(wchar_t *ws, int n, FILE *f);
int fputws_unlocked(const wchar_t *ws, FILE *f);
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) */

View File

@ -21,8 +21,10 @@
.source __FILE__
clearerr_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call clearerr
.leafepilogue
pop %rbp
ret
.endfn clearerr_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
feof_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call feof
.leafepilogue
pop %rbp
ret
.endfn feof_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
ferror_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call ferror
.leafepilogue
pop %rbp
ret
.endfn ferror_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fflush_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fflush
.leafepilogue
pop %rbp
ret
.endfn fflush_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fgetc_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fgetc
.leafepilogue
pop %rbp
ret
.endfn fgetc_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fgets_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fgets
.leafepilogue
pop %rbp
ret
.endfn fgets_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fgetwc_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fgetwc
.leafepilogue
pop %rbp
ret
.endfn fgetwc_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fgetws_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fgetws
.leafepilogue
pop %rbp
ret
.endfn fgetws_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fileno_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fileno
.leafepilogue
pop %rbp
ret
.endfn fileno_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fputc_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fputc
.leafepilogue
pop %rbp
ret
.endfn fputc_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fputs_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fputs
.leafepilogue
pop %rbp
ret
.endfn fputs_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fputwc_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fputwc
.leafepilogue
pop %rbp
ret
.endfn fputwc_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fputws_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fputws
.leafepilogue
pop %rbp
ret
.endfn fputws_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fread_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fread
.leafepilogue
pop %rbp
ret
.endfn fread_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
fwrite_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fwrite
.leafepilogue
pop %rbp
ret
.endfn fwrite_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
getc_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call getc
.leafepilogue
pop %rbp
ret
.endfn getc_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
getchar_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call getchar
.leafepilogue
pop %rbp
ret
.endfn getchar_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
getwc_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fgetwc_unlocked
.leafepilogue
pop %rbp
ret
.endfn getwc_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
getwchar_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call getwchar
.leafepilogue
pop %rbp
ret
.endfn getwchar_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
putc_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call putc
.leafepilogue
pop %rbp
ret
.endfn putc_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
putchar_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call putchar
.leafepilogue
pop %rbp
ret
.endfn putchar_unlocked,globl

View File

@ -21,8 +21,10 @@
.source __FILE__
putwc_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call fputwc_unlocked
.leafepilogue
pop %rbp
ret
.endfn putwc_unlocked,globl

View File

@ -22,8 +22,10 @@
.source __FILE__
putwchar_unlocked:
.leafprologue
.profilable # so we can fix code supporting this abomination
push %rbp
mov %rsp,%rbp
.profilable # note: no consensus for threads exists in abis
call putwchar
.leafepilogue
pop %rbp
ret
.endfn putwchar_unlocked,globl

View File

@ -1760,18 +1760,6 @@ syscon misc READ_POSITION 52 0 0 0 0
syscon misc READ_REVERSE 15 0 0 0 0
syscon misc READ_TOC 67 0 0 0 0
syscon glob GLOB_NOCHECK 0x10 0x10 0x10 0x10 0 # unix consensus
syscon glob GLOB_ABORTED 2 -2 -2 -2 0 # bsd consensus
syscon glob GLOB_APPEND 0x20 1 1 1 0 # bsd consensus
syscon glob GLOB_DOOFFS 8 2 2 2 0 # bsd consensus
syscon glob GLOB_ERR 1 4 4 4 0 # bsd consensus
syscon glob GLOB_MARK 2 8 8 8 0 # bsd consensus
syscon glob GLOB_NOMATCH 3 -3 -3 -3 0 # bsd consensus
syscon glob GLOB_NOSORT 4 0x20 0x20 0x20 0 # bsd consensus
syscon glob GLOB_NOSPACE 1 -1 -1 -1 0 # bsd consensus
syscon glob GLOB_NOSYS 4 -4 -4 -4 0 # bsd consensus
syscon glob GLOB_NOESCAPE 0x40 0x2000 0x2000 0x1000 0
# getpriority() / setpriority() magnums (a.k.a. nice)
#
# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD XENIX Commentary

View File

@ -1,34 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_GLOB_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_GLOB_H_
#include "libc/runtime/symbolic.h"
#define GLOB_ABORTED SYMBOLIC(GLOB_ABORTED)
#define GLOB_APPEND SYMBOLIC(GLOB_APPEND)
#define GLOB_DOOFFS SYMBOLIC(GLOB_DOOFFS)
#define GLOB_ERR SYMBOLIC(GLOB_ERR)
#define GLOB_MARK SYMBOLIC(GLOB_MARK)
#define GLOB_NOCHECK SYMBOLIC(GLOB_NOCHECK)
#define GLOB_NOESCAPE SYMBOLIC(GLOB_NOESCAPE)
#define GLOB_NOMATCH SYMBOLIC(GLOB_NOMATCH)
#define GLOB_NOSORT SYMBOLIC(GLOB_NOSORT)
#define GLOB_NOSPACE SYMBOLIC(GLOB_NOSPACE)
#define GLOB_NOSYS SYMBOLIC(GLOB_NOSYS)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
hidden extern const long GLOB_ABORTED;
hidden extern const long GLOB_APPEND;
hidden extern const long GLOB_DOOFFS;
hidden extern const long GLOB_ERR;
hidden extern const long GLOB_MARK;
hidden extern const long GLOB_NOCHECK;
hidden extern const long GLOB_NOESCAPE;
hidden extern const long GLOB_NOMATCH;
hidden extern const long GLOB_NOSORT;
hidden extern const long GLOB_NOSPACE;
hidden extern const long GLOB_NOSYS;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_GLOB_H_ */

View File

@ -60,6 +60,7 @@ void *xvalloc(size_t) attributeallocsize((1)) _XMALPG;
void *xmemalign(size_t, size_t) attributeallocalign((1))
attributeallocsize((2)) _XMAL;
char *xstrdup(const char *) _XPNN _XMAL;
char *xstrndup(const char *, size_t) _XPNN _XMAL;
char *xstrcat(const char *, ...) paramsnonnull((1)) nullterminated() _XMAL;
char *xstrmul(const char *, size_t) paramsnonnull((1)) _XMAL;
char *xinet_ntop(int, const void *) _XPNN _XMAL;

36
libc/x/xstrndup.c 100644
View 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/log/log.h"
#include "libc/mem/mem.h"
#include "libc/x/x.h"
/**
* Allocates new copy of string, with byte limit.
*
* @param s is a NUL-terminated byte string
* @param n if less than strlen(s) will truncate the string
* @return new string or NULL w/ errno
* @error ENOMEM
*/
char *xstrndup(const char *s, size_t n) {
void *res = strndup(s, n);
if (!res) die();
return res;
}

View File

@ -41,6 +41,7 @@ TEST(SUITE(sprintf), testCharacterCounting) {
TEST(SUITE(snprintf), testTableFlip) {
EXPECT_STREQ("Table flip ", Format("%-20ls", L"Table flip"));
EXPECT_STREQ("(╯°□°)╯︵ ┻━┻ ", Format("%-20ls", L"(╯°□°)╯︵ ┻━┻"));
EXPECT_STREQ("(╯°□°)╯︵ ┻━┻ ", Format("%-20hs", u"(╯°□°)╯︵ ┻━┻"));
EXPECT_STREQ("ちゃぶ台返し ", Format("%-20ls", L"ちゃぶ台返し"));
EXPECT_STREQ(" (╯°□°)╯︵ ┻━┻", Format("%20ls", L"(╯°□°)╯︵ ┻━┻"));
EXPECT_STREQ(" ちゃぶ台返し", Format("%20ls", L"ちゃぶ台返し"));

View File

@ -27,8 +27,8 @@
*
* It is demonstrated that our 3.5kb x86 parser supports all legal x86
* instruction set architectures and addressing modes since the 1970's,
* including the really complicated ones, e.g. avx512; or the unpopular
* ones, e.g. amd 3dnow.
* including the really sophisticated ones, e.g. avx512, as well as the
* less popular ones, e.g. 3dnow.
*/
TEST(x86ild, testSomeThingsNeverChange) {

View File

@ -7,11 +7,10 @@ struct avir1 {
void *p;
};
void avir1init(struct avir1 *self);
void avir1free(struct avir1 *self);
void avir1(struct avir1 *resizer, size_t dyn, size_t dxn, void *dst,
size_t dstsize, size_t syn, size_t sxn, size_t ssw, const void *src,
size_t srcsize);
void avir1init(struct avir1 *);
void avir1free(struct avir1 *);
void avir1(struct avir1 *, size_t, size_t, void *, size_t, size_t, size_t,
size_t, const void *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -20,6 +20,7 @@
#include "libc/bits/mmintrin.h"
#include "libc/bits/xmmintrin.h"
#include "libc/bits/xmmintrin.h"
#include "libc/bits/xmmintrin.h"
#include "libc/bits/emmintrin.h"
namespace avir {

368
third_party/musl/fnmatch.c vendored 100644
View File

@ -0,0 +1,368 @@
/*-*- 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
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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/limits.h"
#include "libc/str/str.h"
#include "third_party/musl/fnmatch.h"
/*
* An implementation of what I call the "Sea of Stars" algorithm for
* POSIX fnmatch(). The basic idea is that we factor the pattern into
* a head component (which we match first and can reject without ever
* measuring the length of the string), an optional tail component
* (which only exists if the pattern contains at least one star), and
* an optional "sea of stars", a set of star-separated components
* between the head and tail. After the head and tail matches have
* been removed from the input string, the components in the "sea of
* stars" are matched sequentially by searching for their first
* occurrence past the end of the previous match.
*
* - Rich Felker, April 2012
*/
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
#define END 0
#define UNMATCHABLE -2
#define BRACKET -3
#define QUESTION -4
#define STAR -5
static int FnmatchNextString(const char *str, size_t n, size_t *step) {
if (!n) {
*step = 0;
return 0;
}
if (str[0] >= 128U) {
wchar_t wc;
int k = mbtowc(&wc, str, n);
if (k < 0) {
*step = 1;
return -1;
}
*step = k;
return wc;
}
*step = 1;
return str[0];
}
static int FnmatchNextPattern(const char *pat, size_t m, size_t *step,
int flags) {
int esc = 0;
if (!m || !*pat) {
*step = 0;
return END;
}
*step = 1;
if (pat[0] == '\\' && pat[1] && !(flags & FNM_NOESCAPE)) {
*step = 2;
pat++;
esc = 1;
goto escaped;
}
if (pat[0] == '[') {
size_t k = 1;
if (k < m)
if (pat[k] == '^' || pat[k] == '!') k++;
if (k < m)
if (pat[k] == ']') k++;
for (; k < m && pat[k] && pat[k] != ']'; k++) {
if (k + 1 < m && pat[k + 1] && pat[k] == '[' &&
(pat[k + 1] == ':' || pat[k + 1] == '.' || pat[k + 1] == '=')) {
int z = pat[k + 1];
k += 2;
if (k < m && pat[k]) k++;
while (k < m && pat[k] && (pat[k - 1] != z || pat[k] != ']')) k++;
if (k == m || !pat[k]) break;
}
}
if (k == m || !pat[k]) {
*step = 1;
return '[';
}
*step = k + 1;
return BRACKET;
}
if (pat[0] == '*') return STAR;
if (pat[0] == '?') return QUESTION;
escaped:
if (pat[0] >= 128U) {
wchar_t wc;
int k = mbtowc(&wc, pat, m);
if (k < 0) {
*step = 0;
return UNMATCHABLE;
}
*step = k + esc;
return wc;
}
return pat[0];
}
static int FnmatchCaseFold(int k) {
int c = towupper(k);
return c == k ? towlower(k) : c;
}
static int FnmatchBracket(const char *p, int k, int kfold) {
wchar_t wc;
int inv = 0;
p++;
if (*p == '^' || *p == '!') {
inv = 1;
p++;
}
if (*p == ']') {
if (k == ']') return !inv;
p++;
} else if (*p == '-') {
if (k == '-') return !inv;
p++;
}
wc = p[-1];
for (; *p != ']'; p++) {
if (p[0] == '-' && p[1] != ']') {
wchar_t wc2;
int l = mbtowc(&wc2, p + 1, 4);
if (l < 0) return 0;
if (wc <= wc2)
if ((unsigned)k - wc <= wc2 - wc || (unsigned)kfold - wc <= wc2 - wc)
return !inv;
p += l - 1;
continue;
}
if (p[0] == '[' && (p[1] == ':' || p[1] == '.' || p[1] == '=')) {
const char *p0 = p + 2;
int z = p[1];
p += 3;
while (p[-1] != z || p[0] != ']') p++;
if (z == ':' && p - 1 - p0 < 16) {
char buf[16];
memcpy(buf, p0, p - 1 - p0);
buf[p - 1 - p0] = 0;
if (iswctype(k, wctype(buf)) || iswctype(kfold, wctype(buf)))
return !inv;
}
continue;
}
if (*p < 128U) {
wc = (unsigned char)*p;
} else {
int l = mbtowc(&wc, p, 4);
if (l < 0) return 0;
p += l - 1;
}
if (wc == k || wc == kfold) return !inv;
}
return inv;
}
static int FnmatchPerform(const char *pat, size_t m, const char *str, size_t n,
int flags) {
const char *p, *ptail, *endpat;
const char *s, *stail, *endstr;
size_t pinc, sinc, tailcnt = 0;
int c, k, kfold;
if (flags & FNM_PERIOD) {
if (*str == '.' && *pat != '.') {
return FNM_NOMATCH;
}
}
for (;;) {
switch ((c = FnmatchNextPattern(pat, m, &pinc, flags))) {
case UNMATCHABLE:
return FNM_NOMATCH;
case STAR:
pat++;
m--;
break;
default:
k = FnmatchNextString(str, n, &sinc);
if (k <= 0) return (c == END) ? 0 : FNM_NOMATCH;
str += sinc;
n -= sinc;
kfold = flags & FNM_CASEFOLD ? FnmatchCaseFold(k) : k;
if (c == BRACKET) {
if (!FnmatchBracket(pat, k, kfold)) return FNM_NOMATCH;
} else if (c != QUESTION && k != c && kfold != c) {
return FNM_NOMATCH;
}
pat += pinc;
m -= pinc;
continue;
}
break;
}
/* Compute real pat length if it was initially unknown/-1 */
m = strnlen(pat, m);
endpat = pat + m;
/* Find the last * in pat and count chars needed after it */
for (p = ptail = pat; p < endpat; p += pinc) {
switch (FnmatchNextPattern(p, endpat - p, &pinc, flags)) {
case UNMATCHABLE:
return FNM_NOMATCH;
case STAR:
tailcnt = 0;
ptail = p + 1;
break;
default:
tailcnt++;
break;
}
}
/* Past this point we need not check for UNMATCHABLE in pat,
* because all of pat has already been parsed once. */
/* Compute real str length if it was initially unknown/-1 */
n = strnlen(str, n);
endstr = str + n;
if (n < tailcnt) {
return FNM_NOMATCH;
}
/* Find the final tailcnt chars of str, accounting for UTF-8.
* On illegal sequences we may get it wrong, but in that case
* we necessarily have a matching failure anyway. */
for (s = endstr; s > str && tailcnt; tailcnt--) {
if (s[-1] < 128U || MB_CUR_MAX == 1) {
s--;
} else {
while ((unsigned char)*--s - 0x80U < 0x40 && s > str)
;
}
}
if (tailcnt) return FNM_NOMATCH;
stail = s;
/* Check that the pat and str tails match */
p = ptail;
for (;;) {
c = FnmatchNextPattern(p, endpat - p, &pinc, flags);
p += pinc;
if ((k = FnmatchNextString(s, endstr - s, &sinc)) <= 0) {
if (c != END) return FNM_NOMATCH;
break;
}
s += sinc;
kfold = flags & FNM_CASEFOLD ? FnmatchCaseFold(k) : k;
if (c == BRACKET) {
if (!FnmatchBracket(p - pinc, k, kfold)) return FNM_NOMATCH;
} else if (c != QUESTION && k != c && kfold != c) {
return FNM_NOMATCH;
}
}
/* We're all done with the tails now, so throw them out */
endstr = stail;
endpat = ptail;
/* Match pattern components until there are none left */
while (pat < endpat) {
p = pat;
s = str;
for (;;) {
c = FnmatchNextPattern(p, endpat - p, &pinc, flags);
p += pinc;
/* Encountering * completes/commits a component */
if (c == STAR) {
pat = p;
str = s;
break;
}
k = FnmatchNextString(s, endstr - s, &sinc);
if (!k) return FNM_NOMATCH;
kfold = flags & FNM_CASEFOLD ? FnmatchCaseFold(k) : k;
if (c == BRACKET) {
if (!FnmatchBracket(p - pinc, k, kfold)) break;
} else if (c != QUESTION && k != c && kfold != c) {
break;
}
s += sinc;
}
if (c == STAR) continue;
/* If we failed, advance str, by 1 char if it's a valid
* char, or past all invalid bytes otherwise. */
k = FnmatchNextString(str, endstr - str, &sinc);
if (k > 0) {
str += sinc;
} else {
str++;
while (FnmatchNextString(str, endstr - str, &sinc) < 0) {
str++;
}
}
}
return 0;
}
/**
* Matches filename.
*
* - `*` for wildcard
* - `?` for single character
* - `[abc]` to match character within set
* - `[!abc]` to match character not within set
* - `\*\?\[\]` for escaping above special syntax
*
* @see glob()
*/
int fnmatch(const char *pat, const char *str, int flags) {
const char *s, *p;
size_t inc;
int c;
if (flags & FNM_PATHNAME) {
for (;;) {
for (s = str; *s && *s != '/'; s++)
;
for (p = pat;
(c = FnmatchNextPattern(p, -1, &inc, flags)) != END && c != '/';
p += inc)
;
if (c != *s && (!*s || !(flags & FNM_LEADING_DIR))) return FNM_NOMATCH;
if (FnmatchPerform(pat, p - pat, str, s - str, flags)) return FNM_NOMATCH;
if (!c) return 0;
str = s + 1;
pat = p + inc;
}
} else if (flags & FNM_LEADING_DIR) {
for (s = str; *s; s++) {
if (*s != '/') continue;
if (!FnmatchPerform(pat, -1, str, s - str, flags)) return 0;
}
}
return FnmatchPerform(pat, -1, str, -1, flags);
}

20
third_party/musl/fnmatch.h vendored 100644
View File

@ -0,0 +1,20 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_REGEX_FNMATCH_H_
#define COSMOPOLITAN_THIRD_PARTY_REGEX_FNMATCH_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define FNM_PATHNAME 0x1
#define FNM_NOESCAPE 0x2
#define FNM_PERIOD 0x4
#define FNM_LEADING_DIR 0x8
#define FNM_CASEFOLD 0x10
#define FNM_FILE_NAME FNM_PATHNAME
#define FNM_NOMATCH 1
#define FNM_NOSYS (-1)
int fnmatch(const char *, const char *, int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_REGEX_FNMATCH_H_ */

320
third_party/musl/glob.c vendored 100644
View File

@ -0,0 +1,320 @@
/*-*- 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
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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/alg/alg.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/dt.h"
#include "third_party/musl/fnmatch.h"
#include "third_party/musl/glob.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
struct GlobList {
struct GlobList *next;
char name[];
};
static int AppendGlob(struct GlobList **tail, const char *name, size_t len,
int mark) {
struct GlobList *new;
if ((new = malloc(sizeof(struct GlobList) + len + 2))) {
(*tail)->next = new;
new->next = NULL;
memcpy(new->name, name, len + 1);
if (mark && len && name[len - 1] != '/') {
new->name[len] = '/';
new->name[len + 1] = 0;
}
*tail = new;
return 0;
} else {
return -1;
}
}
static int PerformGlob(char *buf, size_t pos, int type, char *pat, int flags,
int (*errfunc)(const char *path, int err),
struct GlobList **tail) {
DIR *dir;
size_t l;
char *p, *p2;
char saved_sep;
ptrdiff_t i, j;
struct stat st;
struct dirent *de;
int r, readerr, in_bracket, overflow, old_errno, fnm_flags;
/* If GLOB_MARK is unused, we don't care about type. */
if (!type && !(flags & GLOB_MARK)) type = DT_REG;
/* Special-case the remaining pattern being all slashes, in
* which case we can use caller-passed type if it's a dir. */
if (*pat && type != DT_DIR) type = 0;
while (pos + 1 < PATH_MAX && *pat == '/') {
buf[pos++] = *pat++;
}
/* Consume maximal [escaped-]literal prefix of pattern, copying
* and un-escaping it to the running buffer as we go. */
i = 0;
j = 0;
overflow = 0;
in_bracket = 0;
for (; pat[i] != '*' && pat[i] != '?' && (!in_bracket || pat[i] != ']');
i++) {
if (!pat[i]) {
if (overflow) return 0;
pat += i;
pos += j;
i = j = 0;
break;
} else if (pat[i] == '[') {
in_bracket = 1;
} else if (pat[i] == '\\' && !(flags & GLOB_NOESCAPE)) {
/* Backslashes inside a bracket are (at least by
* our interpretation) non-special, so if next
* char is ']' we have a complete expression. */
if (in_bracket && pat[i + 1] == ']') break;
/* Unpaired final backslash never matches. */
if (!pat[i + 1]) return 0;
i++;
}
if (pat[i] == '/') {
if (overflow) return 0;
in_bracket = 0;
pat += i + 1;
i = -1;
pos += j + 1;
j = -1;
}
/* Only store a character if it fits in the buffer, but if
* a potential bracket expression is open, the overflow
* must be remembered and handled later only if the bracket
* is unterminated (and thereby a literal), so as not to
* disallow long bracket expressions with short matches. */
if (pos + (j + 1) < PATH_MAX) {
buf[pos + j++] = pat[i];
} else if (in_bracket) {
overflow = 1;
} else {
return 0;
}
/* If we consume any new components, the caller-passed type
* or dummy type from above is no longer valid. */
type = 0;
}
buf[pos] = 0;
if (!*pat) {
/* If we consumed any components above, or if GLOB_MARK is
* requested and we don't yet know if the match is a dir,
* we must call stat to confirm the file exists and/or
* determine its type. */
if ((flags & GLOB_MARK) && type == DT_LNK) type = 0;
if (!type && stat(buf, &st)) {
if (errno != ENOENT && (errfunc(buf, errno) || (flags & GLOB_ERR))) {
return GLOB_ABORTED;
}
return 0;
}
if (!type && S_ISDIR(st.st_mode)) type = DT_DIR;
if (AppendGlob(tail, buf, pos, (flags & GLOB_MARK) && type == DT_DIR)) {
return GLOB_NOSPACE;
}
return 0;
}
p2 = strchr(pat, '/');
saved_sep = '/';
/* Check if the '/' was escaped and, if so, remove the escape char
* so that it will not be unpaired when passed to fnmatch. */
if (p2 && !(flags & GLOB_NOESCAPE)) {
for (p = p2; p > pat && p[-1] == '\\'; p--)
;
if ((p2 - p) % 2) {
p2--;
saved_sep = '\\';
}
}
dir = opendir(pos ? buf : ".");
if (!dir) {
if (errfunc(buf, errno) || (flags & GLOB_ERR)) return GLOB_ABORTED;
return 0;
}
old_errno = errno;
while (errno = 0, de = readdir(dir)) {
/* Quickly skip non-directories when there's pattern left. */
if (p2 && de->d_type && de->d_type != DT_DIR && de->d_type != DT_LNK) {
continue;
}
l = strlen(de->d_name);
if (l >= PATH_MAX - pos) continue;
if (p2) *p2 = 0;
fnm_flags = ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) |
((!(flags & GLOB_PERIOD)) ? FNM_PERIOD : 0);
if (fnmatch(pat, de->d_name, fnm_flags)) continue;
/* With GLOB_PERIOD don't allow matching . or .. unless fnmatch()
* would match them with FNM_PERIOD rules in effect. */
if (p2 && (flags & GLOB_PERIOD) && de->d_name[0] == '.' &&
(!de->d_name[1] || de->d_name[1] == '.' && !de->d_name[2]) &&
fnmatch(pat, de->d_name, fnm_flags | FNM_PERIOD)) {
continue;
}
memcpy(buf + pos, de->d_name, l + 1);
if (p2) *p2 = saved_sep;
r = PerformGlob(buf, pos + l, de->d_type, p2 ? p2 : "", flags, errfunc,
tail);
if (r) {
closedir(dir);
return r;
}
}
readerr = errno;
if (p2) *p2 = saved_sep;
closedir(dir);
if (readerr && (errfunc(buf, errno) || (flags & GLOB_ERR))) {
return GLOB_ABORTED;
}
errno = old_errno;
return 0;
}
static int IgnoreGlobError(const char *path, int err) {
return 0;
}
static void FreeGlobList(struct GlobList *head) {
struct GlobList *match, *next;
for (match = head->next; match; match = next) {
next = match->next;
free(match);
}
}
static int GlobPredicate(const void *a, const void *b) {
return strcmp(*(const char **)a, *(const char **)b);
}
/**
* Finds pathnames matching pattern.
*
* For example:
*
* glob_t g = {.gl_offs = 2};
* glob("*.*", GLOB_DOOFFS, NULL, &g);
* glob("../.*", GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
* g.gl_pathv[0] = "ls";
* g.gl_pathv[1] = "-l";
* execvp("ls", &g.gl_pathv[0]);
* globfree(g);
*
* @param pat can have star wildcard see fnmatch()
* @param g will receive matching entries and needs globfree()
* @return 0 on success or GLOB_NOMATCH, GLOB_NOSPACE on OOM, or
* GLOB_ABORTED on read error
*/
int glob(const char *pat, int flags, int errfunc(const char *path, int err),
glob_t *g) {
int error = 0;
size_t cnt, i;
char *p, **pathv, buf[PATH_MAX];
struct GlobList head = {.next = NULL}, *tail = &head;
size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
if (!errfunc) errfunc = IgnoreGlobError;
if (!(flags & GLOB_APPEND)) {
g->gl_offs = offs;
g->gl_pathc = 0;
g->gl_pathv = NULL;
}
if (*pat) {
char *p = strdup(pat);
if (!p) return GLOB_NOSPACE;
buf[0] = 0;
error = PerformGlob(buf, 0, 0, p, flags, errfunc, &tail);
free(p);
}
if (error == GLOB_NOSPACE) {
FreeGlobList(&head);
return error;
}
for (cnt = 0, tail = head.next; tail; tail = tail->next, cnt++)
;
if (!cnt) {
if (flags & GLOB_NOCHECK) {
tail = &head;
if (AppendGlob(&tail, pat, strlen(pat), 0)) {
return GLOB_NOSPACE;
}
cnt++;
} else
return GLOB_NOMATCH;
}
if (flags & GLOB_APPEND) {
pathv =
realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *));
if (!pathv) {
FreeGlobList(&head);
return GLOB_NOSPACE;
}
g->gl_pathv = pathv;
offs += g->gl_pathc;
} else {
g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *));
if (!g->gl_pathv) {
FreeGlobList(&head);
return GLOB_NOSPACE;
}
for (i = 0; i < offs; i++) {
g->gl_pathv[i] = NULL;
}
}
for (i = 0, tail = head.next; i < cnt; tail = tail->next, i++) {
g->gl_pathv[offs + i] = tail->name;
}
g->gl_pathv[offs + i] = NULL;
g->gl_pathc += cnt;
if (!(flags & GLOB_NOSORT)) {
qsort(g->gl_pathv + offs, cnt, sizeof(char *), GlobPredicate);
}
return error;
}
/**
* Frees entries allocated by glob().
*/
void globfree(glob_t *g) {
size_t i;
for (i = 0; i < g->gl_pathc; i++) {
free(g->gl_pathv[g->gl_offs + i] - offsetof(struct GlobList, name));
}
free(g->gl_pathv);
g->gl_pathc = 0;
g->gl_pathv = NULL;
}

36
third_party/musl/glob.h vendored 100644
View File

@ -0,0 +1,36 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_GLOB_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_GLOB_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define GLOB_ERR 0x01
#define GLOB_MARK 0x02
#define GLOB_NOSORT 0x04
#define GLOB_DOOFFS 0x08 /* reserves null slots at start of gl_pathv */
#define GLOB_NOCHECK 0x10 /* just yield pattern if GLOB_NOMATCH happens */
#define GLOB_APPEND 0x20 /* enables us to call glob() multiple times */
#define GLOB_NOESCAPE 0x40 /* don't allow things like \*\?\[\] escaping */
#define GLOB_PERIOD 0x80
#define GLOB_TILDE 0x1000
#define GLOB_TILDE_CHECK 0x4000
#define GLOB_NOSPACE 1
#define GLOB_ABORTED 2
#define GLOB_NOMATCH 3
#define GLOB_NOSYS 4
typedef struct {
size_t gl_pathc;
char **gl_pathv;
size_t gl_offs;
int __dummy1;
void *__dummy2[5];
} glob_t;
int glob(const char *, int, int (*)(const char *, int), glob_t *);
void globfree(glob_t *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_GLOB_H_ */

View File

@ -18,7 +18,9 @@ THIRD_PARTY_MUSL_A_OBJS = \
$(THIRD_PARTY_MUSL_A_SRCS:%.c=o/$(MODE)/%.o)
THIRD_PARTY_MUSL_A_DIRECTDEPS = \
LIBC_ALG \
LIBC_CALLS \
LIBC_CALLS_HEFTY \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_STDIO \

View File

@ -1,294 +0,0 @@
/*-*- 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│
╚─────────────────────────────────────────────────────────────────────────────*/
/* clang-format off */
/*
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#define _BSD_SOURCE
#include <dirent.h>
#include <errno.h>
#include <fnmatch.h>
#include <glob.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
asm(".ident\t\"\\n\\n\
Musl Libc » glob (MIT License)\\n\
Copyright 2005-2014 Rich Felker\"");
struct match
{
struct match *next;
char name[];
};
static int append(struct match **tail, const char *name, size_t len, int mark)
{
struct match *new = malloc(sizeof(struct match) + len + 2);
if (!new) return -1;
(*tail)->next = new;
new->next = NULL;
memcpy(new->name, name, len+1);
if (mark && len && name[len-1]!='/') {
new->name[len] = '/';
new->name[len+1] = 0;
}
*tail = new;
return 0;
}
static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (*errfunc)(const char *path, int err), struct match **tail)
{
/* If GLOB_MARK is unused, we don't care about type. */
if (!type && !(flags & GLOB_MARK)) type = DT_REG;
/* Special-case the remaining pattern being all slashes, in
* which case we can use caller-passed type if it's a dir. */
if (*pat && type!=DT_DIR) type = 0;
while (pos+1 < PATH_MAX && *pat=='/') buf[pos++] = *pat++;
/* Consume maximal [escaped-]literal prefix of pattern, copying
* and un-escaping it to the running buffer as we go. */
ptrdiff_t i=0, j=0;
int in_bracket = 0, overflow = 0;
for (; pat[i]!='*' && pat[i]!='?' && (!in_bracket || pat[i]!=']'); i++) {
if (!pat[i]) {
if (overflow) return 0;
pat += i;
pos += j;
i = j = 0;
break;
} else if (pat[i] == '[') {
in_bracket = 1;
} else if (pat[i] == '\\' && !(flags & GLOB_NOESCAPE)) {
/* Backslashes inside a bracket are (at least by
* our interpretation) non-special, so if next
* char is ']' we have a complete expression. */
if (in_bracket && pat[i+1]==']') break;
/* Unpaired final backslash never matches. */
if (!pat[i+1]) return 0;
i++;
}
if (pat[i] == '/') {
if (overflow) return 0;
in_bracket = 0;
pat += i+1;
i = -1;
pos += j+1;
j = -1;
}
/* Only store a character if it fits in the buffer, but if
* a potential bracket expression is open, the overflow
* must be remembered and handled later only if the bracket
* is unterminated (and thereby a literal), so as not to
* disallow long bracket expressions with short matches. */
if (pos+(j+1) < PATH_MAX) {
buf[pos+j++] = pat[i];
} else if (in_bracket) {
overflow = 1;
} else {
return 0;
}
/* If we consume any new components, the caller-passed type
* or dummy type from above is no longer valid. */
type = 0;
}
buf[pos] = 0;
if (!*pat) {
/* If we consumed any components above, or if GLOB_MARK is
* requested and we don't yet know if the match is a dir,
* we must call stat to confirm the file exists and/or
* determine its type. */
struct stat st;
if ((flags & GLOB_MARK) && type==DT_LNK) type = 0;
if (!type && stat(buf, &st)) {
if (errno!=ENOENT && (errfunc(buf, errno) || (flags & GLOB_ERR)))
return GLOB_ABORTED;
return 0;
}
if (!type && S_ISDIR(st.st_mode)) type = DT_DIR;
if (append(tail, buf, pos, (flags & GLOB_MARK) && type==DT_DIR))
return GLOB_NOSPACE;
return 0;
}
char *p2 = strchr(pat, '/'), saved_sep = '/';
/* Check if the '/' was escaped and, if so, remove the escape char
* so that it will not be unpaired when passed to fnmatch. */
if (p2 && !(flags & GLOB_NOESCAPE)) {
char *p;
for (p=p2; p>pat && p[-1]=='\\'; p--);
if ((p2-p)%2) {
p2--;
saved_sep = '\\';
}
}
DIR *dir = opendir(pos ? buf : ".");
if (!dir) {
if (errfunc(buf, errno) || (flags & GLOB_ERR))
return GLOB_ABORTED;
return 0;
}
int old_errno = errno;
struct dirent *de;
while (errno=0, de=readdir(dir)) {
/* Quickly skip non-directories when there's pattern left. */
if (p2 && de->d_type && de->d_type!=DT_DIR && de->d_type!=DT_LNK)
continue;
size_t l = strlen(de->d_name);
if (l >= PATH_MAX-pos) continue;
if (p2) *p2 = 0;
int fnm_flags= ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
| ((!(flags & GLOB_PERIOD)) ? FNM_PERIOD : 0);
if (fnmatch(pat, de->d_name, fnm_flags))
continue;
/* With GLOB_PERIOD, don't allow matching . or .. unless
* fnmatch would match them with FNM_PERIOD rules in effect. */
if (p2 && (flags & GLOB_PERIOD) && de->d_name[0]=='.'
&& (!de->d_name[1] || de->d_name[1]=='.' && !de->d_name[2])
&& fnmatch(pat, de->d_name, fnm_flags | FNM_PERIOD))
continue;
memcpy(buf+pos, de->d_name, l+1);
if (p2) *p2 = saved_sep;
int r = do_glob(buf, pos+l, de->d_type, p2 ? p2 : "", flags, errfunc, tail);
if (r) {
closedir(dir);
return r;
}
}
int readerr = errno;
if (p2) *p2 = saved_sep;
closedir(dir);
if (readerr && (errfunc(buf, errno) || (flags & GLOB_ERR)))
return GLOB_ABORTED;
errno = old_errno;
return 0;
}
static int ignore_err(const char *path, int err)
{
return 0;
}
static void freelist(struct match *head)
{
struct match *match, *next;
for (match=head->next; match; match=next) {
next = match->next;
free(match);
}
}
static int sort(const void *a, const void *b)
{
return strcmp(*(const char **)a, *(const char **)b);
}
int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, int err), glob_t *restrict g)
{
struct match head = { .next = NULL }, *tail = &head;
size_t cnt, i;
size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
int error = 0;
char buf[PATH_MAX];
if (!errfunc) errfunc = ignore_err;
if (!(flags & GLOB_APPEND)) {
g->gl_offs = offs;
g->gl_pathc = 0;
g->gl_pathv = NULL;
}
if (*pat) {
char *p = strdup(pat);
if (!p) return GLOB_NOSPACE;
buf[0] = 0;
error = do_glob(buf, 0, 0, p, flags, errfunc, &tail);
free(p);
}
if (error == GLOB_NOSPACE) {
freelist(&head);
return error;
}
for (cnt=0, tail=head.next; tail; tail=tail->next, cnt++);
if (!cnt) {
if (flags & GLOB_NOCHECK) {
tail = &head;
if (append(&tail, pat, strlen(pat), 0))
return GLOB_NOSPACE;
cnt++;
} else
return GLOB_NOMATCH;
}
if (flags & GLOB_APPEND) {
char **pathv = realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *));
if (!pathv) {
freelist(&head);
return GLOB_NOSPACE;
}
g->gl_pathv = pathv;
offs += g->gl_pathc;
} else {
g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *));
if (!g->gl_pathv) {
freelist(&head);
return GLOB_NOSPACE;
}
for (i=0; i<offs; i++)
g->gl_pathv[i] = NULL;
}
for (i=0, tail=head.next; i<cnt; tail=tail->next, i++)
g->gl_pathv[offs + i] = tail->name;
g->gl_pathv[offs + i] = NULL;
g->gl_pathc += cnt;
if (!(flags & GLOB_NOSORT))
qsort(g->gl_pathv+offs, cnt, sizeof(char *), sort);
return error;
}
void globfree(glob_t *g)
{
size_t i;
for (i=0; i<g->gl_pathc; i++)
free(g->gl_pathv[g->gl_offs + i] - offsetof(struct match, name));
free(g->gl_pathv);
g->gl_pathc = 0;
g->gl_pathv = NULL;
}

View File

@ -1229,7 +1229,7 @@ privileged static void xed_decode_instruction_length(
*
* @return d->decoded_length is byte length, or 1 w/ error code
* @note binary footprint increases ~4kb if this is used
* @see cf. biggest thing in tensorflow, gdb, clang, etc. binaries
* @see biggest code in gdb/clang/tensorflow binaries
*/
privileged enum XedError xed_instruction_length_decode(
struct XedDecodedInst *xedd, const uint8_t *itext, const size_t bytes) {

View File

@ -1,25 +1,25 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2018 Intel Corporation
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. │
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
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.
http://www.apache.org/licenses/LICENSE-2.0
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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "libc/macros.h"
/ Phash tables for instruction length decoding.
/ @see build/rle.py for more context here
.initbss 300,_init_x86tab
xed_prefix_table_bit:

View File

@ -7,7 +7,7 @@
#
# DESCRIPTION
#
# See test/libc/x86ild_test.c for more information.
# See test/libc/xed/x86ild_test.c for more information.
PKGS += THIRD_PARTY_XED

31
tool/build/summy.c 100644
View File

@ -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
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/stdio/stdio.h"
/**
* @fileoverview Sums per-line integers from stdin.
*/
int main(int argc, char *argv[]) {
long x, sum = 0;
while (scanf("%ld", &x) > 0) sum += x;
printf("%,ld\n", sum);
return 0;
}

View File

@ -62,6 +62,7 @@
char *symbol_;
char *outpath_;
char *yoink_;
const size_t kMinCompressSize = 32;
const char kNoCompressExts[][8] = {".gz", ".xz", ".jpg", ".png",
@ -70,13 +71,14 @@ const char kNoCompressExts[][8] = {".gz", ".xz", ".jpg", ".png",
noreturn void PrintUsage(int rc, FILE *f) {
fprintf(f, "%s%s%s\n", "Usage: ", program_invocation_name,
" [-o FILE] [-s SYMBOL] [FILE...]\n");
" [-o FILE] [-s SYMBOL] [-y YOINK] [FILE...]\n");
exit(rc);
}
void GetOpts(int *argc, char ***argv) {
int opt;
while ((opt = getopt(*argc, *argv, "?ho:s:")) != -1) {
yoink_ = "__zip_start";
while ((opt = getopt(*argc, *argv, "?ho:s:y:")) != -1) {
switch (opt) {
case 'o':
outpath_ = optarg;
@ -84,6 +86,9 @@ void GetOpts(int *argc, char ***argv) {
case 's':
symbol_ = optarg;
break;
case 'y':
yoink_ = optarg;
break;
case '?':
case 'h':
PrintUsage(EXIT_SUCCESS, stdout);
@ -273,8 +278,7 @@ void PullEndOfCentralDirectoryIntoLinkage(struct ElfWriter *elf) {
elfwriter_align(elf, 1, 0);
elfwriter_startsection(elf, ".yoink", SHT_PROGBITS,
SHF_ALLOC | SHF_EXECINSTR);
elfwriter_yoink(elf, "__zip_start");
elfwriter_yoink(elf, "__zip_end");
elfwriter_yoink(elf, yoink_);
elfwriter_finishsection(elf);
}

View File

@ -337,4 +337,10 @@
(add-hook 'asm-mode-hook 'cosmo-asm-supplemental-hook)
(setq asm-font-lock-keywords cosmo-asm-font-lock-keywords))
;; Make -*-unix-assembly-*- mode line work correctly.
;; TODO(jart): Would be nice to use GitHub's name instead of changing asm-mode.
(defun unix-assembly-mode ()
(interactive)
(asm-mode))
(provide 'cosmo-asm-mode)

View File

@ -6,7 +6,7 @@ sudo apt build-dep emacs
cd "$HOME"
export CFLAGS="-O2"
rm -rf emacs-26.3
wget http://mirrors.kernel.org/gnu/emacs/emacs-26.3.tar.gz
wget https://mirrors.kernel.org/gnu/emacs/emacs-26.3.tar.gz
tar xf emacs-26.3.tar.gz
cd emacs-26.3
./configure