aboutsummaryrefslogtreecommitdiff
path: root/src/core/io_linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/io_linux.c')
-rw-r--r--src/core/io_linux.c69
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