From 3bf71671b2360f45cfd8a12f823c226402da1d88 Mon Sep 17 00:00:00 2001 From: Reini Urban Date: Thu, 30 May 2013 14:02:20 -0500 Subject: [PATCH] fix linenoise for windows (code from github.com/Choonster/lua-linenoise-windows) add CROSS: fixes more mingw cross-compiler issues, special strip and ranlib --- Makefile | 4 +- config.mak | 52 ++-- lib/readline/Makefile | 7 +- lib/readline/linenoise.c | 284 ++++++++++++++++++-- lib/readline/linenoise.h | 4 + lib/readline/win32fixes.c | 543 ++++++++++++++++++++++++++++++++++++++ lib/readline/win32fixes.h | 322 ++++++++++++++++++++++ tools/config.sh | 24 +- 8 files changed, 1193 insertions(+), 47 deletions(-) create mode 100644 lib/readline/win32fixes.c create mode 100644 lib/readline/win32fixes.h diff --git a/Makefile b/Makefile index 7e5105c4..8dfae8eb 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ OBJ_POTION = core/potion.${OPIC} OBJ_TEST = test/api/potion-test.o test/api/CuTest.o OBJ_GC_TEST = test/api/gc-test.o test/api/CuTest.o OBJ_GC_BENCH = test/api/gc-bench.o +PLIBS = libpotion${DLL} lib/readline${LOADEXT} DOC = doc/start.textile DOCHTML = ${DOC:.textile=.html} @@ -46,7 +47,7 @@ RUNPRE ?= ./ all: pn +${MAKE} -s usage -pn: potion${EXE} libpotion${DLL} lib/readline${LOADEXT} +pn: potion${EXE} ${PLIBS} static: libpotion.a potion-s${EXE} rebuild: clean pn test @@ -313,5 +314,6 @@ realclean: clean @rm -f config.inc ${GREG} core/syntax.c @rm -f GPATH GTAGS GRTAGS @rm -rf HTML + @find . -name \*.gcov -delete .PHONY: all config clean doc rebuild test bench tarball dist release install diff --git a/config.mak b/config.mak index 72f1aff9..8f38d43a 100644 --- a/config.mak +++ b/config.mak @@ -17,15 +17,17 @@ CLANG = 0 JIT = 0 EXE = APPLE = 0 +CYGWIN = 0 RUNPRE = ./ CAT = /bin/cat ECHO = /bin/echo +RANLIB = ranlib SED = sed EXPR = expr -STRIP ?= `./tools/config.sh "${CC}" strip` -JIT_TARGET ?= `./tools/config.sh "${CC}" jit` +STRIP ?= `tools/config.sh "${CC}" strip` +JIT_TARGET ?= `tools/config.sh "${CC}" jit` ifneq (${JIT_TARGET},) JIT = 1 endif @@ -35,37 +37,37 @@ ifeq (${JIT},1) ifneq (${DEBUG},0) # http://udis86.sourceforge.net/ x86 16,32,64 bit # port install udis86 -ifeq ($(shell ./tools/config.sh "${CC}" lib -ludis86 udis86.h),1) +ifeq ($(shell tools/config.sh "${CC}" lib -ludis86 udis86.h),1) DEFINES += -DHAVE_LIBUDIS86 -DJIT_DEBUG LIBS += -ludis86 else -ifeq ($(shell ./tools/config.sh "${CC}" lib -ludis86 udis86.h /opt/local),1) +ifeq ($(shell tools/config.sh "${CC}" lib -ludis86 udis86.h /opt/local),1) DEFINES += -DHAVE_LIBUDIS86 -DJIT_DEBUG INCS += -I/opt/local/include LIBS += -L/opt/local/lib -ludis86 else -ifeq ($(shell ./tools/config.sh "${CC}" lib -ludis86 udis86.h /usr/local),1) +ifeq ($(shell tools/config.sh "${CC}" lib -ludis86 udis86.h /usr/local),1) DEFINES += -DHAVE_LIBUDIS86 -DJIT_DEBUG INCS += -I/usr/local/include LIBS += -L/usr/local/lib -ludis86 else # http://ragestorm.net/distorm/ x86 16,32,64 bit with all intel/amd extensions # apt-get install libdistorm64-dev -ifeq ($(shell ./tools/config.sh "${CC}" lib -ldistorm64 stdlib.h),1) +ifeq ($(shell tools/config.sh "${CC}" lib -ldistorm64 stdlib.h),1) DEFINES += -DHAVE_LIBDISTORM64 -DJIT_DEBUG LIBS += -ldistorm64 else -ifeq ($(shell ./tools/config.sh "${CC}" lib -ldistorm64 stdlib.h /usr/local),1) +ifeq ($(shell tools/config.sh "${CC}" lib -ldistorm64 stdlib.h /usr/local),1) DEFINES += -DHAVE_LIBDISTORM64 -DJIT_DEBUG LIBS += -L/usr/local/lib -ldistorm64 else # http://bastard.sourceforge.net/libdisasm.html 386 32bit only # apt-get install libdisasm-dev -ifeq ($(shell ./tools/config.sh "${CC}" lib -ldisasm libdis.h),1) +ifeq ($(shell tools/config.sh "${CC}" lib -ldisasm libdis.h),1) DEFINES += -DHAVE_LIBDISASM -DJIT_DEBUG LIBS += -ldisasm else -ifeq ($(shell ./tools/config.sh "${CC}" lib -ldisasm libdis.h /usr/local),1) +ifeq ($(shell tools/config.sh "${CC}" lib -ldisasm libdis.h /usr/local),1) DEFINES += -DHAVE_LIBDISASM -DJIT_DEBUG INCS += -I/usr/local/include LIBS += -L/usr/local/lib -ldisasm @@ -79,11 +81,11 @@ endif endif endif -# JIT with -O still fails some tests +# JIT with -O still fails callcc tests ifneq (${JIT},1) DEBUGFLAGS += -O3 endif -ifneq ($(shell ./tools/config.sh "${CC}" clang),0) +ifneq ($(shell tools/config.sh "${CC}" clang),0) CLANG = 1 WARNINGS += -Wno-unused-value endif @@ -105,30 +107,37 @@ endif # CFLAGS += \${DEFINES} \${DEBUGFLAGS} -ifneq ($(shell ./tools/config.sh "${CC}" bsd),1) +ifneq ($(shell tools/config.sh "${CC}" bsd),1) LIBS += -ldl endif +CROSS = $(shell tools/config.sh "${CC}" cross) # cygwin is not WIN32. detect mingw target on cross -ifeq ($(shell ./tools/config.sh "${CC}" mingw),1) +ifeq ($(shell tools/config.sh "${CC}" mingw),1) WIN32 = 1 LDDLLFLAGS = -shared EXE = .exe - LOADEXT = .dll DLL = .dll + LOADEXT = .dll INCS += -Itools/dlfcn-win32/include LIBS += -Ltools/dlfcn-win32/lib - RUNPRE = RPATH = RPATH_INSTALL = + ifneq (${CROSS},1) + ECHO = echo + CAT = type + RUNPRE = + else + RANLIB = $(shell echo "${CC}" | sed -e "s,-gcc,-ranlib,") + endif else -ifeq ($(shell ./tools/config.sh "${CC}" cygwin),1) +ifeq ($(shell tools/config.sh "${CC}" cygwin),1) CYGWIN = 1 LDDLLFLAGS = -shared - EXE = .exe LOADEXT = .dll + EXE = .exe DLL = .dll else -ifeq ($(shell ./tools/config.sh "${CC}" apple),1) +ifeq ($(shell tools/config.sh "${CC}" apple),1) APPLE = 1 DLL = .dylib LOADEXT = .bundle @@ -170,6 +179,7 @@ config.inc.echo: @${ECHO} "LDDLLFLAGS = ${LDDLLFLAGS}" @${ECHO} "STRIP = ${STRIP}" @${ECHO} "RUNPRE = ${RUNPRE}" + @${ECHO} "CROSS = ${CROSS}" @${ECHO} "APPLE = ${APPLE}" @${ECHO} "WIN32 = ${WIN32}" @${ECHO} "CYGWIN = ${CYGWIN}" @@ -182,18 +192,18 @@ config.inc.echo: config.h.echo: @${ECHO} "#define POTION_CC \"${CC}\"" @${ECHO} "#define POTION_CFLAGS \"${CFLAGS}\"" - @${ECHO} "#define POTION_JIT ${JIT}" @${ECHO} "#define POTION_MAKE \"${MAKE}\"" @${ECHO} "#define POTION_PREFIX \"${PREFIX}\"" - @${ECHO} "#define POTION_WIN32 ${WIN32}" @${ECHO} "#define POTION_EXE \"${EXE}\"" @${ECHO} "#define POTION_DLL \"${DLL}\"" @${ECHO} "#define POTION_LOADEXT \"${LOADEXT}\"" + @${ECHO} "#define POTION_WIN32 ${WIN32}" + @${ECHO} "#define POTION_JIT ${JIT}" @test -n ${JIT_TARGET} && ${ECHO} "#define POTION_JIT_TARGET POTION_${JIT_TARGET}" @test -n ${JIT_TARGET} && ${ECHO} "#define POTION_JIT_NAME " $(shell echo ${JIT_TARGET} | tr A-Z a-z) @${ECHO} ${DEFINES} | perl -lpe's/-D(\w+)/\n#define \1 1/g; s/=/ /g; s{-I[a-z/:]* }{}g;' @${ECHO} - @./tools/config.sh "${CC}" + @tools/config.sh "${CC}" # bootstrap config.inc via `make -f config.mak` config.inc: tools/config.sh config.mak diff --git a/lib/readline/Makefile b/lib/readline/Makefile index 348ec209..83818725 100644 --- a/lib/readline/Makefile +++ b/lib/readline/Makefile @@ -1,12 +1,17 @@ include ../../config.inc INCS += -I../../core LIBS = -L../.. -lpotion +SRC = linenoise.c +ifeq ($(WIN32),1) + SRC += win32fixes.c + LIBS += -lws2_32 +endif all: readline${LOADEXT} %${LOADEXT}: %.c @if [ -f ../../libpotion.a ]; then mv ../../libpotion.a ../../libpotion.a.tmp; fi - @$(CC) $(CFLAGS) -o $@ $(INCS) $(LDDLLFLAGS) linenoise.c $< $(LIBS) + @$(CC) $(CFLAGS) -o $@ $(INCS) $(LDDLLFLAGS) $(SRC) $< $(LIBS) @if [ -f ../../libpotion.a.tmp ]; then mv ../../libpotion.a.tmp ../../libpotion.a; fi test: diff --git a/lib/readline/linenoise.c b/lib/readline/linenoise.c index 4632f7de..f66f676d 100644 --- a/lib/readline/linenoise.c +++ b/lib/readline/linenoise.c @@ -2,8 +2,9 @@ * line editing lib needs to be 20,000 lines of C code. * * You can find the latest source code at: - * * http://github.com/antirez/linenoise + * and the win32 port at: + * http://github.com/Choonster/lua-linenoise-windows * * Does a number of crazy assumptions that happen to be true in 99.9999% of * the 2010 UNIX computers around. @@ -47,7 +48,6 @@ * Todo list: * - Switch to gets() if $TERM is something we can't support. * - Filter bogus Ctrl+ combinations. - * - Win32 support * * Bloat: * - Completion? @@ -84,25 +84,33 @@ * Effect: clear the whole screen * */ - -#include -#include +#ifndef _WIN32 + #include + #include + #include +#endif #include #include #include #include #include #include -#include -#include #include "linenoise.h" +#define NOTUSED(V) ((void) V) +#ifdef _WIN32 + #include "win32fixes.h" +#endif #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 #define LINENOISE_MAX_LINE 4096 +#ifndef _WIN32 static char *unsupported_term[] = {"dumb","cons25",NULL}; +#endif static linenoiseCompletionCallback *completionCallback = NULL; +#ifndef _WIN32 static struct termios orig_termios; /* in order to restore at exit */ +#endif static int rawmode = 0; /* for atexit() function to check if restore is needed*/ static int atexit_registered = 0; /* register atexit just 1 time */ static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; @@ -112,13 +120,141 @@ char **history = NULL; static void linenoiseAtExit(void); int linenoiseHistoryAdd(const char *line); +#ifdef _WIN32 +#ifndef STDIN_FILENO + #define STDIN_FILENO (_fileno(stdin)) +#endif + +HANDLE hOut; +HANDLE hIn; +DWORD consolemode; + +static int win32read(char *c) { + + DWORD foo; + INPUT_RECORD b; + KEY_EVENT_RECORD e; + + while (1) { + if (!ReadConsoleInput(hIn, &b, 1, &foo)) return 0; + if (!foo) return 0; + + if (b.EventType == KEY_EVENT && b.Event.KeyEvent.bKeyDown) { + + e = b.Event.KeyEvent; + *c = b.Event.KeyEvent.uChar.AsciiChar; + + //if (e.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { + /* Alt+key ignored */ + //} else + if (e.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { + + /* Ctrl+Key */ + switch (*c) { + case 'D': + *c = 4; + return 1; + case 'C': + *c = 3; + return 1; + case 'H': + *c = 8; + return 1; + case 'T': + *c = 20; + return 1; + case 'B': /* ctrl-b, left_arrow */ + *c = 2; + return 1; + case 'F': /* ctrl-f right_arrow*/ + *c = 6; + return 1; + case 'P': /* ctrl-p up_arrow*/ + *c = 16; + return 1; + case 'N': /* ctrl-n down_arrow*/ + *c = 14; + return 1; + case 'U': /* Ctrl+u, delete the whole line. */ + *c = 21; + return 1; + case 'K': /* Ctrl+k, delete from current to end of line. */ + *c = 11; + return 1; + case 'A': /* Ctrl+a, go to the start of the line */ + *c = 1; + return 1; + case 'E': /* ctrl+e, go to the end of the line */ + *c = 5; + return 1; + } + + /* Other Ctrl+KEYs ignored */ + } else { + + switch (e.wVirtualKeyCode) { + + case VK_ESCAPE: /* ignore - send ctrl-c, will return -1 */ + *c = 3; + return 1; + case VK_RETURN: /* enter */ + *c = 13; + return 1; + case VK_LEFT: /* left */ + *c = 2; + return 1; + case VK_RIGHT: /* right */ + *c = 6; + return 1; + case VK_UP: /* up */ + *c = 16; + return 1; + case VK_DOWN: /* down */ + *c = 14; + return 1; + case VK_HOME: + *c = 1; + return 1; + case VK_END: + *c = 5; + return 1; + case VK_BACK: + *c = 8; + return 1; + case VK_DELETE: + *c = 127; + return 1; + default: + if (*c) return 1; + } + } + } + } + + return -1; /* Makes compiler happy */ +} + +#ifdef __STRICT_ANSI__ +char *strdup(const char *s) { + size_t l = strlen(s)+1; + char *p = malloc(l); + + memcpy(p,s,l); + return p; +} +#endif /* __STRICT_ANSI__ */ + +#endif /* _WIN32 */ + static int isUnsupportedTerm(void) { +#ifndef _WIN32 char *term = getenv("TERM"); int j; if (term == NULL) return 0; for (j = 0; unsupported_term[j]; j++) if (!strcasecmp(term,unsupported_term[j])) return 1; +#endif return 0; } @@ -133,6 +269,7 @@ static void freeHistory(void) { } static int enableRawMode(int fd) { +#ifndef _WIN32 struct termios raw; if (!isatty(STDIN_FILENO)) goto fatal; @@ -160,6 +297,37 @@ static int enableRawMode(int fd) { /* put terminal in raw mode after flushing */ if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal; rawmode = 1; +#else + NOTUSED(fd); + + if (!atexit_registered) { + /* Init windows console handles only once */ + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (hOut==INVALID_HANDLE_VALUE) goto fatal; + + if (!GetConsoleMode(hOut, &consolemode)) { + CloseHandle(hOut); + errno = ENOTTY; + return -1; + }; + + hIn = GetStdHandle(STD_INPUT_HANDLE); + if (hIn == INVALID_HANDLE_VALUE) { + CloseHandle(hOut); + errno = ENOTTY; + return -1; + } + + GetConsoleMode(hIn, &consolemode); + SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT); + + /* Cleanup them at exit */ + atexit(linenoiseAtExit); + atexit_registered = 1; + } + + rawmode = 1; +#endif return 0; fatal: @@ -168,26 +336,49 @@ static int enableRawMode(int fd) { } static void disableRawMode(int fd) { +#ifdef _WIN32 + NOTUSED(fd); + rawmode = 0; +#else /* Don't even check the return value as it's too late. */ if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1) rawmode = 0; +#endif } /* At exit we'll try to fix the terminal to the initial conditions. */ static void linenoiseAtExit(void) { +#ifdef _WIN32 + SetConsoleMode(hIn, consolemode); + CloseHandle(hOut); + CloseHandle(hIn); +#else disableRawMode(STDIN_FILENO); +#endif freeHistory(); } static int getColumns(void) { +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO b; + + if (!GetConsoleScreenBufferInfo(hOut, &b)) return 80; + return b.srWindow.Right - b.srWindow.Left; +#else struct winsize ws; if (ioctl(1, TIOCGWINSZ, &ws) == -1) return 80; return ws.ws_col; +#endif } static void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_t pos, size_t cols) { char seq[64]; +#ifdef _WIN32 + DWORD pl, bl, w; + CONSOLE_SCREEN_BUFFER_INFO b; + COORD coord; +#endif size_t plen = strlen(prompt); while((plen+pos) >= cols) { @@ -199,6 +390,7 @@ static void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_ len--; } +#ifndef _WIN32 /* Cursor to left edge */ snprintf(seq,64,"\x1b[0G"); if (write(fd,seq,strlen(seq)) == -1) return; @@ -211,6 +403,27 @@ static void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_ /* Move cursor to original position. */ snprintf(seq,64,"\x1b[0G\x1b[%dC", (int)(pos+plen)); if (write(fd,seq,strlen(seq)) == -1) return; +#else + + NOTUSED(seq); + NOTUSED(fd); + + /* Get buffer console info */ + if (!GetConsoleScreenBufferInfo(hOut, &b)) return; + /* Erase Line */ + coord.X = 0; + coord.Y = b.dwCursorPosition.Y; + FillConsoleOutputCharacterA(hOut, ' ', b.dwSize.X, coord, &w); + /* Cursor to the left edge */ + SetConsoleCursorPosition(hOut, coord); + /* Write the prompt and the current buffer content */ + WriteConsole(hOut, prompt, (DWORD)plen, &pl, NULL); + WriteConsole(hOut, buf, (DWORD)len, &bl, NULL); + /* Move cursor to original position. */ + coord.X = (int)(pos+plen); + coord.Y = b.dwCursorPosition.Y; + SetConsoleCursorPosition(hOut, coord); +#endif } static void beep() { @@ -293,8 +506,9 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) size_t len = 0; size_t cols = getColumns(); int history_index = 0; - size_t old_pos; - size_t diff; +#ifdef _WIN32 + DWORD foo; +#endif buf[0] = '\0'; buflen--; /* Make sure there is always space for the nulterm */ @@ -303,14 +517,22 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) * initially is just an empty string. */ linenoiseHistoryAdd(""); +#ifdef _WIN32 + if (!WriteConsole(hOut, prompt, (DWORD)plen, &foo, NULL)) return -1; +#else if (write(fd,prompt,plen) == -1) return -1; +#endif while(1) { char c; int nread; char seq[2], seq2[2]; +#ifdef _WIN32 + nread = win32read(&c); +#else nread = read(fd,&c,1); - if (nread <= 0) return len; +#endif + if (nread <= 0) return (int)len; /* Only autocomplete when the callback is set. It returns < 0 when * there was an error reading from fd. Otherwise it will return the @@ -318,7 +540,7 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) if (c == 9 && completionCallback != NULL) { c = completeLine(fd,prompt,buf,buflen,&len,&pos,cols); /* Return on errors */ - if (c < 0) return len; + if (c < 0) return (int)len; /* Read next character when 0 */ if (c == 0) continue; } @@ -332,6 +554,17 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) errno = EAGAIN; return -1; case 127: /* backspace */ +#ifdef _WIN32 + /* delete in _WIN32*/ + /* win32read() will send 127 for DEL and 8 for BS and Ctrl-H */ + if (pos < len && len > 0) { + memmove(buf+pos,buf+pos+1,len-pos); + len--; + buf[len] = '\0'; + refreshLine(fd,prompt,buf,len,pos,cols); + } + break; +#endif case 8: /* ctrl-h */ if (pos > 0 && len > 0) { memmove(buf+pos-1,buf+pos,len-pos); @@ -435,7 +668,11 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) if (plen+len < cols) { /* Avoid a full update of the line in the * trivial case. */ +#ifdef _WIN32 + if (!WriteConsole(hOut, &c, 1, &foo, NULL)) return -1; +#else if (write(fd,&c,1) == -1) return -1; +#endif } else { refreshLine(fd,prompt,buf,len,pos,cols); } @@ -472,7 +709,9 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) refreshLine(fd,prompt,buf,len,pos,cols); break; case 23: /* ctrl+w, delete previous word */ - old_pos = pos; + { + size_t old_pos = pos; + size_t diff; while (pos > 0 && buf[pos-1] == ' ') pos--; while (pos > 0 && buf[pos-1] != ' ') @@ -482,9 +721,10 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) len -= diff; refreshLine(fd,prompt,buf,len,pos,cols); break; + } } } - return len; + return (int)len; } static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { @@ -496,8 +736,8 @@ static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { return -1; } if (!isatty(STDIN_FILENO)) { - if (fgets(buf, buflen, stdin) == NULL) return -1; - count = strlen(buf); + if (fgets(buf, (int)buflen, stdin) == NULL) return -1; + count = (int)strlen(buf); if (count && buf[count-1] == '\n') { count--; buf[count] = '\0'; @@ -570,18 +810,18 @@ int linenoiseHistoryAdd(const char *line) { } int linenoiseHistorySetMaxLen(int len) { - char **new; + char **newC; if (len < 1) return 0; if (history) { int tocopy = history_len; - new = malloc(sizeof(char*)*len); - if (new == NULL) return 0; + newC = malloc(sizeof(char*)*len); + if (newC == NULL) return 0; if (len < tocopy) tocopy = len; - memcpy(new,history+(history_max_len-tocopy), sizeof(char*)*tocopy); + memcpy(newC,history+(history_max_len-tocopy), sizeof(char*)*tocopy); free(history); - history = new; + history = newC; } history_max_len = len; if (history_len > history_max_len) @@ -592,7 +832,11 @@ int linenoiseHistorySetMaxLen(int len) { /* Save the history in the specified file. On success 0 is returned * otherwise -1 is returned. */ int linenoiseHistorySave(char *filename) { +#ifdef _WIN32 + FILE *fp = fopen(filename,"wb"); +#else FILE *fp = fopen(filename,"w"); +#endif int j; if (fp == NULL) return -1; diff --git a/lib/readline/linenoise.h b/lib/readline/linenoise.h index 15f2a31e..709643b8 100644 --- a/lib/readline/linenoise.h +++ b/lib/readline/linenoise.h @@ -37,6 +37,10 @@ #ifndef __LINENOISE_H #define __LINENOISE_H +#ifdef _WIN32 +# define off off_t +#endif + typedef struct linenoiseCompletions { size_t len; char **cvec; diff --git a/lib/readline/win32fixes.c b/lib/readline/win32fixes.c new file mode 100644 index 00000000..5bce1cc0 --- /dev/null +++ b/lib/readline/win32fixes.c @@ -0,0 +1,543 @@ +/* +* Modified by Henry Rawas (henryr@schakra.com) +* - make it compatible with Visual Studio builds +* - added wstrtod to handle INF, NAN +* - added gettimeofday routine +* - modified rename to retry after failure +*/ + +#ifdef _WIN32 + +#include +#include +#include +#ifndef FD_SETSIZE +# define FD_SETSIZE 16000 +#endif +#include +#include +#include +#include +#include +#include +#include "win32fixes.h" + + +/* Redefined here to avoid redis.h so it can be used in other projects */ +#define NOTUSED(V) ((void) V) +#define THREAD_STACK_SIZE (1024*1024*4) + +/* Winsock requires library initialization on startup */ +int w32initWinSock(void) { + + WSADATA t_wsa; + WORD wVers; + int iError; + + wVers = MAKEWORD(2, 2); + iError = WSAStartup(wVers, &t_wsa); + + if(iError != NO_ERROR || LOBYTE(t_wsa.wVersion) != 2 || HIBYTE(t_wsa.wVersion) != 2 ) { + return 0; /* not done; check WSAGetLastError() for error number */ + }; + + return 1; +} + +/* Behaves as posix, works without ifdefs, makes compiler happy */ +int sigaction(int sig, struct sigaction *in, struct sigaction *out) { + NOTUSED(out); + + /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction + * is used. Otherwise, sa_handler is used */ + if (in->sa_flags & SA_SIGINFO) + signal(sig, in->sa_sigaction); + else + signal(sig, in->sa_handler); + + return 0; +} + +/* Terminates process, implemented only for SIGKILL */ +int kill(pid_t pid, int sig) { + + if (sig == SIGKILL) { + + HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, pid); + + if (!TerminateProcess(h, 127)) { + errno = EINVAL; /* GetLastError() */ + CloseHandle(h); + return -1; + }; + + CloseHandle(h); + return 0; + } else { + errno = EINVAL; + return -1; + }; +} + +/* Forced write to disk */ +int fsync (int fd) { + HANDLE h = (HANDLE) _get_osfhandle(fd); + DWORD err; + + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + if (!FlushFileBuffers(h)) { + /* Windows error -> Unix */ + err = GetLastError(); + switch (err) { + case ERROR_INVALID_HANDLE: + errno = EINVAL; + break; + + default: + errno = EIO; + } + return -1; + } + + return 0; +} + +/* Missing wait3() implementation */ +pid_t wait3(int *stat_loc, int options, void *rusage) { + NOTUSED(stat_loc); + NOTUSED(options); + NOTUSED(rusage); + return (pid_t) waitpid((intptr_t) -1, 0, WAIT_FLAGS); +} + +/* Replace MS C rtl rand which is 15bit with 32 bit */ +int replace_random() { + unsigned int x=0; + if (RtlGenRandom == NULL) { + // load proc if not loaded + HMODULE lib = LoadLibraryA("advapi32.dll"); + RtlGenRandom = (RtlGenRandomFunc)GetProcAddress(lib, "SystemFunction036"); + if (RtlGenRandom == NULL) return 1; + } + RtlGenRandom(&x, sizeof(UINT_MAX)); + return (int)(x >> 1); +} + +/* BSD sockets compatibile replacement */ +int replace_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) { + return (setsockopt)((SOCKET)socket, level, optname, (const char *)optval, optlen); +} + +/* set size with 64bit support */ +int replace_ftruncate(int fd, off64_t length) { + HANDLE h = (HANDLE) _get_osfhandle (fd); + LARGE_INTEGER l, o; + + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + l.QuadPart = length; + + if (!SetFilePointerEx(h, l, &o, FILE_BEGIN)) return -1; + if (!SetEndOfFile(h)) return -1; + + return 0; +} + +/* Rename which works on Windows when file exists */ +int replace_rename(const char *src, const char *dst) { + /* anti-virus may lock file - error code 5. Retry until it works or get a different error */ + int retries = 50; + while (1) { + if (MoveFileEx(src, dst, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH)) { + return 0; + } else { + errno = GetLastError(); + if (errno != 5) break; + retries--; + if (retries == 0) { + retries = 50; + Sleep(10); + } + } + } + /* On error we will return generic error code without GetLastError() */ + return -1; +} + +/* Proxy structure to pass func and arg to thread */ +typedef struct thread_params +{ + void *(*func)(void *); + void * arg; +} thread_params; + +/* Proxy function by windows thread requirements */ +static unsigned __stdcall win32_proxy_threadproc(void *arg) { + + thread_params *p = (thread_params *) arg; + p->func(p->arg); + + /* Dealocate params */ + free(p); + + _endthreadex(0); + return 0; +} + +int pthread_create(pthread_t *thread, const void *unused, + void *(*start_routine)(void*), void *arg) { + HANDLE h; + thread_params *params = (thread_params *)malloc(sizeof(thread_params)); + NOTUSED(unused); + + params->func = start_routine; + params->arg = arg; + + h =(HANDLE) _beginthreadex(NULL, /* Security not used */ + THREAD_STACK_SIZE, /* Set custom stack size */ + win32_proxy_threadproc, /* calls win32 stdcall proxy */ + params, /* real threadproc is passed as paremeter */ + STACK_SIZE_PARAM_IS_A_RESERVATION, /* reserve stack */ + thread /* returned thread id */ + ); + + if (!h) + return errno; + + CloseHandle(h); + return 0; +} + +/* Noop in windows */ +int pthread_detach (pthread_t thread) { + NOTUSED(thread); + return 0; /* noop */ + } + +pthread_t pthread_self(void) { + return GetCurrentThreadId(); +} + +int win32_pthread_join(pthread_t *thread, void **value_ptr) { + int result; + HANDLE h = OpenThread(SYNCHRONIZE, FALSE, *thread); + NOTUSED(value_ptr); + + switch (WaitForSingleObject(h, INFINITE)) { + case WAIT_OBJECT_0: + result = 0; + case WAIT_ABANDONED: + result = EINVAL; + default: + result = GetLastError(); + } + + CloseHandle(h); + return result; +} + +int pthread_cond_init(pthread_cond_t *cond, const void *unused) { + NOTUSED(unused); + cond->waiters = 0; + cond->was_broadcast = 0; + + InitializeCriticalSection(&cond->waiters_lock); + + cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL); + if (!cond->sema) { + errno = GetLastError(); + return -1; + } + + cond->continue_broadcast = CreateEvent(NULL, /* security */ + FALSE, /* auto-reset */ + FALSE, /* not signaled */ + NULL); /* name */ + if (!cond->continue_broadcast) { + errno = GetLastError(); + return -1; + } + + return 0; +} + +int pthread_cond_destroy(pthread_cond_t *cond) { + CloseHandle(cond->sema); + CloseHandle(cond->continue_broadcast); + DeleteCriticalSection(&cond->waiters_lock); + return 0; +} + +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { + int last_waiter; + + EnterCriticalSection(&cond->waiters_lock); + cond->waiters++; + LeaveCriticalSection(&cond->waiters_lock); + + /* + * Unlock external mutex and wait for signal. + * NOTE: we've held mutex locked long enough to increment + * waiters count above, so there's no problem with + * leaving mutex unlocked before we wait on semaphore. + */ + LeaveCriticalSection(mutex); + + /* let's wait - ignore return value */ + WaitForSingleObject(cond->sema, INFINITE); + + /* + * Decrease waiters count. If we are the last waiter, then we must + * notify the broadcasting thread that it can continue. + * But if we continued due to cond_signal, we do not have to do that + * because the signaling thread knows that only one waiter continued. + */ + EnterCriticalSection(&cond->waiters_lock); + cond->waiters--; + last_waiter = cond->was_broadcast && cond->waiters == 0; + LeaveCriticalSection(&cond->waiters_lock); + + if (last_waiter) { + /* + * cond_broadcast was issued while mutex was held. This means + * that all other waiters have continued, but are contending + * for the mutex at the end of this function because the + * broadcasting thread did not leave cond_broadcast, yet. + * (This is so that it can be sure that each waiter has + * consumed exactly one slice of the semaphor.) + * The last waiter must tell the broadcasting thread that it + * can go on. + */ + SetEvent(cond->continue_broadcast); + /* + * Now we go on to contend with all other waiters for + * the mutex. Auf in den Kampf! + */ + } + /* lock external mutex again */ + EnterCriticalSection(mutex); + + return 0; +} + +/* + * IMPORTANT: This implementation requires that pthread_cond_signal + * is called while the mutex is held that is used in the corresponding + * pthread_cond_wait calls! + */ +int pthread_cond_signal(pthread_cond_t *cond) { + int have_waiters; + + EnterCriticalSection(&cond->waiters_lock); + have_waiters = cond->waiters > 0; + LeaveCriticalSection(&cond->waiters_lock); + + /* + * Signal only when there are waiters + */ + if (have_waiters) + return ReleaseSemaphore(cond->sema, 1, NULL) ? + 0 : GetLastError(); + else + return 0; +} + + +/* Redis forks to perform background writing */ +/* fork() on unix will split process in two */ +/* marking memory pages as Copy-On-Write so */ +/* child process will have data snapshot. */ +/* Windows has no support for fork(). */ +int fork(void) { + return -1; + } + +/* Redis CPU GetProcessTimes -> rusage */ +int getrusage(int who, struct rusage * r) { + + FILETIME starttime, exittime, kerneltime, usertime; + ULARGE_INTEGER li; + + if (r == NULL) { + errno = EFAULT; + return -1; + } + + memset(r, 0, sizeof(struct rusage)); + + if (who == RUSAGE_SELF) { + if (!GetProcessTimes(GetCurrentProcess(), + &starttime, + &exittime, + &kerneltime, + &usertime)) + { + errno = EFAULT; + return -1; + } + } + + if (who == RUSAGE_CHILDREN) { + /* Childless on windows */ + starttime.dwLowDateTime = 0; + starttime.dwHighDateTime = 0; + exittime.dwLowDateTime = 0; + exittime.dwHighDateTime = 0; + kerneltime.dwLowDateTime = 0; + kerneltime.dwHighDateTime = 0; + usertime.dwLowDateTime = 0; + usertime.dwHighDateTime = 0; + } + memcpy(&li, &kerneltime, sizeof(FILETIME)); + li.QuadPart /= 10L; + r->ru_stime.tv_sec = (long)(li.QuadPart / 1000000L); + r->ru_stime.tv_usec = (long)(li.QuadPart % 1000000L); + + memcpy(&li, &usertime, sizeof(FILETIME)); + li.QuadPart /= 10L; + r->ru_utime.tv_sec = (long)(li.QuadPart / 1000000L); + r->ru_utime.tv_usec = (long)(li.QuadPart % 1000000L); + + return 0; +} + +#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 + +#if 0 +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + FILETIME ft; + unsigned __int64 tmpres = 0; + static int tzflag; + + if (NULL != tv) + { + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + + /*converting file time to unix epoch*/ + tmpres -= DELTA_EPOCH_IN_MICROSECS; + tmpres /= 10; /*convert into microseconds*/ + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + + if (NULL != tz) + { + if (!tzflag) + { + _tzset(); + tzflag++; + } + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + return 0; +} +#endif + +static _locale_t clocale = NULL; +double wstrtod(const char *nptr, char **eptr) { + double d; + char *leptr; +#if 0 + if (clocale == NULL) + clocale = _create_locale(LC_ALL, "C"); +#endif + d = _strtod_l(nptr, &leptr, clocale); + /* if 0, check if input was inf */ + if (d == 0 && nptr == leptr) { + int neg = 0; + while (isspace(*nptr)) + nptr++; + if (*nptr == '+') + nptr++; + else if (*nptr == '-') { + nptr++; + neg = 1; + } + + if (strnicmp("INF", nptr, 3) == 0) { + if (eptr != NULL) { + if (strnicmp("INFINITE", nptr, 8) == 0) + *eptr = (char*)(nptr + 8); + else + *eptr = (char*)(nptr + 3); + } + if (neg == 1) + return -HUGE_VAL; + else + return HUGE_VAL; + } else if (strnicmp("NAN", nptr, 3) == 0) { + if (eptr != NULL) + *eptr = (char*)(nptr + 3); + /* create a NaN : 0 * infinity*/ + d = HUGE_VAL; + return d * 0; + } + } + if (eptr != NULL) + *eptr = leptr; + return d; +} + +int strerror_r(int err, char* buf, size_t buflen) { + int size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + 0, + buf, + (DWORD)buflen, + NULL); + if (size == 0) { + char* strerr = strerror(err); + if (strlen(strerr) >= buflen) { + errno = ERANGE; + return -1; + } + strcpy(buf, strerr); + } + if (size > 2 && buf[size - 2] == '\r') { + /* remove extra CRLF */ + buf[size - 2] = '\0'; + } + return 0; +} + +char wsa_strerror_buf[128]; +char *wsa_strerror(int err) { + int size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + 0, + wsa_strerror_buf, + 128, + NULL); + if (size == 0) return strerror(err); + if (size > 2 && wsa_strerror_buf[size - 2] == '\r') { + /* remove extra CRLF */ + wsa_strerror_buf[size - 2] = '\0'; + } + return wsa_strerror_buf; +} + +#endif diff --git a/lib/readline/win32fixes.h b/lib/readline/win32fixes.h new file mode 100644 index 00000000..107143dc --- /dev/null +++ b/lib/readline/win32fixes.h @@ -0,0 +1,322 @@ +/* +* Modified by Henry Rawas (henryr@schakra.com) +* - make it compatible with Visual Studio builds +* - added wstrtod to handle INF, NAN +* - added support for using IOCP with sockets +*/ + +#ifndef WIN32FIXES_H +#define WIN32FIXES_H + +#ifdef WIN32 +#ifndef _WIN32 +#define _WIN32 +#endif +#endif + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#define NOGDI +#define __USE_W32_SOCKETS + +#include "fmacros.h" +#include +#include +#include +#include +#include +#ifndef FD_SETSIZE +#define FD_SETSIZE 16000 +#endif +#include /* setsocketopt */ +#include +#include +#include +#include /* _O_BINARY */ +#include /* INT_MAX */ +#include +#include + +#define fseeko fseeko64 +#define ftello ftello64 + +#define inline __inline + +#undef ftruncate +#define ftruncate replace_ftruncate +#ifndef off64_t +#define off64_t off_t +#endif + +int replace_ftruncate(int fd, off64_t length); + + +#define snprintf _snprintf +#define ftello64 _ftelli64 +#define fseeko64 _fseeki64 +#define strcasecmp _stricmp +#define strtoll _strtoi64 +#ifndef _MATH_H_ + #define isnan _isnan + #define isfinite _finite + #define isinf(x) (!_finite(x)) +#endif +#define lseek64 lseek +/* following defined to choose little endian byte order */ +#define __i386__ 1 +#if !defined(va_copy) +#define va_copy(d,s) d = (s) +#endif + +#define sleep(x) Sleep((x)*1000) + +#ifndef __RTL_GENRANDOM +#define __RTL_GENRANDOM 1 +typedef BOOLEAN (_stdcall* RtlGenRandomFunc)(void * RandomBuffer, ULONG RandomBufferLength); +#endif +RtlGenRandomFunc RtlGenRandom; + +#define random() (long)replace_random() +#define rand() replace_random() +int replace_random(); + +#if !defined(ssize_t) +typedef int ssize_t; +#endif + +#if !defined(mode_t) +#define mode_t long +#endif + +#if !defined(u_int32_t) +/* sha1 */ +typedef unsigned __int32 u_int32_t; +#endif + +/* Redis calls usleep(1) to give thread some time +* Sleep(0) should do the same on windows +* In other cases, usleep is called with milisec resolution, +* which can be directly translated to winapi Sleep() */ +#undef usleep +#define usleep(x) (x == 1) ? Sleep(0) : Sleep((int)((x)/1000)) + +#define pipe(fds) _pipe(fds, 8192, _O_BINARY|_O_NOINHERIT) + +/* Processes */ +#define waitpid(pid,statusp,options) _cwait (statusp, pid, WAIT_CHILD) + +#define WAIT_T int +#define WTERMSIG(x) ((x) & 0xff) /* or: SIGABRT ?? */ +#define WCOREDUMP(x) 0 +#define WEXITSTATUS(x) (((x) >> 8) & 0xff) /* or: (x) ?? */ +#define WIFSIGNALED(x) (WTERMSIG (x) != 0) /* or: ((x) == 3) ?? */ +#define WIFEXITED(x) (WTERMSIG (x) == 0) /* or: ((x) != 3) ?? */ +#define WIFSTOPPED(x) 0 + +#define WNOHANG 1 + +/* file mapping */ +#define PROT_READ 1 +#define PROT_WRITE 2 + +#define MAP_FAILED (void *) -1 + +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 + +/* rusage */ +#define RUSAGE_SELF 0 +#define RUSAGE_CHILDREN (-1) + +#ifndef _RUSAGE_T_ +#define _RUSAGE_T_ +struct rusage { + struct timeval ru_utime; /* user time used */ + struct timeval ru_stime; /* system time used */ +}; +#endif + +int getrusage(int who, struct rusage * rusage); + +/* Signals */ +#define SIGNULL 0 /* Null Check access to pid*/ +#define SIGHUP 1 /* Hangup Terminate; can be trapped*/ +#define SIGINT 2 /* Interrupt Terminate; can be trapped */ +#define SIGQUIT 3 /* Quit Terminate with core dump; can be trapped */ +#define SIGTRAP 5 +#define SIGBUS 7 +#define SIGKILL 9 /* Kill Forced termination; cannot be trapped */ +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 /* Terminate Terminate; can be trapped */ +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGABRT 22 +/* #define SIGSTOP 24 / * Pause the process; cannot be trapped */ +/* #define SIGTSTP 25 / * Terminal stop Pause the process; can be trapped */ +/* #define SIGCONT 26 */ +#define SIGWINCH 28 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define ucontext_t void* + +#define SA_NOCLDSTOP 0x00000001u +#define SA_NOCLDWAIT 0x00000002u +#define SA_SIGINFO 0x00000004u +#define SA_ONSTACK 0x08000000u +#define SA_RESTART 0x10000000u +#define SA_NODEFER 0x40000000u +#define SA_RESETHAND 0x80000000u +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND +#define SA_RESTORER 0x04000000 + + +#define sigemptyset(pset) (*(pset) = 0) +#define sigfillset(pset) (*(pset) = (unsigned int)-1) +#define sigaddset(pset, num) (*(pset) |= (1L<<(num))) +#define sigdelset(pset, num) (*(pset) &= ~(1L<<(num))) +#define sigismember(pset, num) (*(pset) & (1L<<(num))) + +#ifndef SIG_SETMASK +#define SIG_SETMASK (0) +#define SIG_BLOCK (1) +#define SIG_UNBLOCK (2) +#endif /*SIG_SETMASK*/ + +typedef void (*__p_sig_fn_t)(int); +typedef int pid_t; + +#ifndef _SIGSET_T_ +#define _SIGSET_T_ +#ifdef _WIN64 +typedef unsigned long long _sigset_t; +#else +typedef unsigned long _sigset_t; +#endif +#endif /* _SIGSET_T_ */ +#ifndef _POSIX +# define sigset_t _sigset_t +#endif + +struct sigaction { + int sa_flags; + sigset_t sa_mask; + __p_sig_fn_t sa_handler; + __p_sig_fn_t sa_sigaction; +}; + +int sigaction(int sig, struct sigaction *in, struct sigaction *out); + +/* Sockets */ + +#ifndef ECONNRESET +#define ECONNRESET WSAECONNRESET +#endif + +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif + +#ifndef ETIMEDOUT +#define ETIMEDOUT WSAETIMEDOUT +#endif + +#define setsockopt(a,b,c,d,e) replace_setsockopt(a,b,c,d,e) + +int replace_setsockopt(int socket, int level, int optname, + const void *optval, socklen_t optlen); + +#define rename(a,b) replace_rename(a,b) +int replace_rename(const char *src, const char *dest); + +//threads avoiding pthread.h + +#define pthread_mutex_t CRITICAL_SECTION +#define pthread_attr_t ssize_t + +#define pthread_mutex_init(a,b) (InitializeCriticalSectionAndSpinCount((a), 0x80000400),0) +#define pthread_mutex_destroy(a) DeleteCriticalSection((a)) +#define pthread_mutex_lock EnterCriticalSection +#define pthread_mutex_unlock LeaveCriticalSection + +#define pthread_equal(t1, t2) ((t1) == (t2)) + +#define pthread_attr_init(x) (*(x) = 0) +#define pthread_attr_getstacksize(x, y) (*(y) = *(x)) +#define pthread_attr_setstacksize(x, y) (*(x) = y) + +#define pthread_t u_int + +int pthread_create(pthread_t *thread, const void *unused, + void *(*start_routine)(void*), void *arg); + +pthread_t pthread_self(void); + +typedef struct { + CRITICAL_SECTION waiters_lock; + LONG waiters; + int was_broadcast; + HANDLE sema; + HANDLE continue_broadcast; +} pthread_cond_t; + +int pthread_cond_init(pthread_cond_t *cond, const void *unused); +int pthread_cond_destroy(pthread_cond_t *cond); +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +int pthread_cond_signal(pthread_cond_t *cond); + +int pthread_detach (pthread_t thread); + +/* Misc Unix -> Win32 */ +int kill(pid_t pid, int sig); +int fsync (int fd); +pid_t wait3(int *stat_loc, int options, void *rusage); + +int w32initWinSock(void); +/* int inet_aton(const char *cp_arg, struct in_addr *addr) */ + +/* redis-check-dump */ +//void *mmap(void *start, size_t length, int prot, int flags, int fd, off offset); +//int munmap(void *start, size_t length); + +int fork(void); +//int gettimeofday(struct timeval *tv, struct timezone *tz); + +/* strtod does not handle Inf and Nan +We need to do the check before calling strtod */ +#undef strtod +#define strtod(nptr, eptr) wstrtod((nptr), (eptr)) + +double wstrtod(const char *nptr, char **eptr); + + +/* structs and functions for using IOCP with windows sockets */ + +/* need callback on write complete. aeWinSendReq is used to pass parameters */ +typedef struct aeWinSendReq { + void *client; + void *data; + char *buf; + int len; +} aeWinSendReq; + + +int aeWinSocketAttach(int fd); +int aeWinSocketDetach(int fd, int shutd); +int aeWinReceiveDone(int fd); +int aeWinSocketSend(int fd, char *buf, int len, int flags, + void *eventLoop, void *client, void *data, void *proc); +int aeWinListen(SOCKET sock, int backlog); +int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len); + +int strerror_r(int err, char* buf, size_t buflen); +char *wsa_strerror(int err); + +#endif /* WIN32 */ +#endif /* WIN32FIXES_H */ diff --git a/tools/config.sh b/tools/config.sh index 2ec1935e..6659eeb9 100755 --- a/tools/config.sh +++ b/tools/config.sh @@ -22,6 +22,8 @@ JIT_PPC=`echo "$TARGET" | sed "/powerpc/!d"` JIT_I686=`echo "$TARGET" | sed "/i686/!d"` JIT_AMD64=`echo "$TARGET" | sed "/amd64/!d"` JIT_ARM=`echo "$TARGET" | sed "/arm/!d"` +JIT_X86_64=`echo "$TARGET" | sed "/x86_64/!d"` +CROSS=0 if [ $MINGW -eq 0 ]; then EXE="" @@ -47,6 +49,10 @@ else LOADEXT=".dll" DLL=".dll" LIBEXT=".a" + case `uname -o` in + *Linux|Cygwin|Darwin) CROSS=1 ;; + *) CROSS=0 ;; + esac fi if [ "$2" = "mingw" ]; then @@ -72,6 +78,8 @@ elif [ "$2" = "target" ]; then else echo "$TARGET" | sed -e"s,-unknown,," fi +elif [ "$2" = "cross" ]; then + echo $CROSS elif [ "$2" = "jit" ]; then if [ "$JIT_X86$MINGW_GCC" != "" -o "$JIT_I686" != "" -o "$JIT_AMD64" != "" ]; then echo "X86" @@ -88,7 +96,11 @@ elif [ "$2" = "strip" ]; then echo "strip" fi else - echo "echo" + if [ $CROSS -eq 1 ]; then + echo "$CC" | sed -e"s,-gcc,-strip," + else + echo "echo" + fi fi elif [ "$2" = "lib" ]; then prefix=$5 @@ -114,10 +126,14 @@ else if [ "$HAVE_ASAN" != "" ]; then HAVE_ASAN=0; else HAVE_ASAN=1; fi else # hard coded win32 values - CHAR="1" - SHORT="2" - LONG="4" + if [ "$JIT_X86_64" != "" -o "$JIT_AMD64" != "" ]; then + LONG="8" + else + LONG="4" + fi INT="4" + SHORT="2" + CHAR="1" DOUBLE="8" LLONG="8" LILEND="1"