From 9c6918c52e76704d0cb3305d307c57e6454bd9bd Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Sat, 2 Dec 2000 04:04:25 +0000
Subject: [PATCH] Added console, thread, and semaphore wrappers.

---
 xtrn/sdk/xsdkwrap.c | 130 +++++++++++++++++++++++++++++++++++++++++++-
 xtrn/sdk/xsdkwrap.h |  77 +++++++++++++++++++++++++-
 2 files changed, 202 insertions(+), 5 deletions(-)

diff --git a/xtrn/sdk/xsdkwrap.c b/xtrn/sdk/xsdkwrap.c
index 18a491c181..c642a31b10 100644
--- a/xtrn/sdk/xsdkwrap.c
+++ b/xtrn/sdk/xsdkwrap.c
@@ -1,6 +1,6 @@
 /* xsdkwrap.c */
 
-/* Synchronet XSDK system-call wrappers */
+/* Synchronet XSDK system-call wrappers (compiler & platform portability) */
 
 /* $Id$ */
 
@@ -42,6 +42,13 @@
 #include <string.h>     /* strlen() */
 #include <unistd.h>     /* getpid() */
 #include <fcntl.h>      /* fcntl() file/record locking */
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/kd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <signal.h>
 
 #endif
 
@@ -59,6 +66,100 @@
 #define STAT		struct stat
 #endif
 
+#ifdef __unix__
+
+struct termios current;            // our current term settings
+struct termios original;           // old termios settings
+struct timeval timeout = {0, 0};   // passed in select() call
+fd_set inp;                        // ditto
+static int beensetup = 0;          // has _termios_setup() been called?
+
+/*
+	I'm using a variable function here simply for the sake of speed.  The
+    termios functions must be called before a kbhit() can be successful, so
+    on the first call, we just set up the terminal, point to variable function
+    to kbhit_norm(), and then call the new function.  Otherwise, testing would
+	be required on every call to determine if termios has already been setup.
+
+    Maybe I'm being way too anal, though.
+*/
+
+/* Resets the termios to its previous state */
+void _termios_reset(void)
+{
+	tcsetattr(0, TCSANOW, &original);
+}
+
+/************************************************
+  This pair of functions handles Ctrl-Z presses
+************************************************/
+
+void _sighandler_stop(int sig)
+{
+    // clean up the terminal
+    _termios_reset();
+
+    // ... and stop
+	kill(getpid(), SIGSTOP);
+}
+
+void _sighandler_cont(int sig)
+{
+    // restore terminal
+	tcsetattr(0, TCSANOW, &current);
+}
+
+
+/* Prepares termios for non-blocking action */
+void _termios_setup(void)
+{
+	beensetup = 1;
+    
+	tcgetattr(0, &original);
+  
+	memcpy(&current, &original, sizeof(struct termios));
+	current.c_cc[VMIN] = 1;           // read() will return with one char
+	current.c_cc[VTIME] = 0;          // read() blocks forever
+	current.c_lflag &= ~ICANON;       // character mode
+    current.c_lflag &= ~ECHO;         // turn off echoing
+	tcsetattr(0, TCSANOW, &current);
+
+    // Let's install an exit function, also.  This way, we can reset
+    // the termios silently
+    atexit(_termios_reset);
+
+    // install the Ctrl-Z handler
+    signal(SIGSTOP, _sighandler_stop);
+    signal(SIGCONT, _sighandler_cont);
+}
+
+
+int kbhit(void)
+{
+	// set up select() args
+	FD_ZERO(&inp);
+	FD_SET(0, &inp);
+
+	return select(1, &inp, NULL, NULL, &timeout);
+}
+
+int getch(void)
+{
+	char c;
+
+    if (!beensetup)
+    	// I hate to test for this every time, but this shouldn't be
+        // called that often anyway...
+    	_termios_setup();
+
+    // get a char out of stdin
+    read(0, &c, 1);
+
+    return c;
+}
+
+#endif // __unix__
+
 /****************************************************************************/
 /* Convert ASCIIZ string to upper case										*/
 /****************************************************************************/
@@ -278,4 +379,29 @@ int unlock(int file, long offset, int size)
 	return(i);
 }
 
-#endif	/* !Unix && (MSVC || MinGW) */
\ No newline at end of file
+#endif	/* !Unix && (MSVC || MinGW) */
+
+/****************************************************************************/
+/* Return ASCII string representation of ulong								*/
+/* There may be a native GNU C Library function to this...					*/
+/****************************************************************************/
+#if !defined _MSC_VER && !defined __BORLANDC__
+char* ultoa(unsigned long val, char* str, int radix)
+{
+	switch(radix) {
+		case 8:
+			sprintf(str,"%lo",val);
+			break;
+		case 10:
+			sprintf(str,"%lu",val);
+			break;
+		case 16:
+			sprintf(str,"%lx",val);
+			break;
+		default:
+			sprintf(str,"bad radix: %d",radix);
+			break;
+	}
+	return(str);
+}
+#endif
diff --git a/xtrn/sdk/xsdkwrap.h b/xtrn/sdk/xsdkwrap.h
index e9781d848c..fa1af1e6d9 100644
--- a/xtrn/sdk/xsdkwrap.h
+++ b/xtrn/sdk/xsdkwrap.h
@@ -38,9 +38,16 @@
 #ifndef _XSDKWRAP_H
 #define _XSDKWRAP_H
 
-/**********/
-/* Macros */
-/**********/
+#if defined(__unix__)
+
+	int kbhit(void);
+	int getch(void);
+
+#else	/* DOS-Based */
+
+	#include <conio.h>
+
+#endif
 
 #if defined(_WIN32)
 
@@ -78,6 +85,66 @@
 
 #endif
 
+#ifdef __unix__
+
+	#include <pthread.h>	/* POSIX threads and mutexes */
+	#include <semaphore.h>	/* POSIX semaphores */
+	ulong _beginthread(void( *start_address )( void * )
+		,unsigned stack_size, void *arglist);
+
+#elif defined(_WIN32)	
+
+	/* POIX semaphores */
+	typedef HANDLE sem_t;
+	#define sem_init(psem,ps,v)			ResetEvent(*(psem))
+	#define sem_wait(psem)				WaitForSingleObject(*(psem),INFINITE)
+	#define sem_post(psem)				SetEvent(*(psem))
+	#define sem_destroy(psem)			CloseHandle(*(psem))
+
+	/* POIX mutexes */
+	typedef HANDLE pthread_mutex_t;
+	#define pthread_mutex_init(pmtx,v)	*(pmtx)=CreateMutex(NULL,FALSE,NULL)
+	#define pthread_mutex_lock(pmtx)	WaitForSingleObject(*(pmtx),INFINITE)
+	#define pthread_mutex_unlock(pmtx)	ReleaseMutex(*(pmtx))
+	#define	pthread_mutex_destroy(pmtx)	CloseHandle(*(pmtx))
+
+#else
+
+	#warning "Need semaphore wrappers."
+
+#endif
+
+
+#if defined(_WIN32)
+
+	#define mswait(x)			Sleep(x)
+
+#elif defined(__OS2__)
+
+	#define mswait(x)			DosSleep(x)
+
+#elif defined(__unix__)
+
+	#define mswait(x)			usleep(x*1000)
+	#define _mkdir(dir)			mkdir(dir,0777)
+	#define _rmdir(dir)			rmdir(dir)
+	#define tell(fd)			lseek(fd,0,SEEK_CUR)
+
+	char* _fullpath(char* absPath, const char* relPath
+								,size_t maxLength);
+
+#elif defined(__MSDOS__)
+
+	void mswait(int ms);	/* Wait a specific number of milliseconds */
+
+#else	/* Unsupported OS */
+
+	#warning "Unsupported Target: Need some macros of function prototypes here."
+
+#endif
+
+
+
 #ifndef BOOL
 	#define BOOL	int
 #endif
@@ -106,6 +173,10 @@ extern "C" {
 	char*	strlwr(char* str);
 #endif
 
+#if !defined(_MSC_VER) && !defined(__BORLANDC__)
+	char*	ultoa(unsigned long val, char* str, int radix);
+#endif
+
 BOOL	fexist(char *filespec);
 long	flength(char *filename);
 
-- 
GitLab