Initial import

This commit is contained in:
Justine Tunney 2020-06-15 07:18:57 -07:00
commit c91b3c5006
14915 changed files with 590219 additions and 0 deletions

8
libc/mem/alloca.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_MEM_ALLOCA_H_
#define COSMOPOLITAN_LIBC_MEM_ALLOCA_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define alloca(size) __builtin_alloca(size)
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_MEM_ALLOCA_H_ */

38
libc/mem/asprintf.c Normal file
View 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/mem/mem.h"
/**
* Formats string, allocating needed memory.
*
* @param *strp is output-only and must be free'd, even on error; this
* behavior was adopted to help put your needs first in terms of
* portability, since that's guaranteed to work with all libraries
* @return bytes written (excluding NUL) or -1 w/ errno
* @see xasprintf() for a better API
*/
int(asprintf)(char **strp, const char *fmt, ...) {
int res;
va_list va;
va_start(va, fmt);
res = (vasprintf)(strp, fmt, va);
va_end(va);
return res;
}

34
libc/mem/calloc-hook.S Normal file
View file

@ -0,0 +1,34 @@
/*-*- 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/macros.h"
.yoink __FILE__
.initbss 800,_init_calloc
hook$calloc:
.quad 0
.endobj hook$calloc,globl,hidden
.previous
.init.start 800,_init_calloc
.hidden dlcalloc
ezlea dlcalloc,ax
stosq
yoink free
.init.end 800,_init_calloc

32
libc/mem/calloc.S Normal file
View file

@ -0,0 +1,32 @@
/*-*- 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/macros.h"
#include "libc/notice.inc"
.yoink __FILE__
/ Allocates n * itemsize bytes, initialized to zero.
/
/ @param rdi is number of items (n)
/ @param rsi is size of each item (itemsize)
/ @return rax is memory address, or NULL w/ errno
/ @note overreliance on memalign is a sure way to fragment space
/ @see dlcalloc()
calloc: jmp *hook$calloc(%rip)
.endfn calloc,globl

59
libc/mem/free-cxx.S Normal file
View file

@ -0,0 +1,59 @@
/*-*- 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/macros.h"
.yoink __FILE__
/ Frees memory the C++ way.
/
/ @param %rdi is pointer, or NULL for no-op
/ @param %rsi is ignored
/ @param %rdx is ignored
_ZdlPvSt11align_val_tRKSt9nothrow_t:
nop
_ZdaPvSt11align_val_tRKSt9nothrow_t:
nop
_ZdlPvRKSt9nothrow_t:
nop
_ZdaPvRKSt9nothrow_t:
nop
_ZdlPvmSt11align_val_t:
nop
_ZdaPvmSt11align_val_t:
nop
_ZdlPvSt11align_val_t:
nop
_ZdaPvSt11align_val_t:
nop
_ZdaPvm:nop
_ZdlPvm:nop
_ZdaPv: nop
_ZdlPv: jmp *hook$free(%rip)
.endfn _ZdlPv,globl,weak
.endfn _ZdaPv,globl,weak
.endfn _ZdaPvm,globl,weak
.endfn _ZdlPvm,globl,weak
.endfn _ZdaPvRKSt9nothrow_t,globl,weak
.endfn _ZdlPvRKSt9nothrow_t,globl,weak
.endfn _ZdaPvSt11align_val_t,globl,weak
.endfn _ZdlPvSt11align_val_t,globl,weak
.endfn _ZdaPvmSt11align_val_t,globl,weak
.endfn _ZdlPvmSt11align_val_t,globl,weak
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,globl,weak
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,globl,weak

35
libc/mem/free-hook.S Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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/macros.h"
.yoink __FILE__
.initbss 800,_init_free
hook$free:
.quad 0
.endobj hook$free,globl,hidden
.previous
.init.start 800,_init_free
ezlea dlfree,ax
stosq
yoink realloc
.init.end 800,_init_free
.hidden dlfree

34
libc/mem/free.S Normal file
View file

@ -0,0 +1,34 @@
/*-*- 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/macros.h"
.yoink __FILE__
/ Free memory returned by malloc() & co.
/
/ Releases the chunk of memory pointed to by p, that had been
/ previously allocated using malloc or a related routine such as
/ realloc. It has no effect if p is null. If p was not malloced or
/ already freed, free(p) will by default cuase the current program to
/ abort.
/
/ @param rdi is allocation address, which may be NULL
/ @see dlfree()
free: jmp *hook$free(%rip)
.endfn free,globl

10
libc/mem/internal.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef COSMOPOLITAN_LIBC_MEM_INTERNAL_H_
#define COSMOPOLITAN_LIBC_MEM_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int PutEnvImpl(char *string, bool overwrite) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_MEM_INTERNAL_H_ */

40
libc/mem/malloc-cxx.S Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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/macros.h"
.yoink __FILE__
/ Allocates memory the C++ way.
/
/ @param %rdi is bytes to allocate
/ @param %rsi is ignored
/ @return new memory or NULL on OOM
_ZnamRKSt9nothrow_t:
nop
_ZnwmRKSt9nothrow_t:
nop
_Znam: nop
_Znwm: test %rdi,%rdi
jne 1f
mov $1,%edi
1: jmp *hook$malloc(%rip)
.endfn _Znwm,globl,weak
.endfn _Znam,globl,weak
.endfn _ZnwmRKSt9nothrow_t,globl,weak
.endfn _ZnamRKSt9nothrow_t,globl,weak

35
libc/mem/malloc-hook.S Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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/macros.h"
.yoink __FILE__
.initbss 800,_init_malloc
hook$malloc:
.quad 0
.endobj hook$malloc,globl,hidden
.previous
.init.start 800,_init_malloc
ezlea dlmalloc,ax
stosq
yoink free
.init.end 800,_init_malloc
.hidden dlmalloc

42
libc/mem/malloc.S Normal file
View file

@ -0,0 +1,42 @@
/*-*- 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/macros.h"
.yoink __FILE__
/ Allocates uninitialized memory.
/
/ Returns a pointer to a newly allocated chunk of at least n bytes, or
/ null if no space is available, in which case errno is set to ENOMEM
/ on ANSI C systems.
/
/ If n is zero, malloc returns a minimum-sized chunk. (The minimum size
/ is 32 bytes on 64bit systems.) Note that size_t is an unsigned type,
/ so calls with arguments that would be negative if signed are
/ interpreted as requests for huge amounts of space, which will often
/ fail. The maximum supported value of n differs across systems, but is
/ in all cases less than the maximum representable value of a size_t.
/
/ @param rdi is number of bytes needed
/ @return new memory, or NULL w/ errno
/ @note malloc(0) → malloc(32)
/ @see dlmalloc()
malloc: jmp *hook$malloc(%rip)
.endfn malloc,globl

View file

@ -0,0 +1,53 @@
/*-*- 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/macros.h"
#include "libc/notice.inc"
.yoink __FILE__
/ Returns the number of bytes you can actually use in
/ an allocated chunk, which may be more than you requested
/ (although often not) due to alignment and minimum size
/ constraints.
/
/ You can use this many bytes without worrying about overwriting
/ other allocated objects. This is not a particularly great
/ programming practice. malloc_usable_size can be more useful in
/ debugging and assertions, for example:
/
/ p = malloc(n)
/ assert(malloc_usable_size(p) >= 256)
/
/ @param rdi is address of allocation
/ @return rax is total number of bytes
/ @see dlmalloc_usable_size()
malloc_usable_size:
jmp *hook$malloc_usable_size(%rip)
.endfn malloc_usable_size,globl
.initbss 800,_init_malloc_usable_size
hook$malloc_usable_size:
.quad 0
.endobj hook$malloc_usable_size,globl,hidden
.previous
.init.start 800,_init_malloc_usable_size
ezlea dlmalloc_usable_size,ax
stosq
.init.end 800,_init_malloc_usable_size

77
libc/mem/mem.h Normal file
View file

@ -0,0 +1,77 @@
#ifndef COSMOPOLITAN_LIBC_MEM_MEM_H_
#define COSMOPOLITAN_LIBC_MEM_MEM_H_
#include "libc/fmt/pflink.h"
#define M_TRIM_THRESHOLD (-1)
#define M_GRANULARITY (-2)
#define M_MMAP_THRESHOLD (-3)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § dynamic memory
*/
void free(void *) libcesque;
void *malloc(size_t) attributeallocsize((1)) mallocesque;
void *calloc(size_t, size_t) attributeallocsize((1, 2)) mallocesque;
void *memalign(size_t, size_t) attributeallocalign((1))
attributeallocsize((2)) mallocesque;
void *realloc(void *, size_t) reallocesque;
void *realloc_in_place(void *, size_t);
bool grow(void *, size_t *, size_t, size_t) paramsnonnull((1, 2)) libcesque;
void *reallocarray(void *, size_t, size_t) nodiscard;
void *valloc(size_t) attributeallocsize((1)) vallocesque;
void *pvalloc(size_t) attributeallocsize((1)) mallocesque;
char *strdup(const char *) paramsnonnull() mallocesque;
char *strndup(const char *, size_t) paramsnonnull()
attributeallocsize((2)) mallocesque;
int posix_memalign(void **, size_t, size_t); /* wut */
int malloc_trim(size_t);
size_t bulk_free(void **, size_t);
size_t malloc_usable_size(const void *);
void **independent_calloc(size_t, size_t, void **);
void **independent_comalloc(size_t, size_t *, void **);
int asprintf(char **, const char *, ...) printfesque(2)
paramsnonnull((1, 2)) libcesque;
int vasprintf(char **, const char *, va_list) paramsnonnull() libcesque;
wchar_t *wcsdup(const wchar_t *) strlenesque nodiscard;
struct mallinfo {
size_t arena; /* non-mmapped space allocated from system */
size_t ordblks; /* number of free chunks */
size_t smblks; /* always 0 */
size_t hblks; /* always 0 */
size_t hblkhd; /* space in mmapped regions */
size_t usmblks; /* maximum total allocated space */
size_t fsmblks; /* always 0 */
size_t uordblks; /* total allocated space */
size_t fordblks; /* total free space */
size_t keepcost; /* releasable (via malloc_trim) space */
};
struct mallinfo mallinfo(void);
void malloc_stats(void);
bool32 mallopt(int, int);
size_t malloc_footprint(void);
size_t malloc_max_footprint(void);
size_t malloc_footprint_limit(void);
size_t malloc_set_footprint_limit(size_t);
void malloc_inspect_all(void (*handler)(void *, void *, size_t, void *),
void *);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § dynamic memory » optimizations
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define asprintf(SP, FMT, ...) (asprintf)(SP, PFLINK(FMT), ##__VA_ARGS__)
#define vasprintf(SP, FMT, VA) (vasprintf)(SP, PFLINK(FMT), VA)
#endif
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_MEM_MEM_H_ */

59
libc/mem/mem.mk Normal file
View file

@ -0,0 +1,59 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
PKGS += LIBC_MEM
LIBC_MEM_ARTIFACTS += LIBC_MEM_A
LIBC_MEM = $(LIBC_MEM_A_DEPS) $(LIBC_MEM_A)
LIBC_MEM_A = o/$(MODE)/libc/mem/mem.a
LIBC_MEM_A_FILES := $(wildcard libc/mem/*)
LIBC_MEM_A_HDRS = $(filter %.h,$(LIBC_MEM_A_FILES))
LIBC_MEM_A_SRCS_S = $(filter %.S,$(LIBC_MEM_A_FILES))
LIBC_MEM_A_SRCS_C = $(filter %.c,$(LIBC_MEM_A_FILES))
LIBC_MEM_A_SRCS = \
$(LIBC_MEM_A_SRCS_S) \
$(LIBC_MEM_A_SRCS_C)
LIBC_MEM_A_OBJS = \
$(LIBC_MEM_A_SRCS:%=o/$(MODE)/%.zip.o) \
$(LIBC_MEM_A_SRCS_S:%.S=o/$(MODE)/%.o) \
$(LIBC_MEM_A_SRCS_C:%.c=o/$(MODE)/%.o)
LIBC_MEM_A_CHECKS = \
$(LIBC_MEM_A).pkg \
$(LIBC_MEM_A_HDRS:%=o/$(MODE)/%.ok)
LIBC_MEM_A_DIRECTDEPS = \
LIBC_STR \
LIBC_FMT \
LIBC_RAND \
LIBC_STUBS \
LIBC_CALLS \
LIBC_RUNTIME \
LIBC_NEXGEN32E \
LIBC_SYSV \
THIRD_PARTY_DLMALLOC
LIBC_MEM_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_MEM_A_DIRECTDEPS),$($(x))))
$(LIBC_MEM_A): libc/mem/ \
$(LIBC_MEM_A).pkg \
$(LIBC_MEM_A_OBJS)
$(LIBC_MEM_A).pkg: \
$(LIBC_MEM_A_OBJS) \
$(foreach x,$(LIBC_MEM_A_DIRECTDEPS),$($(x)_A).pkg)
LIBC_MEM_LIBS = $(foreach x,$(LIBC_MEM_ARTIFACTS),$($(x)))
LIBC_MEM_SRCS = $(foreach x,$(LIBC_MEM_ARTIFACTS),$($(x)_SRCS))
LIBC_MEM_HDRS = $(foreach x,$(LIBC_MEM_ARTIFACTS),$($(x)_HDRS))
LIBC_MEM_BINS = $(foreach x,$(LIBC_MEM_ARTIFACTS),$($(x)_BINS))
LIBC_MEM_CHECKS = $(foreach x,$(LIBC_MEM_ARTIFACTS),$($(x)_CHECKS))
LIBC_MEM_OBJS = $(foreach x,$(LIBC_MEM_ARTIFACTS),$($(x)_OBJS))
LIBC_MEM_TESTS = $(foreach x,$(LIBC_MEM_ARTIFACTS),$($(x)_TESTS))
$(LIBC_MEM_OBJS): $(BUILD_FILES) libc/mem/mem.mk
.PHONY: o/$(MODE)/libc/mem
o/$(MODE)/libc/mem: $(LIBC_MEM_CHECKS)

47
libc/mem/memalign-cxx.S Normal file
View file

@ -0,0 +1,47 @@
/*-*- 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/macros.h"
.yoink __FILE__
/ Allocates aligned memory the C++ way.
/
/ @param %rdi is bytes to allocate
/ @param %rsi is byte alignment
/ @param %rdx is ignored
/ @return new memory or NULL on OOM
_ZnamSt11align_val_tRKSt9nothrow_t:
nop
_ZnwmSt11align_val_tRKSt9nothrow_t:
nop
_ZnwmSt11align_val_t:
nop
_ZnamSt11align_val_t:
test %rdi,%rdi
jnz 1f
mov $1,%eax
1: mov $__BIGGEST_ALIGNMENT__,%eax
cmp %rax,%rsi
cmovb %rax,%rsi
xchg %rdi,%rsi
jmp *hook$memalign(%rip)
.endfn _ZnwmSt11align_val_t,globl,weak
.endfn _ZnamSt11align_val_t,globl,weak
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,globl,weak
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,globl,weak

35
libc/mem/memalign-hook.S Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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/macros.h"
.yoink __FILE__
.initbss 800,_init_memalign
hook$memalign:
.quad 0
.endobj hook$memalign,globl,hidden
.previous
.init.start 800,_init_memalign
ezlea dlmemalign,ax
stosq
yoink free
.init.end 800,_init_memalign
.hidden dlmemalign

40
libc/mem/memalign.S Normal file
View file

@ -0,0 +1,40 @@
/*-*- 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/macros.h"
#include "libc/notice.inc"
.yoink __FILE__
/ Allocates aligned memory.
/
/ Returns a pointer to a newly allocated chunk of n bytes, aligned in
/ accord with the alignment argument. The alignment argument should be
/ a power of two. If the argument is not a power of two, the nearest
/ greater power is used. 8-byte alignment is guaranteed by normal
/ malloc calls, so don't bother calling memalign with an argument of 8
/ or less.
/
/ @param rdi is alignment in bytes
/ @param rsi (newsize) is number of bytes needed
/ @return rax is memory address, or NULL w/ errno
/ @note overreliance on memalign is a sure way to fragment space
/ @see dlmemalign()
memalign:
jmp *hook$memalign(%rip)
.endfn memalign,globl

51
libc/mem/posix_memalign.S Normal file
View file

@ -0,0 +1,51 @@
/*-*- 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/macros.h"
.yoink __FILE__
/ Allocates aligned memory the POSIX way.
/
/ Allocates a chunk of n bytes, aligned in accord with the alignment
/ argument. Differs from memalign only in that it (1) assigns the
/ allocated memory to *pp rather than returning it, (2) fails and
/ returns EINVAL if the alignment is not a power of two (3) fails and
/ returns ENOMEM if memory cannot be allocated.
/
/ @param rdi is void **pp
/ @param rsi is size_t align
/ @param rdx is size_t size
/ @return eax
posix_memalign:
jmp *hook$posix_memalign(%rip)
.endfn posix_memalign,globl
.initbss 800,_init_posix_memalign
hook$posix_memalign:
.quad 0
.endobj hook$posix_memalign,globl,hidden
.previous
.init.start 800,_init_posix_memalign
.hidden dlposix_memalign
ezlea dlposix_memalign,ax
stosq
.init.end 800,_init_posix_memalign
yoink free

76
libc/mem/putenv.c Normal file
View file

@ -0,0 +1,76 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
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/mem/internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
static size_t g_environcap;
int PutEnvImpl(char *string, bool overwrite) {
if (!environ) {
g_environcap = 0;
if ((environ = calloc(8, sizeof(char *)))) {
g_environcap = 8;
}
}
char *equalp = strchr(string, '=');
if (!equalp) return einval();
unsigned namelen = equalp + 1 - string;
unsigned i;
for (i = 0; environ[i]; ++i) {
if (strncmp(environ[i], string, namelen) == 0) {
if (!overwrite) {
free_s(&string);
return 0;
}
goto replace;
}
}
if (i + 1 >= g_environcap) {
if (!g_environcap) g_environcap = i + 1;
if (!grow(&environ, &g_environcap, sizeof(char *), 0)) {
free_s(&string);
return -1;
}
}
environ[i + 1] = NULL;
replace:
free_s(&environ[i]);
environ[i] = string;
return 0;
}
/**
* Emplaces environment key=value.
* @see setenv(), getenv()
*/
int putenv(char *string) { return PutEnvImpl(string, true); }
textexit static void putenv_fini(void) {
for (char **envp = environ; *envp; ++envp) free_s(envp);
free_s(&environ);
}
textstartup static void putenv_init(void) { atexit(putenv_fini); }
const void *const putenv_ctor[] initarray = {putenv_init};

45
libc/mem/pvalloc.S Normal file
View file

@ -0,0 +1,45 @@
/*-*- 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/macros.h"
#include "libc/notice.inc"
.yoink __FILE__
/ Equivalent to valloc(minimum-page-that-holds(n)), that is,
/ round up n to nearest PAGESIZE.
/
/ @param rdi is number of bytes needed
/ @return rax is memory address, or NULL w/ errno
/ @see dlpvalloc()
pvalloc:jmp *hook$pvalloc(%rip)
.endfn pvalloc,globl
.initbss 800,_init_pvalloc
hook$pvalloc:
.quad 0
.endobj hook$pvalloc,globl,hidden
.previous
.init.start 800,_init_pvalloc
.hidden dlpvalloc
ezlea dlpvalloc,ax
stosq
.init.end 800,_init_pvalloc
yoink free

34
libc/mem/realloc-hook.S Normal file
View file

@ -0,0 +1,34 @@
/*-*- 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/macros.h"
.yoink __FILE__
.initbss 800,_init_realloc
hook$realloc:
.quad 0
.endobj hook$realloc,globl,hidden
.previous
.init.start 800,_init_realloc
.hidden dlrealloc
ezlea dlrealloc,ax
stosq
yoink free
.init.end 800,_init_realloc

59
libc/mem/realloc.S Normal file
View file

@ -0,0 +1,59 @@
/*-*- 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/macros.h"
#include "libc/notice.inc"
.yoink __FILE__
/ Allocates / resizes / frees memory, e.g.
/
/ Returns a pointer to a chunk of size n that contains the same data as
/ does chunk p up to the minimum of (n, p's size) bytes, or null if no
/ space is available.
/
/ If p is NULL, realloc is equivalent to malloc.
/ If p is not NULL and n is 0, realloc is equivalent to free.
/
/ The returned pointer may or may not be the same as p. The algorithm
/ prefers extending p in most cases when possible, otherwise it employs
/ the equivalent of a malloc-copy-free sequence.
/
/ Please note that p is NOT free()'d should realloc() fail, thus:
/
/ if ((p2 = realloc(p, n2))) {
/ p = p2;
/ ...
/ } else {
/ ...
/ }
/
/ if n is for fewer bytes than already held by p, the newly unused
/ space is lopped off and freed if possible.
/
/ The old unix realloc convention of allowing the last-free'd chunk to
/ be used as an argument to realloc is not supported.
/
/ @param rdi (p) is address of current allocation or NULL
/ @param rsi (n) is number of bytes needed
/ @return rax is result, or NULL w/ errno w/o free(p)
/ @note realloc(p=0, n=0) → malloc(32)
/ @note realloc(p≠0, n=0) → free(p)
/ @see dlrealloc()
realloc:jmp *hook$realloc(%rip)
.endfn realloc,globl

View file

@ -0,0 +1,53 @@
/*-*- 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/macros.h"
#include "libc/notice.inc"
.yoink __FILE__
/ Resizes the space allocated for p to size n, only if this can be
/ done without moving p (i.e., only if there is adjacent space
/ available if n is greater than p's current allocated size, or n is
/ less than or equal to p's size). This may be used instead of plain
/ realloc if an alternative allocation strategy is needed upon failure
/ to expand space, for example, reallocation of a buffer that must be
/ memory-aligned or cleared. You can use realloc_in_place to trigger
/ these alternatives only when needed.
/
/ @param rdi (p) is address of current allocation
/ @param rsi (newsize) is number of bytes needed
/ @return rax is result, or NULL w/ errno
/ @see dlrealloc_in_place()
realloc_in_place:
jmp *hook$realloc_in_place(%rip)
.endfn realloc_in_place,globl
.initbss 800,_init_realloc_in_place
hook$realloc_in_place:
.quad 0
.endobj hook$realloc_in_place,globl,hidden
.previous
.init.start 800,_init_realloc_in_place
.hidden dlrealloc_in_place
ezlea dlrealloc_in_place,ax
stosq
.init.end 800,_init_realloc_in_place
yoink free

35
libc/mem/reallocarray.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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/conv/sizemultiply.h"
#include "libc/mem/mem.h"
/**
* Manages array memory, the BSD way.
*
* @param ptr may be NULL for malloc() behavior
* @param nmemb may be 0 for free() behavior; shrinking is promised too
* @return new address or NULL w/ errno and ptr is NOT free()'d
*/
void *reallocarray(void *ptr, size_t nmemb, size_t itemsize) {
size_t newsize;
sizemultiply(&newsize, nmemb, itemsize); /* punts error */
return realloc(ptr, newsize);
}

37
libc/mem/setenv.c Normal file
View 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/mem/internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
/**
* Copies variable to environment.
*
* @return 0 on success, or -1 w/ errno
* @see putenv(), getenv()
*/
int setenv(const char *name, const char *value, int overwrite) {
size_t namelen = strlen(name);
size_t valuelen = strlen(value);
char *s = malloc(namelen + valuelen + 2);
memcpy(mempcpy(mempcpy(s, name, namelen), "=", 1), value, valuelen + 1);
return PutEnvImpl(s, overwrite);
}

34
libc/mem/strdup.c Normal file
View file

@ -0,0 +1,34 @@
/*-*- 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
*/
#include "libc/mem/mem.h"
#include "libc/str/str.h"
/**
* Allocates new copy of string.
*
* @param s is a NUL-terminated byte string
* @return new string or NULL w/ errno
* @error ENOMEM
*/
char *strdup(const char *s) {
size_t len = strlen(s);
char *s2 = malloc(len + 1);
return s2 ? memcpy(s2, s, len + 1) : NULL;
}

40
libc/mem/strndup.c Normal file
View file

@ -0,0 +1,40 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=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
*/
#include "libc/mem/mem.h"
#include "libc/str/str.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 *strndup(const char *s, size_t n) {
char *s2;
size_t len = strnlen(s, n);
if ((s2 = malloc(len + 1))) {
memcpy(s2, s, len);
s2[len] = '\0';
return s2;
}
return s2;
}

29
libc/mem/unhexstr.c Normal file
View 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/assert.h"
#include "libc/fmt/bing.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
nodiscard void *unhexstr(const char *hexdigs) {
assert(strlen(hexdigs) % 2 == 0);
return unhexbuf(memalign(__BIGGEST_ALIGNMENT__, strlen(hexdigs) / 2),
strlen(hexdigs), hexdigs);
}

44
libc/mem/valloc.S Normal file
View file

@ -0,0 +1,44 @@
/*-*- 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/macros.h"
#include "libc/notice.inc"
.yoink __FILE__
/ Equivalent to memalign(PAGESIZE, n).
/
/ @param rdi is number of bytes needed
/ @return rax is memory address, or NULL w/ errno
/ @see dlvalloc()
valloc: jmp *hook$valloc(%rip)
.endfn valloc,globl
.initbss 800,_init_valloc
hook$valloc:
.quad 0
.endobj hook$valloc,globl,hidden
.previous
.init.start 800,_init_valloc
.hidden dlvalloc
ezlea dlvalloc,ax
stosq
.init.end 800,_init_valloc
yoink free

57
libc/mem/vasprintf.c Normal file
View file

@ -0,0 +1,57 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 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/fmt.h"
#include "libc/mem/mem.h"
/**
* Formats string w/ dynamic memory allocation.
*
* @param *strp is output-only and must be free'd, even on error; since
* that's the behavior that'll make your code most portable
* @return complete bytes written (excluding NUL) or -1 w/ errno
* @see xasprintf() for a better API
*/
int(vasprintf)(char **strp, const char *fmt, va_list va) {
/**
* This implementation guarantees the smallest possible allocation,
* using an optimistic approach w/o changing asymptotic complexity.
*/
size_t size = 32;
if ((*strp = malloc(size))) {
va_list va2;
va_copy(va2, va);
int wrote = (vsnprintf)(*strp, size, fmt, va);
if (wrote == -1) return -1;
if (wrote <= size - 1) {
return wrote;
} else {
size = wrote + 1;
char *buf2 = realloc(*strp, size);
if (buf2) {
*strp = buf2;
wrote = (vsnprintf)(*strp, size, fmt, va2);
assert(wrote == size - 1);
return wrote;
}
}
}
return -1;
}

27
libc/mem/wcsdup.c Normal file
View file

@ -0,0 +1,27 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
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/mem/mem.h"
#include "libc/str/str.h"
wchar_t *wcsdup(const wchar_t *s) {
size_t len = wcslen(s);
char *s2 = malloc(len * sizeof(wchar_t) + 1);
return s2 ? memcpy(s2, s, len * sizeof(wchar_t) + 1) : NULL;
}