From adcad5d80c2462d0c8a665b5b57473494790b4a2 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Thu, 30 Mar 2023 19:04:46 +0300 Subject: [PATCH 01/10] Makefile.regen: prepare for additional targets Adjust the whitespace in the target definition, to avoid the need for spurious -/+ to realign when adding additional targets. --- Makefile.regen | 148 +++++++++++++++++++++++++------------------------ 1 file changed, 75 insertions(+), 73 deletions(-) diff --git a/Makefile.regen b/Makefile.regen index 8af26fa..7fbe7e0 100644 --- a/Makefile.regen +++ b/Makefile.regen @@ -1,78 +1,80 @@ .PHONY: distcheck -VERSION = 0.3.12 -COMPATS = compat_err.c \ - compat_b64_ntop.c \ - compat_explicit_bzero.c \ - compat_fts.c \ - compat_getprogname.c \ - compat_md5.c \ - compat_memmem.c \ - compat_memrchr.c \ - compat_mkfifoat.c \ - compat_mknodat.c \ - compat_readpassphrase.c \ - compat_reallocarray.c \ - compat_recallocarray.c \ - compat_scan_scaled.c \ - compat_setresgid.c \ - compat_setresuid.c \ - compat_sha2.c \ - compat_strlcat.c \ - compat_strlcpy.c \ - compat_strndup.c \ - compat_strnlen.c \ - compat_strtonum.c -TESTS = test-__progname.c \ - test-arc4random.c \ - test-b64_ntop.c \ - test-capsicum.c \ - test-crypt.c \ - test-crypt_newhash.c \ - test-endian_h.c \ - test-err.c \ - test-explicit_bzero.c \ - test-fts.c \ - test-getexecname.c \ - test-getprogname.c \ - test-INFTIM.c \ - test-landlock.c \ - test-lib_socket.c \ - test-md5.c \ - test-memmem.c \ - test-memrchr.c \ - test-memset_s.c \ - test-mkfifoat.c \ - test-mknodat.c \ - test-osbyteorder_h.c \ - test-PATH_MAX.c \ - test-pledge.c \ - test-program_invocation_short_name.c \ - test-readpassphrase.c \ - test-reallocarray.c \ - test-recallocarray.c \ - test-sandbox_init.c \ - test-scan_scaled.c \ - test-seccomp_filter.c \ - test-setresgid.c \ - test-setresuid.c \ - test-sha2.c \ - test-SOCK_NONBLOCK.c \ - test-static.c \ - test-strlcat.c \ - test-strlcpy.c \ - test-strndup.c \ - test-strnlen.c \ - test-strtonum.c \ - test-sys_byteorder_h.c \ - test-sys_endian_h.c \ - test-sys_mkdev_h.c \ - test-sys_queue.c \ - test-sys_sysmacros_h.c \ - test-sys_tree.c \ - test-termios.c \ - test-unveil.c \ - test-WAIT_ANY.c +VERSION = 0.3.12 +COMPATS = \ + compat_err.c \ + compat_b64_ntop.c \ + compat_explicit_bzero.c \ + compat_fts.c \ + compat_getprogname.c \ + compat_md5.c \ + compat_memmem.c \ + compat_memrchr.c \ + compat_mkfifoat.c \ + compat_mknodat.c \ + compat_readpassphrase.c \ + compat_reallocarray.c \ + compat_recallocarray.c \ + compat_scan_scaled.c \ + compat_setresgid.c \ + compat_setresuid.c \ + compat_sha2.c \ + compat_strlcat.c \ + compat_strlcpy.c \ + compat_strndup.c \ + compat_strnlen.c \ + compat_strtonum.c +TESTS = \ + test-__progname.c \ + test-arc4random.c \ + test-b64_ntop.c \ + test-capsicum.c \ + test-crypt.c \ + test-crypt_newhash.c \ + test-endian_h.c \ + test-err.c \ + test-explicit_bzero.c \ + test-fts.c \ + test-getexecname.c \ + test-getprogname.c \ + test-INFTIM.c \ + test-landlock.c \ + test-lib_socket.c \ + test-md5.c \ + test-memmem.c \ + test-memrchr.c \ + test-memset_s.c \ + test-mkfifoat.c \ + test-mknodat.c \ + test-osbyteorder_h.c \ + test-PATH_MAX.c \ + test-pledge.c \ + test-program_invocation_short_name.c \ + test-readpassphrase.c \ + test-reallocarray.c \ + test-recallocarray.c \ + test-sandbox_init.c \ + test-scan_scaled.c \ + test-seccomp_filter.c \ + test-setresgid.c \ + test-setresuid.c \ + test-sha2.c \ + test-SOCK_NONBLOCK.c \ + test-static.c \ + test-strlcat.c \ + test-strlcpy.c \ + test-strndup.c \ + test-strnlen.c \ + test-strtonum.c \ + test-sys_byteorder_h.c \ + test-sys_endian_h.c \ + test-sys_mkdev_h.c \ + test-sys_queue.c \ + test-sys_sysmacros_h.c \ + test-sys_tree.c \ + test-termios.c \ + test-unveil.c \ + test-WAIT_ANY.c all: compats.c tests.c configure From 9f2dd8da69817a540f3e26215ca0de6ccb09ca9f Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Sun, 14 Nov 2021 16:27:42 +0200 Subject: [PATCH 02/10] Initial stab at moving headers to compats.h configure currently has a lot of ${HAVE_...} -eq 0 ] if blocks, printing out header code for compats.c, to config.h. This is a lot of repetition, does not allow for splitting the code up properly, and makes the configure code a bit less maintainable. Introduce instead a "compats.h" that should now be included by downstreams, alongside compats.c. Also, add Makefile.regen code to generate said file from the different compat_*.h parts, in the same way compats.c is generated. --- Makefile.regen | 38 ++++- README.md | 1 + compat_b64_ntop.h | 5 + compat_err.h | 15 ++ compat_explicit_bzero.h | 4 + compat_fts.h | 78 +++++++++ compat_getprogname.h | 4 + compat_md5.h | 19 +++ compat_memmem.h | 4 + compat_memrchr.h | 4 + compat_mkfifoat.h | 4 + compat_mknodat.h | 4 + compat_readpassphrase.h | 11 ++ compat_reallocarray.h | 4 + compat_recallocarray.h | 4 + compat_scan_scaled.h | 6 + compat_setresgid.h | 4 + compat_setresuid.h | 4 + compat_sha2.h | 57 +++++++ compat_strlcat.h | 4 + compat_strlcpy.h | 4 + compat_strndup.h | 4 + compat_strnlen.h | 4 + compat_strtonum.h | 4 + compats.h | 295 +++++++++++++++++++++++++++++++++ configure | 359 +--------------------------------------- configure.in | 359 +--------------------------------------- 27 files changed, 589 insertions(+), 714 deletions(-) create mode 100644 compat_b64_ntop.h create mode 100644 compat_err.h create mode 100644 compat_explicit_bzero.h create mode 100644 compat_fts.h create mode 100644 compat_getprogname.h create mode 100644 compat_md5.h create mode 100644 compat_memmem.h create mode 100644 compat_memrchr.h create mode 100644 compat_mkfifoat.h create mode 100644 compat_mknodat.h create mode 100644 compat_readpassphrase.h create mode 100644 compat_reallocarray.h create mode 100644 compat_recallocarray.h create mode 100644 compat_scan_scaled.h create mode 100644 compat_setresgid.h create mode 100644 compat_setresuid.h create mode 100644 compat_sha2.h create mode 100644 compat_strlcat.h create mode 100644 compat_strlcpy.h create mode 100644 compat_strndup.h create mode 100644 compat_strnlen.h create mode 100644 compat_strtonum.h create mode 100644 compats.h diff --git a/Makefile.regen b/Makefile.regen index 7fbe7e0..e73991d 100644 --- a/Makefile.regen +++ b/Makefile.regen @@ -24,6 +24,29 @@ COMPATS = \ compat_strndup.c \ compat_strnlen.c \ compat_strtonum.c +COMPATS_H = \ + compat_err.h \ + compat_b64_ntop.h \ + compat_explicit_bzero.h \ + compat_fts.h \ + compat_getprogname.h \ + compat_md5.h \ + compat_memmem.h \ + compat_memrchr.h \ + compat_mkfifoat.h \ + compat_mknodat.h \ + compat_readpassphrase.h \ + compat_reallocarray.h \ + compat_recallocarray.h \ + compat_scan_scaled.h \ + compat_setresgid.h \ + compat_setresuid.h \ + compat_sha2.h \ + compat_strlcat.h \ + compat_strlcpy.h \ + compat_strndup.h \ + compat_strnlen.h \ + compat_strtonum.h TESTS = \ test-__progname.c \ test-arc4random.c \ @@ -76,7 +99,7 @@ TESTS = \ test-unveil.c \ test-WAIT_ANY.c -all: compats.c tests.c configure +all: compats.c compats.h tests.c configure distcheck: grep "^## $(VERSION)$$" versions.md >/dev/null @@ -104,6 +127,17 @@ compats.c: $(COMPATS) Makefile.regen echo "#endif /* !HAVE_$${up} */" ; \ done >>$@ +compats.h: $(COMPATS_H) Makefile.regen + echo -n >$@ + for f in $(COMPATS_H) ; \ + do \ + ff="`echo $$f | sed -e 's!\.h$$!!' -e 's!^compat_!!'`" ; \ + up="`echo $$ff | tr '[:lower:]' '[:upper:]'`" ; \ + echo "#if !HAVE_$${up}" ; \ + cat "$$f" ; \ + echo "#endif /* !HAVE_$${up} */" ; \ + done >>$@ + tests.c: $(TESTS) Makefile.regen for f in $(TESTS) ; \ do \ @@ -115,4 +149,4 @@ tests.c: $(TESTS) Makefile.regen done >$@ clean: - rm -f configure compats.c tests.c + rm -f configure compats.c compats.h tests.c diff --git a/README.md b/README.md index 83ab3d9..52d62ce 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ To use (tl;dr edition): 1. copy [configure](https://raw.githubusercontent.com/kristapsdz/oconfigure/master/configure), [compats.c](https://raw.githubusercontent.com/kristapsdz/oconfigure/master/compats.c), +[compats.h](https://raw.githubusercontent.com/kristapsdz/oconfigure/master/compats.h), and [tests.c](https://raw.githubusercontent.com/kristapsdz/oconfigure/master/tests.c) into your source tree diff --git a/compat_b64_ntop.h b/compat_b64_ntop.h new file mode 100644 index 0000000..062c0fe --- /dev/null +++ b/compat_b64_ntop.h @@ -0,0 +1,5 @@ +/* + * Compatibility for b64_ntop(3). + */ +extern int b64_ntop(unsigned char const *, size_t, char *, size_t); +extern int b64_pton(char const *, unsigned char *, size_t); diff --git a/compat_err.h b/compat_err.h new file mode 100644 index 0000000..2a1850d --- /dev/null +++ b/compat_err.h @@ -0,0 +1,15 @@ +/* + * Compatibility functions for err(3). + */ +extern void err(int, const char *, ...) __attribute__((noreturn)); +extern void errc(int, int, const char *, ...) __attribute__((noreturn)); +extern void errx(int, const char *, ...) __attribute__((noreturn)); +extern void verr(int, const char *, va_list) __attribute__((noreturn)); +extern void verrc(int, int, const char *, va_list) __attribute__((noreturn)); +extern void verrx(int, const char *, va_list) __attribute__((noreturn)); +extern void warn(const char *, ...); +extern void warnx(const char *, ...); +extern void warnc(int, const char *, ...); +extern void vwarn(const char *, va_list); +extern void vwarnc(int, const char *, va_list); +extern void vwarnx(const char *, va_list); diff --git a/compat_explicit_bzero.h b/compat_explicit_bzero.h new file mode 100644 index 0000000..d458637 --- /dev/null +++ b/compat_explicit_bzero.h @@ -0,0 +1,4 @@ +/* + * Compatibility for explicit_bzero(3). + */ +extern void explicit_bzero(void *, size_t); diff --git a/compat_fts.h b/compat_fts.h new file mode 100644 index 0000000..abf34f5 --- /dev/null +++ b/compat_fts.h @@ -0,0 +1,78 @@ +/* + * Compatibility for fts(3) functions. + */ +typedef struct { + struct _ftsent *fts_cur; /* current node */ + struct _ftsent *fts_child; /* linked list of children */ + struct _ftsent **fts_array; /* sort array */ + dev_t fts_dev; /* starting device # */ + char *fts_path; /* path for this descent */ + int fts_rfd; /* fd for root */ + size_t fts_pathlen; /* sizeof(path) */ + int fts_nitems; /* elements in the sort array */ + int (*fts_compar)(const struct _ftsent **, const struct _ftsent **); /* compare function */ +#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ +#define FTS_LOGICAL 0x0002 /* logical walk */ +#define FTS_NOCHDIR 0x0004 /* don't change directories */ +#define FTS_NOSTAT 0x0008 /* don't get stat info */ +#define FTS_PHYSICAL 0x0010 /* physical walk */ +#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ +#define FTS_XDEV 0x0040 /* don't cross devices */ +#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ +#define FTS_NAMEONLY 0x1000 /* (private) child names only */ +#define FTS_STOP 0x2000 /* (private) unrecoverable error */ + int fts_options; /* fts_open options, global flags */ +} FTS; + +typedef struct _ftsent { + struct _ftsent *fts_cycle; /* cycle node */ + struct _ftsent *fts_parent; /* parent directory */ + struct _ftsent *fts_link; /* next file in directory */ + long fts_number; /* local numeric value */ + void *fts_pointer; /* local address value */ + char *fts_accpath; /* access path */ + char *fts_path; /* root path */ + int fts_errno; /* errno for this node */ + int fts_symfd; /* fd for symlink */ + size_t fts_pathlen; /* strlen(fts_path) */ + size_t fts_namelen; /* strlen(fts_name) */ + ino_t fts_ino; /* inode */ + dev_t fts_dev; /* device */ + nlink_t fts_nlink; /* link count */ +#define FTS_ROOTPARENTLEVEL -1 +#define FTS_ROOTLEVEL 0 +#define FTS_MAXLEVEL 0x7fffffff + int fts_level; /* depth (-1 to N) */ +#define FTS_D 1 /* preorder directory */ +#define FTS_DC 2 /* directory that causes cycles */ +#define FTS_DEFAULT 3 /* none of the above */ +#define FTS_DNR 4 /* unreadable directory */ +#define FTS_DOT 5 /* dot or dot-dot */ +#define FTS_DP 6 /* postorder directory */ +#define FTS_ERR 7 /* error; errno is set */ +#define FTS_F 8 /* regular file */ +#define FTS_INIT 9 /* initialized only */ +#define FTS_NS 10 /* stat(2) failed */ +#define FTS_NSOK 11 /* no stat(2) requested */ +#define FTS_SL 12 /* symbolic link */ +#define FTS_SLNONE 13 /* symbolic link without target */ + unsigned short fts_info; /* user flags for FTSENT structure */ +#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ +#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ + unsigned short fts_flags; /* private flags for FTSENT structure */ +#define FTS_AGAIN 1 /* read node again */ +#define FTS_FOLLOW 2 /* follow symbolic link */ +#define FTS_NOINSTR 3 /* no instructions */ +#define FTS_SKIP 4 /* discard node */ + unsigned short fts_instr; /* fts_set() instructions */ + unsigned short fts_spare; /* unused */ + struct stat *fts_statp; /* stat(2) information */ + char fts_name[1]; /* file name */ +} FTSENT; + +FTSENT *fts_children(FTS *, int); +int fts_close(FTS *); +FTS *fts_open(char * const *, int, + int (*)(const FTSENT **, const FTSENT **)); +FTSENT *fts_read(FTS *); +int fts_set(FTS *, FTSENT *, int); diff --git a/compat_getprogname.h b/compat_getprogname.h new file mode 100644 index 0000000..e931185 --- /dev/null +++ b/compat_getprogname.h @@ -0,0 +1,4 @@ +/* + * Compatibility for getprogname(3). + */ +extern const char *getprogname(void); diff --git a/compat_md5.h b/compat_md5.h new file mode 100644 index 0000000..592df2c --- /dev/null +++ b/compat_md5.h @@ -0,0 +1,19 @@ +/* + * Compatibility for md4(3). + */ +#define MD5_BLOCK_LENGTH 64 +#define MD5_DIGEST_LENGTH 16 +#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) + +typedef struct MD5Context { + uint32_t state[4]; + uint64_t count; + uint8_t buffer[MD5_BLOCK_LENGTH]; +} MD5_CTX; + +extern void MD5Init(MD5_CTX *); +extern void MD5Update(MD5_CTX *, const uint8_t *, size_t); +extern void MD5Pad(MD5_CTX *); +extern void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH]); +extern char *MD5End(MD5_CTX *, char *); +extern void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *); diff --git a/compat_memmem.h b/compat_memmem.h new file mode 100644 index 0000000..98e2539 --- /dev/null +++ b/compat_memmem.h @@ -0,0 +1,4 @@ +/* + * Compatibility for memmem(3). + */ +void *memmem(const void *, size_t, const void *, size_t); diff --git a/compat_memrchr.h b/compat_memrchr.h new file mode 100644 index 0000000..baf4cde --- /dev/null +++ b/compat_memrchr.h @@ -0,0 +1,4 @@ +/* + * Compatibility for memrchr(3). + */ +void *memrchr(const void *b, int, size_t); diff --git a/compat_mkfifoat.h b/compat_mkfifoat.h new file mode 100644 index 0000000..2e3ca37 --- /dev/null +++ b/compat_mkfifoat.h @@ -0,0 +1,4 @@ +/* + * Compatibility for mkfifoat(2). + */ +int mkfifoat(int, const char *, mode_t); diff --git a/compat_mknodat.h b/compat_mknodat.h new file mode 100644 index 0000000..5bfcc84 --- /dev/null +++ b/compat_mknodat.h @@ -0,0 +1,4 @@ +/* + * Compatibility for mknodat(2). + */ +int mknodat(int, const char *, mode_t, dev_t); diff --git a/compat_readpassphrase.h b/compat_readpassphrase.h new file mode 100644 index 0000000..f6be73a --- /dev/null +++ b/compat_readpassphrase.h @@ -0,0 +1,11 @@ +/* + * Macros and function required for readpassphrase(3). + */ +#define RPP_ECHO_OFF 0x00 +#define RPP_ECHO_ON 0x01 +#define RPP_REQUIRE_TTY 0x02 +#define RPP_FORCELOWER 0x04 +#define RPP_FORCEUPPER 0x08 +#define RPP_SEVENBIT 0x10 +#define RPP_STDIN 0x20 +char *readpassphrase(const char *, char *, size_t, int); diff --git a/compat_reallocarray.h b/compat_reallocarray.h new file mode 100644 index 0000000..b17cbb5 --- /dev/null +++ b/compat_reallocarray.h @@ -0,0 +1,4 @@ +/* + * Compatibility for reallocarray(3). + */ +extern void *reallocarray(void *, size_t, size_t); diff --git a/compat_recallocarray.h b/compat_recallocarray.h new file mode 100644 index 0000000..61c049c --- /dev/null +++ b/compat_recallocarray.h @@ -0,0 +1,4 @@ +/* + * Compatibility for recallocarray(3). + */ +extern void *recallocarray(void *, size_t, size_t, size_t); diff --git a/compat_scan_scaled.h b/compat_scan_scaled.h new file mode 100644 index 0000000..213c0f2 --- /dev/null +++ b/compat_scan_scaled.h @@ -0,0 +1,6 @@ +/* + * Compatibility for scan_scaled(3) and fmt_scaled(3). + */ +#define FMT_SCALED_STRSIZE 7 /* minus sign, 4 digits, suffix, null byte */ +int fmt_scaled(long long, char *); +int scan_scaled(char *, long long *); diff --git a/compat_setresgid.h b/compat_setresgid.h new file mode 100644 index 0000000..fe77764 --- /dev/null +++ b/compat_setresgid.h @@ -0,0 +1,4 @@ +/* + * Compatibility for setresgid(2). + */ +int setresgid(gid_t rgid, gid_t egid, gid_t sgid); diff --git a/compat_setresuid.h b/compat_setresuid.h new file mode 100644 index 0000000..3a25be7 --- /dev/null +++ b/compat_setresuid.h @@ -0,0 +1,4 @@ +/* + * Compatibility for setresuid(2). + */ +int setresuid(uid_t ruid, uid_t euid, uid_t suid); diff --git a/compat_sha2.h b/compat_sha2.h new file mode 100644 index 0000000..49ff54e --- /dev/null +++ b/compat_sha2.h @@ -0,0 +1,57 @@ +/* + * Compatibility for sha2(3). + */ + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) +#define SHA512_256_BLOCK_LENGTH 128 +#define SHA512_256_DIGEST_LENGTH 32 +#define SHA512_256_DIGEST_STRING_LENGTH (SHA512_256_DIGEST_LENGTH * 2 + 1) + +/*** SHA-224/256/384/512 Context Structure *******************************/ +typedef struct _SHA2_CTX { + union { + uint32_t st32[8]; + uint64_t st64[8]; + } state; + uint64_t bitcount[2]; + uint8_t buffer[SHA512_BLOCK_LENGTH]; +} SHA2_CTX; + +void SHA256Init(SHA2_CTX *); +void SHA256Transform(uint32_t state[8], const uint8_t [SHA256_BLOCK_LENGTH]); +void SHA256Update(SHA2_CTX *, const uint8_t *, size_t); +void SHA256Pad(SHA2_CTX *); +void SHA256Final(uint8_t [SHA256_DIGEST_LENGTH], SHA2_CTX *); +char *SHA256End(SHA2_CTX *, char *); +char *SHA256File(const char *, char *); +char *SHA256FileChunk(const char *, char *, off_t, off_t); +char *SHA256Data(const uint8_t *, size_t, char *); + +void SHA384Init(SHA2_CTX *); +void SHA384Transform(uint64_t state[8], const uint8_t [SHA384_BLOCK_LENGTH]); +void SHA384Update(SHA2_CTX *, const uint8_t *, size_t); +void SHA384Pad(SHA2_CTX *); +void SHA384Final(uint8_t [SHA384_DIGEST_LENGTH], SHA2_CTX *); +char *SHA384End(SHA2_CTX *, char *); +char *SHA384File(const char *, char *); +char *SHA384FileChunk(const char *, char *, off_t, off_t); +char *SHA384Data(const uint8_t *, size_t, char *); + +void SHA512Init(SHA2_CTX *); +void SHA512Transform(uint64_t state[8], const uint8_t [SHA512_BLOCK_LENGTH]); +void SHA512Update(SHA2_CTX *, const uint8_t *, size_t); +void SHA512Pad(SHA2_CTX *); +void SHA512Final(uint8_t [SHA512_DIGEST_LENGTH], SHA2_CTX *); +char *SHA512End(SHA2_CTX *, char *); +char *SHA512File(const char *, char *); +char *SHA512FileChunk(const char *, char *, off_t, off_t); +char *SHA512Data(const uint8_t *, size_t, char *); diff --git a/compat_strlcat.h b/compat_strlcat.h new file mode 100644 index 0000000..6e0d33a --- /dev/null +++ b/compat_strlcat.h @@ -0,0 +1,4 @@ +/* + * Compatibility for strlcat(3). + */ +extern size_t strlcat(char *, const char *, size_t); diff --git a/compat_strlcpy.h b/compat_strlcpy.h new file mode 100644 index 0000000..1319183 --- /dev/null +++ b/compat_strlcpy.h @@ -0,0 +1,4 @@ +/* + * Compatibility for strlcpy(3). + */ +extern size_t strlcpy(char *, const char *, size_t); diff --git a/compat_strndup.h b/compat_strndup.h new file mode 100644 index 0000000..60bdf0d --- /dev/null +++ b/compat_strndup.h @@ -0,0 +1,4 @@ +/* + * Compatibility for strndup(3). + */ +extern char *strndup(const char *, size_t); diff --git a/compat_strnlen.h b/compat_strnlen.h new file mode 100644 index 0000000..c6f8aa9 --- /dev/null +++ b/compat_strnlen.h @@ -0,0 +1,4 @@ +/* + * Compatibility for strnlen(3). + */ +extern size_t strnlen(const char *, size_t); diff --git a/compat_strtonum.h b/compat_strtonum.h new file mode 100644 index 0000000..a0936be --- /dev/null +++ b/compat_strtonum.h @@ -0,0 +1,4 @@ +/* + * Compatibility for strotnum(3). + */ +extern long long strtonum(const char *, long long, long long, const char **); diff --git a/compats.h b/compats.h new file mode 100644 index 0000000..e78c3e9 --- /dev/null +++ b/compats.h @@ -0,0 +1,295 @@ +#if !HAVE_ERR +/* + * Compatibility functions for err(3). + */ +extern void err(int, const char *, ...) __attribute__((noreturn)); +extern void errc(int, int, const char *, ...) __attribute__((noreturn)); +extern void errx(int, const char *, ...) __attribute__((noreturn)); +extern void verr(int, const char *, va_list) __attribute__((noreturn)); +extern void verrc(int, int, const char *, va_list) __attribute__((noreturn)); +extern void verrx(int, const char *, va_list) __attribute__((noreturn)); +extern void warn(const char *, ...); +extern void warnx(const char *, ...); +extern void warnc(int, const char *, ...); +extern void vwarn(const char *, va_list); +extern void vwarnc(int, const char *, va_list); +extern void vwarnx(const char *, va_list); +#endif /* !HAVE_ERR */ +#if !HAVE_B64_NTOP +/* + * Compatibility for b64_ntop(3). + */ +extern int b64_ntop(unsigned char const *, size_t, char *, size_t); +extern int b64_pton(char const *, unsigned char *, size_t); +#endif /* !HAVE_B64_NTOP */ +#if !HAVE_EXPLICIT_BZERO +/* + * Compatibility for explicit_bzero(3). + */ +extern void explicit_bzero(void *, size_t); +#endif /* !HAVE_EXPLICIT_BZERO */ +#if !HAVE_FTS +/* + * Compatibility for fts(3) functions. + */ +typedef struct { + struct _ftsent *fts_cur; /* current node */ + struct _ftsent *fts_child; /* linked list of children */ + struct _ftsent **fts_array; /* sort array */ + dev_t fts_dev; /* starting device # */ + char *fts_path; /* path for this descent */ + int fts_rfd; /* fd for root */ + size_t fts_pathlen; /* sizeof(path) */ + int fts_nitems; /* elements in the sort array */ + int (*fts_compar)(const struct _ftsent **, const struct _ftsent **); /* compare function */ +#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ +#define FTS_LOGICAL 0x0002 /* logical walk */ +#define FTS_NOCHDIR 0x0004 /* don't change directories */ +#define FTS_NOSTAT 0x0008 /* don't get stat info */ +#define FTS_PHYSICAL 0x0010 /* physical walk */ +#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ +#define FTS_XDEV 0x0040 /* don't cross devices */ +#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ +#define FTS_NAMEONLY 0x1000 /* (private) child names only */ +#define FTS_STOP 0x2000 /* (private) unrecoverable error */ + int fts_options; /* fts_open options, global flags */ +} FTS; + +typedef struct _ftsent { + struct _ftsent *fts_cycle; /* cycle node */ + struct _ftsent *fts_parent; /* parent directory */ + struct _ftsent *fts_link; /* next file in directory */ + long fts_number; /* local numeric value */ + void *fts_pointer; /* local address value */ + char *fts_accpath; /* access path */ + char *fts_path; /* root path */ + int fts_errno; /* errno for this node */ + int fts_symfd; /* fd for symlink */ + size_t fts_pathlen; /* strlen(fts_path) */ + size_t fts_namelen; /* strlen(fts_name) */ + ino_t fts_ino; /* inode */ + dev_t fts_dev; /* device */ + nlink_t fts_nlink; /* link count */ +#define FTS_ROOTPARENTLEVEL -1 +#define FTS_ROOTLEVEL 0 +#define FTS_MAXLEVEL 0x7fffffff + int fts_level; /* depth (-1 to N) */ +#define FTS_D 1 /* preorder directory */ +#define FTS_DC 2 /* directory that causes cycles */ +#define FTS_DEFAULT 3 /* none of the above */ +#define FTS_DNR 4 /* unreadable directory */ +#define FTS_DOT 5 /* dot or dot-dot */ +#define FTS_DP 6 /* postorder directory */ +#define FTS_ERR 7 /* error; errno is set */ +#define FTS_F 8 /* regular file */ +#define FTS_INIT 9 /* initialized only */ +#define FTS_NS 10 /* stat(2) failed */ +#define FTS_NSOK 11 /* no stat(2) requested */ +#define FTS_SL 12 /* symbolic link */ +#define FTS_SLNONE 13 /* symbolic link without target */ + unsigned short fts_info; /* user flags for FTSENT structure */ +#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ +#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ + unsigned short fts_flags; /* private flags for FTSENT structure */ +#define FTS_AGAIN 1 /* read node again */ +#define FTS_FOLLOW 2 /* follow symbolic link */ +#define FTS_NOINSTR 3 /* no instructions */ +#define FTS_SKIP 4 /* discard node */ + unsigned short fts_instr; /* fts_set() instructions */ + unsigned short fts_spare; /* unused */ + struct stat *fts_statp; /* stat(2) information */ + char fts_name[1]; /* file name */ +} FTSENT; + +FTSENT *fts_children(FTS *, int); +int fts_close(FTS *); +FTS *fts_open(char * const *, int, + int (*)(const FTSENT **, const FTSENT **)); +FTSENT *fts_read(FTS *); +int fts_set(FTS *, FTSENT *, int); +#endif /* !HAVE_FTS */ +#if !HAVE_GETPROGNAME +/* + * Compatibility for getprogname(3). + */ +extern const char *getprogname(void); +#endif /* !HAVE_GETPROGNAME */ +#if !HAVE_MD5 +/* + * Compatibility for md4(3). + */ +#define MD5_BLOCK_LENGTH 64 +#define MD5_DIGEST_LENGTH 16 +#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) + +typedef struct MD5Context { + uint32_t state[4]; + uint64_t count; + uint8_t buffer[MD5_BLOCK_LENGTH]; +} MD5_CTX; + +extern void MD5Init(MD5_CTX *); +extern void MD5Update(MD5_CTX *, const uint8_t *, size_t); +extern void MD5Pad(MD5_CTX *); +extern void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH]); +extern char *MD5End(MD5_CTX *, char *); +extern void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *); +#endif /* !HAVE_MD5 */ +#if !HAVE_MEMMEM +/* + * Compatibility for memmem(3). + */ +void *memmem(const void *, size_t, const void *, size_t); +#endif /* !HAVE_MEMMEM */ +#if !HAVE_MEMRCHR +/* + * Compatibility for memrchr(3). + */ +void *memrchr(const void *b, int, size_t); +#endif /* !HAVE_MEMRCHR */ +#if !HAVE_MKFIFOAT +/* + * Compatibility for mkfifoat(2). + */ +int mkfifoat(int, const char *, mode_t); +#endif /* !HAVE_MKFIFOAT */ +#if !HAVE_MKNODAT +/* + * Compatibility for mknodat(2). + */ +int mknodat(int, const char *, mode_t, dev_t); +#endif /* !HAVE_MKNODAT */ +#if !HAVE_READPASSPHRASE +/* + * Macros and function required for readpassphrase(3). + */ +#define RPP_ECHO_OFF 0x00 +#define RPP_ECHO_ON 0x01 +#define RPP_REQUIRE_TTY 0x02 +#define RPP_FORCELOWER 0x04 +#define RPP_FORCEUPPER 0x08 +#define RPP_SEVENBIT 0x10 +#define RPP_STDIN 0x20 +char *readpassphrase(const char *, char *, size_t, int); +#endif /* !HAVE_READPASSPHRASE */ +#if !HAVE_REALLOCARRAY +/* + * Compatibility for reallocarray(3). + */ +extern void *reallocarray(void *, size_t, size_t); +#endif /* !HAVE_REALLOCARRAY */ +#if !HAVE_RECALLOCARRAY +/* + * Compatibility for recallocarray(3). + */ +extern void *recallocarray(void *, size_t, size_t, size_t); +#endif /* !HAVE_RECALLOCARRAY */ +#if !HAVE_SCAN_SCALED +/* + * Compatibility for scan_scaled(3) and fmt_scaled(3). + */ +#define FMT_SCALED_STRSIZE 7 /* minus sign, 4 digits, suffix, null byte */ +int fmt_scaled(long long, char *); +int scan_scaled(char *, long long *); +#endif /* !HAVE_SCAN_SCALED */ +#if !HAVE_SETRESGID +/* + * Compatibility for setresgid(2). + */ +int setresgid(gid_t rgid, gid_t egid, gid_t sgid); +#endif /* !HAVE_SETRESGID */ +#if !HAVE_SETRESUID +/* + * Compatibility for setresuid(2). + */ +int setresuid(uid_t ruid, uid_t euid, uid_t suid); +#endif /* !HAVE_SETRESUID */ +#if !HAVE_SHA2 +/* + * Compatibility for sha2(3). + */ + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) +#define SHA512_256_BLOCK_LENGTH 128 +#define SHA512_256_DIGEST_LENGTH 32 +#define SHA512_256_DIGEST_STRING_LENGTH (SHA512_256_DIGEST_LENGTH * 2 + 1) + +/*** SHA-224/256/384/512 Context Structure *******************************/ +typedef struct _SHA2_CTX { + union { + uint32_t st32[8]; + uint64_t st64[8]; + } state; + uint64_t bitcount[2]; + uint8_t buffer[SHA512_BLOCK_LENGTH]; +} SHA2_CTX; + +void SHA256Init(SHA2_CTX *); +void SHA256Transform(uint32_t state[8], const uint8_t [SHA256_BLOCK_LENGTH]); +void SHA256Update(SHA2_CTX *, const uint8_t *, size_t); +void SHA256Pad(SHA2_CTX *); +void SHA256Final(uint8_t [SHA256_DIGEST_LENGTH], SHA2_CTX *); +char *SHA256End(SHA2_CTX *, char *); +char *SHA256File(const char *, char *); +char *SHA256FileChunk(const char *, char *, off_t, off_t); +char *SHA256Data(const uint8_t *, size_t, char *); + +void SHA384Init(SHA2_CTX *); +void SHA384Transform(uint64_t state[8], const uint8_t [SHA384_BLOCK_LENGTH]); +void SHA384Update(SHA2_CTX *, const uint8_t *, size_t); +void SHA384Pad(SHA2_CTX *); +void SHA384Final(uint8_t [SHA384_DIGEST_LENGTH], SHA2_CTX *); +char *SHA384End(SHA2_CTX *, char *); +char *SHA384File(const char *, char *); +char *SHA384FileChunk(const char *, char *, off_t, off_t); +char *SHA384Data(const uint8_t *, size_t, char *); + +void SHA512Init(SHA2_CTX *); +void SHA512Transform(uint64_t state[8], const uint8_t [SHA512_BLOCK_LENGTH]); +void SHA512Update(SHA2_CTX *, const uint8_t *, size_t); +void SHA512Pad(SHA2_CTX *); +void SHA512Final(uint8_t [SHA512_DIGEST_LENGTH], SHA2_CTX *); +char *SHA512End(SHA2_CTX *, char *); +char *SHA512File(const char *, char *); +char *SHA512FileChunk(const char *, char *, off_t, off_t); +char *SHA512Data(const uint8_t *, size_t, char *); +#endif /* !HAVE_SHA2 */ +#if !HAVE_STRLCAT +/* + * Compatibility for strlcat(3). + */ +extern size_t strlcat(char *, const char *, size_t); +#endif /* !HAVE_STRLCAT */ +#if !HAVE_STRLCPY +/* + * Compatibility for strlcpy(3). + */ +extern size_t strlcpy(char *, const char *, size_t); +#endif /* !HAVE_STRLCPY */ +#if !HAVE_STRNDUP +/* + * Compatibility for strndup(3). + */ +extern char *strndup(const char *, size_t); +#endif /* !HAVE_STRNDUP */ +#if !HAVE_STRNLEN +/* + * Compatibility for strnlen(3). + */ +extern size_t strnlen(const char *, size_t); +#endif /* !HAVE_STRNLEN */ +#if !HAVE_STRTONUM +/* + * Compatibility for strotnum(3). + */ +extern long long strtonum(const char *, long long, long long, const char **); +#endif /* !HAVE_STRTONUM */ diff --git a/configure b/configure index 9931dd2..ee73c0f 100755 --- a/configure +++ b/configure @@ -692,110 +692,9 @@ cat << __HEREDOC__ __HEREDOC__ -# Now we do our function declarations for missing functions. - -[ ${HAVE_ERR} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility functions for err(3). - */ -extern void err(int, const char *, ...) __attribute__((noreturn)); -extern void errc(int, int, const char *, ...) __attribute__((noreturn)); -extern void errx(int, const char *, ...) __attribute__((noreturn)); -extern void verr(int, const char *, va_list) __attribute__((noreturn)); -extern void verrc(int, int, const char *, va_list) __attribute__((noreturn)); -extern void verrx(int, const char *, va_list) __attribute__((noreturn)); -extern void warn(const char *, ...); -extern void warnx(const char *, ...); -extern void warnc(int, const char *, ...); -extern void vwarn(const char *, va_list); -extern void vwarnc(int, const char *, va_list); -extern void vwarnx(const char *, va_list); -__HEREDOC__ - -[ ${HAVE_MD5} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for md4(3). - */ -#define MD5_BLOCK_LENGTH 64 -#define MD5_DIGEST_LENGTH 16 -#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) - -typedef struct MD5Context { - uint32_t state[4]; - uint64_t count; - uint8_t buffer[MD5_BLOCK_LENGTH]; -} MD5_CTX; - -extern void MD5Init(MD5_CTX *); -extern void MD5Update(MD5_CTX *, const uint8_t *, size_t); -extern void MD5Pad(MD5_CTX *); -extern void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH]); -extern char *MD5End(MD5_CTX *, char *); -extern void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *); - -__HEREDOC__ - -[ ${HAVE_SHA2} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for sha2(3). - */ - -/*** SHA-256/384/512 Various Length Definitions ***********************/ -#define SHA256_BLOCK_LENGTH 64 -#define SHA256_DIGEST_LENGTH 32 -#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) -#define SHA384_BLOCK_LENGTH 128 -#define SHA384_DIGEST_LENGTH 48 -#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) -#define SHA512_BLOCK_LENGTH 128 -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) -#define SHA512_256_BLOCK_LENGTH 128 -#define SHA512_256_DIGEST_LENGTH 32 -#define SHA512_256_DIGEST_STRING_LENGTH (SHA512_256_DIGEST_LENGTH * 2 + 1) - -/*** SHA-224/256/384/512 Context Structure *******************************/ -typedef struct _SHA2_CTX { - union { - uint32_t st32[8]; - uint64_t st64[8]; - } state; - uint64_t bitcount[2]; - uint8_t buffer[SHA512_BLOCK_LENGTH]; -} SHA2_CTX; - -void SHA256Init(SHA2_CTX *); -void SHA256Transform(uint32_t state[8], const uint8_t [SHA256_BLOCK_LENGTH]); -void SHA256Update(SHA2_CTX *, const uint8_t *, size_t); -void SHA256Pad(SHA2_CTX *); -void SHA256Final(uint8_t [SHA256_DIGEST_LENGTH], SHA2_CTX *); -char *SHA256End(SHA2_CTX *, char *); -char *SHA256File(const char *, char *); -char *SHA256FileChunk(const char *, char *, off_t, off_t); -char *SHA256Data(const uint8_t *, size_t, char *); - -void SHA384Init(SHA2_CTX *); -void SHA384Transform(uint64_t state[8], const uint8_t [SHA384_BLOCK_LENGTH]); -void SHA384Update(SHA2_CTX *, const uint8_t *, size_t); -void SHA384Pad(SHA2_CTX *); -void SHA384Final(uint8_t [SHA384_DIGEST_LENGTH], SHA2_CTX *); -char *SHA384End(SHA2_CTX *, char *); -char *SHA384File(const char *, char *); -char *SHA384FileChunk(const char *, char *, off_t, off_t); -char *SHA384Data(const uint8_t *, size_t, char *); - -void SHA512Init(SHA2_CTX *); -void SHA512Transform(uint64_t state[8], const uint8_t [SHA512_BLOCK_LENGTH]); -void SHA512Update(SHA2_CTX *, const uint8_t *, size_t); -void SHA512Pad(SHA2_CTX *); -void SHA512Final(uint8_t [SHA512_DIGEST_LENGTH], SHA2_CTX *); -char *SHA512End(SHA2_CTX *, char *); -char *SHA512File(const char *, char *); -char *SHA512FileChunk(const char *, char *, off_t, off_t); -char *SHA512Data(const uint8_t *, size_t, char *); +cat << __HEREDOC__ +/* include function declarations for missing functions */ +#include "compats.h" __HEREDOC__ @@ -818,174 +717,6 @@ if [ ${HAVE_SECCOMP_FILTER} -eq 1 ]; then echo fi -[ ${HAVE_B64_NTOP} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for b64_ntop(3). - */ -extern int b64_ntop(unsigned char const *, size_t, char *, size_t); -extern int b64_pton(char const *, unsigned char *, size_t); - -__HEREDOC__ - -[ ${HAVE_SCAN_SCALED} -eq 0 ] && \ - cat << __HEREDOC__ -#define FMT_SCALED_STRSIZE 7 /* minus sign, 4 digits, suffix, null byte */ -int fmt_scaled(long long, char *); -int scan_scaled(char *, long long *); -__HEREDOC__ - -[ ${HAVE_EXPLICIT_BZERO} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for explicit_bzero(3). - */ -extern void explicit_bzero(void *, size_t); - -__HEREDOC__ - -[ ${HAVE_MEMMEM} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for memmem(3). - */ -void *memmem(const void *, size_t, const void *, size_t); - -__HEREDOC__ - -[ ${HAVE_MEMRCHR} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for memrchr(3). - */ -void *memrchr(const void *b, int, size_t); - -__HEREDOC__ - -[ ${HAVE_GETPROGNAME} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for getprogname(3). - */ -extern const char *getprogname(void); - -__HEREDOC__ - -[ ${HAVE_READPASSPHRASE} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Macros and function required for readpassphrase(3). - */ -#define RPP_ECHO_OFF 0x00 -#define RPP_ECHO_ON 0x01 -#define RPP_REQUIRE_TTY 0x02 -#define RPP_FORCELOWER 0x04 -#define RPP_FORCEUPPER 0x08 -#define RPP_SEVENBIT 0x10 -#define RPP_STDIN 0x20 -char *readpassphrase(const char *, char *, size_t, int); - -__HEREDOC__ - -[ ${HAVE_REALLOCARRAY} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for reallocarray(3). - */ -extern void *reallocarray(void *, size_t, size_t); - -__HEREDOC__ - -[ ${HAVE_RECALLOCARRAY} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for recallocarray(3). - */ -extern void *recallocarray(void *, size_t, size_t, size_t); - -__HEREDOC__ - -[ ${HAVE_STRLCAT} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strlcat(3). - */ -extern size_t strlcat(char *, const char *, size_t); - -__HEREDOC__ - -[ ${HAVE_STRLCPY} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strlcpy(3). - */ -extern size_t strlcpy(char *, const char *, size_t); - -__HEREDOC__ - -[ ${HAVE_STRNDUP} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strndup(3). - */ -extern char *strndup(const char *, size_t); - -__HEREDOC__ - -[ ${HAVE_STRNLEN} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strnlen(3). - */ -extern size_t strnlen(const char *, size_t); - -__HEREDOC__ - -[ ${HAVE_STRTONUM} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strotnum(3). - */ -extern long long strtonum(const char *, long long, long long, const char **); - -__HEREDOC__ - -[ ${HAVE_MKFIFOAT} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for mkfifoat(2). - */ -int mkfifoat(int, const char *, mode_t); - -__HEREDOC__ - -[ ${HAVE_MKNODAT} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for mknodat(2). - */ -int mknodat(int, const char *, mode_t, dev_t); - -__HEREDOC__ - -[ ${HAVE_SETRESGID} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for setresgid(2). - */ -int setresgid(gid_t rgid, gid_t egid, gid_t sgid); - -__HEREDOC__ - -[ ${HAVE_SETRESUID} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for setresuid(2). - */ -int setresuid(uid_t ruid, uid_t euid, uid_t suid); - -__HEREDOC__ - if [ ${HAVE_SYS_QUEUE} -eq 0 ]; then cat << __HEREDOC__ /* @@ -2364,90 +2095,6 @@ name##_RB_MINMAX(struct name *head, int val) \\ __HEREDOC__ fi -if [ ${HAVE_FTS} -eq 0 ]; then - cat << __HEREDOC__ -/* - * Compatibility for fts(3) functions. - */ -typedef struct { - struct _ftsent *fts_cur; /* current node */ - struct _ftsent *fts_child; /* linked list of children */ - struct _ftsent **fts_array; /* sort array */ - dev_t fts_dev; /* starting device # */ - char *fts_path; /* path for this descent */ - int fts_rfd; /* fd for root */ - size_t fts_pathlen; /* sizeof(path) */ - int fts_nitems; /* elements in the sort array */ - int (*fts_compar)(const struct _ftsent **, const struct _ftsent **); /* compare function */ -#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ -#define FTS_LOGICAL 0x0002 /* logical walk */ -#define FTS_NOCHDIR 0x0004 /* don't change directories */ -#define FTS_NOSTAT 0x0008 /* don't get stat info */ -#define FTS_PHYSICAL 0x0010 /* physical walk */ -#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ -#define FTS_XDEV 0x0040 /* don't cross devices */ -#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ -#define FTS_NAMEONLY 0x1000 /* (private) child names only */ -#define FTS_STOP 0x2000 /* (private) unrecoverable error */ - int fts_options; /* fts_open options, global flags */ -} FTS; - -typedef struct _ftsent { - struct _ftsent *fts_cycle; /* cycle node */ - struct _ftsent *fts_parent; /* parent directory */ - struct _ftsent *fts_link; /* next file in directory */ - long fts_number; /* local numeric value */ - void *fts_pointer; /* local address value */ - char *fts_accpath; /* access path */ - char *fts_path; /* root path */ - int fts_errno; /* errno for this node */ - int fts_symfd; /* fd for symlink */ - size_t fts_pathlen; /* strlen(fts_path) */ - size_t fts_namelen; /* strlen(fts_name) */ - ino_t fts_ino; /* inode */ - dev_t fts_dev; /* device */ - nlink_t fts_nlink; /* link count */ -#define FTS_ROOTPARENTLEVEL -1 -#define FTS_ROOTLEVEL 0 -#define FTS_MAXLEVEL 0x7fffffff - int fts_level; /* depth (-1 to N) */ -#define FTS_D 1 /* preorder directory */ -#define FTS_DC 2 /* directory that causes cycles */ -#define FTS_DEFAULT 3 /* none of the above */ -#define FTS_DNR 4 /* unreadable directory */ -#define FTS_DOT 5 /* dot or dot-dot */ -#define FTS_DP 6 /* postorder directory */ -#define FTS_ERR 7 /* error; errno is set */ -#define FTS_F 8 /* regular file */ -#define FTS_INIT 9 /* initialized only */ -#define FTS_NS 10 /* stat(2) failed */ -#define FTS_NSOK 11 /* no stat(2) requested */ -#define FTS_SL 12 /* symbolic link */ -#define FTS_SLNONE 13 /* symbolic link without target */ - unsigned short fts_info; /* user flags for FTSENT structure */ -#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ -#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ - unsigned short fts_flags; /* private flags for FTSENT structure */ -#define FTS_AGAIN 1 /* read node again */ -#define FTS_FOLLOW 2 /* follow symbolic link */ -#define FTS_NOINSTR 3 /* no instructions */ -#define FTS_SKIP 4 /* discard node */ - unsigned short fts_instr; /* fts_set() instructions */ - unsigned short fts_spare; /* unused */ - struct stat *fts_statp; /* stat(2) information */ - char fts_name[1]; /* file name */ -} FTSENT; - -FTSENT *fts_children(FTS *, int); -int fts_close(FTS *); -FTS *fts_open(char * const *, int, - int (*)(const FTSENT **, const FTSENT **)); -FTSENT *fts_read(FTS *); -int fts_set(FTS *, FTSENT *, int); - -__HEREDOC__ -fi - cat << __HEREDOC__ #endif /*!OCONFIGURE_CONFIG_H*/ __HEREDOC__ diff --git a/configure.in b/configure.in index 9879ea5..36aedfc 100644 --- a/configure.in +++ b/configure.in @@ -692,110 +692,9 @@ cat << __HEREDOC__ __HEREDOC__ -# Now we do our function declarations for missing functions. - -[ ${HAVE_ERR} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility functions for err(3). - */ -extern void err(int, const char *, ...) __attribute__((noreturn)); -extern void errc(int, int, const char *, ...) __attribute__((noreturn)); -extern void errx(int, const char *, ...) __attribute__((noreturn)); -extern void verr(int, const char *, va_list) __attribute__((noreturn)); -extern void verrc(int, int, const char *, va_list) __attribute__((noreturn)); -extern void verrx(int, const char *, va_list) __attribute__((noreturn)); -extern void warn(const char *, ...); -extern void warnx(const char *, ...); -extern void warnc(int, const char *, ...); -extern void vwarn(const char *, va_list); -extern void vwarnc(int, const char *, va_list); -extern void vwarnx(const char *, va_list); -__HEREDOC__ - -[ ${HAVE_MD5} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for md4(3). - */ -#define MD5_BLOCK_LENGTH 64 -#define MD5_DIGEST_LENGTH 16 -#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) - -typedef struct MD5Context { - uint32_t state[4]; - uint64_t count; - uint8_t buffer[MD5_BLOCK_LENGTH]; -} MD5_CTX; - -extern void MD5Init(MD5_CTX *); -extern void MD5Update(MD5_CTX *, const uint8_t *, size_t); -extern void MD5Pad(MD5_CTX *); -extern void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH]); -extern char *MD5End(MD5_CTX *, char *); -extern void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *); - -__HEREDOC__ - -[ ${HAVE_SHA2} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for sha2(3). - */ - -/*** SHA-256/384/512 Various Length Definitions ***********************/ -#define SHA256_BLOCK_LENGTH 64 -#define SHA256_DIGEST_LENGTH 32 -#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) -#define SHA384_BLOCK_LENGTH 128 -#define SHA384_DIGEST_LENGTH 48 -#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) -#define SHA512_BLOCK_LENGTH 128 -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) -#define SHA512_256_BLOCK_LENGTH 128 -#define SHA512_256_DIGEST_LENGTH 32 -#define SHA512_256_DIGEST_STRING_LENGTH (SHA512_256_DIGEST_LENGTH * 2 + 1) - -/*** SHA-224/256/384/512 Context Structure *******************************/ -typedef struct _SHA2_CTX { - union { - uint32_t st32[8]; - uint64_t st64[8]; - } state; - uint64_t bitcount[2]; - uint8_t buffer[SHA512_BLOCK_LENGTH]; -} SHA2_CTX; - -void SHA256Init(SHA2_CTX *); -void SHA256Transform(uint32_t state[8], const uint8_t [SHA256_BLOCK_LENGTH]); -void SHA256Update(SHA2_CTX *, const uint8_t *, size_t); -void SHA256Pad(SHA2_CTX *); -void SHA256Final(uint8_t [SHA256_DIGEST_LENGTH], SHA2_CTX *); -char *SHA256End(SHA2_CTX *, char *); -char *SHA256File(const char *, char *); -char *SHA256FileChunk(const char *, char *, off_t, off_t); -char *SHA256Data(const uint8_t *, size_t, char *); - -void SHA384Init(SHA2_CTX *); -void SHA384Transform(uint64_t state[8], const uint8_t [SHA384_BLOCK_LENGTH]); -void SHA384Update(SHA2_CTX *, const uint8_t *, size_t); -void SHA384Pad(SHA2_CTX *); -void SHA384Final(uint8_t [SHA384_DIGEST_LENGTH], SHA2_CTX *); -char *SHA384End(SHA2_CTX *, char *); -char *SHA384File(const char *, char *); -char *SHA384FileChunk(const char *, char *, off_t, off_t); -char *SHA384Data(const uint8_t *, size_t, char *); - -void SHA512Init(SHA2_CTX *); -void SHA512Transform(uint64_t state[8], const uint8_t [SHA512_BLOCK_LENGTH]); -void SHA512Update(SHA2_CTX *, const uint8_t *, size_t); -void SHA512Pad(SHA2_CTX *); -void SHA512Final(uint8_t [SHA512_DIGEST_LENGTH], SHA2_CTX *); -char *SHA512End(SHA2_CTX *, char *); -char *SHA512File(const char *, char *); -char *SHA512FileChunk(const char *, char *, off_t, off_t); -char *SHA512Data(const uint8_t *, size_t, char *); +cat << __HEREDOC__ +/* include function declarations for missing functions */ +#include "compats.h" __HEREDOC__ @@ -818,174 +717,6 @@ if [ ${HAVE_SECCOMP_FILTER} -eq 1 ]; then echo fi -[ ${HAVE_B64_NTOP} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for b64_ntop(3). - */ -extern int b64_ntop(unsigned char const *, size_t, char *, size_t); -extern int b64_pton(char const *, unsigned char *, size_t); - -__HEREDOC__ - -[ ${HAVE_SCAN_SCALED} -eq 0 ] && \ - cat << __HEREDOC__ -#define FMT_SCALED_STRSIZE 7 /* minus sign, 4 digits, suffix, null byte */ -int fmt_scaled(long long, char *); -int scan_scaled(char *, long long *); -__HEREDOC__ - -[ ${HAVE_EXPLICIT_BZERO} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for explicit_bzero(3). - */ -extern void explicit_bzero(void *, size_t); - -__HEREDOC__ - -[ ${HAVE_MEMMEM} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for memmem(3). - */ -void *memmem(const void *, size_t, const void *, size_t); - -__HEREDOC__ - -[ ${HAVE_MEMRCHR} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for memrchr(3). - */ -void *memrchr(const void *b, int, size_t); - -__HEREDOC__ - -[ ${HAVE_GETPROGNAME} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for getprogname(3). - */ -extern const char *getprogname(void); - -__HEREDOC__ - -[ ${HAVE_READPASSPHRASE} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Macros and function required for readpassphrase(3). - */ -#define RPP_ECHO_OFF 0x00 -#define RPP_ECHO_ON 0x01 -#define RPP_REQUIRE_TTY 0x02 -#define RPP_FORCELOWER 0x04 -#define RPP_FORCEUPPER 0x08 -#define RPP_SEVENBIT 0x10 -#define RPP_STDIN 0x20 -char *readpassphrase(const char *, char *, size_t, int); - -__HEREDOC__ - -[ ${HAVE_REALLOCARRAY} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for reallocarray(3). - */ -extern void *reallocarray(void *, size_t, size_t); - -__HEREDOC__ - -[ ${HAVE_RECALLOCARRAY} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for recallocarray(3). - */ -extern void *recallocarray(void *, size_t, size_t, size_t); - -__HEREDOC__ - -[ ${HAVE_STRLCAT} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strlcat(3). - */ -extern size_t strlcat(char *, const char *, size_t); - -__HEREDOC__ - -[ ${HAVE_STRLCPY} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strlcpy(3). - */ -extern size_t strlcpy(char *, const char *, size_t); - -__HEREDOC__ - -[ ${HAVE_STRNDUP} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strndup(3). - */ -extern char *strndup(const char *, size_t); - -__HEREDOC__ - -[ ${HAVE_STRNLEN} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strnlen(3). - */ -extern size_t strnlen(const char *, size_t); - -__HEREDOC__ - -[ ${HAVE_STRTONUM} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for strotnum(3). - */ -extern long long strtonum(const char *, long long, long long, const char **); - -__HEREDOC__ - -[ ${HAVE_MKFIFOAT} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for mkfifoat(2). - */ -int mkfifoat(int, const char *, mode_t); - -__HEREDOC__ - -[ ${HAVE_MKNODAT} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for mknodat(2). - */ -int mknodat(int, const char *, mode_t, dev_t); - -__HEREDOC__ - -[ ${HAVE_SETRESGID} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for setresgid(2). - */ -int setresgid(gid_t rgid, gid_t egid, gid_t sgid); - -__HEREDOC__ - -[ ${HAVE_SETRESUID} -eq 0 ] && \ - cat << __HEREDOC__ -/* - * Compatibility for setresuid(2). - */ -int setresuid(uid_t ruid, uid_t euid, uid_t suid); - -__HEREDOC__ - if [ ${HAVE_SYS_QUEUE} -eq 0 ]; then cat << __HEREDOC__ /* @@ -1006,90 +737,6 @@ if [ ${HAVE_SYS_TREE} -eq 0 ]; then __HEREDOC__ fi -if [ ${HAVE_FTS} -eq 0 ]; then - cat << __HEREDOC__ -/* - * Compatibility for fts(3) functions. - */ -typedef struct { - struct _ftsent *fts_cur; /* current node */ - struct _ftsent *fts_child; /* linked list of children */ - struct _ftsent **fts_array; /* sort array */ - dev_t fts_dev; /* starting device # */ - char *fts_path; /* path for this descent */ - int fts_rfd; /* fd for root */ - size_t fts_pathlen; /* sizeof(path) */ - int fts_nitems; /* elements in the sort array */ - int (*fts_compar)(const struct _ftsent **, const struct _ftsent **); /* compare function */ -#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ -#define FTS_LOGICAL 0x0002 /* logical walk */ -#define FTS_NOCHDIR 0x0004 /* don't change directories */ -#define FTS_NOSTAT 0x0008 /* don't get stat info */ -#define FTS_PHYSICAL 0x0010 /* physical walk */ -#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ -#define FTS_XDEV 0x0040 /* don't cross devices */ -#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ -#define FTS_NAMEONLY 0x1000 /* (private) child names only */ -#define FTS_STOP 0x2000 /* (private) unrecoverable error */ - int fts_options; /* fts_open options, global flags */ -} FTS; - -typedef struct _ftsent { - struct _ftsent *fts_cycle; /* cycle node */ - struct _ftsent *fts_parent; /* parent directory */ - struct _ftsent *fts_link; /* next file in directory */ - long fts_number; /* local numeric value */ - void *fts_pointer; /* local address value */ - char *fts_accpath; /* access path */ - char *fts_path; /* root path */ - int fts_errno; /* errno for this node */ - int fts_symfd; /* fd for symlink */ - size_t fts_pathlen; /* strlen(fts_path) */ - size_t fts_namelen; /* strlen(fts_name) */ - ino_t fts_ino; /* inode */ - dev_t fts_dev; /* device */ - nlink_t fts_nlink; /* link count */ -#define FTS_ROOTPARENTLEVEL -1 -#define FTS_ROOTLEVEL 0 -#define FTS_MAXLEVEL 0x7fffffff - int fts_level; /* depth (-1 to N) */ -#define FTS_D 1 /* preorder directory */ -#define FTS_DC 2 /* directory that causes cycles */ -#define FTS_DEFAULT 3 /* none of the above */ -#define FTS_DNR 4 /* unreadable directory */ -#define FTS_DOT 5 /* dot or dot-dot */ -#define FTS_DP 6 /* postorder directory */ -#define FTS_ERR 7 /* error; errno is set */ -#define FTS_F 8 /* regular file */ -#define FTS_INIT 9 /* initialized only */ -#define FTS_NS 10 /* stat(2) failed */ -#define FTS_NSOK 11 /* no stat(2) requested */ -#define FTS_SL 12 /* symbolic link */ -#define FTS_SLNONE 13 /* symbolic link without target */ - unsigned short fts_info; /* user flags for FTSENT structure */ -#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ -#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ - unsigned short fts_flags; /* private flags for FTSENT structure */ -#define FTS_AGAIN 1 /* read node again */ -#define FTS_FOLLOW 2 /* follow symbolic link */ -#define FTS_NOINSTR 3 /* no instructions */ -#define FTS_SKIP 4 /* discard node */ - unsigned short fts_instr; /* fts_set() instructions */ - unsigned short fts_spare; /* unused */ - struct stat *fts_statp; /* stat(2) information */ - char fts_name[1]; /* file name */ -} FTSENT; - -FTSENT *fts_children(FTS *, int); -int fts_close(FTS *); -FTS *fts_open(char * const *, int, - int (*)(const FTSENT **, const FTSENT **)); -FTSENT *fts_read(FTS *); -int fts_set(FTS *, FTSENT *, int); - -__HEREDOC__ -fi - cat << __HEREDOC__ #endif /*!OCONFIGURE_CONFIG_H*/ __HEREDOC__ From be6e88d4deaf3b074131013ac47497b7b9cf69f3 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Sun, 14 Nov 2021 16:37:36 +0200 Subject: [PATCH 03/10] Move sys_queue.h & sys_tree.h to compats.h Use the new compats.h facility to include the sys_queue.h and sys_tree.h code. This removes the special-casing of that header code, and the configure.in/configure.1/configure.2 sed replacements, making the code cleaner and more aligned to the rest of the compatibility code. --- Makefile.regen | 15 +- configure-sys_queue.h => compat_sys_queue.h | 4 + configure-sys_tree.h => compat_sys_tree.h | 4 + compats.h | 1372 ++++++++++++++++++ configure | 1378 ------------------- configure.in | 20 - 6 files changed, 1385 insertions(+), 1408 deletions(-) rename configure-sys_queue.h => compat_sys_queue.h (99%) rename configure-sys_tree.h => compat_sys_tree.h (99%) diff --git a/Makefile.regen b/Makefile.regen index e73991d..941d2e2 100644 --- a/Makefile.regen +++ b/Makefile.regen @@ -46,7 +46,9 @@ COMPATS_H = \ compat_strlcpy.h \ compat_strndup.h \ compat_strnlen.h \ - compat_strtonum.h + compat_strtonum.h \ + compat_sys_queue.h \ + compat_sys_tree.h TESTS = \ test-__progname.c \ test-arc4random.c \ @@ -104,16 +106,9 @@ all: compats.c compats.h tests.c configure distcheck: grep "^## $(VERSION)$$" versions.md >/dev/null -configure: configure.in Makefile.regen configure-sys_queue.h +configure: configure.in Makefile.regen rm -f $@ - ( sed -n '/^@CONFIGURE_SYS_QUEUE_H@$$/!p;//q' configure.in ; \ - sed -e 's!\\$$!\\\\!g' -e 's!\$$!\\$$!g' configure-sys_queue.h ; \ - sed '1,/^@CONFIGURE_SYS_QUEUE_H@$$/d' configure.in ; ) > configure.1 - ( sed -n '/^@CONFIGURE_SYS_TREE_H@$$/!p;//q' configure.1 ; \ - sed -e 's!\\$$!\\\\!g' -e 's!\$$!\\$$!g' configure-sys_tree.h ; \ - sed '1,/^@CONFIGURE_SYS_TREE_H@$$/d' configure.1 ; ) > configure.2 - sed "s!@VERSION@!$(VERSION)!g" configure.2 >$@ - rm -f configure.1 configure.2 + sed "s!@VERSION@!$(VERSION)!g" configure.in >$@ chmod 555 $@ compats.c: $(COMPATS) Makefile.regen diff --git a/configure-sys_queue.h b/compat_sys_queue.h similarity index 99% rename from configure-sys_queue.h rename to compat_sys_queue.h index fa5397f..fdfd044 100644 --- a/configure-sys_queue.h +++ b/compat_sys_queue.h @@ -1,3 +1,7 @@ +/* + * A compatible version of OpenBSD . + */ + /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. diff --git a/configure-sys_tree.h b/compat_sys_tree.h similarity index 99% rename from configure-sys_tree.h rename to compat_sys_tree.h index de7535d..c67fbea 100644 --- a/configure-sys_tree.h +++ b/compat_sys_tree.h @@ -1,3 +1,7 @@ +/* + * A compatible version of OpenBSD . + */ + /* * Copyright 2002 Niels Provos * All rights reserved. diff --git a/compats.h b/compats.h index e78c3e9..1d84732 100644 --- a/compats.h +++ b/compats.h @@ -293,3 +293,1375 @@ extern size_t strnlen(const char *, size_t); */ extern long long strtonum(const char *, long long, long long, const char **); #endif /* !HAVE_STRTONUM */ +#if !HAVE_SYS_QUEUE +/* + * A compatible version of OpenBSD . + */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +/* OPENBSD ORIGINAL: sys/sys/queue.h */ + +/* + * Require for OS/X and other platforms that have old/broken/incomplete + * . + */ + +#undef LIST_EMPTY +#undef LIST_END +#undef LIST_ENTRY +#undef LIST_FIRST +#undef LIST_FOREACH +#undef LIST_FOREACH_SAFE +#undef LIST_HEAD +#undef LIST_HEAD_INITIALIZER +#undef LIST_INIT +#undef LIST_INSERT_AFTER +#undef LIST_INSERT_BEFORE +#undef LIST_INSERT_HEAD +#undef LIST_NEXT +#undef LIST_REMOVE +#undef LIST_REPLACE +#undef SIMPLEQ_CONCAT +#undef SIMPLEQ_EMPTY +#undef SIMPLEQ_END +#undef SIMPLEQ_ENTRY +#undef SIMPLEQ_FIRST +#undef SIMPLEQ_FOREACH +#undef SIMPLEQ_FOREACH_SAFE +#undef SIMPLEQ_HEAD +#undef SIMPLEQ_HEAD_INITIALIZER +#undef SIMPLEQ_INIT +#undef SIMPLEQ_INSERT_AFTER +#undef SIMPLEQ_INSERT_HEAD +#undef SIMPLEQ_INSERT_TAIL +#undef SIMPLEQ_NEXT +#undef SIMPLEQ_REMOVE_AFTER +#undef SIMPLEQ_REMOVE_HEAD +#undef SLIST_EMPTY +#undef SLIST_END +#undef SLIST_ENTRY +#undef SLIST_FIRST +#undef SLIST_FOREACH +#undef SLIST_FOREACH_SAFE +#undef SLIST_HEAD +#undef SLIST_HEAD_INITIALIZER +#undef SLIST_INIT +#undef SLIST_INSERT_AFTER +#undef SLIST_INSERT_HEAD +#undef SLIST_NEXT +#undef SLIST_REMOVE +#undef SLIST_REMOVE_AFTER +#undef SLIST_REMOVE_HEAD +#undef TAILQ_CONCAT +#undef TAILQ_EMPTY +#undef TAILQ_END +#undef TAILQ_ENTRY +#undef TAILQ_FIRST +#undef TAILQ_FOREACH +#undef TAILQ_FOREACH_REVERSE +#undef TAILQ_FOREACH_REVERSE_SAFE +#undef TAILQ_FOREACH_SAFE +#undef TAILQ_HEAD +#undef TAILQ_HEAD_INITIALIZER +#undef TAILQ_INIT +#undef TAILQ_INSERT_AFTER +#undef TAILQ_INSERT_BEFORE +#undef TAILQ_INSERT_HEAD +#undef TAILQ_INSERT_TAIL +#undef TAILQ_LAST +#undef TAILQ_NEXT +#undef TAILQ_PREV +#undef TAILQ_REMOVE +#undef TAILQ_REPLACE +#undef XSIMPLEQ_EMPTY +#undef XSIMPLEQ_END +#undef XSIMPLEQ_ENTRY +#undef XSIMPLEQ_FIRST +#undef XSIMPLEQ_FOREACH +#undef XSIMPLEQ_FOREACH_SAFE +#undef XSIMPLEQ_HEAD +#undef XSIMPLEQ_INIT +#undef XSIMPLEQ_INSERT_AFTER +#undef XSIMPLEQ_INSERT_HEAD +#undef XSIMPLEQ_INSERT_TAIL +#undef XSIMPLEQ_NEXT +#undef XSIMPLEQ_REMOVE_AFTER +#undef XSIMPLEQ_REMOVE_HEAD +#undef XSIMPLEQ_XOR + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues and XOR simple queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * An XOR simple queue is used in the same way as a regular simple queue. + * The difference is that the head structure also includes a "cookie" that + * is XOR'd with the queue pointer (first, last or next) to generate the + * real pointer value. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) +#define _Q_INVALID ((void *)-1) +#define _Q_INVALIDATE(a) (a) = _Q_INVALID +#else +#define _Q_INVALIDATE(a) +#endif + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST(head); \ + (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ + _Q_INVALIDATE((elm)->field.sle_next); \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods. + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST(head); \ + (var) && ((tvar) = LIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SIMPLEQ_FIRST(head); \ + (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_CONCAT(head1, head2) do { \ + if (!SIMPLEQ_EMPTY((head2))) { \ + *(head1)->sqh_last = (head2)->sqh_first; \ + (head1)->sqh_last = (head2)->sqh_last; \ + SIMPLEQ_INIT((head2)); \ + } \ +} while (0) + +/* + * XOR Simple queue definitions. + */ +#define XSIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqx_first; /* first element */ \ + struct type **sqx_last; /* addr of last next element */ \ + unsigned long sqx_cookie; \ +} + +#define XSIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqx_next; /* next element */ \ +} + +/* + * XOR Simple queue access methods. + */ +#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ + (unsigned long)(ptr))) +#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) +#define XSIMPLEQ_END(head) NULL +#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) +#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) + + +#define XSIMPLEQ_FOREACH(var, head, field) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) != XSIMPLEQ_END(head); \ + (var) = XSIMPLEQ_NEXT(head, var, field)) + +#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ + (var) = (tvar)) + +/* + * XOR Simple queue functions. + */ +#define XSIMPLEQ_INIT(head) do { \ + arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqx_next = (head)->sqx_first) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ + *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + +#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ + (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ + (elm)->field.sqx_next)->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * Tail queue access methods. + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) + + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ +} while (0) +#endif /* !HAVE_SYS_QUEUE */ +#if !HAVE_SYS_TREE +/* + * A compatible version of OpenBSD . + */ + +/* + * Copyright 2002 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* OPENBSD ORIGINAL: sys/sys/tree.h */ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-black tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) do {} while (0) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) +#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ +attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ +attr struct type *name##_RB_INSERT(struct name *, struct type *); \ +attr struct type *name##_RB_FIND(struct name *, struct type *); \ +attr struct type *name##_RB_NFIND(struct name *, struct type *); \ +attr struct type *name##_RB_NEXT(struct type *); \ +attr struct type *name##_RB_PREV(struct type *); \ +attr struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_STATIC(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) +#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ +attr void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +attr void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +/* Finds the first node greater than or equal to the search key */ \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_PREV(name, x, y) name##_RB_PREV(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#define RB_FOREACH_SAFE(x, name, head, y) \ + for ((x) = RB_MIN(name, head); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE(x, name, head) \ + for ((x) = RB_MAX(name, head); \ + (x) != NULL; \ + (x) = name##_RB_PREV(x)) + +#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ + for ((x) = RB_MAX(name, head); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \ + (x) = (y)) +#endif /* !HAVE_SYS_TREE */ diff --git a/configure b/configure index ee73c0f..5c2ffd0 100755 --- a/configure +++ b/configure @@ -717,1384 +717,6 @@ if [ ${HAVE_SECCOMP_FILTER} -eq 1 ]; then echo fi -if [ ${HAVE_SYS_QUEUE} -eq 0 ]; then - cat << __HEREDOC__ -/* - * A compatible version of OpenBSD . - */ -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -/* OPENBSD ORIGINAL: sys/sys/queue.h */ - -/* - * Require for OS/X and other platforms that have old/broken/incomplete - * . - */ - -#undef LIST_EMPTY -#undef LIST_END -#undef LIST_ENTRY -#undef LIST_FIRST -#undef LIST_FOREACH -#undef LIST_FOREACH_SAFE -#undef LIST_HEAD -#undef LIST_HEAD_INITIALIZER -#undef LIST_INIT -#undef LIST_INSERT_AFTER -#undef LIST_INSERT_BEFORE -#undef LIST_INSERT_HEAD -#undef LIST_NEXT -#undef LIST_REMOVE -#undef LIST_REPLACE -#undef SIMPLEQ_CONCAT -#undef SIMPLEQ_EMPTY -#undef SIMPLEQ_END -#undef SIMPLEQ_ENTRY -#undef SIMPLEQ_FIRST -#undef SIMPLEQ_FOREACH -#undef SIMPLEQ_FOREACH_SAFE -#undef SIMPLEQ_HEAD -#undef SIMPLEQ_HEAD_INITIALIZER -#undef SIMPLEQ_INIT -#undef SIMPLEQ_INSERT_AFTER -#undef SIMPLEQ_INSERT_HEAD -#undef SIMPLEQ_INSERT_TAIL -#undef SIMPLEQ_NEXT -#undef SIMPLEQ_REMOVE_AFTER -#undef SIMPLEQ_REMOVE_HEAD -#undef SLIST_EMPTY -#undef SLIST_END -#undef SLIST_ENTRY -#undef SLIST_FIRST -#undef SLIST_FOREACH -#undef SLIST_FOREACH_SAFE -#undef SLIST_HEAD -#undef SLIST_HEAD_INITIALIZER -#undef SLIST_INIT -#undef SLIST_INSERT_AFTER -#undef SLIST_INSERT_HEAD -#undef SLIST_NEXT -#undef SLIST_REMOVE -#undef SLIST_REMOVE_AFTER -#undef SLIST_REMOVE_HEAD -#undef TAILQ_CONCAT -#undef TAILQ_EMPTY -#undef TAILQ_END -#undef TAILQ_ENTRY -#undef TAILQ_FIRST -#undef TAILQ_FOREACH -#undef TAILQ_FOREACH_REVERSE -#undef TAILQ_FOREACH_REVERSE_SAFE -#undef TAILQ_FOREACH_SAFE -#undef TAILQ_HEAD -#undef TAILQ_HEAD_INITIALIZER -#undef TAILQ_INIT -#undef TAILQ_INSERT_AFTER -#undef TAILQ_INSERT_BEFORE -#undef TAILQ_INSERT_HEAD -#undef TAILQ_INSERT_TAIL -#undef TAILQ_LAST -#undef TAILQ_NEXT -#undef TAILQ_PREV -#undef TAILQ_REMOVE -#undef TAILQ_REPLACE -#undef XSIMPLEQ_EMPTY -#undef XSIMPLEQ_END -#undef XSIMPLEQ_ENTRY -#undef XSIMPLEQ_FIRST -#undef XSIMPLEQ_FOREACH -#undef XSIMPLEQ_FOREACH_SAFE -#undef XSIMPLEQ_HEAD -#undef XSIMPLEQ_INIT -#undef XSIMPLEQ_INSERT_AFTER -#undef XSIMPLEQ_INSERT_HEAD -#undef XSIMPLEQ_INSERT_TAIL -#undef XSIMPLEQ_NEXT -#undef XSIMPLEQ_REMOVE_AFTER -#undef XSIMPLEQ_REMOVE_HEAD -#undef XSIMPLEQ_XOR - -/* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues and XOR simple queues. - * - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * An XOR simple queue is used in the same way as a regular simple queue. - * The difference is that the head structure also includes a "cookie" that - * is XOR'd with the queue pointer (first, last or next) to generate the - * real pointer value. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) -#define _Q_INVALID ((void *)-1) -#define _Q_INVALIDATE(a) (a) = _Q_INVALID -#else -#define _Q_INVALIDATE(a) -#endif - -/* - * Singly-linked List definitions. - */ -#define SLIST_HEAD(name, type) \\ -struct name { \\ - struct type *slh_first; /* first element */ \\ -} - -#define SLIST_HEAD_INITIALIZER(head) \\ - { NULL } - -#define SLIST_ENTRY(type) \\ -struct { \\ - struct type *sle_next; /* next element */ \\ -} - -/* - * Singly-linked List access methods. - */ -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_END(head) NULL -#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \\ - for((var) = SLIST_FIRST(head); \\ - (var) != SLIST_END(head); \\ - (var) = SLIST_NEXT(var, field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \\ - for ((var) = SLIST_FIRST(head); \\ - (var) && ((tvar) = SLIST_NEXT(var, field), 1); \\ - (var) = (tvar)) - -/* - * Singly-linked List functions. - */ -#define SLIST_INIT(head) { \\ - SLIST_FIRST(head) = SLIST_END(head); \\ -} - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \\ - (elm)->field.sle_next = (slistelm)->field.sle_next; \\ - (slistelm)->field.sle_next = (elm); \\ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \\ - (elm)->field.sle_next = (head)->slh_first; \\ - (head)->slh_first = (elm); \\ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \\ - (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \\ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \\ - (head)->slh_first = (head)->slh_first->field.sle_next; \\ -} while (0) - -#define SLIST_REMOVE(head, elm, type, field) do { \\ - if ((head)->slh_first == (elm)) { \\ - SLIST_REMOVE_HEAD((head), field); \\ - } else { \\ - struct type *curelm = (head)->slh_first; \\ - \\ - while (curelm->field.sle_next != (elm)) \\ - curelm = curelm->field.sle_next; \\ - curelm->field.sle_next = \\ - curelm->field.sle_next->field.sle_next; \\ - } \\ - _Q_INVALIDATE((elm)->field.sle_next); \\ -} while (0) - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \\ -struct name { \\ - struct type *lh_first; /* first element */ \\ -} - -#define LIST_HEAD_INITIALIZER(head) \\ - { NULL } - -#define LIST_ENTRY(type) \\ -struct { \\ - struct type *le_next; /* next element */ \\ - struct type **le_prev; /* address of previous next element */ \\ -} - -/* - * List access methods. - */ -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_END(head) NULL -#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_FOREACH(var, head, field) \\ - for((var) = LIST_FIRST(head); \\ - (var)!= LIST_END(head); \\ - (var) = LIST_NEXT(var, field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \\ - for ((var) = LIST_FIRST(head); \\ - (var) && ((tvar) = LIST_NEXT(var, field), 1); \\ - (var) = (tvar)) - -/* - * List functions. - */ -#define LIST_INIT(head) do { \\ - LIST_FIRST(head) = LIST_END(head); \\ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \\ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \\ - (listelm)->field.le_next->field.le_prev = \\ - &(elm)->field.le_next; \\ - (listelm)->field.le_next = (elm); \\ - (elm)->field.le_prev = &(listelm)->field.le_next; \\ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \\ - (elm)->field.le_prev = (listelm)->field.le_prev; \\ - (elm)->field.le_next = (listelm); \\ - *(listelm)->field.le_prev = (elm); \\ - (listelm)->field.le_prev = &(elm)->field.le_next; \\ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \\ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \\ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\\ - (head)->lh_first = (elm); \\ - (elm)->field.le_prev = &(head)->lh_first; \\ -} while (0) - -#define LIST_REMOVE(elm, field) do { \\ - if ((elm)->field.le_next != NULL) \\ - (elm)->field.le_next->field.le_prev = \\ - (elm)->field.le_prev; \\ - *(elm)->field.le_prev = (elm)->field.le_next; \\ - _Q_INVALIDATE((elm)->field.le_prev); \\ - _Q_INVALIDATE((elm)->field.le_next); \\ -} while (0) - -#define LIST_REPLACE(elm, elm2, field) do { \\ - if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \\ - (elm2)->field.le_next->field.le_prev = \\ - &(elm2)->field.le_next; \\ - (elm2)->field.le_prev = (elm)->field.le_prev; \\ - *(elm2)->field.le_prev = (elm2); \\ - _Q_INVALIDATE((elm)->field.le_prev); \\ - _Q_INVALIDATE((elm)->field.le_next); \\ -} while (0) - -/* - * Simple queue definitions. - */ -#define SIMPLEQ_HEAD(name, type) \\ -struct name { \\ - struct type *sqh_first; /* first element */ \\ - struct type **sqh_last; /* addr of last next element */ \\ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \\ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \\ -struct { \\ - struct type *sqe_next; /* next element */ \\ -} - -/* - * Simple queue access methods. - */ -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_END(head) NULL -#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -#define SIMPLEQ_FOREACH(var, head, field) \\ - for((var) = SIMPLEQ_FIRST(head); \\ - (var) != SIMPLEQ_END(head); \\ - (var) = SIMPLEQ_NEXT(var, field)) - -#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \\ - for ((var) = SIMPLEQ_FIRST(head); \\ - (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \\ - (var) = (tvar)) - -/* - * Simple queue functions. - */ -#define SIMPLEQ_INIT(head) do { \\ - (head)->sqh_first = NULL; \\ - (head)->sqh_last = &(head)->sqh_first; \\ -} while (0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \\ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \\ - (head)->sqh_last = &(elm)->field.sqe_next; \\ - (head)->sqh_first = (elm); \\ -} while (0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \\ - (elm)->field.sqe_next = NULL; \\ - *(head)->sqh_last = (elm); \\ - (head)->sqh_last = &(elm)->field.sqe_next; \\ -} while (0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \\ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\\ - (head)->sqh_last = &(elm)->field.sqe_next; \\ - (listelm)->field.sqe_next = (elm); \\ -} while (0) - -#define SIMPLEQ_REMOVE_HEAD(head, field) do { \\ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \\ - (head)->sqh_last = &(head)->sqh_first; \\ -} while (0) - -#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \\ - if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \\ - == NULL) \\ - (head)->sqh_last = &(elm)->field.sqe_next; \\ -} while (0) - -#define SIMPLEQ_CONCAT(head1, head2) do { \\ - if (!SIMPLEQ_EMPTY((head2))) { \\ - *(head1)->sqh_last = (head2)->sqh_first; \\ - (head1)->sqh_last = (head2)->sqh_last; \\ - SIMPLEQ_INIT((head2)); \\ - } \\ -} while (0) - -/* - * XOR Simple queue definitions. - */ -#define XSIMPLEQ_HEAD(name, type) \\ -struct name { \\ - struct type *sqx_first; /* first element */ \\ - struct type **sqx_last; /* addr of last next element */ \\ - unsigned long sqx_cookie; \\ -} - -#define XSIMPLEQ_ENTRY(type) \\ -struct { \\ - struct type *sqx_next; /* next element */ \\ -} - -/* - * XOR Simple queue access methods. - */ -#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \\ - (unsigned long)(ptr))) -#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) -#define XSIMPLEQ_END(head) NULL -#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) -#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) - - -#define XSIMPLEQ_FOREACH(var, head, field) \\ - for ((var) = XSIMPLEQ_FIRST(head); \\ - (var) != XSIMPLEQ_END(head); \\ - (var) = XSIMPLEQ_NEXT(head, var, field)) - -#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \\ - for ((var) = XSIMPLEQ_FIRST(head); \\ - (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \\ - (var) = (tvar)) - -/* - * XOR Simple queue functions. - */ -#define XSIMPLEQ_INIT(head) do { \\ - arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \\ - (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \\ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \\ -} while (0) - -#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \\ - if (((elm)->field.sqx_next = (head)->sqx_first) == \\ - XSIMPLEQ_XOR(head, NULL)) \\ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \\ - (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \\ -} while (0) - -#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \\ - (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \\ - *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \\ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \\ -} while (0) - -#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \\ - if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \\ - XSIMPLEQ_XOR(head, NULL)) \\ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \\ - (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \\ -} while (0) - -#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \\ - if (((head)->sqx_first = XSIMPLEQ_XOR(head, \\ - (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \\ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \\ -} while (0) - -#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \\ - if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \\ - (elm)->field.sqx_next)->field.sqx_next) \\ - == XSIMPLEQ_XOR(head, NULL)) \\ - (head)->sqx_last = \\ - XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \\ -} while (0) - - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \\ -struct name { \\ - struct type *tqh_first; /* first element */ \\ - struct type **tqh_last; /* addr of last next element */ \\ -} - -#define TAILQ_HEAD_INITIALIZER(head) \\ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \\ -struct { \\ - struct type *tqe_next; /* next element */ \\ - struct type **tqe_prev; /* address of previous next element */ \\ -} - -/* - * Tail queue access methods. - */ -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \\ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -/* XXX */ -#define TAILQ_PREV(elm, headname, field) \\ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \\ - (TAILQ_FIRST(head) == TAILQ_END(head)) - -#define TAILQ_FOREACH(var, head, field) \\ - for((var) = TAILQ_FIRST(head); \\ - (var) != TAILQ_END(head); \\ - (var) = TAILQ_NEXT(var, field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \\ - for ((var) = TAILQ_FIRST(head); \\ - (var) != TAILQ_END(head) && \\ - ((tvar) = TAILQ_NEXT(var, field), 1); \\ - (var) = (tvar)) - - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \\ - for((var) = TAILQ_LAST(head, headname); \\ - (var) != TAILQ_END(head); \\ - (var) = TAILQ_PREV(var, headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \\ - for ((var) = TAILQ_LAST(head, headname); \\ - (var) != TAILQ_END(head) && \\ - ((tvar) = TAILQ_PREV(var, headname, field), 1); \\ - (var) = (tvar)) - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \\ - (head)->tqh_first = NULL; \\ - (head)->tqh_last = &(head)->tqh_first; \\ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \\ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \\ - (head)->tqh_first->field.tqe_prev = \\ - &(elm)->field.tqe_next; \\ - else \\ - (head)->tqh_last = &(elm)->field.tqe_next; \\ - (head)->tqh_first = (elm); \\ - (elm)->field.tqe_prev = &(head)->tqh_first; \\ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \\ - (elm)->field.tqe_next = NULL; \\ - (elm)->field.tqe_prev = (head)->tqh_last; \\ - *(head)->tqh_last = (elm); \\ - (head)->tqh_last = &(elm)->field.tqe_next; \\ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \\ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\\ - (elm)->field.tqe_next->field.tqe_prev = \\ - &(elm)->field.tqe_next; \\ - else \\ - (head)->tqh_last = &(elm)->field.tqe_next; \\ - (listelm)->field.tqe_next = (elm); \\ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \\ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \\ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \\ - (elm)->field.tqe_next = (listelm); \\ - *(listelm)->field.tqe_prev = (elm); \\ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \\ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \\ - if (((elm)->field.tqe_next) != NULL) \\ - (elm)->field.tqe_next->field.tqe_prev = \\ - (elm)->field.tqe_prev; \\ - else \\ - (head)->tqh_last = (elm)->field.tqe_prev; \\ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \\ - _Q_INVALIDATE((elm)->field.tqe_prev); \\ - _Q_INVALIDATE((elm)->field.tqe_next); \\ -} while (0) - -#define TAILQ_REPLACE(head, elm, elm2, field) do { \\ - if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \\ - (elm2)->field.tqe_next->field.tqe_prev = \\ - &(elm2)->field.tqe_next; \\ - else \\ - (head)->tqh_last = &(elm2)->field.tqe_next; \\ - (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \\ - *(elm2)->field.tqe_prev = (elm2); \\ - _Q_INVALIDATE((elm)->field.tqe_prev); \\ - _Q_INVALIDATE((elm)->field.tqe_next); \\ -} while (0) - -#define TAILQ_CONCAT(head1, head2, field) do { \\ - if (!TAILQ_EMPTY(head2)) { \\ - *(head1)->tqh_last = (head2)->tqh_first; \\ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \\ - (head1)->tqh_last = (head2)->tqh_last; \\ - TAILQ_INIT((head2)); \\ - } \\ -} while (0) - -__HEREDOC__ -fi - -if [ ${HAVE_SYS_TREE} -eq 0 ]; then - cat << __HEREDOC__ -/* - * A compatible version of OpenBSD . - */ -/* - * Copyright 2002 Niels Provos - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* OPENBSD ORIGINAL: sys/sys/tree.h */ - -/* - * This file defines data structures for different types of trees: - * splay trees and red-black trees. - * - * A splay tree is a self-organizing data structure. Every operation - * on the tree causes a splay to happen. The splay moves the requested - * node to the root of the tree and partly rebalances it. - * - * This has the benefit that request locality causes faster lookups as - * the requested nodes move to the top of the tree. On the other hand, - * every lookup causes memory writes. - * - * The Balance Theorem bounds the total access time for m operations - * and n inserts on an initially empty tree as O((m + n)lg n). The - * amortized cost for a sequence of m accesses to a splay tree is O(lg n); - * - * A red-black tree is a binary search tree with the node color as an - * extra attribute. It fulfills a set of conditions: - * - every search path from the root to a leaf consists of the - * same number of black nodes, - * - each red node (except for the root) has a black parent, - * - each leaf node is black. - * - * Every operation on a red-black tree is bounded as O(lg n). - * The maximum height of a red-black tree is 2lg (n+1). - */ - -#define SPLAY_HEAD(name, type) \\ -struct name { \\ - struct type *sph_root; /* root of the tree */ \\ -} - -#define SPLAY_INITIALIZER(root) \\ - { NULL } - -#define SPLAY_INIT(root) do { \\ - (root)->sph_root = NULL; \\ -} while (0) - -#define SPLAY_ENTRY(type) \\ -struct { \\ - struct type *spe_left; /* left element */ \\ - struct type *spe_right; /* right element */ \\ -} - -#define SPLAY_LEFT(elm, field) (elm)->field.spe_left -#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right -#define SPLAY_ROOT(head) (head)->sph_root -#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) - -/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ -#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \\ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \\ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \\ - (head)->sph_root = tmp; \\ -} while (0) - -#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \\ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \\ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \\ - (head)->sph_root = tmp; \\ -} while (0) - -#define SPLAY_LINKLEFT(head, tmp, field) do { \\ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \\ - tmp = (head)->sph_root; \\ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \\ -} while (0) - -#define SPLAY_LINKRIGHT(head, tmp, field) do { \\ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \\ - tmp = (head)->sph_root; \\ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \\ -} while (0) - -#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \\ - SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \\ - SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\\ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \\ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \\ -} while (0) - -/* Generates prototypes and inline functions */ - -#define SPLAY_PROTOTYPE(name, type, field, cmp) \\ -void name##_SPLAY(struct name *, struct type *); \\ -void name##_SPLAY_MINMAX(struct name *, int); \\ -struct type *name##_SPLAY_INSERT(struct name *, struct type *); \\ -struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \\ - \\ -/* Finds the node with the same key as elm */ \\ -static __inline struct type * \\ -name##_SPLAY_FIND(struct name *head, struct type *elm) \\ -{ \\ - if (SPLAY_EMPTY(head)) \\ - return(NULL); \\ - name##_SPLAY(head, elm); \\ - if ((cmp)(elm, (head)->sph_root) == 0) \\ - return (head->sph_root); \\ - return (NULL); \\ -} \\ - \\ -static __inline struct type * \\ -name##_SPLAY_NEXT(struct name *head, struct type *elm) \\ -{ \\ - name##_SPLAY(head, elm); \\ - if (SPLAY_RIGHT(elm, field) != NULL) { \\ - elm = SPLAY_RIGHT(elm, field); \\ - while (SPLAY_LEFT(elm, field) != NULL) { \\ - elm = SPLAY_LEFT(elm, field); \\ - } \\ - } else \\ - elm = NULL; \\ - return (elm); \\ -} \\ - \\ -static __inline struct type * \\ -name##_SPLAY_MIN_MAX(struct name *head, int val) \\ -{ \\ - name##_SPLAY_MINMAX(head, val); \\ - return (SPLAY_ROOT(head)); \\ -} - -/* Main splay operation. - * Moves node close to the key of elm to top - */ -#define SPLAY_GENERATE(name, type, field, cmp) \\ -struct type * \\ -name##_SPLAY_INSERT(struct name *head, struct type *elm) \\ -{ \\ - if (SPLAY_EMPTY(head)) { \\ - SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \\ - } else { \\ - int __comp; \\ - name##_SPLAY(head, elm); \\ - __comp = (cmp)(elm, (head)->sph_root); \\ - if(__comp < 0) { \\ - SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\\ - SPLAY_RIGHT(elm, field) = (head)->sph_root; \\ - SPLAY_LEFT((head)->sph_root, field) = NULL; \\ - } else if (__comp > 0) { \\ - SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\\ - SPLAY_LEFT(elm, field) = (head)->sph_root; \\ - SPLAY_RIGHT((head)->sph_root, field) = NULL; \\ - } else \\ - return ((head)->sph_root); \\ - } \\ - (head)->sph_root = (elm); \\ - return (NULL); \\ -} \\ - \\ -struct type * \\ -name##_SPLAY_REMOVE(struct name *head, struct type *elm) \\ -{ \\ - struct type *__tmp; \\ - if (SPLAY_EMPTY(head)) \\ - return (NULL); \\ - name##_SPLAY(head, elm); \\ - if ((cmp)(elm, (head)->sph_root) == 0) { \\ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \\ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\\ - } else { \\ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \\ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\\ - name##_SPLAY(head, elm); \\ - SPLAY_RIGHT((head)->sph_root, field) = __tmp; \\ - } \\ - return (elm); \\ - } \\ - return (NULL); \\ -} \\ - \\ -void \\ -name##_SPLAY(struct name *head, struct type *elm) \\ -{ \\ - struct type __node, *__left, *__right, *__tmp; \\ - int __comp; \\ -\\ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\\ - __left = __right = &__node; \\ -\\ - while ((__comp = (cmp)(elm, (head)->sph_root))) { \\ - if (__comp < 0) { \\ - __tmp = SPLAY_LEFT((head)->sph_root, field); \\ - if (__tmp == NULL) \\ - break; \\ - if ((cmp)(elm, __tmp) < 0){ \\ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \\ - if (SPLAY_LEFT((head)->sph_root, field) == NULL)\\ - break; \\ - } \\ - SPLAY_LINKLEFT(head, __right, field); \\ - } else if (__comp > 0) { \\ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \\ - if (__tmp == NULL) \\ - break; \\ - if ((cmp)(elm, __tmp) > 0){ \\ - SPLAY_ROTATE_LEFT(head, __tmp, field); \\ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\\ - break; \\ - } \\ - SPLAY_LINKRIGHT(head, __left, field); \\ - } \\ - } \\ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \\ -} \\ - \\ -/* Splay with either the minimum or the maximum element \\ - * Used to find minimum or maximum element in tree. \\ - */ \\ -void name##_SPLAY_MINMAX(struct name *head, int __comp) \\ -{ \\ - struct type __node, *__left, *__right, *__tmp; \\ -\\ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\\ - __left = __right = &__node; \\ -\\ - while (1) { \\ - if (__comp < 0) { \\ - __tmp = SPLAY_LEFT((head)->sph_root, field); \\ - if (__tmp == NULL) \\ - break; \\ - if (__comp < 0){ \\ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \\ - if (SPLAY_LEFT((head)->sph_root, field) == NULL)\\ - break; \\ - } \\ - SPLAY_LINKLEFT(head, __right, field); \\ - } else if (__comp > 0) { \\ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \\ - if (__tmp == NULL) \\ - break; \\ - if (__comp > 0) { \\ - SPLAY_ROTATE_LEFT(head, __tmp, field); \\ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\\ - break; \\ - } \\ - SPLAY_LINKRIGHT(head, __left, field); \\ - } \\ - } \\ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \\ -} - -#define SPLAY_NEGINF -1 -#define SPLAY_INF 1 - -#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) -#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) -#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) -#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) -#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \\ - : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) -#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \\ - : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) - -#define SPLAY_FOREACH(x, name, head) \\ - for ((x) = SPLAY_MIN(name, head); \\ - (x) != NULL; \\ - (x) = SPLAY_NEXT(name, head, x)) - -/* Macros that define a red-black tree */ -#define RB_HEAD(name, type) \\ -struct name { \\ - struct type *rbh_root; /* root of the tree */ \\ -} - -#define RB_INITIALIZER(root) \\ - { NULL } - -#define RB_INIT(root) do { \\ - (root)->rbh_root = NULL; \\ -} while (0) - -#define RB_BLACK 0 -#define RB_RED 1 -#define RB_ENTRY(type) \\ -struct { \\ - struct type *rbe_left; /* left element */ \\ - struct type *rbe_right; /* right element */ \\ - struct type *rbe_parent; /* parent element */ \\ - int rbe_color; /* node color */ \\ -} - -#define RB_LEFT(elm, field) (elm)->field.rbe_left -#define RB_RIGHT(elm, field) (elm)->field.rbe_right -#define RB_PARENT(elm, field) (elm)->field.rbe_parent -#define RB_COLOR(elm, field) (elm)->field.rbe_color -#define RB_ROOT(head) (head)->rbh_root -#define RB_EMPTY(head) (RB_ROOT(head) == NULL) - -#define RB_SET(elm, parent, field) do { \\ - RB_PARENT(elm, field) = parent; \\ - RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \\ - RB_COLOR(elm, field) = RB_RED; \\ -} while (0) - -#define RB_SET_BLACKRED(black, red, field) do { \\ - RB_COLOR(black, field) = RB_BLACK; \\ - RB_COLOR(red, field) = RB_RED; \\ -} while (0) - -#ifndef RB_AUGMENT -#define RB_AUGMENT(x) do {} while (0) -#endif - -#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \\ - (tmp) = RB_RIGHT(elm, field); \\ - if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \\ - RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \\ - } \\ - RB_AUGMENT(elm); \\ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \\ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \\ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \\ - else \\ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \\ - } else \\ - (head)->rbh_root = (tmp); \\ - RB_LEFT(tmp, field) = (elm); \\ - RB_PARENT(elm, field) = (tmp); \\ - RB_AUGMENT(tmp); \\ - if ((RB_PARENT(tmp, field))) \\ - RB_AUGMENT(RB_PARENT(tmp, field)); \\ -} while (0) - -#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \\ - (tmp) = RB_LEFT(elm, field); \\ - if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \\ - RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \\ - } \\ - RB_AUGMENT(elm); \\ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \\ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \\ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \\ - else \\ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \\ - } else \\ - (head)->rbh_root = (tmp); \\ - RB_RIGHT(tmp, field) = (elm); \\ - RB_PARENT(elm, field) = (tmp); \\ - RB_AUGMENT(tmp); \\ - if ((RB_PARENT(tmp, field))) \\ - RB_AUGMENT(RB_PARENT(tmp, field)); \\ -} while (0) - -/* Generates prototypes and inline functions */ -#define RB_PROTOTYPE(name, type, field, cmp) \\ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) -#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \\ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) -#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \\ -attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \\ -attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\\ -attr struct type *name##_RB_REMOVE(struct name *, struct type *); \\ -attr struct type *name##_RB_INSERT(struct name *, struct type *); \\ -attr struct type *name##_RB_FIND(struct name *, struct type *); \\ -attr struct type *name##_RB_NFIND(struct name *, struct type *); \\ -attr struct type *name##_RB_NEXT(struct type *); \\ -attr struct type *name##_RB_PREV(struct type *); \\ -attr struct type *name##_RB_MINMAX(struct name *, int); \\ - \\ - -/* Main rb operation. - * Moves node close to the key of elm to top - */ -#define RB_GENERATE(name, type, field, cmp) \\ - RB_GENERATE_INTERNAL(name, type, field, cmp,) -#define RB_GENERATE_STATIC(name, type, field, cmp) \\ - RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) -#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \\ -attr void \\ -name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \\ -{ \\ - struct type *parent, *gparent, *tmp; \\ - while ((parent = RB_PARENT(elm, field)) && \\ - RB_COLOR(parent, field) == RB_RED) { \\ - gparent = RB_PARENT(parent, field); \\ - if (parent == RB_LEFT(gparent, field)) { \\ - tmp = RB_RIGHT(gparent, field); \\ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \\ - RB_COLOR(tmp, field) = RB_BLACK; \\ - RB_SET_BLACKRED(parent, gparent, field);\\ - elm = gparent; \\ - continue; \\ - } \\ - if (RB_RIGHT(parent, field) == elm) { \\ - RB_ROTATE_LEFT(head, parent, tmp, field);\\ - tmp = parent; \\ - parent = elm; \\ - elm = tmp; \\ - } \\ - RB_SET_BLACKRED(parent, gparent, field); \\ - RB_ROTATE_RIGHT(head, gparent, tmp, field); \\ - } else { \\ - tmp = RB_LEFT(gparent, field); \\ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \\ - RB_COLOR(tmp, field) = RB_BLACK; \\ - RB_SET_BLACKRED(parent, gparent, field);\\ - elm = gparent; \\ - continue; \\ - } \\ - if (RB_LEFT(parent, field) == elm) { \\ - RB_ROTATE_RIGHT(head, parent, tmp, field);\\ - tmp = parent; \\ - parent = elm; \\ - elm = tmp; \\ - } \\ - RB_SET_BLACKRED(parent, gparent, field); \\ - RB_ROTATE_LEFT(head, gparent, tmp, field); \\ - } \\ - } \\ - RB_COLOR(head->rbh_root, field) = RB_BLACK; \\ -} \\ - \\ -attr void \\ -name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \\ -{ \\ - struct type *tmp; \\ - while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \\ - elm != RB_ROOT(head)) { \\ - if (RB_LEFT(parent, field) == elm) { \\ - tmp = RB_RIGHT(parent, field); \\ - if (RB_COLOR(tmp, field) == RB_RED) { \\ - RB_SET_BLACKRED(tmp, parent, field); \\ - RB_ROTATE_LEFT(head, parent, tmp, field);\\ - tmp = RB_RIGHT(parent, field); \\ - } \\ - if ((RB_LEFT(tmp, field) == NULL || \\ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\\ - (RB_RIGHT(tmp, field) == NULL || \\ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\\ - RB_COLOR(tmp, field) = RB_RED; \\ - elm = parent; \\ - parent = RB_PARENT(elm, field); \\ - } else { \\ - if (RB_RIGHT(tmp, field) == NULL || \\ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\\ - struct type *oleft; \\ - if ((oleft = RB_LEFT(tmp, field)))\\ - RB_COLOR(oleft, field) = RB_BLACK;\\ - RB_COLOR(tmp, field) = RB_RED; \\ - RB_ROTATE_RIGHT(head, tmp, oleft, field);\\ - tmp = RB_RIGHT(parent, field); \\ - } \\ - RB_COLOR(tmp, field) = RB_COLOR(parent, field);\\ - RB_COLOR(parent, field) = RB_BLACK; \\ - if (RB_RIGHT(tmp, field)) \\ - RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\\ - RB_ROTATE_LEFT(head, parent, tmp, field);\\ - elm = RB_ROOT(head); \\ - break; \\ - } \\ - } else { \\ - tmp = RB_LEFT(parent, field); \\ - if (RB_COLOR(tmp, field) == RB_RED) { \\ - RB_SET_BLACKRED(tmp, parent, field); \\ - RB_ROTATE_RIGHT(head, parent, tmp, field);\\ - tmp = RB_LEFT(parent, field); \\ - } \\ - if ((RB_LEFT(tmp, field) == NULL || \\ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\\ - (RB_RIGHT(tmp, field) == NULL || \\ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\\ - RB_COLOR(tmp, field) = RB_RED; \\ - elm = parent; \\ - parent = RB_PARENT(elm, field); \\ - } else { \\ - if (RB_LEFT(tmp, field) == NULL || \\ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\\ - struct type *oright; \\ - if ((oright = RB_RIGHT(tmp, field)))\\ - RB_COLOR(oright, field) = RB_BLACK;\\ - RB_COLOR(tmp, field) = RB_RED; \\ - RB_ROTATE_LEFT(head, tmp, oright, field);\\ - tmp = RB_LEFT(parent, field); \\ - } \\ - RB_COLOR(tmp, field) = RB_COLOR(parent, field);\\ - RB_COLOR(parent, field) = RB_BLACK; \\ - if (RB_LEFT(tmp, field)) \\ - RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\\ - RB_ROTATE_RIGHT(head, parent, tmp, field);\\ - elm = RB_ROOT(head); \\ - break; \\ - } \\ - } \\ - } \\ - if (elm) \\ - RB_COLOR(elm, field) = RB_BLACK; \\ -} \\ - \\ -attr struct type * \\ -name##_RB_REMOVE(struct name *head, struct type *elm) \\ -{ \\ - struct type *child, *parent, *old = elm; \\ - int color; \\ - if (RB_LEFT(elm, field) == NULL) \\ - child = RB_RIGHT(elm, field); \\ - else if (RB_RIGHT(elm, field) == NULL) \\ - child = RB_LEFT(elm, field); \\ - else { \\ - struct type *left; \\ - elm = RB_RIGHT(elm, field); \\ - while ((left = RB_LEFT(elm, field))) \\ - elm = left; \\ - child = RB_RIGHT(elm, field); \\ - parent = RB_PARENT(elm, field); \\ - color = RB_COLOR(elm, field); \\ - if (child) \\ - RB_PARENT(child, field) = parent; \\ - if (parent) { \\ - if (RB_LEFT(parent, field) == elm) \\ - RB_LEFT(parent, field) = child; \\ - else \\ - RB_RIGHT(parent, field) = child; \\ - RB_AUGMENT(parent); \\ - } else \\ - RB_ROOT(head) = child; \\ - if (RB_PARENT(elm, field) == old) \\ - parent = elm; \\ - (elm)->field = (old)->field; \\ - if (RB_PARENT(old, field)) { \\ - if (RB_LEFT(RB_PARENT(old, field), field) == old)\\ - RB_LEFT(RB_PARENT(old, field), field) = elm;\\ - else \\ - RB_RIGHT(RB_PARENT(old, field), field) = elm;\\ - RB_AUGMENT(RB_PARENT(old, field)); \\ - } else \\ - RB_ROOT(head) = elm; \\ - RB_PARENT(RB_LEFT(old, field), field) = elm; \\ - if (RB_RIGHT(old, field)) \\ - RB_PARENT(RB_RIGHT(old, field), field) = elm; \\ - if (parent) { \\ - left = parent; \\ - do { \\ - RB_AUGMENT(left); \\ - } while ((left = RB_PARENT(left, field))); \\ - } \\ - goto color; \\ - } \\ - parent = RB_PARENT(elm, field); \\ - color = RB_COLOR(elm, field); \\ - if (child) \\ - RB_PARENT(child, field) = parent; \\ - if (parent) { \\ - if (RB_LEFT(parent, field) == elm) \\ - RB_LEFT(parent, field) = child; \\ - else \\ - RB_RIGHT(parent, field) = child; \\ - RB_AUGMENT(parent); \\ - } else \\ - RB_ROOT(head) = child; \\ -color: \\ - if (color == RB_BLACK) \\ - name##_RB_REMOVE_COLOR(head, parent, child); \\ - return (old); \\ -} \\ - \\ -/* Inserts a node into the RB tree */ \\ -attr struct type * \\ -name##_RB_INSERT(struct name *head, struct type *elm) \\ -{ \\ - struct type *tmp; \\ - struct type *parent = NULL; \\ - int comp = 0; \\ - tmp = RB_ROOT(head); \\ - while (tmp) { \\ - parent = tmp; \\ - comp = (cmp)(elm, parent); \\ - if (comp < 0) \\ - tmp = RB_LEFT(tmp, field); \\ - else if (comp > 0) \\ - tmp = RB_RIGHT(tmp, field); \\ - else \\ - return (tmp); \\ - } \\ - RB_SET(elm, parent, field); \\ - if (parent != NULL) { \\ - if (comp < 0) \\ - RB_LEFT(parent, field) = elm; \\ - else \\ - RB_RIGHT(parent, field) = elm; \\ - RB_AUGMENT(parent); \\ - } else \\ - RB_ROOT(head) = elm; \\ - name##_RB_INSERT_COLOR(head, elm); \\ - return (NULL); \\ -} \\ - \\ -/* Finds the node with the same key as elm */ \\ -attr struct type * \\ -name##_RB_FIND(struct name *head, struct type *elm) \\ -{ \\ - struct type *tmp = RB_ROOT(head); \\ - int comp; \\ - while (tmp) { \\ - comp = cmp(elm, tmp); \\ - if (comp < 0) \\ - tmp = RB_LEFT(tmp, field); \\ - else if (comp > 0) \\ - tmp = RB_RIGHT(tmp, field); \\ - else \\ - return (tmp); \\ - } \\ - return (NULL); \\ -} \\ - \\ -/* Finds the first node greater than or equal to the search key */ \\ -attr struct type * \\ -name##_RB_NFIND(struct name *head, struct type *elm) \\ -{ \\ - struct type *tmp = RB_ROOT(head); \\ - struct type *res = NULL; \\ - int comp; \\ - while (tmp) { \\ - comp = cmp(elm, tmp); \\ - if (comp < 0) { \\ - res = tmp; \\ - tmp = RB_LEFT(tmp, field); \\ - } \\ - else if (comp > 0) \\ - tmp = RB_RIGHT(tmp, field); \\ - else \\ - return (tmp); \\ - } \\ - return (res); \\ -} \\ - \\ -/* ARGSUSED */ \\ -attr struct type * \\ -name##_RB_NEXT(struct type *elm) \\ -{ \\ - if (RB_RIGHT(elm, field)) { \\ - elm = RB_RIGHT(elm, field); \\ - while (RB_LEFT(elm, field)) \\ - elm = RB_LEFT(elm, field); \\ - } else { \\ - if (RB_PARENT(elm, field) && \\ - (elm == RB_LEFT(RB_PARENT(elm, field), field))) \\ - elm = RB_PARENT(elm, field); \\ - else { \\ - while (RB_PARENT(elm, field) && \\ - (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\\ - elm = RB_PARENT(elm, field); \\ - elm = RB_PARENT(elm, field); \\ - } \\ - } \\ - return (elm); \\ -} \\ - \\ -/* ARGSUSED */ \\ -attr struct type * \\ -name##_RB_PREV(struct type *elm) \\ -{ \\ - if (RB_LEFT(elm, field)) { \\ - elm = RB_LEFT(elm, field); \\ - while (RB_RIGHT(elm, field)) \\ - elm = RB_RIGHT(elm, field); \\ - } else { \\ - if (RB_PARENT(elm, field) && \\ - (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \\ - elm = RB_PARENT(elm, field); \\ - else { \\ - while (RB_PARENT(elm, field) && \\ - (elm == RB_LEFT(RB_PARENT(elm, field), field)))\\ - elm = RB_PARENT(elm, field); \\ - elm = RB_PARENT(elm, field); \\ - } \\ - } \\ - return (elm); \\ -} \\ - \\ -attr struct type * \\ -name##_RB_MINMAX(struct name *head, int val) \\ -{ \\ - struct type *tmp = RB_ROOT(head); \\ - struct type *parent = NULL; \\ - while (tmp) { \\ - parent = tmp; \\ - if (val < 0) \\ - tmp = RB_LEFT(tmp, field); \\ - else \\ - tmp = RB_RIGHT(tmp, field); \\ - } \\ - return (parent); \\ -} - -#define RB_NEGINF -1 -#define RB_INF 1 - -#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) -#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) -#define RB_FIND(name, x, y) name##_RB_FIND(x, y) -#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) -#define RB_NEXT(name, x, y) name##_RB_NEXT(y) -#define RB_PREV(name, x, y) name##_RB_PREV(y) -#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) -#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) - -#define RB_FOREACH(x, name, head) \\ - for ((x) = RB_MIN(name, head); \\ - (x) != NULL; \\ - (x) = name##_RB_NEXT(x)) - -#define RB_FOREACH_SAFE(x, name, head, y) \\ - for ((x) = RB_MIN(name, head); \\ - ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \\ - (x) = (y)) - -#define RB_FOREACH_REVERSE(x, name, head) \\ - for ((x) = RB_MAX(name, head); \\ - (x) != NULL; \\ - (x) = name##_RB_PREV(x)) - -#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \\ - for ((x) = RB_MAX(name, head); \\ - ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \\ - (x) = (y)) - -__HEREDOC__ -fi - cat << __HEREDOC__ #endif /*!OCONFIGURE_CONFIG_H*/ __HEREDOC__ diff --git a/configure.in b/configure.in index 36aedfc..7e73cda 100644 --- a/configure.in +++ b/configure.in @@ -717,26 +717,6 @@ if [ ${HAVE_SECCOMP_FILTER} -eq 1 ]; then echo fi -if [ ${HAVE_SYS_QUEUE} -eq 0 ]; then - cat << __HEREDOC__ -/* - * A compatible version of OpenBSD . - */ -@CONFIGURE_SYS_QUEUE_H@ - -__HEREDOC__ -fi - -if [ ${HAVE_SYS_TREE} -eq 0 ]; then - cat << __HEREDOC__ -/* - * A compatible version of OpenBSD . - */ -@CONFIGURE_SYS_TREE_H@ - -__HEREDOC__ -fi - cat << __HEREDOC__ #endif /*!OCONFIGURE_CONFIG_H*/ __HEREDOC__ From 48ae61f447df0342942a74c182d52bac7e944970 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Sun, 14 Nov 2021 16:56:19 +0200 Subject: [PATCH 04/10] Move stdlib #includes to their respective compat header Remove more "if HAVE_..." code from configure, relying on simple "#include" statements in compat_*.h code instead. --- compat_err.h | 2 ++ compat_fts.h | 2 ++ compat_md5.h | 3 +++ compat_memmem.h | 2 ++ compat_memrchr.h | 2 ++ compat_mkfifoat.h | 2 ++ compat_mknodat.h | 2 ++ compat_readpassphrase.h | 2 ++ compat_reallocarray.h | 2 ++ compat_recallocarray.h | 2 ++ compat_setresgid.h | 2 ++ compat_setresuid.h | 2 ++ compat_sha2.h | 3 +++ compat_strlcat.h | 2 ++ compat_strlcpy.h | 2 ++ compat_strndup.h | 2 ++ compat_strnlen.h | 2 ++ compats.h | 36 ++++++++++++++++++++++++++++++++++++ configure | 39 --------------------------------------- configure.in | 39 --------------------------------------- 20 files changed, 72 insertions(+), 78 deletions(-) diff --git a/compat_err.h b/compat_err.h index 2a1850d..98785d8 100644 --- a/compat_err.h +++ b/compat_err.h @@ -1,3 +1,5 @@ +#include + /* * Compatibility functions for err(3). */ diff --git a/compat_fts.h b/compat_fts.h index abf34f5..eba282f 100644 --- a/compat_fts.h +++ b/compat_fts.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for fts(3) functions. */ diff --git a/compat_md5.h b/compat_md5.h index 592df2c..5888436 100644 --- a/compat_md5.h +++ b/compat_md5.h @@ -1,3 +1,6 @@ +#include /* size_t, mode_t, dev_t */ +#include /* C99 [u]int[nn]_t types */ + /* * Compatibility for md4(3). */ diff --git a/compat_memmem.h b/compat_memmem.h index 98e2539..96a13ed 100644 --- a/compat_memmem.h +++ b/compat_memmem.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for memmem(3). */ diff --git a/compat_memrchr.h b/compat_memrchr.h index baf4cde..3e69d9f 100644 --- a/compat_memrchr.h +++ b/compat_memrchr.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for memrchr(3). */ diff --git a/compat_mkfifoat.h b/compat_mkfifoat.h index 2e3ca37..cd505e8 100644 --- a/compat_mkfifoat.h +++ b/compat_mkfifoat.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for mkfifoat(2). */ diff --git a/compat_mknodat.h b/compat_mknodat.h index 5bfcc84..476ee81 100644 --- a/compat_mknodat.h +++ b/compat_mknodat.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for mknodat(2). */ diff --git a/compat_readpassphrase.h b/compat_readpassphrase.h index f6be73a..1b92ce7 100644 --- a/compat_readpassphrase.h +++ b/compat_readpassphrase.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Macros and function required for readpassphrase(3). */ diff --git a/compat_reallocarray.h b/compat_reallocarray.h index b17cbb5..e341152 100644 --- a/compat_reallocarray.h +++ b/compat_reallocarray.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for reallocarray(3). */ diff --git a/compat_recallocarray.h b/compat_recallocarray.h index 61c049c..50594af 100644 --- a/compat_recallocarray.h +++ b/compat_recallocarray.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for recallocarray(3). */ diff --git a/compat_setresgid.h b/compat_setresgid.h index fe77764..3ec81f3 100644 --- a/compat_setresgid.h +++ b/compat_setresgid.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for setresgid(2). */ diff --git a/compat_setresuid.h b/compat_setresuid.h index 3a25be7..f4d226e 100644 --- a/compat_setresuid.h +++ b/compat_setresuid.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for setresuid(2). */ diff --git a/compat_sha2.h b/compat_sha2.h index 49ff54e..9f4a08d 100644 --- a/compat_sha2.h +++ b/compat_sha2.h @@ -1,3 +1,6 @@ +#include /* size_t, mode_t, dev_t */ +#include /* C99 [u]int[nn]_t types */ + /* * Compatibility for sha2(3). */ diff --git a/compat_strlcat.h b/compat_strlcat.h index 6e0d33a..90a5e7a 100644 --- a/compat_strlcat.h +++ b/compat_strlcat.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for strlcat(3). */ diff --git a/compat_strlcpy.h b/compat_strlcpy.h index 1319183..7ec877a 100644 --- a/compat_strlcpy.h +++ b/compat_strlcpy.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for strlcpy(3). */ diff --git a/compat_strndup.h b/compat_strndup.h index 60bdf0d..1678b30 100644 --- a/compat_strndup.h +++ b/compat_strndup.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for strndup(3). */ diff --git a/compat_strnlen.h b/compat_strnlen.h index c6f8aa9..58d0e06 100644 --- a/compat_strnlen.h +++ b/compat_strnlen.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for strnlen(3). */ diff --git a/compats.h b/compats.h index 1d84732..06e5997 100644 --- a/compats.h +++ b/compats.h @@ -1,4 +1,6 @@ #if !HAVE_ERR +#include + /* * Compatibility functions for err(3). */ @@ -29,6 +31,8 @@ extern int b64_pton(char const *, unsigned char *, size_t); extern void explicit_bzero(void *, size_t); #endif /* !HAVE_EXPLICIT_BZERO */ #if !HAVE_FTS +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for fts(3) functions. */ @@ -115,6 +119,9 @@ int fts_set(FTS *, FTSENT *, int); extern const char *getprogname(void); #endif /* !HAVE_GETPROGNAME */ #if !HAVE_MD5 +#include /* size_t, mode_t, dev_t */ +#include /* C99 [u]int[nn]_t types */ + /* * Compatibility for md4(3). */ @@ -136,30 +143,40 @@ extern char *MD5End(MD5_CTX *, char *); extern void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *); #endif /* !HAVE_MD5 */ #if !HAVE_MEMMEM +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for memmem(3). */ void *memmem(const void *, size_t, const void *, size_t); #endif /* !HAVE_MEMMEM */ #if !HAVE_MEMRCHR +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for memrchr(3). */ void *memrchr(const void *b, int, size_t); #endif /* !HAVE_MEMRCHR */ #if !HAVE_MKFIFOAT +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for mkfifoat(2). */ int mkfifoat(int, const char *, mode_t); #endif /* !HAVE_MKFIFOAT */ #if !HAVE_MKNODAT +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for mknodat(2). */ int mknodat(int, const char *, mode_t, dev_t); #endif /* !HAVE_MKNODAT */ #if !HAVE_READPASSPHRASE +#include /* size_t, mode_t, dev_t */ + /* * Macros and function required for readpassphrase(3). */ @@ -173,12 +190,16 @@ int mknodat(int, const char *, mode_t, dev_t); char *readpassphrase(const char *, char *, size_t, int); #endif /* !HAVE_READPASSPHRASE */ #if !HAVE_REALLOCARRAY +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for reallocarray(3). */ extern void *reallocarray(void *, size_t, size_t); #endif /* !HAVE_REALLOCARRAY */ #if !HAVE_RECALLOCARRAY +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for recallocarray(3). */ @@ -193,18 +214,25 @@ int fmt_scaled(long long, char *); int scan_scaled(char *, long long *); #endif /* !HAVE_SCAN_SCALED */ #if !HAVE_SETRESGID +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for setresgid(2). */ int setresgid(gid_t rgid, gid_t egid, gid_t sgid); #endif /* !HAVE_SETRESGID */ #if !HAVE_SETRESUID +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for setresuid(2). */ int setresuid(uid_t ruid, uid_t euid, uid_t suid); #endif /* !HAVE_SETRESUID */ #if !HAVE_SHA2 +#include /* size_t, mode_t, dev_t */ +#include /* C99 [u]int[nn]_t types */ + /* * Compatibility for sha2(3). */ @@ -264,24 +292,32 @@ char *SHA512FileChunk(const char *, char *, off_t, off_t); char *SHA512Data(const uint8_t *, size_t, char *); #endif /* !HAVE_SHA2 */ #if !HAVE_STRLCAT +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for strlcat(3). */ extern size_t strlcat(char *, const char *, size_t); #endif /* !HAVE_STRLCAT */ #if !HAVE_STRLCPY +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for strlcpy(3). */ extern size_t strlcpy(char *, const char *, size_t); #endif /* !HAVE_STRLCPY */ #if !HAVE_STRNDUP +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for strndup(3). */ extern char *strndup(const char *, size_t); #endif /* !HAVE_STRNDUP */ #if !HAVE_STRNLEN +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for strnlen(3). */ diff --git a/configure b/configure index 5c2ffd0..a00e5f7 100755 --- a/configure +++ b/configure @@ -485,45 +485,6 @@ cat << __HEREDOC__ __HEREDOC__ -# This is just for size_t, mode_t, and dev_t. -# Most of these functions, in the real world, pull in or -# someting that pulls in support for size_t. -# Our function declarations are standalone, so specify them here. - -if [ ${HAVE_FTS} -eq 0 -o \ - ${HAVE_MD5} -eq 0 -o \ - ${HAVE_MEMMEM} -eq 0 -o \ - ${HAVE_MEMRCHR} -eq 0 -o \ - ${HAVE_MKFIFOAT} -eq 0 -o \ - ${HAVE_MKNODAT} -eq 0 -o \ - ${HAVE_READPASSPHRASE} -eq 0 -o \ - ${HAVE_REALLOCARRAY} -eq 0 -o \ - ${HAVE_RECALLOCARRAY} -eq 0 -o \ - ${HAVE_SETRESGID} -eq 0 -o \ - ${HAVE_SETRESUID} -eq 0 -o \ - ${HAVE_SHA2} -eq 0 -o \ - ${HAVE_STRLCAT} -eq 0 -o \ - ${HAVE_STRLCPY} -eq 0 -o \ - ${HAVE_STRNDUP} -eq 0 -o \ - ${HAVE_STRNLEN} -eq 0 ] -then - echo "#include /* size_t, mode_t, dev_t */ " - echo -fi - -if [ ${HAVE_MD5} -eq 0 -o \ - ${HAVE_SHA2} -eq 0 ] -then - echo "#include /* C99 [u]int[nn]_t types */" - echo -fi - -if [ ${HAVE_ERR} -eq 0 ] -then - echo "#include /* err(3) */" - echo -fi - # Now we handle our HAVE_xxxx values. # Most will just be defined as 0 or 1. diff --git a/configure.in b/configure.in index 7e73cda..1381aaa 100644 --- a/configure.in +++ b/configure.in @@ -485,45 +485,6 @@ cat << __HEREDOC__ __HEREDOC__ -# This is just for size_t, mode_t, and dev_t. -# Most of these functions, in the real world, pull in or -# someting that pulls in support for size_t. -# Our function declarations are standalone, so specify them here. - -if [ ${HAVE_FTS} -eq 0 -o \ - ${HAVE_MD5} -eq 0 -o \ - ${HAVE_MEMMEM} -eq 0 -o \ - ${HAVE_MEMRCHR} -eq 0 -o \ - ${HAVE_MKFIFOAT} -eq 0 -o \ - ${HAVE_MKNODAT} -eq 0 -o \ - ${HAVE_READPASSPHRASE} -eq 0 -o \ - ${HAVE_REALLOCARRAY} -eq 0 -o \ - ${HAVE_RECALLOCARRAY} -eq 0 -o \ - ${HAVE_SETRESGID} -eq 0 -o \ - ${HAVE_SETRESUID} -eq 0 -o \ - ${HAVE_SHA2} -eq 0 -o \ - ${HAVE_STRLCAT} -eq 0 -o \ - ${HAVE_STRLCPY} -eq 0 -o \ - ${HAVE_STRNDUP} -eq 0 -o \ - ${HAVE_STRNLEN} -eq 0 ] -then - echo "#include /* size_t, mode_t, dev_t */ " - echo -fi - -if [ ${HAVE_MD5} -eq 0 -o \ - ${HAVE_SHA2} -eq 0 ] -then - echo "#include /* C99 [u]int[nn]_t types */" - echo -fi - -if [ ${HAVE_ERR} -eq 0 ] -then - echo "#include /* err(3) */" - echo -fi - # Now we handle our HAVE_xxxx values. # Most will just be defined as 0 or 1. From 819ab7eede566583c72a42bc31b4b3f5a3d2fe39 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Sun, 14 Nov 2021 17:11:32 +0200 Subject: [PATCH 05/10] Move INFTIM/PATH_MAX/WAIT_ANY to compats.h as well --- Makefile.regen | 5 ++++- compat_INFTIM.h | 1 + compat_PATH_MAX.h | 1 + compat_WAIT_ANY.h | 2 ++ compats.h | 10 ++++++++++ configure | 26 -------------------------- configure.in | 26 -------------------------- 7 files changed, 18 insertions(+), 53 deletions(-) create mode 100644 compat_INFTIM.h create mode 100644 compat_PATH_MAX.h create mode 100644 compat_WAIT_ANY.h diff --git a/Makefile.regen b/Makefile.regen index 941d2e2..9475ad3 100644 --- a/Makefile.regen +++ b/Makefile.regen @@ -30,11 +30,13 @@ COMPATS_H = \ compat_explicit_bzero.h \ compat_fts.h \ compat_getprogname.h \ + compat_INFTIM.h \ compat_md5.h \ compat_memmem.h \ compat_memrchr.h \ compat_mkfifoat.h \ compat_mknodat.h \ + compat_PATH_MAX.h \ compat_readpassphrase.h \ compat_reallocarray.h \ compat_recallocarray.h \ @@ -48,7 +50,8 @@ COMPATS_H = \ compat_strnlen.h \ compat_strtonum.h \ compat_sys_queue.h \ - compat_sys_tree.h + compat_sys_tree.h \ + compat_WAIT_ANY.h TESTS = \ test-__progname.c \ test-arc4random.c \ diff --git a/compat_INFTIM.h b/compat_INFTIM.h new file mode 100644 index 0000000..a13e519 --- /dev/null +++ b/compat_INFTIM.h @@ -0,0 +1 @@ +#define INFTIM (-1) /* poll.h */ diff --git a/compat_PATH_MAX.h b/compat_PATH_MAX.h new file mode 100644 index 0000000..2f75bfb --- /dev/null +++ b/compat_PATH_MAX.h @@ -0,0 +1 @@ +#define PATH_MAX 4096 diff --git a/compat_WAIT_ANY.h b/compat_WAIT_ANY.h new file mode 100644 index 0000000..585fce6 --- /dev/null +++ b/compat_WAIT_ANY.h @@ -0,0 +1,2 @@ +#define WAIT_ANY (-1) /* sys/wait.h */ +#define WAIT_MYPGRP 0 diff --git a/compats.h b/compats.h index 06e5997..422159b 100644 --- a/compats.h +++ b/compats.h @@ -118,6 +118,9 @@ int fts_set(FTS *, FTSENT *, int); */ extern const char *getprogname(void); #endif /* !HAVE_GETPROGNAME */ +#if !HAVE_INFTIM +#define INFTIM (-1) /* poll.h */ +#endif /* !HAVE_INFTIM */ #if !HAVE_MD5 #include /* size_t, mode_t, dev_t */ #include /* C99 [u]int[nn]_t types */ @@ -174,6 +177,9 @@ int mkfifoat(int, const char *, mode_t); */ int mknodat(int, const char *, mode_t, dev_t); #endif /* !HAVE_MKNODAT */ +#if !HAVE_PATH_MAX +#define PATH_MAX 4096 +#endif /* !HAVE_PATH_MAX */ #if !HAVE_READPASSPHRASE #include /* size_t, mode_t, dev_t */ @@ -1701,3 +1707,7 @@ name##_RB_MINMAX(struct name *head, int val) \ ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \ (x) = (y)) #endif /* !HAVE_SYS_TREE */ +#if !HAVE_WAIT_ANY +#define WAIT_ANY (-1) /* sys/wait.h */ +#define WAIT_MYPGRP 0 +#endif /* !HAVE_WAIT_ANY */ diff --git a/configure b/configure index a00e5f7..041478a 100755 --- a/configure +++ b/configure @@ -483,32 +483,6 @@ cat << __HEREDOC__ # define __END_DECLS #endif -__HEREDOC__ - -# Now we handle our HAVE_xxxx values. -# Most will just be defined as 0 or 1. - -if [ ${HAVE_PATH_MAX} -eq 0 ] -then - echo "#define PATH_MAX 4096" - echo -fi - -if [ ${HAVE_WAIT_ANY} -eq 0 ] -then - echo "#define WAIT_ANY (-1) /* sys/wait.h */" - echo "#define WAIT_MYPGRP 0" - echo -fi - - -if [ ${HAVE_INFTIM} -eq 0 ] -then - echo "#define INFTIM (-1) /* poll.h */" - echo -fi - -cat << __HEREDOC__ /* * Results of configuration feature-testing. */ diff --git a/configure.in b/configure.in index 1381aaa..a7c4a5d 100644 --- a/configure.in +++ b/configure.in @@ -483,32 +483,6 @@ cat << __HEREDOC__ # define __END_DECLS #endif -__HEREDOC__ - -# Now we handle our HAVE_xxxx values. -# Most will just be defined as 0 or 1. - -if [ ${HAVE_PATH_MAX} -eq 0 ] -then - echo "#define PATH_MAX 4096" - echo -fi - -if [ ${HAVE_WAIT_ANY} -eq 0 ] -then - echo "#define WAIT_ANY (-1) /* sys/wait.h */" - echo "#define WAIT_MYPGRP 0" - echo -fi - - -if [ ${HAVE_INFTIM} -eq 0 ] -then - echo "#define INFTIM (-1) /* poll.h */" - echo -fi - -cat << __HEREDOC__ /* * Results of configuration feature-testing. */ From d7d06936e730e734a0e74527d5f911c58765f7c0 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Mon, 15 Nov 2021 03:37:10 +0200 Subject: [PATCH 06/10] Move endian, major/minor and byteorder to compats.h --- Makefile.regen | 4 ++ compat_endian.h | 16 ++++++++ compat_major_minor.h | 12 ++++++ compat_osbyteorder.h | 17 ++++++++ compat_sys_byteorder.h | 17 ++++++++ compats.h | 70 +++++++++++++++++++++++++++++++++ configure | 88 ------------------------------------------ configure.in | 88 ------------------------------------------ 8 files changed, 136 insertions(+), 176 deletions(-) create mode 100644 compat_endian.h create mode 100644 compat_major_minor.h create mode 100644 compat_osbyteorder.h create mode 100644 compat_sys_byteorder.h diff --git a/Makefile.regen b/Makefile.regen index 9475ad3..f0d1fa8 100644 --- a/Makefile.regen +++ b/Makefile.regen @@ -27,15 +27,18 @@ COMPATS = \ COMPATS_H = \ compat_err.h \ compat_b64_ntop.h \ + compat_endian.h \ compat_explicit_bzero.h \ compat_fts.h \ compat_getprogname.h \ compat_INFTIM.h \ + compat_major_minor.h \ compat_md5.h \ compat_memmem.h \ compat_memrchr.h \ compat_mkfifoat.h \ compat_mknodat.h \ + compat_osbyteorder.h \ compat_PATH_MAX.h \ compat_readpassphrase.h \ compat_reallocarray.h \ @@ -49,6 +52,7 @@ COMPATS_H = \ compat_strndup.h \ compat_strnlen.h \ compat_strtonum.h \ + compat_sys_byteorder.h \ compat_sys_queue.h \ compat_sys_tree.h \ compat_WAIT_ANY.h diff --git a/compat_endian.h b/compat_endian.h new file mode 100644 index 0000000..627ba2b --- /dev/null +++ b/compat_endian.h @@ -0,0 +1,16 @@ +/* + * Make it easier to include endian.h forms. + */ +#if HAVE_ENDIAN_H +# define COMPAT_ENDIAN_H +#elif HAVE_SYS_ENDIAN_H +# define COMPAT_ENDIAN_H +#elif HAVE_OSBYTEORDER_H +# define COMPAT_ENDIAN_H +#elif HAVE_SYS_BYTEORDER_H +# define COMPAT_ENDIAN_H +#else +# warning No suitable endian.h could be found. +# warning Please e-mail the maintainers with your OS. +# define COMPAT_ENDIAN_H +#endif diff --git a/compat_major_minor.h b/compat_major_minor.h new file mode 100644 index 0000000..a50f31a --- /dev/null +++ b/compat_major_minor.h @@ -0,0 +1,12 @@ +/* + * Handle the various major()/minor() header files. + * Use sys/mkdev.h before sys/sysmacros.h because SunOS + * has both, where only the former works properly. + */ +#if HAVE_SYS_MKDEV_H +# define COMPAT_MAJOR_MINOR_H +#elif HAVE_SYS_SYSMACROS_H +# define COMPAT_MAJOR_MINOR_H +#else +# define COMPAT_MAJOR_MINOR_H +#endif diff --git a/compat_osbyteorder.h b/compat_osbyteorder.h new file mode 100644 index 0000000..6db3337 --- /dev/null +++ b/compat_osbyteorder.h @@ -0,0 +1,17 @@ +/* + * endian.h compatibility with libkern/OSByteOrder.h. + */ +#if HAVE_OSBYTEORDER_H && !HAVE_ENDIAN_H && !HAVE_SYS_BYTEORDER_H && !HAVE_SYS_ENDIAN_H +#define htobe16(x) OSSwapHostToBigInt16(x) +#define htole16(x) OSSwapHostToLittleInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define le16toh(x) OSSwapLittleToHostInt16(x) +#define htobe32(x) OSSwapHostToBigInt32(x) +#define htole32(x) OSSwapHostToLittleInt32(x) +#define be32toh(x) OSSwapBigToHostInt32(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) +#define htobe64(x) OSSwapHostToBigInt64(x) +#define htole64(x) OSSwapHostToLittleInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) +#endif /* HAVE_OSBYTEORDER_H && !HAVE_ENDIAN_H && !HAVE_SYS_BYTEORDER_H && !HAVE_SYS_ENDIAN_H */ diff --git a/compat_sys_byteorder.h b/compat_sys_byteorder.h new file mode 100644 index 0000000..dcb463f --- /dev/null +++ b/compat_sys_byteorder.h @@ -0,0 +1,17 @@ +/* + * endian.h compatibility with sys/byteorder.h. + */ +#if HAVE_SYS_BYTEORDER_H && !HAVE_ENDIAN_H && !HAVE_OSBYTEORDER_H && !HAVE_SYS_ENDIAN_H +#define htobe16(x) BE_16(x) +#define htole16(x) LE_16(x) +#define be16toh(x) BE_16(x) +#define le16toh(x) LE_16(x) +#define htobe32(x) BE_32(x) +#define htole32(x) LE_32(x) +#define be32toh(x) BE_32(x) +#define le32toh(x) LE_32(x) +#define htobe64(x) BE_64(x) +#define htole64(x) LE_64(x) +#define be64toh(x) BE_64(x) +#define le64toh(x) LE_64(x) +#endif /* HAVE_SYS_BYTEORDER_H && !HAVE_ENDIAN_H && !HAVE_OSBYTEORDER_H && !HAVE_SYS_ENDIAN_H */ diff --git a/compats.h b/compats.h index 422159b..f28f51f 100644 --- a/compats.h +++ b/compats.h @@ -24,6 +24,24 @@ extern void vwarnx(const char *, va_list); extern int b64_ntop(unsigned char const *, size_t, char *, size_t); extern int b64_pton(char const *, unsigned char *, size_t); #endif /* !HAVE_B64_NTOP */ +#if !HAVE_ENDIAN +/* + * Make it easier to include endian.h forms. + */ +#if HAVE_ENDIAN_H +# define COMPAT_ENDIAN_H +#elif HAVE_SYS_ENDIAN_H +# define COMPAT_ENDIAN_H +#elif HAVE_OSBYTEORDER_H +# define COMPAT_ENDIAN_H +#elif HAVE_SYS_BYTEORDER_H +# define COMPAT_ENDIAN_H +#else +# warning No suitable endian.h could be found. +# warning Please e-mail the maintainers with your OS. +# define COMPAT_ENDIAN_H +#endif +#endif /* !HAVE_ENDIAN */ #if !HAVE_EXPLICIT_BZERO /* * Compatibility for explicit_bzero(3). @@ -121,6 +139,20 @@ extern const char *getprogname(void); #if !HAVE_INFTIM #define INFTIM (-1) /* poll.h */ #endif /* !HAVE_INFTIM */ +#if !HAVE_MAJOR_MINOR +/* + * Handle the various major()/minor() header files. + * Use sys/mkdev.h before sys/sysmacros.h because SunOS + * has both, where only the former works properly. + */ +#if HAVE_SYS_MKDEV_H +# define COMPAT_MAJOR_MINOR_H +#elif HAVE_SYS_SYSMACROS_H +# define COMPAT_MAJOR_MINOR_H +#else +# define COMPAT_MAJOR_MINOR_H +#endif +#endif /* !HAVE_MAJOR_MINOR */ #if !HAVE_MD5 #include /* size_t, mode_t, dev_t */ #include /* C99 [u]int[nn]_t types */ @@ -177,6 +209,25 @@ int mkfifoat(int, const char *, mode_t); */ int mknodat(int, const char *, mode_t, dev_t); #endif /* !HAVE_MKNODAT */ +#if !HAVE_OSBYTEORDER +/* + * endian.h compatibility with libkern/OSByteOrder.h. + */ +#if HAVE_OSBYTEORDER_H && !HAVE_ENDIAN_H && !HAVE_SYS_BYTEORDER_H && !HAVE_SYS_ENDIAN_H +#define htobe16(x) OSSwapHostToBigInt16(x) +#define htole16(x) OSSwapHostToLittleInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define le16toh(x) OSSwapLittleToHostInt16(x) +#define htobe32(x) OSSwapHostToBigInt32(x) +#define htole32(x) OSSwapHostToLittleInt32(x) +#define be32toh(x) OSSwapBigToHostInt32(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) +#define htobe64(x) OSSwapHostToBigInt64(x) +#define htole64(x) OSSwapHostToLittleInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) +#endif /* HAVE_OSBYTEORDER_H && !HAVE_ENDIAN_H && !HAVE_SYS_BYTEORDER_H && !HAVE_SYS_ENDIAN_H */ +#endif /* !HAVE_OSBYTEORDER */ #if !HAVE_PATH_MAX #define PATH_MAX 4096 #endif /* !HAVE_PATH_MAX */ @@ -335,6 +386,25 @@ extern size_t strnlen(const char *, size_t); */ extern long long strtonum(const char *, long long, long long, const char **); #endif /* !HAVE_STRTONUM */ +#if !HAVE_SYS_BYTEORDER +/* + * endian.h compatibility with sys/byteorder.h. + */ +#if HAVE_SYS_BYTEORDER_H && !HAVE_ENDIAN_H && !HAVE_OSBYTEORDER_H && !HAVE_SYS_ENDIAN_H +#define htobe16(x) BE_16(x) +#define htole16(x) LE_16(x) +#define be16toh(x) BE_16(x) +#define le16toh(x) LE_16(x) +#define htobe32(x) BE_32(x) +#define htole32(x) LE_32(x) +#define be32toh(x) BE_32(x) +#define le32toh(x) LE_32(x) +#define htobe64(x) BE_64(x) +#define htole64(x) LE_64(x) +#define be64toh(x) BE_64(x) +#define le64toh(x) LE_64(x) +#endif /* HAVE_SYS_BYTEORDER_H && !HAVE_ENDIAN_H && !HAVE_OSBYTEORDER_H && !HAVE_SYS_ENDIAN_H */ +#endif /* !HAVE_SYS_BYTEORDER */ #if !HAVE_SYS_QUEUE /* * A compatible version of OpenBSD . diff --git a/configure b/configure index 041478a..f1a5c62 100755 --- a/configure +++ b/configure @@ -539,94 +539,6 @@ cat << __HEREDOC__ __HEREDOC__ -# Compat for libkern/OSByteOrder.h in place of endian.h. - -[ ${HAVE_OSBYTEORDER_H} -eq 1 -a \ - ${HAVE_ENDIAN_H} -eq 0 -a \ - ${HAVE_SYS_BYTEORDER_H} -eq 0 -a \ - ${HAVE_SYS_ENDIAN_H} -eq 0 ] \ - && cat << __HEREDOC__ -/* - * endian.h compatibility with libkern/OSByteOrder.h. - */ -#define htobe16(x) OSSwapHostToBigInt16(x) -#define htole16(x) OSSwapHostToLittleInt16(x) -#define be16toh(x) OSSwapBigToHostInt16(x) -#define le16toh(x) OSSwapLittleToHostInt16(x) -#define htobe32(x) OSSwapHostToBigInt32(x) -#define htole32(x) OSSwapHostToLittleInt32(x) -#define be32toh(x) OSSwapBigToHostInt32(x) -#define le32toh(x) OSSwapLittleToHostInt32(x) -#define htobe64(x) OSSwapHostToBigInt64(x) -#define htole64(x) OSSwapHostToLittleInt64(x) -#define be64toh(x) OSSwapBigToHostInt64(x) -#define le64toh(x) OSSwapLittleToHostInt64(x) - -__HEREDOC__ - -[ ${HAVE_SYS_BYTEORDER_H} -eq 1 -a \ - ${HAVE_ENDIAN_H} -eq 0 -a \ - ${HAVE_OSBYTEORDER_H} -eq 0 -a \ - ${HAVE_SYS_ENDIAN_H} -eq 0 ] \ - && cat << __HEREDOC__ -/* - * endian.h compatibility with sys/byteorder.h. - */ -#define htobe16(x) BE_16(x) -#define htole16(x) LE_16(x) -#define be16toh(x) BE_16(x) -#define le16toh(x) LE_16(x) -#define htobe32(x) BE_32(x) -#define htole32(x) LE_32(x) -#define be32toh(x) BE_32(x) -#define le32toh(x) LE_32(x) -#define htobe64(x) BE_64(x) -#define htole64(x) LE_64(x) -#define be64toh(x) BE_64(x) -#define le64toh(x) LE_64(x) - -__HEREDOC__ - -# Make minor()/major()/makedev() easier to use. - -cat << __HEREDOC__ -/* - * Handle the various major()/minor() header files. - * Use sys/mkdev.h before sys/sysmacros.h because SunOS - * has both, where only the former works properly. - */ -#if HAVE_SYS_MKDEV_H -# define COMPAT_MAJOR_MINOR_H -#elif HAVE_SYS_SYSMACROS_H -# define COMPAT_MAJOR_MINOR_H -#else -# define COMPAT_MAJOR_MINOR_H -#endif - -__HEREDOC__ - -# Make endian.h easier by providing a COMPAT_ENDIAN_H. - -cat << __HEREDOC__ -/* - * Make it easier to include endian.h forms. - */ -#if HAVE_ENDIAN_H -# define COMPAT_ENDIAN_H -#elif HAVE_SYS_ENDIAN_H -# define COMPAT_ENDIAN_H -#elif HAVE_OSBYTEORDER_H -# define COMPAT_ENDIAN_H -#elif HAVE_SYS_BYTEORDER_H -# define COMPAT_ENDIAN_H -#else -# warning No suitable endian.h could be found. -# warning Please e-mail the maintainers with your OS. -# define COMPAT_ENDIAN_H -#endif - -__HEREDOC__ - cat << __HEREDOC__ /* include function declarations for missing functions */ #include "compats.h" diff --git a/configure.in b/configure.in index a7c4a5d..b4c431f 100644 --- a/configure.in +++ b/configure.in @@ -539,94 +539,6 @@ cat << __HEREDOC__ __HEREDOC__ -# Compat for libkern/OSByteOrder.h in place of endian.h. - -[ ${HAVE_OSBYTEORDER_H} -eq 1 -a \ - ${HAVE_ENDIAN_H} -eq 0 -a \ - ${HAVE_SYS_BYTEORDER_H} -eq 0 -a \ - ${HAVE_SYS_ENDIAN_H} -eq 0 ] \ - && cat << __HEREDOC__ -/* - * endian.h compatibility with libkern/OSByteOrder.h. - */ -#define htobe16(x) OSSwapHostToBigInt16(x) -#define htole16(x) OSSwapHostToLittleInt16(x) -#define be16toh(x) OSSwapBigToHostInt16(x) -#define le16toh(x) OSSwapLittleToHostInt16(x) -#define htobe32(x) OSSwapHostToBigInt32(x) -#define htole32(x) OSSwapHostToLittleInt32(x) -#define be32toh(x) OSSwapBigToHostInt32(x) -#define le32toh(x) OSSwapLittleToHostInt32(x) -#define htobe64(x) OSSwapHostToBigInt64(x) -#define htole64(x) OSSwapHostToLittleInt64(x) -#define be64toh(x) OSSwapBigToHostInt64(x) -#define le64toh(x) OSSwapLittleToHostInt64(x) - -__HEREDOC__ - -[ ${HAVE_SYS_BYTEORDER_H} -eq 1 -a \ - ${HAVE_ENDIAN_H} -eq 0 -a \ - ${HAVE_OSBYTEORDER_H} -eq 0 -a \ - ${HAVE_SYS_ENDIAN_H} -eq 0 ] \ - && cat << __HEREDOC__ -/* - * endian.h compatibility with sys/byteorder.h. - */ -#define htobe16(x) BE_16(x) -#define htole16(x) LE_16(x) -#define be16toh(x) BE_16(x) -#define le16toh(x) LE_16(x) -#define htobe32(x) BE_32(x) -#define htole32(x) LE_32(x) -#define be32toh(x) BE_32(x) -#define le32toh(x) LE_32(x) -#define htobe64(x) BE_64(x) -#define htole64(x) LE_64(x) -#define be64toh(x) BE_64(x) -#define le64toh(x) LE_64(x) - -__HEREDOC__ - -# Make minor()/major()/makedev() easier to use. - -cat << __HEREDOC__ -/* - * Handle the various major()/minor() header files. - * Use sys/mkdev.h before sys/sysmacros.h because SunOS - * has both, where only the former works properly. - */ -#if HAVE_SYS_MKDEV_H -# define COMPAT_MAJOR_MINOR_H -#elif HAVE_SYS_SYSMACROS_H -# define COMPAT_MAJOR_MINOR_H -#else -# define COMPAT_MAJOR_MINOR_H -#endif - -__HEREDOC__ - -# Make endian.h easier by providing a COMPAT_ENDIAN_H. - -cat << __HEREDOC__ -/* - * Make it easier to include endian.h forms. - */ -#if HAVE_ENDIAN_H -# define COMPAT_ENDIAN_H -#elif HAVE_SYS_ENDIAN_H -# define COMPAT_ENDIAN_H -#elif HAVE_OSBYTEORDER_H -# define COMPAT_ENDIAN_H -#elif HAVE_SYS_BYTEORDER_H -# define COMPAT_ENDIAN_H -#else -# warning No suitable endian.h could be found. -# warning Please e-mail the maintainers with your OS. -# define COMPAT_ENDIAN_H -#endif - -__HEREDOC__ - cat << __HEREDOC__ /* include function declarations for missing functions */ #include "compats.h" From 55b0d2395daa35e4ceafa0718eda701c54303678 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Mon, 15 Nov 2021 04:33:36 +0200 Subject: [PATCH 07/10] Add sys/types.h include to b64_ntop/explicit_bzero They use size_t but have not been including it (even pre-refactor) --- compat_b64_ntop.h | 2 ++ compat_explicit_bzero.h | 2 ++ compats.h | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/compat_b64_ntop.h b/compat_b64_ntop.h index 062c0fe..26c1c32 100644 --- a/compat_b64_ntop.h +++ b/compat_b64_ntop.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for b64_ntop(3). */ diff --git a/compat_explicit_bzero.h b/compat_explicit_bzero.h index d458637..3ef43c1 100644 --- a/compat_explicit_bzero.h +++ b/compat_explicit_bzero.h @@ -1,3 +1,5 @@ +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for explicit_bzero(3). */ diff --git a/compats.h b/compats.h index f28f51f..29b0b52 100644 --- a/compats.h +++ b/compats.h @@ -18,6 +18,8 @@ extern void vwarnc(int, const char *, va_list); extern void vwarnx(const char *, va_list); #endif /* !HAVE_ERR */ #if !HAVE_B64_NTOP +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for b64_ntop(3). */ @@ -43,6 +45,8 @@ extern int b64_pton(char const *, unsigned char *, size_t); #endif #endif /* !HAVE_ENDIAN */ #if !HAVE_EXPLICIT_BZERO +#include /* size_t, mode_t, dev_t */ + /* * Compatibility for explicit_bzero(3). */ From 1dcda46cdfbbfb56d402e85093e29cd4da26b6eb Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Fri, 8 Jul 2022 23:38:56 +0300 Subject: [PATCH 08/10] Move SECCOMP_AUDIT_ARCH definition to compats.h Given this is now a header file, also convert it from using sh/uname to define it conditionally, to using preprocessor macros. --- Makefile.regen | 1 + compat_seccomp_filter.h | 12 ++++++++++++ compats.h | 14 ++++++++++++++ configure | 22 ---------------------- configure.in | 22 ---------------------- 5 files changed, 27 insertions(+), 44 deletions(-) create mode 100644 compat_seccomp_filter.h diff --git a/Makefile.regen b/Makefile.regen index f0d1fa8..cbc70b1 100644 --- a/Makefile.regen +++ b/Makefile.regen @@ -44,6 +44,7 @@ COMPATS_H = \ compat_reallocarray.h \ compat_recallocarray.h \ compat_scan_scaled.h \ + compat_seccomp_filter.h \ compat_setresgid.h \ compat_setresuid.h \ compat_sha2.h \ diff --git a/compat_seccomp_filter.h b/compat_seccomp_filter.h new file mode 100644 index 0000000..7969176 --- /dev/null +++ b/compat_seccomp_filter.h @@ -0,0 +1,12 @@ +/* + * Define SECCOMP_AUDIT_ARCH based on the architecture. + */ +#if defined(__x86_64__) +# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64 +#elif defined(__i386__) +# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386 +#elif defined(__arm__) +# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM +#elif defined(__aarch64__) +# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64 +#endif diff --git a/compats.h b/compats.h index 29b0b52..b4045d2 100644 --- a/compats.h +++ b/compats.h @@ -274,6 +274,20 @@ extern void *recallocarray(void *, size_t, size_t, size_t); int fmt_scaled(long long, char *); int scan_scaled(char *, long long *); #endif /* !HAVE_SCAN_SCALED */ +#if !HAVE_SECCOMP_FILTER +/* + * Define SECCOMP_AUDIT_ARCH based on the architecture. + */ +#if defined(__x86_64__) +# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64 +#elif defined(__i386__) +# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386 +#elif defined(__arm__) +# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM +#elif defined(__aarch64__) +# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64 +#endif +#endif /* !HAVE_SECCOMP_FILTER */ #if !HAVE_SETRESGID #include /* size_t, mode_t, dev_t */ diff --git a/configure b/configure index f1a5c62..70db546 100755 --- a/configure +++ b/configure @@ -543,28 +543,6 @@ cat << __HEREDOC__ /* include function declarations for missing functions */ #include "compats.h" -__HEREDOC__ - -if [ ${HAVE_SECCOMP_FILTER} -eq 1 ]; then - arch=$(uname -m 2>/dev/null || echo unknown) - case "$arch" in - x86_64) - echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64" - ;; - i*86) - echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386" - ;; - arm*) - echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM" - ;; - aarch64) - echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64" - ;; - esac - echo -fi - -cat << __HEREDOC__ #endif /*!OCONFIGURE_CONFIG_H*/ __HEREDOC__ diff --git a/configure.in b/configure.in index b4c431f..33ae8eb 100644 --- a/configure.in +++ b/configure.in @@ -543,28 +543,6 @@ cat << __HEREDOC__ /* include function declarations for missing functions */ #include "compats.h" -__HEREDOC__ - -if [ ${HAVE_SECCOMP_FILTER} -eq 1 ]; then - arch=$(uname -m 2>/dev/null || echo unknown) - case "$arch" in - x86_64) - echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64" - ;; - i*86) - echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386" - ;; - arm*) - echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM" - ;; - aarch64) - echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64" - ;; - esac - echo -fi - -cat << __HEREDOC__ #endif /*!OCONFIGURE_CONFIG_H*/ __HEREDOC__ From f326aedea99789c8e93e03bbe887fd691e4c2c73 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Fri, 8 Jul 2022 23:45:53 +0300 Subject: [PATCH 09/10] Move the config.h preamble to compats.h This lets compats.h define _GNU_SOURCE etc., rather than config.h, and moves these ifdefs outside of configure. --- Makefile.regen | 1 + compat-preamble.h | 29 +++++++++++++++++++++++++++++ compats.h | 29 +++++++++++++++++++++++++++++ configure | 32 -------------------------------- configure.in | 32 -------------------------------- 5 files changed, 59 insertions(+), 64 deletions(-) create mode 100644 compat-preamble.h diff --git a/Makefile.regen b/Makefile.regen index cbc70b1..f412ca5 100644 --- a/Makefile.regen +++ b/Makefile.regen @@ -132,6 +132,7 @@ compats.c: $(COMPATS) Makefile.regen compats.h: $(COMPATS_H) Makefile.regen echo -n >$@ + cat compat-preamble.h >>$@ for f in $(COMPATS_H) ; \ do \ ff="`echo $$f | sed -e 's!\.h$$!!' -e 's!^compat_!!'`" ; \ diff --git a/compat-preamble.h b/compat-preamble.h new file mode 100644 index 0000000..3654ec5 --- /dev/null +++ b/compat-preamble.h @@ -0,0 +1,29 @@ +#ifdef __cplusplus +# error "Do not use C++: this is a C application." +#endif +#if !defined(__GNUC__) || (__GNUC__ < 4) +# define __attribute__(x) +#endif +#if defined(__linux__) || defined(__MINT__) || defined(__wasi__) +# define _GNU_SOURCE /* memmem, memrchr, setresuid... */ +# define _DEFAULT_SOURCE /* le32toh, crypt, ... */ +#endif +#if defined(__NetBSD__) +# define _OPENBSD_SOURCE /* reallocarray, etc. */ +#endif +#if defined(__sun) +# ifndef _XOPEN_SOURCE /* SunOS already defines */ +# define _XOPEN_SOURCE /* XPGx */ +# endif +# define _XOPEN_SOURCE_EXTENDED 1 /* XPG4v2 */ +# ifndef __EXTENSIONS__ /* SunOS already defines */ +# define __EXTENSIONS__ /* reallocarray, etc. */ +# endif +#endif +#if !defined(__BEGIN_DECLS) +# define __BEGIN_DECLS +#endif +#if !defined(__END_DECLS) +# define __END_DECLS +#endif + diff --git a/compats.h b/compats.h index b4045d2..c167115 100644 --- a/compats.h +++ b/compats.h @@ -1,3 +1,32 @@ +#ifdef __cplusplus +# error "Do not use C++: this is a C application." +#endif +#if !defined(__GNUC__) || (__GNUC__ < 4) +# define __attribute__(x) +#endif +#if defined(__linux__) || defined(__MINT__) || defined(__wasi__) +# define _GNU_SOURCE /* memmem, memrchr, setresuid... */ +# define _DEFAULT_SOURCE /* le32toh, crypt, ... */ +#endif +#if defined(__NetBSD__) +# define _OPENBSD_SOURCE /* reallocarray, etc. */ +#endif +#if defined(__sun) +# ifndef _XOPEN_SOURCE /* SunOS already defines */ +# define _XOPEN_SOURCE /* XPGx */ +# endif +# define _XOPEN_SOURCE_EXTENDED 1 /* XPG4v2 */ +# ifndef __EXTENSIONS__ /* SunOS already defines */ +# define __EXTENSIONS__ /* reallocarray, etc. */ +# endif +#endif +#if !defined(__BEGIN_DECLS) +# define __BEGIN_DECLS +#endif +#if !defined(__END_DECLS) +# define __END_DECLS +#endif + #if !HAVE_ERR #include diff --git a/configure b/configure index 70db546..0f81e6b 100755 --- a/configure +++ b/configure @@ -454,35 +454,6 @@ cat << __HEREDOC__ #ifndef OCONFIGURE_CONFIG_H #define OCONFIGURE_CONFIG_H -#ifdef __cplusplus -# error "Do not use C++: this is a C application." -#endif -#if !defined(__GNUC__) || (__GNUC__ < 4) -# define __attribute__(x) -#endif -#if defined(__linux__) || defined(__MINT__) || defined(__wasi__) -# define _GNU_SOURCE /* memmem, memrchr, setresuid... */ -# define _DEFAULT_SOURCE /* le32toh, crypt, ... */ -#endif -#if defined(__NetBSD__) -# define _OPENBSD_SOURCE /* reallocarray, etc. */ -#endif -#if defined(__sun) -# ifndef _XOPEN_SOURCE /* SunOS already defines */ -# define _XOPEN_SOURCE /* XPGx */ -# endif -# define _XOPEN_SOURCE_EXTENDED 1 /* XPG4v2 */ -# ifndef __EXTENSIONS__ /* SunOS already defines */ -# define __EXTENSIONS__ /* reallocarray, etc. */ -# endif -#endif -#if !defined(__BEGIN_DECLS) -# define __BEGIN_DECLS -#endif -#if !defined(__END_DECLS) -# define __END_DECLS -#endif - /* * Results of configuration feature-testing. */ @@ -537,9 +508,6 @@ cat << __HEREDOC__ #define HAVE_WAIT_ANY ${HAVE_WAIT_ANY} #define HAVE___PROGNAME ${HAVE___PROGNAME} -__HEREDOC__ - -cat << __HEREDOC__ /* include function declarations for missing functions */ #include "compats.h" diff --git a/configure.in b/configure.in index 33ae8eb..d2c9862 100644 --- a/configure.in +++ b/configure.in @@ -454,35 +454,6 @@ cat << __HEREDOC__ #ifndef OCONFIGURE_CONFIG_H #define OCONFIGURE_CONFIG_H -#ifdef __cplusplus -# error "Do not use C++: this is a C application." -#endif -#if !defined(__GNUC__) || (__GNUC__ < 4) -# define __attribute__(x) -#endif -#if defined(__linux__) || defined(__MINT__) || defined(__wasi__) -# define _GNU_SOURCE /* memmem, memrchr, setresuid... */ -# define _DEFAULT_SOURCE /* le32toh, crypt, ... */ -#endif -#if defined(__NetBSD__) -# define _OPENBSD_SOURCE /* reallocarray, etc. */ -#endif -#if defined(__sun) -# ifndef _XOPEN_SOURCE /* SunOS already defines */ -# define _XOPEN_SOURCE /* XPGx */ -# endif -# define _XOPEN_SOURCE_EXTENDED 1 /* XPG4v2 */ -# ifndef __EXTENSIONS__ /* SunOS already defines */ -# define __EXTENSIONS__ /* reallocarray, etc. */ -# endif -#endif -#if !defined(__BEGIN_DECLS) -# define __BEGIN_DECLS -#endif -#if !defined(__END_DECLS) -# define __END_DECLS -#endif - /* * Results of configuration feature-testing. */ @@ -537,9 +508,6 @@ cat << __HEREDOC__ #define HAVE_WAIT_ANY ${HAVE_WAIT_ANY} #define HAVE___PROGNAME ${HAVE___PROGNAME} -__HEREDOC__ - -cat << __HEREDOC__ /* include function declarations for missing functions */ #include "compats.h" From c5a254f0ecb897a0a39f3f61148030471ad234a3 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Fri, 8 Jul 2022 23:51:54 +0300 Subject: [PATCH 10/10] Add a duplicate include guard to compats.h --- Makefile.regen | 4 ++++ compats.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Makefile.regen b/Makefile.regen index f412ca5..012bb20 100644 --- a/Makefile.regen +++ b/Makefile.regen @@ -132,6 +132,9 @@ compats.c: $(COMPATS) Makefile.regen compats.h: $(COMPATS_H) Makefile.regen echo -n >$@ + echo "#ifndef OCONFIGURE_COMPAT_H" >>$@ + echo "#define OCONFIGURE_COMPAT_H" >>$@ + echo >>$@ cat compat-preamble.h >>$@ for f in $(COMPATS_H) ; \ do \ @@ -141,6 +144,7 @@ compats.h: $(COMPATS_H) Makefile.regen cat "$$f" ; \ echo "#endif /* !HAVE_$${up} */" ; \ done >>$@ + echo "#endif /* OCONFIGURE_COMPAT_H */" >>$@ tests.c: $(TESTS) Makefile.regen for f in $(TESTS) ; \ diff --git a/compats.h b/compats.h index c167115..2eb841e 100644 --- a/compats.h +++ b/compats.h @@ -1,3 +1,6 @@ +#ifndef OCONFIGURE_COMPAT_H +#define OCONFIGURE_COMPAT_H + #ifdef __cplusplus # error "Do not use C++: this is a C application." #endif @@ -1828,3 +1831,4 @@ name##_RB_MINMAX(struct name *head, int val) \ #define WAIT_ANY (-1) /* sys/wait.h */ #define WAIT_MYPGRP 0 #endif /* !HAVE_WAIT_ANY */ +#endif /* OCONFIGURE_COMPAT_H */