commit fb2d807ad3fdd7d0fc498c4c7870e382eef6800d
parent 49ecc50304f3c0a51129710024b0c73a137f68d7
Author: sin <sin@2f30.org>
Date: Sat, 14 Jun 2014 19:49:59 +0100
Add mg
Diffstat:
3 files changed, 762 insertions(+), 0 deletions(-)
diff --git a/mg/mg.mk b/mg/mg.mk
@@ -0,0 +1,14 @@
+TARG = mg
+DEPS = ncurses
+INSTALL_BIN = mg
+INSTALL_MAN1 = mg.1
+
+<$mkbuild/mk.common
+
+mg:QV:
+ export CFLAGS="$CFLAGS -I. -D_GNU_SOURCE -DFKEYS -DREGEX -DXKEYS $DEPS_CFLAGS"
+ export LDFLAGS="$LDFLAGS $DEPS_LDFLAGS"
+ CC="${CC} -static" make \
+ PREFIX="$PREFIX"
+ CFLAGS="$CFLAGS" \
+ LDFLAGS="$LDFLAGS"
diff --git a/mg/mkfile b/mg/mkfile
@@ -0,0 +1,7 @@
+<$mkbuild/mk.3rdparty
+
+src = mg-openbsd
+git = git://github.com/scott-parker/mg-openbsd.git
+mkfile = ../mg.mk
+patches = \
+ ../musl-fixup.patch
diff --git a/mg/musl-fixup.patch b/mg/musl-fixup.patch
@@ -0,0 +1,741 @@
+From 57dee7a87c40cd2210bd548013f67f4ad060ec7c Mon Sep 17 00:00:00 2001
+From: sin <sin@2f30.org>
+Date: Sat, 14 Jun 2014 19:46:29 +0100
+Subject: [PATCH] Fix up patch to make it compile against musl
+
+---
+ Makefile | 2 +-
+ def.h | 1 +
+ fileio.c | 4 +-
+ linux.c | 1 -
+ re_search.c | 1 +
+ sys/queue.h | 648 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 653 insertions(+), 4 deletions(-)
+ create mode 100644 sys/queue.h
+
+diff --git a/Makefile b/Makefile
+index 9935033..04ce580 100644
+--- a/Makefile
++++ b/Makefile
+@@ -5,7 +5,7 @@ DOCDIR?= $(PREFIX)/share/doc
+
+ CC?= gcc
+ CFLAGS+= -O2 -Wall -D_GNU_SOURCE -DFKEYS -DREGEX -DXKEYS
+-LDADD+= -lcurses
++LDADD+= -lncurses
+
+ SRCS= $(shell ls *.c)
+ OBJS= $(SRCS:.c=.o)
+diff --git a/def.h b/def.h
+index 562516f..485c823 100644
+--- a/def.h
++++ b/def.h
+@@ -10,6 +10,7 @@
+ * per-terminal definitions are in special header files.
+ */
+
++#include <sys/types.h>
+ #include "sysdef.h" /* Order is critical. */
+ #include "ttydef.h"
+ #include "chrdef.h"
+diff --git a/fileio.c b/fileio.c
+index 78bd876..e6eca16 100644
+--- a/fileio.c
++++ b/fileio.c
+@@ -95,7 +95,7 @@ int
+ ffwopen(FILE ** ffp, const char *fn, struct buffer *bp)
+ {
+ int fd;
+- mode_t fmode = DEFFILEMODE;
++ mode_t fmode = 0666;
+
+ if (bp && bp->b_fi.fi_mode)
+ fmode = bp->b_fi.fi_mode & 07777;
+@@ -361,7 +361,7 @@ copy(char *frname, char *toname)
+ {
+ int ifd, ofd;
+ char buf[BUFSIZ];
+- mode_t fmode = DEFFILEMODE; /* XXX?? */
++ mode_t fmode = 0666;
+ struct stat orig;
+ ssize_t sr;
+
+diff --git a/linux.c b/linux.c
+index ebceec4..6a41919 100644
+--- a/linux.c
++++ b/linux.c
+@@ -1,5 +1,4 @@
+ #include <sys/types.h>
+-#include <sys/cdefs.h>
+
+ #include <errno.h>
+ #include <limits.h>
+diff --git a/re_search.c b/re_search.c
+index d8d4008..1a64d5b 100644
+--- a/re_search.c
++++ b/re_search.c
+@@ -28,6 +28,7 @@
+ #define SRCH_ACCM (-4)
+ #define SRCH_MARK (-5)
+
++#define REG_STARTEND (1 << 2)
+ #define RE_NMATCH 10 /* max number of matches */
+ #define REPLEN 256 /* max length of replacement string */
+
+diff --git a/sys/queue.h b/sys/queue.h
+new file mode 100644
+index 0000000..f8f09bf
+--- /dev/null
++++ b/sys/queue.h
+@@ -0,0 +1,648 @@
++/* $OpenBSD: queue.h,v 1.38 2013/07/03 15:05:21 fgsch Exp $ */
++/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
++
++/*
++ * 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
++ */
++
++#ifndef _SYS_QUEUE_H_
++#define _SYS_QUEUE_H_
++
++/*
++ * This file defines five types of data structures: singly-linked lists,
++ * lists, simple queues, tail queues, and circular 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 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.
++ *
++ * A circle 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 circle queue may be traversed in either direction, but has a more
++ * complex end of list detection.
++ *
++ * 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_INVALIDATE(a) (a) = ((void *)-1)
++#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)
++
++/*
++ * 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)
++
++/*
++ * Circular queue definitions.
++ */
++#define CIRCLEQ_HEAD(name, type) \
++struct name { \
++ struct type *cqh_first; /* first element */ \
++ struct type *cqh_last; /* last element */ \
++}
++
++#define CIRCLEQ_HEAD_INITIALIZER(head) \
++ { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
++
++#define CIRCLEQ_ENTRY(type) \
++struct { \
++ struct type *cqe_next; /* next element */ \
++ struct type *cqe_prev; /* previous element */ \
++}
++
++/*
++ * Circular queue access methods
++ */
++#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
++#define CIRCLEQ_LAST(head) ((head)->cqh_last)
++#define CIRCLEQ_END(head) ((void *)(head))
++#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
++#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
++#define CIRCLEQ_EMPTY(head) \
++ (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
++
++#define CIRCLEQ_FOREACH(var, head, field) \
++ for((var) = CIRCLEQ_FIRST(head); \
++ (var) != CIRCLEQ_END(head); \
++ (var) = CIRCLEQ_NEXT(var, field))
++
++#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \
++ for ((var) = CIRCLEQ_FIRST(head); \
++ (var) != CIRCLEQ_END(head) && \
++ ((tvar) = CIRCLEQ_NEXT(var, field), 1); \
++ (var) = (tvar))
++
++#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
++ for((var) = CIRCLEQ_LAST(head); \
++ (var) != CIRCLEQ_END(head); \
++ (var) = CIRCLEQ_PREV(var, field))
++
++#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
++ for ((var) = CIRCLEQ_LAST(head, headname); \
++ (var) != CIRCLEQ_END(head) && \
++ ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \
++ (var) = (tvar))
++
++/*
++ * Circular queue functions.
++ */
++#define CIRCLEQ_INIT(head) do { \
++ (head)->cqh_first = CIRCLEQ_END(head); \
++ (head)->cqh_last = CIRCLEQ_END(head); \
++} while (0)
++
++#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
++ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
++ (elm)->field.cqe_prev = (listelm); \
++ if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
++ (head)->cqh_last = (elm); \
++ else \
++ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
++ (listelm)->field.cqe_next = (elm); \
++} while (0)
++
++#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
++ (elm)->field.cqe_next = (listelm); \
++ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
++ if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
++ (head)->cqh_first = (elm); \
++ else \
++ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
++ (listelm)->field.cqe_prev = (elm); \
++} while (0)
++
++#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
++ (elm)->field.cqe_next = (head)->cqh_first; \
++ (elm)->field.cqe_prev = CIRCLEQ_END(head); \
++ if ((head)->cqh_last == CIRCLEQ_END(head)) \
++ (head)->cqh_last = (elm); \
++ else \
++ (head)->cqh_first->field.cqe_prev = (elm); \
++ (head)->cqh_first = (elm); \
++} while (0)
++
++#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
++ (elm)->field.cqe_next = CIRCLEQ_END(head); \
++ (elm)->field.cqe_prev = (head)->cqh_last; \
++ if ((head)->cqh_first == CIRCLEQ_END(head)) \
++ (head)->cqh_first = (elm); \
++ else \
++ (head)->cqh_last->field.cqe_next = (elm); \
++ (head)->cqh_last = (elm); \
++} while (0)
++
++#define CIRCLEQ_REMOVE(head, elm, field) do { \
++ if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
++ (head)->cqh_last = (elm)->field.cqe_prev; \
++ else \
++ (elm)->field.cqe_next->field.cqe_prev = \
++ (elm)->field.cqe_prev; \
++ if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
++ (head)->cqh_first = (elm)->field.cqe_next; \
++ else \
++ (elm)->field.cqe_prev->field.cqe_next = \
++ (elm)->field.cqe_next; \
++ _Q_INVALIDATE((elm)->field.cqe_prev); \
++ _Q_INVALIDATE((elm)->field.cqe_next); \
++} while (0)
++
++#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
++ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
++ CIRCLEQ_END(head)) \
++ (head)->cqh_last = (elm2); \
++ else \
++ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
++ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
++ CIRCLEQ_END(head)) \
++ (head)->cqh_first = (elm2); \
++ else \
++ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
++ _Q_INVALIDATE((elm)->field.cqe_prev); \
++ _Q_INVALIDATE((elm)->field.cqe_next); \
++} while (0)
++
++#endif /* !_SYS_QUEUE_H_ */
+--
+2.0.0
+