Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f34270d63d | |||
| f76ccc0590 | |||
| 2b2a1246e7 | |||
| f78da81aa4 | |||
| 2597a092bb | |||
| 226b798407 | |||
| 58753a88d7 | |||
| edff25180e | |||
| 6271cb42b2 | |||
| 3da9181deb | |||
| 192241c7c1 | |||
| e7c2dc7734 | |||
| f7bd99ae45 | |||
| 93d36fddb1 | |||
| 2d751890ea | |||
| 99b113ea9d | |||
| c087b97093 | |||
| 718a2e0c06 | |||
| b6187501fd | |||
| 18e1ab6db1 | |||
| 2dec76c87a | |||
| a36a62ca14 | |||
| 28ef43264a |
Vendored
BIN
Binary file not shown.
@@ -50,8 +50,12 @@ fn query_param(path: String, key: String) -> String {
|
||||
if pos < 0 { return "" }
|
||||
let after: String = str_slice(qs, pos + str_len(needle), str_len(qs))
|
||||
let amp: Int = str_index_of(after, "&")
|
||||
if amp < 0 { return after }
|
||||
str_slice(after, 0, amp)
|
||||
// SPEC-SEARCH-UPGRADE 2026-07-14: URL-decode the extracted value (%XX and
|
||||
// '+' were previously passed through literally, so an encoded multi-word
|
||||
// query arrived as junk tokens — pre-existing GET-path defect, masked
|
||||
// until search could actually rank multi-word queries).
|
||||
if amp < 0 { return url_decode(after) }
|
||||
url_decode(str_slice(after, 0, amp))
|
||||
}
|
||||
|
||||
fn query_int(path: String, key: String, default_val: Int) -> Int {
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
#ifndef EL_PLATFORM_WIN_H
|
||||
#define EL_PLATFORM_WIN_H
|
||||
/*
|
||||
* el_platform_win.h — Windows OS-boundary shim for el_runtime.c.
|
||||
*
|
||||
* Branch: feat/windows-el-runtime. Included ONLY when _WIN32 is defined; the POSIX build is
|
||||
* untouched. Goal: let el_runtime.c (a BSD-sockets / dlfcn / fork host) compile and link with
|
||||
* mingw-w64 into a native neuron.exe, with no behavioural change to the Linux/macOS build.
|
||||
*
|
||||
* What it maps:
|
||||
* - sockets : winsock2 (same call names: socket/bind/listen/accept/recv/send/setsockopt).
|
||||
* Sockets close with closesocket() (see el_closesocket), and the stack must be
|
||||
* started once with WSAStartup — done automatically via a load-time constructor.
|
||||
* - dlsym : el_runtime.c uses dlsym(RTLD_DEFAULT, name) to resolve callback/tool symbols
|
||||
* exported by the main module. Windows equivalent: GetProcAddress on the process
|
||||
* module. Link the soul with -Wl,--export-all-symbols so the symbols are findable.
|
||||
* - popen : mapped to _popen/_pclose.
|
||||
* - threads : UNCHANGED. mingw-w64 ships winpthreads, so <pthread.h> + -lpthread just work.
|
||||
*/
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
|
||||
/* Portable headers mingw-w64 provides (verified present). */
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h> /* strcasecmp */
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h> /* mingw-w64 provides gettimeofday here */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* ── socket close ─────────────────────────────────────────────────────────── */
|
||||
/* Winsock closes sockets with closesocket(), not close() (close() is for file fds). The POSIX
|
||||
build defines the same helper as close() so the call sites are identical across platforms. */
|
||||
static inline int el_closesocket(SOCKET s) { return closesocket(s); }
|
||||
|
||||
/* ── winsock init (once, at load) ─────────────────────────────────────────── */
|
||||
static void el__win_net_init(void) {
|
||||
static int inited = 0;
|
||||
if (!inited) { WSADATA w; WSAStartup(MAKEWORD(2, 2), &w); inited = 1; }
|
||||
}
|
||||
__attribute__((constructor)) static void el__win_ctor(void) { el__win_net_init(); }
|
||||
|
||||
/* ── dlsym → GetProcAddress ───────────────────────────────────────────────── */
|
||||
#ifndef RTLD_DEFAULT
|
||||
#define RTLD_DEFAULT ((void*)0)
|
||||
#endif
|
||||
static inline void* el_win_dlsym(void* handle, const char* name) {
|
||||
(void)handle;
|
||||
return (void*)(uintptr_t)GetProcAddress(GetModuleHandleA(NULL), name);
|
||||
}
|
||||
#define dlsym(h, n) el_win_dlsym((h), (n))
|
||||
|
||||
/* ── popen / pclose ───────────────────────────────────────────────────────── */
|
||||
#define popen _popen
|
||||
#define pclose _pclose
|
||||
|
||||
/* ── misc POSIX → Win32 shims ─────────────────────────────────────────────── */
|
||||
#include <direct.h> /* _mkdir */
|
||||
#define mkdir(path, mode) _mkdir(path) /* POSIX mkdir(path,mode) → _mkdir(path) */
|
||||
#define timegm _mkgmtime /* UTC tm → time_t */
|
||||
|
||||
/* setenv/unsetenv: not in the Windows CRT; map to _putenv_s / SetEnvironmentVariable. */
|
||||
static inline int setenv(const char* name, const char* value, int overwrite) {
|
||||
(void)overwrite;
|
||||
return _putenv_s(name, value ? value : "");
|
||||
}
|
||||
static inline int unsetenv(const char* name) {
|
||||
/* _putenv_s(name, "") sets VAR="" rather than removing it.
|
||||
* SetEnvironmentVariableA(name, NULL) truly deletes it from the Win32
|
||||
* env block; then we sync the CRT cache with _putenv("NAME="). */
|
||||
SetEnvironmentVariableA(name, NULL);
|
||||
size_t len = strlen(name);
|
||||
char *buf = (char*)malloc(len + 2);
|
||||
if (!buf) return -1;
|
||||
memcpy(buf, name, len);
|
||||
buf[len] = '=';
|
||||
buf[len + 1] = '\0';
|
||||
_putenv(buf);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* nanosleep — not available in MSVC/UCRT; approximate with Sleep(). */
|
||||
static inline int el_nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
(void)rem;
|
||||
DWORD ms = (DWORD)((req->tv_sec * 1000ULL) + (req->tv_nsec / 1000000ULL));
|
||||
Sleep(ms ? ms : 1);
|
||||
return 0;
|
||||
}
|
||||
#define nanosleep(req, rem) el_nanosleep((req), (rem))
|
||||
|
||||
/* localtime_r/gmtime_r: Windows offers localtime_s/gmtime_s with reversed arg order. */
|
||||
static inline struct tm* localtime_r(const time_t* t, struct tm* out) {
|
||||
return localtime_s(out, t) == 0 ? out : (struct tm*)0;
|
||||
}
|
||||
static inline struct tm* gmtime_r(const time_t* t, struct tm* out) {
|
||||
return gmtime_s(out, t) == 0 ? out : (struct tm*)0;
|
||||
}
|
||||
|
||||
#endif /* EL_PLATFORM_WIN_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,12 @@
|
||||
|
||||
typedef int64_t el_val_t;
|
||||
|
||||
/* HTTP request-handler function-pointer types. Public because soul modules (routes/chat/etc.)
|
||||
* register handlers across translation units; previously defined only inside el_runtime.c, which
|
||||
* made cross-module references (and the Windows build) fail. Home in the shared header. */
|
||||
typedef el_val_t (*http_handler_fn)(el_val_t method, el_val_t path, el_val_t body);
|
||||
typedef el_val_t (*http_handler4_fn)(el_val_t method, el_val_t path, el_val_t body, el_val_t headers);
|
||||
|
||||
#define EL_STR(s) ((el_val_t)(uintptr_t)(s))
|
||||
#define EL_CSTR(v) ((const char*)(uintptr_t)(v))
|
||||
#define EL_INT(v) (v)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// auto-generated by elc --emit-header — do not edit
|
||||
extern fn el_escape(s: String) -> String
|
||||
extern fn el_text(s: String) -> String
|
||||
extern fn el_attr(name: String, value: String) -> String
|
||||
extern fn el_div(attrs: String, children: String) -> String
|
||||
extern fn el_section(attrs: String, children: String) -> String
|
||||
extern fn el_article(attrs: String, children: String) -> String
|
||||
extern fn el_header(attrs: String, children: String) -> String
|
||||
extern fn el_footer(attrs: String, children: String) -> String
|
||||
extern fn el_main(attrs: String, children: String) -> String
|
||||
extern fn el_nav(attrs: String, children: String) -> String
|
||||
extern fn el_aside(attrs: String, children: String) -> String
|
||||
extern fn el_ul(attrs: String, children: String) -> String
|
||||
extern fn el_ol(attrs: String, children: String) -> String
|
||||
extern fn el_li(attrs: String, children: String) -> String
|
||||
extern fn el_p(attrs: String, children: String) -> String
|
||||
extern fn el_span(attrs: String, children: String) -> String
|
||||
extern fn el_form(attrs: String, children: String) -> String
|
||||
extern fn el_h1(attrs: String, text: String) -> String
|
||||
extern fn el_h2(attrs: String, text: String) -> String
|
||||
extern fn el_h3(attrs: String, text: String) -> String
|
||||
extern fn el_h4(attrs: String, text: String) -> String
|
||||
extern fn el_button(attrs: String, label: String) -> String
|
||||
extern fn el_a(href: String, attrs: String, children: String) -> String
|
||||
extern fn el_input(type_attr: String, attrs: String) -> String
|
||||
extern fn el_textarea(attrs: String, value: String) -> String
|
||||
extern fn el_label(for_id: String, attrs: String, children: String) -> String
|
||||
extern fn el_img(src: String, alt: String, attrs: String) -> String
|
||||
extern fn el_video(attrs: String, children: String) -> String
|
||||
extern fn el_strong(children: String) -> String
|
||||
extern fn el_em(children: String) -> String
|
||||
extern fn el_code(children: String) -> String
|
||||
extern fn el_pre(attrs: String, children: String) -> String
|
||||
extern fn el_hr() -> String
|
||||
extern fn el_br() -> String
|
||||
extern fn el_html_doc(lang: String, head_html: String, body_html: String) -> String
|
||||
extern fn el_meta(name: String, content: String) -> String
|
||||
extern fn el_meta_charset(charset: String) -> String
|
||||
extern fn el_link_stylesheet(href: String) -> String
|
||||
extern fn el_script_src(src: String, defer_load: Bool) -> String
|
||||
extern fn el_script_inline(js: String) -> String
|
||||
extern fn el_title(text: String) -> String
|
||||
Reference in New Issue
Block a user