diff options
Diffstat (limited to 'src/core/io_linux.c')
| -rw-r--r-- | src/core/io_linux.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/core/io_linux.c b/src/core/io_linux.c new file mode 100644 index 0000000..8a024aa --- /dev/null +++ b/src/core/io_linux.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#ifdef _WIN32 +#include <fcntl.h> +#include <io.h> +#else +#include <unistd.h> +#include <poll.h> +#endif + +int J; + +#ifdef _WIN32 +static int pk(void){int c=getchar();ungetc(c,stdin);return c==EOF;} +char Q(void){int c=getchar();J=pk();return c;} +#else +/* input is read here, not through stdio, so the end-of-input flag J never blocks. + a client that keeps the pipe open (an editor talking to the language server) sends + one message and waits for the answer: peeking for the next byte after the last + one would wait for a message that comes only after the answer. so J is 1 only + when the end is known, and 0 when more may come. the output is flushed before + any read that can wait, for the same reason. */ +static unsigned char ib[65536]; +static int ip, in, ieof; +/* make a byte available. wait is 0 to look without waiting. returns 1 when one is ready */ +static int fill(int wait) +{ + int n; + if (ip < in) return 1; + if (ieof) return 0; + if (!wait) { + struct pollfd f; f.fd = 0; f.events = POLLIN; f.revents = 0; + if (poll(&f, 1, 0) <= 0) return 0; /* nothing yet: not the end, not a byte */ + } else fflush(stdout); + n = (int)read(0, ib, sizeof ib); + if (n <= 0) { ieof = 1; return 0; } + ip = 0; in = n; + return 1; +} +static int pk(void) { if (ip < in) return 0; if (ieof) return 1; fill(0); return ieof; } +char Q(void) +{ + int c; + if (!fill(1)) { J = 1; return (char)-1; } + c = ib[ip++]; + J = pk(); + return (char)c; +} +#endif +void G(char c){putchar(c);} + +static void init_io(void) { +#ifdef _WIN32 + _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdout), _O_BINARY); + J = pk(); +#else + J = pk(); +#endif +} + +#if defined(__GNUC__) || defined(__clang__) +__attribute__((constructor)) static void init(void) { init_io(); } +#elif defined(_MSC_VER) +#pragma section(".CRT$XCU", read) +static void __cdecl msc_init(void) { init_io(); } +__declspec(allocate(".CRT$XCU")) static void (__cdecl *msc_init_fn)(void) = msc_init; +#else +static void init(void) { init_io(); } +#endif |
