mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Make it build/run on Linux.
This commit is contained in:
		
							
								
								
									
										6
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -1,3 +1,7 @@ | ||||
| 31 October 2007 | ||||
|  | ||||
| * (nicm) Linux port. | ||||
|  | ||||
| 30 October 2007 | ||||
|  | ||||
| * (nicm) swap-window command. Same as link-window but swaps windows. | ||||
| @@ -182,5 +186,5 @@ | ||||
|   (including mutt, emacs). No status bar yet and no key remapping or other | ||||
|   customisation. | ||||
|  | ||||
| $Id: CHANGES,v 1.56 2007-10-30 11:10:33 nicm Exp $ | ||||
| $Id: CHANGES,v 1.57 2007-10-31 14:26:26 nicm Exp $ | ||||
|  | ||||
|   | ||||
							
								
								
									
										79
									
								
								GNUmakefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								GNUmakefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| # $Id: GNUmakefile,v 1.1 2007-10-31 14:26:26 nicm Exp $ | ||||
|  | ||||
| .PHONY: clean | ||||
|  | ||||
| PROG= tmux | ||||
| VERSION= 1.5 | ||||
|  | ||||
| DATE= $(shell date +%Y%m%d-%H%M) | ||||
|  | ||||
| DEBUG= 1 | ||||
|  | ||||
| META?= \002 | ||||
|  | ||||
| SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ | ||||
|       xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c window.c \ | ||||
|       session.c local.c log.c client.c client-msg.c client-fn.c key-string.c \ | ||||
|       key-bindings.c resize.c cmd.c cmd-new-session.c cmd-detach-session.c \ | ||||
|       cmd-list-sessions.c cmd-new-window.c cmd-next-window.c cmd-bind-key.c \ | ||||
|       cmd-unbind-key.c cmd-previous-window.c cmd-last-window.c cmd-list-keys.c \ | ||||
|       cmd-set-option.c cmd-rename-window.c cmd-select-window.c \ | ||||
|       cmd-list-windows.c cmd-attach-session.c cmd-send-prefix.c \ | ||||
|       cmd-refresh-session.c cmd-kill-window.c cmd-list-clients.c \ | ||||
|       cmd-has-session.c cmd-link-window.c cmd-unlink-window.c cmd-swap-window.c | ||||
|  | ||||
| CC?= gcc | ||||
| INCDIRS+= -I. -I- | ||||
| CFLAGS+= -DBUILD="\"$(VERSION) ($(DATE))\"" -DMETA="'${META}'" | ||||
| ifdef DEBUG | ||||
| CFLAGS+= -g -ggdb -DDEBUG | ||||
| LDFLAGS+= -Wl,-E | ||||
| endif | ||||
| CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2 | ||||
| CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations | ||||
| CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare | ||||
| CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align | ||||
|  | ||||
| LDFLAGS+=  | ||||
| LIBS+= -lncurses | ||||
|  | ||||
| PREFIX?= /usr/local | ||||
| INSTALLBIN= install -g bin -o root -m 555 | ||||
| INSTALLMAN= install -g bin -o root -m 444 | ||||
|  | ||||
| ifeq ($(shell uname),Darwin) | ||||
| INCDIRS+= -I/usr/local/include/openssl -Icompat | ||||
| SRCS+= compat/strtonum.c | ||||
| CFLAGS+= -DNO_STRTONUM -DNO_SETRESUID -DNO_SETRESGID -DNO_SETPROCTITLE | ||||
| endif | ||||
|  | ||||
| ifeq ($(shell uname),Linux) | ||||
| INCDIRS+= -I/usr/include/openssl -Icompat | ||||
| SRCS+= compat/strlcpy.c compat/strlcat.c compat/strtonum.c | ||||
| CFLAGS+= $(shell getconf LFS_CFLAGS) -D_GNU_SOURCE \ | ||||
|          -DNO_STRLCPY -DNO_STRLCAT -DNO_STRTONUM -DNO_SETPROCTITLE \ | ||||
|          -DNO_QUEUE_H -DNO_TREE_H -DUSE_PTY_H | ||||
| LDFLAGS+= -lresolv -lutil | ||||
| # Required for LLONG_MAX and friends | ||||
| CFLAGS+= -std=c99 | ||||
| endif | ||||
|  | ||||
| OBJS= $(patsubst %.c,%.o,$(SRCS)) | ||||
|  | ||||
| CLEANFILES= $(PROG) y.tab.c y.tab.h $(OBJS) .depend | ||||
|  | ||||
| CPPFLAGS+= $(INCDIRS) | ||||
|  | ||||
| all: $(PROG) | ||||
|  | ||||
| $(PROG): $(OBJS) | ||||
| 	$(CC) $(LDFLAGS) $(LIBS) -o $@ $+ | ||||
|  | ||||
| depend: $(SRCS) | ||||
| 	$(CC) $(CFLAGS) $(INCDIRS) -MM $(SRCS) > .depend | ||||
|  | ||||
| install: | ||||
| 	$(INSTALLBIN) $(PROG) $(DESTDIR)$(PREFIX)/bin/$(PROG) | ||||
|  | ||||
| clean: | ||||
| 	rm -f $(CLEANFILES) | ||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| # $Id: Makefile,v 1.35 2007-10-30 11:10:33 nicm Exp $ | ||||
| # $Id: Makefile,v 1.36 2007-10-31 14:26:26 nicm Exp $ | ||||
|  | ||||
| .SUFFIXES: .c .o .y .h | ||||
| .PHONY: clean | ||||
| @@ -26,8 +26,6 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ | ||||
|       cmd-refresh-session.c cmd-kill-window.c cmd-list-clients.c \ | ||||
|       cmd-has-session.c cmd-link-window.c cmd-unlink-window.c cmd-swap-window.c | ||||
|  | ||||
| YACC= yacc -d | ||||
|  | ||||
| CC?= cc | ||||
| INCDIRS+= -I. -I- -I/usr/local/include | ||||
| CFLAGS+= -DBUILD="\"$(VERSION) ($(DATE))\"" -DMETA="'${META}'" | ||||
|   | ||||
							
								
								
									
										4
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								client.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: client.c,v 1.18 2007-10-24 11:42:02 nicm Exp $ */ | ||||
| /* $Id: client.c,v 1.19 2007-10-31 14:26:26 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -137,7 +137,9 @@ client_main(struct client_ctx *cctx) | ||||
| 	int		 timeout; | ||||
|  | ||||
| 	logfile("client"); | ||||
| #ifndef NO_SETPROCTITLE | ||||
| 	setproctitle("client"); | ||||
| #endif | ||||
|  | ||||
| 	siginit(); | ||||
| 	if ((cctx->loc_fd = local_init(&cctx->loc_in, &cctx->loc_out)) == -1) | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-list-windows.c,v 1.5 2007-10-30 10:59:43 nicm Exp $ */ | ||||
| /* $Id: cmd-list-windows.c,v 1.6 2007-10-31 14:26:26 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -30,8 +30,8 @@ | ||||
| void	cmd_list_windows_exec(void *, struct cmd_ctx *); | ||||
|  | ||||
| const struct cmd_entry cmd_list_windows_entry = { | ||||
| 	"list-windows", "lsw", 0, | ||||
| 	NULL, | ||||
| 	"list-windows", "lsw", NULL, | ||||
| 	0, | ||||
| 	NULL, | ||||
| 	cmd_list_windows_exec, | ||||
| 	NULL, | ||||
|   | ||||
							
								
								
									
										528
									
								
								compat/queue.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										528
									
								
								compat/queue.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,528 @@ | ||||
| /* $Id: queue.h,v 1.1 2007-10-31 14:26:26 nicm Exp $ */ | ||||
| /*	$OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto 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. | ||||
|  */ | ||||
|  | ||||
| #ifdef QUEUE_MACRO_DEBUG | ||||
| #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_PREVPTR(var, varp, head, field)			\ | ||||
| 	for ((varp) = &SLIST_FIRST((head));				\ | ||||
| 	    ((var) = *(varp)) != SLIST_END(head);			\ | ||||
| 	    (varp) = &SLIST_NEXT((var), field)) | ||||
|  | ||||
| /* | ||||
|  * 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_NEXT(head, 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)) | ||||
|  | ||||
| /* | ||||
|  * 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)) | ||||
|  | ||||
| /* | ||||
|  * 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) | ||||
|  | ||||
| /* | ||||
|  * 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_REVERSE(var, head, headname, field)		\ | ||||
| 	for((var) = TAILQ_LAST(head, headname);				\ | ||||
| 	    (var) != TAILQ_END(head);					\ | ||||
| 	    (var) = TAILQ_PREV(var, headname, field)) | ||||
|  | ||||
| /* | ||||
|  * 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_REVERSE(var, head, field)			\ | ||||
| 	for((var) = CIRCLEQ_LAST(head);					\ | ||||
| 	    (var) != CIRCLEQ_END(head);					\ | ||||
| 	    (var) = CIRCLEQ_PREV(var, field)) | ||||
|  | ||||
| /* | ||||
|  * 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_ */ | ||||
							
								
								
									
										58
									
								
								compat/strlcat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								compat/strlcat.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /* $Id: strlcat.c,v 1.1 2007-10-31 14:26:26 nicm Exp $ */ | ||||
| /*	$OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $	*/ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> | ||||
|  * | ||||
|  * Permission to use, copy, modify, and distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| /* | ||||
|  * Appends src to string dst of size siz (unlike strncat, siz is the | ||||
|  * full size of dst, not space left).  At most siz-1 characters | ||||
|  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)). | ||||
|  * Returns strlen(src) + MIN(siz, strlen(initial dst)). | ||||
|  * If retval >= siz, truncation occurred. | ||||
|  */ | ||||
| size_t | ||||
| strlcat(char *dst, const char *src, size_t siz) | ||||
| { | ||||
| 	char *d = dst; | ||||
| 	const char *s = src; | ||||
| 	size_t n = siz; | ||||
| 	size_t dlen; | ||||
|  | ||||
| 	/* Find the end of dst and adjust bytes left but don't go past end */ | ||||
| 	while (n-- != 0 && *d != '\0') | ||||
| 		d++; | ||||
| 	dlen = d - dst; | ||||
| 	n = siz - dlen; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return(dlen + strlen(s)); | ||||
| 	while (*s != '\0') { | ||||
| 		if (n != 1) { | ||||
| 			*d++ = *s; | ||||
| 			n--; | ||||
| 		} | ||||
| 		s++; | ||||
| 	} | ||||
| 	*d = '\0'; | ||||
|  | ||||
| 	return(dlen + (s - src));	/* count does not include NUL */ | ||||
| } | ||||
							
								
								
									
										54
									
								
								compat/strlcpy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								compat/strlcpy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| /* $Id: strlcpy.c,v 1.1 2007-10-31 14:26:26 nicm Exp $ */ | ||||
| /*	$OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $	*/ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> | ||||
|  * | ||||
|  * Permission to use, copy, modify, and distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| /* | ||||
|  * Copy src to string dst of size siz.  At most siz-1 characters | ||||
|  * will be copied.  Always NUL terminates (unless siz == 0). | ||||
|  * Returns strlen(src); if retval >= siz, truncation occurred. | ||||
|  */ | ||||
| size_t | ||||
| strlcpy(char *dst, const char *src, size_t siz) | ||||
| { | ||||
| 	char *d = dst; | ||||
| 	const char *s = src; | ||||
| 	size_t n = siz; | ||||
|  | ||||
| 	/* Copy as many bytes as will fit */ | ||||
| 	if (n != 0 && --n != 0) { | ||||
| 		do { | ||||
| 			if ((*d++ = *s++) == 0) | ||||
| 				break; | ||||
| 		} while (--n != 0); | ||||
| 	} | ||||
|  | ||||
| 	/* Not enough room in dst, add NUL and traverse rest of src */ | ||||
| 	if (n == 0) { | ||||
| 		if (siz != 0) | ||||
| 			*d = '\0';		/* NUL-terminate dst */ | ||||
| 		while (*s++) | ||||
| 			; | ||||
| 	} | ||||
|  | ||||
| 	return(s - src - 1);	/* count does not include NUL */ | ||||
| } | ||||
							
								
								
									
										68
									
								
								compat/strtonum.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								compat/strtonum.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| /* $Id: strtonum.c,v 1.1 2007-10-31 14:26:26 nicm Exp $ */ | ||||
| /*	$OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $	*/ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2004 Ted Unangst and Todd Miller | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <limits.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| #define INVALID 	1 | ||||
| #define TOOSMALL 	2 | ||||
| #define TOOLARGE 	3 | ||||
|  | ||||
| long long | ||||
| strtonum(const char *numstr, long long minval, long long maxval, | ||||
|     const char **errstrp) | ||||
| { | ||||
| 	long long ll = 0; | ||||
| 	char *ep; | ||||
| 	int error = 0; | ||||
| 	struct errval { | ||||
| 		const char *errstr; | ||||
| 		int err; | ||||
| 	} ev[4] = { | ||||
| 		{ NULL,		0 }, | ||||
| 		{ "invalid",	EINVAL }, | ||||
| 		{ "too small",	ERANGE }, | ||||
| 		{ "too large",	ERANGE }, | ||||
| 	}; | ||||
|  | ||||
| 	ev[0].err = errno; | ||||
| 	errno = 0; | ||||
| 	if (minval > maxval) | ||||
| 		error = INVALID; | ||||
| 	else { | ||||
| 		ll = strtoll(numstr, &ep, 10); | ||||
| 		if (numstr == ep || *ep != '\0') | ||||
| 			error = INVALID; | ||||
| 		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) | ||||
| 			error = TOOSMALL; | ||||
| 		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) | ||||
| 			error = TOOLARGE; | ||||
| 	} | ||||
| 	if (errstrp != NULL) | ||||
| 		*errstrp = ev[error].errstr; | ||||
| 	errno = ev[error].err; | ||||
| 	if (error) | ||||
| 		ll = 0; | ||||
|  | ||||
| 	return (ll); | ||||
| } | ||||
							
								
								
									
										678
									
								
								compat/tree.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										678
									
								
								compat/tree.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,678 @@ | ||||
| /* $Id: tree.h,v 1.1 2007-10-31 14:26:26 nicm Exp $ */ | ||||
| /*	$OpenBSD: tree.h,v 1.9 2004/11/24 18:10:42 tdeval Exp $	*/ | ||||
| /* | ||||
|  * Copyright 2002 Niels Provos <provos@citi.umich.edu> | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef	_SYS_TREE_H_ | ||||
| #define	_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) | ||||
| #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)				\ | ||||
| void name##_RB_INSERT_COLOR(struct name *, struct type *);	\ | ||||
| void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ | ||||
| struct type *name##_RB_REMOVE(struct name *, struct type *);		\ | ||||
| struct type *name##_RB_INSERT(struct name *, struct type *);		\ | ||||
| struct type *name##_RB_FIND(struct name *, struct type *);		\ | ||||
| struct type *name##_RB_NEXT(struct type *);				\ | ||||
| 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)				\ | ||||
| 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;			\ | ||||
| }									\ | ||||
| 									\ | ||||
| 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;			\ | ||||
| }									\ | ||||
| 									\ | ||||
| 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 */					\ | ||||
| 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 */				\ | ||||
| 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);							\ | ||||
| }									\ | ||||
| 									\ | ||||
| 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);							\ | ||||
| }									\ | ||||
| 									\ | ||||
| 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_NEXT(name, x, y)	name##_RB_NEXT(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)) | ||||
|  | ||||
| #endif	/* _SYS_TREE_H_ */ | ||||
							
								
								
									
										5
									
								
								local.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								local.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: local.c,v 1.16 2007-10-24 11:45:25 nicm Exp $ */ | ||||
| /* $Id: local.c,v 1.17 2007-10-31 14:26:26 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -24,9 +24,10 @@ | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #define TTYDEFCHARS | ||||
| /* glibc requires unistd.h before termios.h for TTYDEFCHARS. */ | ||||
| #include <unistd.h>	 | ||||
| #include <termios.h> | ||||
| #include <term.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
|   | ||||
							
								
								
									
										4
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								server.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: server.c,v 1.36 2007-10-30 10:59:43 nicm Exp $ */ | ||||
| /* $Id: server.c,v 1.37 2007-10-31 14:26:26 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -77,7 +77,9 @@ server_start(char *path) | ||||
| #endif | ||||
|  | ||||
| 	logfile("server"); | ||||
| #ifndef NO_SETPROCTITLE | ||||
| 	setproctitle("server (%s)", path); | ||||
| #endif | ||||
| 	log_debug("server started, pid %ld", (long) getpid()); | ||||
|  | ||||
| 	memset(&sa, 0, sizeof sa); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: session.c,v 1.27 2007-10-26 16:57:32 nicm Exp $ */ | ||||
| /* $Id: session.c,v 1.28 2007-10-31 14:26:26 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -159,16 +159,16 @@ struct winlink * | ||||
| session_new(struct session *s, const char *name, const char *cmd, int idx) | ||||
| { | ||||
| 	struct window	*w; | ||||
| 	const char	*environ[] = { NULL, "TERM=screen", NULL }; | ||||
| 	const char	*env[] = { NULL, "TERM=screen", NULL }; | ||||
| 	char		 buf[256]; | ||||
| 	u_int		 i; | ||||
|  | ||||
| 	if (session_index(s, &i) != 0) | ||||
| 		fatalx("session not found"); | ||||
| 	xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); | ||||
| 	environ[0] = buf; | ||||
| 	env[0] = buf; | ||||
| 	 | ||||
| 	if ((w = window_create(name, cmd, environ, s->sx, s->sy)) == NULL) | ||||
| 	if ((w = window_create(name, cmd, env, s->sx, s->sy)) == NULL) | ||||
| 		return (NULL); | ||||
| 	return (session_attach(s, w, idx)); | ||||
| } | ||||
|   | ||||
							
								
								
									
										35
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tmux.h,v 1.75 2007-10-30 11:10:33 nicm Exp $ */ | ||||
| /* $Id: tmux.h,v 1.76 2007-10-31 14:26:26 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -23,17 +23,33 @@ | ||||
| #define RB_AUGMENT(x) do {} while (0) | ||||
|  | ||||
| #include <sys/param.h> | ||||
| #include <sys/tree.h> | ||||
|  | ||||
| #ifndef NO_QUEUE_H | ||||
| #include <sys/queue.h> | ||||
| #else | ||||
| #include "compat/queue.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef NO_TREE_H | ||||
| #include <sys/tree.h> | ||||
| #else | ||||
| #include "compat/tree.h" | ||||
| #endif | ||||
|  | ||||
| #include <poll.h> | ||||
| #include <signal.h> | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #include "array.h" | ||||
|  | ||||
| extern char    *__progname; | ||||
|  | ||||
| #ifndef INFTIM | ||||
| #define INFTIM -1 | ||||
| #endif | ||||
|  | ||||
| #ifndef __dead | ||||
| #define __dead __attribute__ ((__noreturn__)) | ||||
| #endif | ||||
| @@ -511,6 +527,21 @@ struct binding { | ||||
| }; | ||||
| ARRAY_DECL(bindings, struct binding *); | ||||
|  | ||||
| #ifdef NO_STRTONUM | ||||
| /* strtonum.c */ | ||||
| long long	 strtonum(const char *, long long, long long, const char **); | ||||
| #endif | ||||
|  | ||||
| #ifdef NO_STRLCPY | ||||
| /* strlcpy.c */ | ||||
| size_t	 	 strlcpy(char *, const char *, size_t); | ||||
| #endif | ||||
|  | ||||
| #ifdef NO_STRLCAT | ||||
| /* strlcat.c */ | ||||
| size_t	 	 strlcat(char *, const char *, size_t); | ||||
| #endif | ||||
|  | ||||
| /* tmux.c */ | ||||
| extern volatile sig_atomic_t sigwinch; | ||||
| extern volatile sig_atomic_t sigterm; | ||||
|   | ||||
							
								
								
									
										10
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								window.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: window.c,v 1.24 2007-10-26 12:29:07 nicm Exp $ */ | ||||
| /* $Id: window.c,v 1.25 2007-10-31 14:26:26 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -31,8 +31,12 @@ | ||||
| #ifdef USE_LIBUTIL_H | ||||
| #include <libutil.h> | ||||
| #else | ||||
| #ifdef USE_PTY_H | ||||
| #include <pty.h> | ||||
| #else | ||||
| #include <util.h> | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| @@ -153,7 +157,7 @@ winlink_previous(struct winlinks *wwl, struct winlink *wl) | ||||
|  | ||||
| struct window * | ||||
| window_create( | ||||
|     const char *name, const char *cmd, const char **environ, u_int sx, u_int sy) | ||||
|     const char *name, const char *cmd, const char **env, u_int sx, u_int sy) | ||||
| { | ||||
| 	struct window	*w; | ||||
| 	struct winsize	 ws; | ||||
| @@ -169,7 +173,7 @@ window_create( | ||||
| 	case -1: | ||||
| 		return (NULL); | ||||
| 	case 0: | ||||
| 		for (entry = environ; *entry != NULL; entry++) { | ||||
| 		for (entry = env; *entry != NULL; entry++) { | ||||
| 			if (putenv(*entry) != 0) | ||||
| 				fatal("putenv failed"); | ||||
| 		} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Nicholas Marriott
					Nicholas Marriott