From db5505d87f68151af943f2f09e3fdf3dacaa7685 Mon Sep 17 00:00:00 2001
From: deuce <>
Date: Sat, 26 Apr 2003 17:31:45 +0000
Subject: [PATCH] Initial NetBSD and QNX support.

---
 src/xpdev/GNUmakefile  |  22 +++-
 src/xpdev/filewrap.c   |  14 ++-
 src/xpdev/filewrap.h   |  44 ++++---
 src/xpdev/genwrap.c    |   2 +-
 src/xpdev/genwrap.h    |  19 +++
 src/xpdev/sem.c        | 255 ++++++++++++++++++++++++++++++++++++-----
 src/xpdev/sem.h        |  78 +++++++++++--
 src/xpdev/threadwrap.c |   4 +-
 8 files changed, 372 insertions(+), 66 deletions(-)

diff --git a/src/xpdev/GNUmakefile b/src/xpdev/GNUmakefile
index 6c68724473..0d87bd9fa2 100644
--- a/src/xpdev/GNUmakefile
+++ b/src/xpdev/GNUmakefile
@@ -53,11 +53,21 @@ else
  ifeq ($(os),openbsd)	# OpenBSD
   CFLAGS	+= -D_THREAD_SAFE
   LFLAGS	:=	-pthread
- else					# Linux / Other UNIX
-  ifdef bcc
-   LFLAGS	:=	libpthread.a
+ else
+  ifeq ($(os),netbsd)	# NetBSD
+  CFLAGS	+= -D_THREAD_SAFE -D__unix__ -D_NEED_SEM -I/usr/pkg/include
+  LFLAGS	:=	-lpth -lpthread -L/usr/pkg/lib
   else
-   LFLAGS	:=	-lpthread
+   ifeq ($(os),qnx)	# QNX
+    CFLAGS	+= -D_THREAD_SAFE
+    LFLAGS	:= 
+   else			# Linux / Other UNIX
+    ifdef bcc
+     LFLAGS	:=	libpthread.a
+    else
+     LFLAGS	:=	-lpthread
+    endif
+   endif
   endif
  endif
 endif
@@ -77,6 +87,10 @@ endif
 include objects.mk		# defines $(OBJS)
 include targets.mk		# defines all and clean targets
 
+ifeq ($(os),netbsd)
+ OBJS	+= $(ODIR)$(SLASH)sem.$(OFILE)
+endif
+
 # Implicit C Compile Rule
 $(ODIR)/%.o : %.c
 	@echo Compiling $<
diff --git a/src/xpdev/filewrap.c b/src/xpdev/filewrap.c
index 82446f24f1..3b89c85e84 100644
--- a/src/xpdev/filewrap.c
+++ b/src/xpdev/filewrap.c
@@ -82,7 +82,11 @@ long DLLCALL filelength(int fd)
 }
 
 /* Sets a lock on a portion of a file */
+#ifdef __QNX__
+int DLLCALL lock(int fd, long pos, long len)
+#else
 int DLLCALL lock(int fd, long pos, int len)
+#endif
 {
 #if defined(F_SANERDLCKNO) || !defined(BSD)
  	struct flock alock;
@@ -101,7 +105,7 @@ int DLLCALL lock(int fd, long pos, int len)
 #endif
 	alock.l_whence = L_SET;		/* SEEK_SET */
 	alock.l_start = pos;
-	alock.l_len = len;
+	alock.l_len = (int)len;
 
 	if(fcntl(fd, F_SETLK, &alock)==-1)
 		return(-1);
@@ -117,7 +121,11 @@ int DLLCALL lock(int fd, long pos, int len)
 }
 
 /* Removes a lock from a file record */
+#ifdef __QNX__
+int DLLCALL unlock(int fd, long pos, long len)
+#else
 int DLLCALL unlock(int fd, long pos, int len)
+#endif
 {
 
 #if defined(F_SANEUNLCK) || !defined(BSD)
@@ -129,7 +137,7 @@ int DLLCALL unlock(int fd, long pos, int len)
 #endif
 	alock.l_whence = L_SET;
 	alock.l_start = pos;
-	alock.l_len = len;
+	alock.l_len = (int)len;
 	if(fcntl(fd, F_SETLK, &alock)==-1)
 		return(-1);
 #endif
@@ -143,6 +151,7 @@ int DLLCALL unlock(int fd, long pos, int len)
 	return(0);
 }
 
+#ifndef __QNX__
 /* Opens a file in specified sharing (file-locking) mode */
 int DLLCALL sopen(char *fn, int access, int share)
 {
@@ -189,6 +198,7 @@ int DLLCALL sopen(char *fn, int access, int share)
 
 	return fd;
 }
+#endif
 
 #elif defined _MSC_VER || defined __MINGW32__
 
diff --git a/src/xpdev/filewrap.h b/src/xpdev/filewrap.h
index f4f2aa4235..e15b080a93 100644
--- a/src/xpdev/filewrap.h
+++ b/src/xpdev/filewrap.h
@@ -72,24 +72,28 @@
 
 	#include <fcntl.h>
 
-	#define O_TEXT		0		/* all files in binary mode on Unix */
-	#define O_BINARY	0		/* all files in binary mode on Unix */
-	#undef	O_DENYNONE
-	#define O_DENYNONE  (1<<31)	/* req'd for Baja/nopen compatibility */
-
-	#define SH_DENYNO	2          // no locks
-#ifdef F_SANEWRLCKNO
-	#define SH_DENYRW	F_SANEWRLCKNO	   // exclusive lock
-#else
-	#define SH_DENYRW	F_WRLCK	   // exclusive lock
-#endif
-
-#ifdef F_SANERDLCKNO
-	#define SH_DENYWR   F_SANERDLCKNO    // shareable lock
-#else
-	#define SH_DENYWR   F_RDLCK    // shareable lock
-#endif
-	
+	#ifdef __QNX__
+		#include <share.h>			/* SH_DENY */
+		#define L_SET	SEEK_SET
+	#else
+		#define O_TEXT		0		/* all files in binary mode on Unix */
+		#define O_BINARY	0		/* all files in binary mode on Unix */
+		#undef	O_DENYNONE
+		#define O_DENYNONE  (1<<31)	/* req'd for Baja/nopen compatibility */
+
+		#define SH_DENYNO	2          // no locks
+		#ifdef F_SANEWRLCKNO
+			#define SH_DENYRW	F_SANEWRLCKNO	   // exclusive lock
+		#else
+			#define SH_DENYRW	F_WRLCK	   // exclusive lock
+		#endif
+
+		#ifdef F_SANERDLCKNO
+			#define SH_DENYWR   F_SANERDLCKNO    // shareable lock
+		#else
+			#define SH_DENYWR   F_RDLCK    // shareable lock
+		#endif
+	#endif
 	#define chsize(fd,size)		ftruncate(fd,size)
 	#define tell(fd)			lseek(fd,0,SEEK_CUR)
 
@@ -111,13 +115,15 @@
 extern "C" {
 #endif
 
-#if !defined(__BORLANDC__)
+#if !defined(__BORLANDC__) && !defined(__QNX__)
 	DLLEXPORT int	DLLCALL	lock(int fd, long pos, int len);
 	DLLEXPORT int	DLLCALL unlock(int fd, long pos, int len);
 #endif
 
 #if !defined(__BORLANDC__) && defined(__unix__)
+#if !defined(__QNX__)
 	DLLEXPORT int	DLLCALL sopen(char *fn, int access, int share);
+#endif
 	DLLEXPORT long	DLLCALL filelength(int fd);
 #endif
 
diff --git a/src/xpdev/genwrap.c b/src/xpdev/genwrap.c
index 03b3fb3cb0..565e8b8047 100644
--- a/src/xpdev/genwrap.c
+++ b/src/xpdev/genwrap.c
@@ -123,7 +123,7 @@ void DLLCALL unix_beep(int freq, int dur)
 {
 	static int console_fd=-1;
 
-#if !defined(__OpenBSD__) && !defined(__GNU__)
+#if !defined(__OpenBSD__) && !defined(__GNU__) && !defined(__NetBSD__) && !defined(__QNX__)
 	if(console_fd == -1) 
   		console_fd = open("/dev/console", O_NOCTTY);
 	
diff --git a/src/xpdev/genwrap.h b/src/xpdev/genwrap.h
index 47c850ad45..a2f3169a55 100644
--- a/src/xpdev/genwrap.h
+++ b/src/xpdev/genwrap.h
@@ -45,6 +45,13 @@
 #if defined(__unix__)
 	#include <unistd.h>		/* usleep */
 	#include <sys/time.h>	/* struct timeval */
+	#if defined(_NEED_SEM)	/* Assumes that if you don't have semaphores, you're using the GNU Pth lib */
+		#include <pth.h>
+	#endif
+#endif
+
+#if defined(__QNX__)
+	#include <strings.h>	/* strcasecmp() */
 #endif
 
 #if defined(__cplusplus)
@@ -100,6 +107,8 @@ extern "C" {
 	#define PLATFORM_DESC	"FreeBSD"
 #elif defined(__OpenBSD__)
 	#define PLATFORM_DESC	"OpenBSD"
+#elif defined(__NetBSD__)
+	#define PLATFORM_DESC	"NetBSD"
 #elif defined(BSD)
 	#define PLATFORM_DESC	"BSD"
 #elif defined(__solaris__)
@@ -108,6 +117,8 @@ extern "C" {
 	#define PLATFORM_DESC	"SunOS"
 #elif defined(__gnu__)
 	#define PLATFORM_DESC	"GNU/Hurd"
+#elif defined(__QNX__)
+	#define PLATFORM_DESC	"QNX"
 #elif defined(__unix__)
 	#define PLATFORM_DESC	"Unix"
 #else
@@ -161,6 +172,14 @@ extern "C" {
 	#define SLEEP(x)		DosSleep(x)
 	#define BEEP(freq,dur)	DosBeep(freq,dur)
 
+#elif defined(_PTH_H_)
+
+	#define SLEEP(x)		({	int y=x; struct timeval tv; \
+								tv.tv_sec=(y/1000); tv.tv_usec=((y%1000)*1000); \
+								pth_nap(tv); })
+	#define BEEP(freq,dur)	unix_beep(freq,dur)
+	DLLEXPORT void	DLLCALL	unix_beep(int freq, int dur);
+
 #elif defined(__unix__)
 
 		/* usleep() apparently doesn't work right (100% CPU utilization) */
diff --git a/src/xpdev/sem.c b/src/xpdev/sem.c
index 825653e603..ea6d5ed248 100644
--- a/src/xpdev/sem.c
+++ b/src/xpdev/sem.c
@@ -1,45 +1,238 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
+ * 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(s), this list of conditions and the following disclaimer as
+ *    the first lines of this file unmodified other than the possible
+ *    addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice(s), 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 COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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.
+ *
+ * $FreeBSD: src/lib/libc_r/uthread/uthread_sem.c,v 1.3.2.1 2000/07/18 02:05:57 jasone Exp $
+ */
+
 #include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "genwrap.h"
 #include "sem.h"
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sem_init(sem_t *sem, int pshared, unsigned int value)
+{
+	int	retval;
+
+	/*
+	 * Range check the arguments.
+	 */
+	if (pshared != 0) {
+		/*
+		 * The user wants a semaphore that can be shared among
+		 * processes, which this implementation can't do.  Sounds like a
+		 * permissions problem to me (yeah right).
+		 */
+		errno = EPERM;
+		retval = -1;
+		goto RETURN;
+	}
+
+	if (value > SEM_VALUE_MAX) {
+		errno = EINVAL;
+		retval = -1;
+		goto RETURN;
+	}
 
-int sem_init(sem_t *sem, int pshared, unsigned int value)  {
-	sem=malloc(sizeof(sem_t));
-	if(sem==NULL)  {
-		errno=ENOSPC;
-		return(-1);
+	*sem = (sem_t)malloc(sizeof(struct sem));
+	if (*sem == NULL) {
+		errno = ENOSPC;
+		retval = -1;
+		goto RETURN;
 	}
-	if(pipe((int *)sem)) {
-		errno=EPERM;
-		return(-1);
+
+	/*
+	 * Initialize the semaphore.
+	 */
+	if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) {
+		free(*sem);
+		errno = ENOSPC;
+		retval = -1;
+		goto RETURN;
+	}
+
+	if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) {
+		pthread_mutex_destroy(&(*sem)->lock);
+		free(*sem);
+		errno = ENOSPC;
+		retval = -1;
+		goto RETURN;
+	}
+	
+	(*sem)->count = (u_int32_t)value;
+	(*sem)->nwaiters = 0;
+	(*sem)->magic = SEM_MAGIC;
+
+	retval = 0;
+  RETURN:
+	return retval;
+}
+
+int
+sem_destroy(sem_t *sem)
+{
+	int	retval;
+	
+	_SEM_CHECK_VALIDITY(sem);
+
+	/* Make sure there are no waiters. */
+	pthread_mutex_lock(&(*sem)->lock);
+	if ((*sem)->nwaiters > 0) {
+		pthread_mutex_unlock(&(*sem)->lock);
+		errno = EBUSY;
+		retval = -1;
+		goto RETURN;
 	}
-	return(0);
+	pthread_mutex_unlock(&(*sem)->lock);
+	
+	pthread_mutex_destroy(&(*sem)->lock);
+	pthread_cond_destroy(&(*sem)->gtzero);
+	(*sem)->magic = 0;
+
+	free(*sem);
+
+	retval = 0;
+  RETURN:
+	return retval;
 }
 
-int sem_destroy(sem_t *sem)  {
-	close(sem->read);
-	close(sem->write);
-	sem=NULL;
-	return(0);
+sem_t *
+sem_open(const char *name, int oflag, ...)
+{
+	errno = ENOSYS;
+	return SEM_FAILED;
 }
 
-int sem_post(sem_t *sem)  {
-	if(sem==NULL)  {
-		errno=EINVAL;
-		return(-1);
+int
+sem_close(sem_t *sem)
+{
+	errno = ENOSYS;
+	return -1;
+}
+
+int
+sem_unlink(const char *name)
+{
+	errno = ENOSYS;
+	return -1;
+}
+
+int
+sem_wait(sem_t *sem)
+{
+	int	retval;
+
+	pthread_testcancel();
+	
+	_SEM_CHECK_VALIDITY(sem);
+
+	pthread_mutex_lock(&(*sem)->lock);
+
+	while ((*sem)->count == 0) {
+		(*sem)->nwaiters++;
+		pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock);
+		(*sem)->nwaiters--;
 	}
-	write(sem->write,"-",1)==1;
-	return(0);
+	(*sem)->count--;
+
+	pthread_mutex_unlock(&(*sem)->lock);
+
+	retval = 0;
+  RETURN:
+
+	pthread_testcancel();
+	return retval;
 }
 
-int sem_wait(sem_t *sem)  {
-	char	buf;
-	if(sem==NULL) {
-		errno=EINVAL;
-		return(-1);
+int
+sem_trywait(sem_t *sem)
+{
+	int	retval;
+
+	_SEM_CHECK_VALIDITY(sem);
+
+	pthread_mutex_lock(&(*sem)->lock);
+
+	if ((*sem)->count > 0) {
+		(*sem)->count--;
+		retval = 0;
+	} else {
+		errno = EAGAIN;
+		retval = -1;
 	}
-	while(read(sem->read,&buf,1)<1)
-		SLEEP(1);
-	return(0);
+	
+	pthread_mutex_unlock(&(*sem)->lock);
+
+  RETURN:
+	return retval;
+}
+
+int
+sem_post(sem_t *sem)
+{
+	int	retval;
+
+	_SEM_CHECK_VALIDITY(sem);
+
+	pthread_mutex_lock(&(*sem)->lock);
+
+	(*sem)->count++;
+	if ((*sem)->nwaiters > 0) {
+		/*
+		 * We must use pthread_cond_broadcast() rather than
+		 * pthread_cond_signal() in order to assure that the highest
+		 * priority thread is run by the scheduler, since
+		 * pthread_cond_signal() signals waiting threads in FIFO order.
+		 */
+		pthread_cond_broadcast(&(*sem)->gtzero);
+	}
+
+	pthread_mutex_unlock(&(*sem)->lock);
+
+	retval = 0;
+  RETURN:
+	return retval;
+}
+
+int
+sem_getvalue(sem_t *sem, int *sval)
+{
+	int	retval;
+
+	_SEM_CHECK_VALIDITY(sem);
+
+	pthread_mutex_lock(&(*sem)->lock);
+	*sval = (int)(*sem)->count;
+	pthread_mutex_unlock(&(*sem)->lock);
+
+	retval = 0;
+  RETURN:
+	return retval;
 }
diff --git a/src/xpdev/sem.h b/src/xpdev/sem.h
index 9dbdd9eb90..1c601c78a8 100644
--- a/src/xpdev/sem.h
+++ b/src/xpdev/sem.h
@@ -1,10 +1,72 @@
-typedef struct {
-	int read;
-	int write;
-}  sem_t;
+#ifndef _SEMAPHORE_H_
+#define _SEMAPHORE_H_
 
-int sem_init(sem_t *sem, int pshared, unsigned int value);
-int sem_destroy(sem_t *sem);
-int sem_post(sem_t *sem);
-int sem_wait(sem_t *sem);
+/*
+ * $Id$
+ *
+ * semaphore.h: POSIX 1003.1b semaphores
+*/
 
+/*-
+ * Copyright (c) 1996, 1997
+ *	HD Associates, Inc.  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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by HD Associates, Inc
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES 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 HD ASSOCIATES 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.
+ *
+ * $FreeBSD: src/sys/posix4/semaphore.h,v 1.6 2000/01/20 07:55:42 jasone Exp $
+ */
+
+#include <machine/limits.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+/* Opaque type definition. */
+struct sem;
+typedef struct sem *sem_t;
+
+#define SEM_FAILED	((sem_t *)0)
+#define SEM_VALUE_MAX	UINT_MAX
+
+#ifndef KERNEL
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int	 sem_init __P((sem_t *, int, unsigned int));
+int	 sem_destroy __P((sem_t *));
+sem_t	*sem_open __P((const char *, int, ...));
+int	 sem_close __P((sem_t *));
+int	 sem_unlink __P((const char *));
+int	 sem_wait __P((sem_t *));
+int	 sem_trywait __P((sem_t *));
+int	 sem_post __P((sem_t *));
+int	 sem_getvalue __P((sem_t *, int *));
+__END_DECLS
+#endif /* KERNEL */
+
+#endif /* _SEMAPHORE_H_ */
diff --git a/src/xpdev/threadwrap.c b/src/xpdev/threadwrap.c
index 00337c5d9b..f958c54ce0 100644
--- a/src/xpdev/threadwrap.c
+++ b/src/xpdev/threadwrap.c
@@ -37,6 +37,7 @@
 
 #if defined(__unix__)
 	#include <unistd.h>	/* _POSIX_THREADS */
+	#include <sys/param.h>	/* BSD */
 #endif
 
 #include "threadwrap.h"	/* DLLCALL */
@@ -62,8 +63,9 @@ ulong _beginthread(void( *start_address )( void * )
 	   that thread resources are freed on exit() */
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
-#ifdef BSD
 	/* Default stack size in BSD is too small for JS stuff */
+/* #ifdef BSD */
+#if 0
 	if(stack_size==0)
 		stack_size=1<<17;
 #endif
-- 
GitLab