Removed dependency from linenoise.
@@ -26,8 +26,9 @@ proc termSave*(): string =
let res = execCmdEx "stty </dev/tty -g" return res[0] - proc termRestore*(c: string) = - discard execCmd "stty </dev/tty " & c + let TERMSETTINGS* = termSave() + proc termRestore*() = + discard execCmd "stty </dev/tty " & TERMSETTINGS proc getchar(): cint = return stdin.readChar().ord.cint@@ -35,12 +36,12 @@
proc putchar(c: cint) = stdout.write(c.chr) - # Types type Key* = int KeySeq* = seq[Key] + KeyCallback* = proc(ed: var LineEditor) LineError* = ref Exception LineEditorMode = enum mdInsert@@ -48,7 +49,6 @@ mdReplace
Line = object text: string position: int - KeyCallback* = proc(ed: var LineEditor) LineHistory = object tainted: bool position: int@@ -58,6 +58,8 @@ LineEditor* = object
history: LineHistory line: Line mode: LineEditorMode + +# Internal Methods proc empty(line: Line): bool = return line.text.len == 0@@ -97,6 +99,46 @@ return
stdout.cursorForward(n) ed.line.position += n +proc `[]`( q: Queue[string], pos: int): string = + var c = 0 + for e in q.items: + if c == pos: + result = e + break + c.inc + +proc `[]=`( q: var Queue[string], pos: int, s: string) = + var c = 0 + for e in q.mitems: + if c == pos: + e = s + break + c.inc + +proc add(h: var LineHistory, s: string, force=false) = + if s == "" and not force: + return + if h.queue.len >= h.max: + discard h.queue.dequeue + if h.tainted: + h.queue[h.queue.len-1] = s + else: + h.queue.enqueue s + +proc previous(h: var LineHistory): string = + if h.queue.len == 0 or h.position <= 0: + return nil + h.position.dec + result = h.queue[h.position] + +proc next(h: var LineHistory): string = + if h.queue.len == 0 or h.position >= h.queue.len-1: + return nil + h.position.inc + result = h.queue[h.position] + +# Public API + proc deletePrevious*(ed: var LineEditor) = if not ed.line.empty: if ed.line.full:@@ -145,11 +187,8 @@ proc changeLine*(ed: var LineEditor, s: string) =
let text = ed.line.text let diff = text.len - s.len let position = ed.line.position - try: + if position > 0: stdout.cursorBackward(position) - except: - discard - #echo "Error setting cursor back by ", position, " chars." for c in s: putchar(c.ord) ed.line.position = s.len@@ -159,44 +198,6 @@ for i in 0.countup(diff-1):
putchar(32) stdout.cursorBackward(diff) -proc `[]`( q: Queue[string], pos: int): string = - var c = 0 - for e in q.items: - if c == pos: - result = e - break - c.inc - -proc `[]=`( q: var Queue[string], pos: int, s: string) = - var c = 0 - for e in q.mitems: - if c == pos: - e = s - break - c.inc - -proc add(h: var LineHistory, s: string, force=false) = - if s == "" and not force: - return - if h.queue.len >= h.max: - discard h.queue.dequeue - if h.tainted: - h.queue[h.queue.len-1] = s - else: - h.queue.enqueue s - -proc previous(h: var LineHistory): string = - if h.queue.len == 0 or h.position <= 0: - return nil - h.position.dec - result = h.queue[h.position] - -proc next(h: var LineHistory): string = - if h.queue.len == 0 or h.position >= h.queue.len-1: - return nil - h.position.inc - result = h.queue[h.position] - proc historyInit*(size = 256): LineHistory = result.queue = initQueue[string](size) result.position = 0@@ -233,9 +234,9 @@ ed.history.position = ed.history.queue.len
ed.history.tainted = false proc initEditor*(mode = mdInsert, historySize = 256): LineEditor = + termSetup() result.mode = mode result.history = historyInit(historySize) - # Character sets const@@ -252,7 +253,6 @@ else:
const ESCAPES* = {27} -let TERMSETTINGS* = termSave() # Key Mappings var KEYMAP*: CritBitTree[KeyCallBack]@@ -275,13 +275,12 @@ ed.back()
KEYMAP["right"] = proc(ed: var LineEditor) = ed.forward() KEYMAP["ctrl+c"] = proc(ed: var LineEditor) = - termRestore(TERMSETTINGS) + termRestore() quit(0) # Key Names var KEYNAMES*: array[0..31, string] KEYNAMES[3] = "ctrl+c" - # Key Sequences var KEYSEQS*: CritBitTree[KeySeq]@@ -303,13 +302,12 @@ KEYSEQS["delete"] = @[27, 91, 51, 126]
proc readLine*(ed: var LineEditor, prompt=""): string = - termSetup() stdout.write(prompt) ed.line = Line(text: "", position: 0) while true: let c1 = getchar() if c1 in {10, 13}: - termRestore(TERMSETTINGS) + stdout.write("\n") ed.historyAdd() ed.historyFlush() return ed.line.text@@ -341,6 +339,10 @@ if s == KEYSEQS["right"]:
KEYMAP["right"](ed) elif s == KEYSEQS["left"]: KEYMAP["left"](ed) + elif s == KEYSEQS["up"]: + KEYMAP["up"](ed) + elif s == KEYSEQS["down"]: + KEYMAP["down"](ed) elif c3 in {50, 51}: let c4 = getchar() s.add(c4)
@@ -9,11 +9,12 @@ ../core/parser,
../core/interpreter, ../core/utils, ../core/regex, - ../vendor/linenoise + ../core/linedit proc lang_module*(i: In) = i.scope .symbol("exit") do (i: In): + termRestore() quit(0) .symbol("symbols") do (i: In):@@ -445,9 +446,6 @@ i.push res.newVal
.symbol("version") do (i: In): i.push version.newVal - - .symbol("clear") do (i: In): - linenoiseClearScreen() # Save/load symbols
@@ -1,5 +1,6 @@
import streams, critbits, parseopt2, strutils, os, json import + core/linedit, core/types, core/parser, core/interpreter,@@ -16,11 +17,7 @@ lib/min_sys,
lib/min_crypto, lib/min_fs -const USE_LINENOISE* = true - -when USE_LINENOISE: - import - vendor/linenoise +const USE_LINENOISE* = false var REPL = false var DEBUGGING = false@@ -55,6 +52,7 @@ getFiles(dir)
return res when USE_LINENOISE: + # TODO: rewrite proc completionCallback*(str: cstring, completions: ptr linenoiseCompletions) {.cdecl.}= var words = ($str).split(" ") var w = if words.len > 0: words.pop else: ""@@ -114,16 +112,6 @@ for s in CURRSCOPE.symbols.keys:
if s.startsWith(w): linenoiseAddCompletion completions, words.join(" ") & sep & s -proc prompt(s: string): string = - when USE_LINENOISE: - var res = linenoise(s) - if not res.isNil: - discard $linenoiseHistoryAdd(res) - return $res - when not(USE_LINENOISE): - stdout.write(s) - return stdin.readLine - proc stdLib(i: In) = i.lang_module i.io_module@@ -177,18 +165,16 @@ i.open(s, "")
var line: string echo "MiNiM Shell v$1" % version echo "-> Type 'exit' or 'quit' to exit." + var ed = initEditor() while true: - when USE_LINENOISE: - CURRSCOPE = i.scope - linenoiseSetCompletionCallback completionCallback - discard linenoiseHistorySetMaxLen(1000) - discard linenoiseHistoryLoad(MINIMHISTORY) - line = prompt(": ") - if line.isNil: - echo "-> Exiting..." - quit(0) - if $line != "(null)": - discard linenoiseHistorySave(MINIMHISTORY) + #when USE_LINENOISE: + #CURRSCOPE = i.scope + #linenoiseSetCompletionCallback completionCallback + #discard linenoiseHistorySetMaxLen(1000) + #discard linenoiseHistoryLoad(MINIMHISTORY) + line = ed.readLine(": ") + #if $line != "(null)": + # discard linenoiseHistorySave(MINIMHISTORY) i.parser.buf = $i.parser.buf & $line i.parser.bufLen = i.parser.buf.len discard i.parser.getToken()
@@ -1,73 +0,0 @@
-when defined(windows): - {.compile: "linenoise/libwin32fixes.c".} -{.compile: "linenoise/liblinenoise.c".} - -type - linenoiseCompletions* = object - len*: csize - cvec*: cstringArray - linenoiseCompletionCallback* = proc (a: cstring, b: ptr linenoiseCompletions) {.cdecl.} - -const - LN_HIDDEN_NO* = (0) # Fully visible entry. - LN_HIDDEN_ALL* = (1) # Fully hidden, no echo at all - LN_HIDDEN_STAR* = (2) # Hidden entry, echoing *'s back - -{.push importc.} -{.push cdecl.} -# -# The callback type for tab completion handlers. -# -#typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); -# -# Sets the current tab completion handler and returns the previous one, or NULL -# if no prior one has been set. -# -proc linenoiseSetCompletionCallback*(a: linenoiseCompletionCallback); -# -# Adds a copy of the given string to the given completion list. The copy is owned -# by the linenoiseCompletions object. -# -proc linenoiseAddCompletion*(a2: ptr linenoiseCompletions; a3: cstring) -# -# Prompts for input using the given string as the input -# prompt. Returns when the user has tapped ENTER or (on an empty -# line) EOF (Ctrl-D on Unix, Ctrl-Z on Windows). Returns either -# a copy of the entered string (for ENTER) or NULL (on EOF). The -# caller owns the returned string and must eventually free() it. -# -proc linenoise*(prompt: cstring): cstring -# -# Activates normal entry in future calls of linenoise(), i.e. user -# input will again be echoed back to the terminal during entry. -# -proc linenoiseGetHidden*(): cint -# -# Adds a copy of the given line of the command history. -# -proc linenoiseHistoryAdd*(line: cstring): cint -# -# Sets the maximum length of the command history, in lines. -# If the history is currently longer, it will be trimmed, -# retaining only the most recent entries. If len is 0 or less -# then this function does nothing. -# -proc linenoiseHistorySetMaxLen*(len: cint): cint -# -# Returns the current maximum length of the history, in lines. -# -proc linenoiseHistoryGetMaxLen*(): cint -# -# Saves the current contents of the history to the given file. -# Returns 0 on success. -# -proc linenoiseHistorySave*(filename: cstring): cint -# -# Replaces the current history with the contents -# of the given file. Returns 0 on success. -# -proc linenoiseHistoryLoad*(filename: cstring): cint -# -# Clears the screen. -# -proc linenoiseClearScreen*()
@@ -1,870 +0,0 @@
-/* linenoise.c -- guerrilla line editing library against the idea that a - * 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. - * - * ------------------------------------------------------------------------ - * - * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com> - * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com> - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * 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 COPYRIGHT HOLDERS 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 COPYRIGHT - * HOLDER 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. - * - * ------------------------------------------------------------------------ - * - * References: - * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html - * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html - * - * Todo list: - * - Switch to gets() if $TERM is something we can't support. - * - Filter bogus Ctrl+<char> combinations. - * - * Bloat: - * - Completion? - * - History search like Ctrl+r in readline? - * - * List of escape sequences used by this program, we do everything just - * with three sequences. In order to be so cheap we may have some - * flickering effect with some slow terminal, but the lesser sequences - * the more compatible. - * - * CHA (Cursor Horizontal Absolute) - * Sequence: ESC [ n G - * Effect: moves cursor to column n - * - * EL (Erase Line) - * Sequence: ESC [ n K - * Effect: if n is 0 or missing, clear from cursor to end of line - * Effect: if n is 1, clear from beginning of line to cursor - * Effect: if n is 2, clear entire line - * - * CUF (CUrsor Forward) - * Sequence: ESC [ n C - * Effect: moves cursor forward of n chars - * - * The following are used to clear the screen: ESC [ H ESC [ 2 J - * This is actually composed of two sequences: - * - * cursorhome - * Sequence: ESC [ H - * Effect: moves the cursor to upper left corner - * - * ED2 (Clear entire screen) - * Sequence: ESC [ 2 J - * Effect: clear the whole screen - * - */ -#ifndef _WIN32 - #include <termios.h> - #include <unistd.h> - #include <sys/ioctl.h> -#endif -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#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; -static int history_len = 0; -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; -} - -static void freeHistory(void) { - if (history) { - int j; - - for (j = 0; j < history_len; j++) - free(history[j]); - free(history); - } -} - -static int enableRawMode(int fd) { -#ifndef _WIN32 - struct termios raw; - - if (!isatty(STDIN_FILENO)) goto fatal; - if (!atexit_registered) { - atexit(linenoiseAtExit); - atexit_registered = 1; - } - if (tcgetattr(fd,&orig_termios) == -1) goto fatal; - - raw = orig_termios; /* modify the original mode */ - /* input modes: no break, no CR to NL, no parity check, no strip char, - * no start/stop output control. */ - raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - /* output modes - disable post processing */ - raw.c_oflag &= ~(OPOST); - /* control modes - set 8 bit chars */ - raw.c_cflag |= (CS8); - /* local modes - choing off, canonical off, no extended functions, - * no signal chars (^Z,^C) */ - raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - /* control chars - set return condition: min number of bytes and timer. - * We want read to return every single byte, without timeout. */ - raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ - - /* 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: - errno = ENOTTY; - return -1; -} - -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) { - buf++; - len--; - pos--; - } - while (plen+len > cols) { - len--; - } - -#ifndef _WIN32 - /* Cursor to left edge */ - snprintf(seq,64,"\x1b[0G"); - if (write(fd,seq,strlen(seq)) == -1) return; - /* Write the prompt and the current buffer content */ - if (write(fd,prompt,strlen(prompt)) == -1) return; - if (write(fd,buf,len) == -1) return; - /* Erase to right */ - snprintf(seq,64,"\x1b[0K"); - if (write(fd,seq,strlen(seq)) == -1) return; - /* 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() { - fprintf(stderr, "\x7"); - fflush(stderr); -} - -static void freeCompletions(linenoiseCompletions *lc) { - size_t i; - for (i = 0; i < lc->len; i++) - free(lc->cvec[i]); - if (lc->cvec != NULL) - free(lc->cvec); -} - -static int completeLine(int fd, const char *prompt, char *buf, size_t buflen, size_t *len, size_t *pos, size_t cols) { - linenoiseCompletions lc = { 0, NULL }; - int nread, nwritten; - char c = 0; - - completionCallback(buf,&lc); - if (lc.len == 0) { - beep(); - } else { - size_t stop = 0, i = 0; - size_t clen; - - while(!stop) { - /* Show completion or original buffer */ - if (i < lc.len) { - clen = strlen(lc.cvec[i]); - refreshLine(fd,prompt,lc.cvec[i],clen,clen,cols); - } else { - refreshLine(fd,prompt,buf,*len,*pos,cols); - } - - nread = read(fd,&c,1); - if (nread <= 0) { - freeCompletions(&lc); - return -1; - } - - switch(c) { - case 9: /* tab */ - i = (i+1) % (lc.len+1); - if (i == lc.len) beep(); - break; - case 27: /* escape */ - /* Re-show original buffer */ - if (i < lc.len) { - refreshLine(fd,prompt,buf,*len,*pos,cols); - } - stop = 1; - break; - default: - /* Update buffer and return */ - if (i < lc.len) { - nwritten = snprintf(buf,buflen,"%s",lc.cvec[i]); - *len = *pos = nwritten; - } - stop = 1; - break; - } - } - } - - freeCompletions(&lc); - return c; /* Return last read character */ -} - -void linenoiseClearScreen(void) { - if (write(STDIN_FILENO,"\x1b[H\x1b[2J",7) <= 0) { - /* nothing to do, just to avoid warning. */ - } -} - -static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) { - size_t plen = strlen(prompt); - size_t pos = 0; - size_t len = 0; - size_t cols = getColumns(); - int history_index = 0; -#ifdef _WIN32 - DWORD foo; -#endif - - buf[0] = '\0'; - buflen--; /* Make sure there is always space for the nulterm */ - - /* The latest history entry is always our current buffer, that - * 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); -#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 - * character that should be handled next. */ - if (c == 9 && completionCallback != NULL) { - c = completeLine(fd,prompt,buf,buflen,&len,&pos,cols); - /* Return on errors */ - if (c < 0) return (int)len; - /* Read next character when 0 */ - if (c == 0) continue; - } - - switch(c) { - case 13: /* enter */ - history_len--; - free(history[history_len]); - return (int)len; - case 3: /* ctrl-c */ - 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); - pos--; - len--; - buf[len] = '\0'; - refreshLine(fd,prompt,buf,len,pos,cols); - } - break; - case 4: /* ctrl-d, remove char at right of cursor */ - if (len > 1 && pos < (len-1)) { - memmove(buf+pos,buf+pos+1,len-pos); - len--; - buf[len] = '\0'; - refreshLine(fd,prompt,buf,len,pos,cols); - } else if (len == 0) { - history_len--; - free(history[history_len]); - return -1; - } - break; - case 20: /* ctrl-t */ - if (pos > 0 && pos < len) { - int aux = buf[pos-1]; - buf[pos-1] = buf[pos]; - buf[pos] = aux; - if (pos != len-1) pos++; - refreshLine(fd,prompt,buf,len,pos,cols); - } - break; - case 2: /* ctrl-b */ - goto left_arrow; - case 6: /* ctrl-f */ - goto right_arrow; - case 16: /* ctrl-p */ - seq[1] = 65; - goto up_down_arrow; - case 14: /* ctrl-n */ - seq[1] = 66; - goto up_down_arrow; - break; - case 27: /* escape sequence */ - if (read(fd,seq,2) == -1) break; - if (seq[0] == 91 && seq[1] == 68) { -left_arrow: - /* left arrow */ - if (pos > 0) { - pos--; - refreshLine(fd,prompt,buf,len,pos,cols); - } - } else if (seq[0] == 91 && seq[1] == 67) { -right_arrow: - /* right arrow */ - if (pos != len) { - pos++; - refreshLine(fd,prompt,buf,len,pos,cols); - } - } else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) { -up_down_arrow: - /* up and down arrow: history */ - if (history_len > 1) { - /* Update the current history entry before to - * overwrite it with tne next one. */ - free(history[history_len-1-history_index]); - history[history_len-1-history_index] = strdup(buf); - /* Show the new entry */ - history_index += (seq[1] == 65) ? 1 : -1; - if (history_index < 0) { - history_index = 0; - break; - } else if (history_index >= history_len) { - history_index = history_len-1; - break; - } - strncpy(buf,history[history_len-1-history_index],buflen); - buf[buflen] = '\0'; - len = pos = strlen(buf); - refreshLine(fd,prompt,buf,len,pos,cols); - } - } else if (seq[0] == 91 && seq[1] > 48 && seq[1] < 55) { - /* extended escape */ - if (read(fd,seq2,2) == -1) break; - if (seq[1] == 51 && seq2[0] == 126) { - /* delete */ - if (len > 0 && pos < len) { - memmove(buf+pos,buf+pos+1,len-pos-1); - len--; - buf[len] = '\0'; - refreshLine(fd,prompt,buf,len,pos,cols); - } - } - } - break; - default: - if (len < buflen) { - if (len == pos) { - buf[pos] = c; - pos++; - len++; - buf[len] = '\0'; - 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); - } - } else { - memmove(buf+pos+1,buf+pos,len-pos); - buf[pos] = c; - len++; - pos++; - buf[len] = '\0'; - refreshLine(fd,prompt,buf,len,pos,cols); - } - } - break; - case 21: /* Ctrl+u, delete the whole line. */ - buf[0] = '\0'; - pos = len = 0; - refreshLine(fd,prompt,buf,len,pos,cols); - break; - case 11: /* Ctrl+k, delete from current to end of line. */ - buf[pos] = '\0'; - len = pos; - refreshLine(fd,prompt,buf,len,pos,cols); - break; - case 1: /* Ctrl+a, go to the start of the line */ - pos = 0; - refreshLine(fd,prompt,buf,len,pos,cols); - break; - case 5: /* ctrl+e, go to the end of the line */ - pos = len; - refreshLine(fd,prompt,buf,len,pos,cols); - break; - case 12: /* ctrl+l, clear screen */ - linenoiseClearScreen(); - refreshLine(fd,prompt,buf,len,pos,cols); - break; - case 23: /* ctrl+w, delete previous word */ - { - size_t old_pos = pos; - size_t diff; - while (pos > 0 && buf[pos-1] == ' ') - pos--; - while (pos > 0 && buf[pos-1] != ' ') - pos--; - diff = old_pos - pos; - memmove(&buf[pos], &buf[old_pos], len-old_pos+1); - len -= diff; - refreshLine(fd,prompt,buf,len,pos,cols); - break; - } - } - } - return (int)len; -} - -static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { - int fd = STDIN_FILENO; - int count; - - if (buflen == 0) { - errno = EINVAL; - return -1; - } - if (!isatty(STDIN_FILENO)) { - if (fgets(buf, (int)buflen, stdin) == NULL) return -1; - count = (int)strlen(buf); - if (count && buf[count-1] == '\n') { - count--; - buf[count] = '\0'; - } - } else { - if (enableRawMode(fd) == -1) return -1; - count = linenoisePrompt(fd, buf, buflen, prompt); - disableRawMode(fd); - printf("\n"); - } - return count; -} - -char *linenoise(const char *prompt) { - char buf[LINENOISE_MAX_LINE]; - int count; - - if (isUnsupportedTerm()) { - size_t len; - - printf("%s",prompt); - fflush(stdout); - if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL; - len = strlen(buf); - while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) { - len--; - buf[len] = '\0'; - } - return strdup(buf); - } else { - count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt); - if (count == -1) return NULL; - return strdup(buf); - } -} - -/* Register a callback function to be called for tab-completion. */ -void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { - completionCallback = fn; -} - -void linenoiseAddCompletion(linenoiseCompletions *lc, char *str) { - size_t len = strlen(str); - char *copy = malloc(len+1); - memcpy(copy,str,len+1); - lc->cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1)); - lc->cvec[lc->len++] = copy; -} - -/* Using a circular buffer is smarter, but a bit more complex to handle. */ -int linenoiseHistoryAdd(const char *line) { - char *linecopy; - - if (history_max_len == 0) return 0; - if (history == NULL) { - history = malloc(sizeof(char*)*history_max_len); - if (history == NULL) return 0; - memset(history,0,(sizeof(char*)*history_max_len)); - } - linecopy = strdup(line); - if (!linecopy) return 0; - if (history_len == history_max_len) { - free(history[0]); - memmove(history,history+1,sizeof(char*)*(history_max_len-1)); - history_len--; - } - history[history_len] = linecopy; - history_len++; - return 1; -} - -int linenoiseHistorySetMaxLen(int len) { - char **newC; - - if (len < 1) return 0; - if (history) { - int tocopy = history_len; - - newC = malloc(sizeof(char*)*len); - if (newC == NULL) return 0; - if (len < tocopy) tocopy = len; - memcpy(newC,history+(history_max_len-tocopy), sizeof(char*)*tocopy); - free(history); - history = newC; - } - history_max_len = len; - if (history_len > history_max_len) - history_len = history_max_len; - return 1; -} - -/* 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; - for (j = 0; j < history_len; j++) - fprintf(fp,"%s\n",history[j]); - fclose(fp); - return 0; -} - -/* Load the history from the specified file. If the file does not exist - * zero is returned and no operation is performed. - * - * If the file exists and the operation succeeded 0 is returned, otherwise - * on error -1 is returned. */ -int linenoiseHistoryLoad(char *filename) { - FILE *fp = fopen(filename,"r"); - char buf[LINENOISE_MAX_LINE]; - - if (fp == NULL) return -1; - - while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { - char *p; - - p = strchr(buf,'\r'); - if (!p) p = strchr(buf,'\n'); - if (p) *p = '\0'; - linenoiseHistoryAdd(buf); - } - fclose(fp); - return 0; -}
@@ -1,549 +0,0 @@
-/* -* 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 <process.h> -#include <stdlib.h> -#include <errno.h> -#ifndef FD_SETSIZE -# define FD_SETSIZE 16000 -#endif -//#include <winsock2.h> -#include <windows.h> -#include <signal.h> -#include <time.h> -#include <locale.h> -#include <math.h> -#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; - }; - - 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; -} - -#if 0 -/* 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; -#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION -# define STACK_SIZE_PARAM_IS_A_RESERVATION 4096 -#endif - - 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; -} -#endif - -/* 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 //0 - -#endif //_WIN32
@@ -1,60 +0,0 @@
-/* linenoise.h -- guerrilla line editing library against the idea that a - * line editing lib needs to be 20,000 lines of C code. - * - * See linenoise.c for more information. - * - * ------------------------------------------------------------------------ - * - * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com> - * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com> - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * 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 COPYRIGHT HOLDERS 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 COPYRIGHT - * HOLDER 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. - */ - -#ifndef __LINENOISE_H -#define __LINENOISE_H - -#ifdef _WIN32 -# define off off_t -#endif - -typedef struct linenoiseCompletions { - size_t len; - char **cvec; -} linenoiseCompletions; - -typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); -void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); -void linenoiseAddCompletion(linenoiseCompletions *, char *); - -char *linenoise(const char *prompt); -int linenoiseHistoryAdd(const char *line); -int linenoiseHistorySetMaxLen(int len); -int linenoiseHistorySave(char *filename); -int linenoiseHistoryLoad(char *filename); -void linenoiseClearScreen(void); - -#endif /* __LINENOISE_H */
@@ -1,327 +0,0 @@
-/* -* 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 <stdlib.h> -#include <stdio.h> -#include <io.h> -#include <signal.h> -#include <sys/types.h> -#ifndef FD_SETSIZE -#define FD_SETSIZE 16000 -#endif -#include <winsock2.h> /* setsocketopt */ -#include <ws2tcpip.h> -#include <windows.h> -#include <float.h> -#include <fcntl.h> /* _O_BINARY */ -#include <limits.h> /* INT_MAX */ -#include <process.h> -#include <sys/types.h> - -// mingw32 only -//#if !defined(__MINGW_SCANF_FORMAT) -//#include "fmacros.h" -//#endif - -#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 */