Compare commits

...

6 Commits

Author SHA1 Message Date
31ae400852 LibertyXDR: update VIM syntax highlight file
All checks were successful
Alpine 3.21 Success
OpenBSD 7.6 Success
2025-05-07 19:47:43 +02:00
b69d3f8692 LibertyXDR: add support for default in unions 2025-05-07 19:42:46 +02:00
9a26284a64 wdye: clean up protected calls
Have a common way of catching Lua errors for resource cleanup purposes.
2025-01-15 02:21:23 +01:00
0f20cce9c8 wdye: pass script arguments
All checks were successful
Alpine 3.20 Success
OpenBSD 7.5 Success
2025-01-10 10:58:27 +01:00
017cb1d570 MPD client: tolerate usage while disconnected
All checks were successful
Alpine 3.20 Success
OpenBSD 7.5 Success
If the client is password-protected, this will not automagically
make queued up commands work, but it's better than hitting
the poller assertion.
2025-01-08 08:07:46 +01:00
1642d387f3 wdye: rename the self-test
add_subdirectory imports it to parent projects, so be more indicative.
2025-01-08 06:24:05 +01:00
7 changed files with 63 additions and 32 deletions

View File

@@ -1594,6 +1594,8 @@ mpd_client_parse_kv (char *line, char **value)
static void static void
mpd_client_update_poller (struct mpd_client *self) mpd_client_update_poller (struct mpd_client *self)
{ {
if (self->state != MPD_CONNECTED)
return;
poller_fd_set (&self->socket_event, poller_fd_set (&self->socket_event,
self->write_buffer.len ? (POLLIN | POLLOUT) : POLLIN); self->write_buffer.len ? (POLLIN | POLLOUT) : POLLIN);
} }

View File

@@ -93,10 +93,12 @@ and always-present field, which must be a tag *enum*:
case CAR: void; case CAR: void;
case LORRY: i8 axles; case LORRY: i8 axles;
case PLANE: i8 engines; case PLANE: i8 engines;
default: void;
}; };
All possible enumeration values must be named, and there is no *case* There is no *case* fall-through.
fall-through. Unless *default* is present, only the listed enumeration values are valid.
Any *default* must currently be empty.
Framing Framing
------- -------

View File

@@ -8,7 +8,7 @@ syn region libertyxdrBlockComment start=+/[*]+ end=+[*]/+
syn match libertyxdrComment "//.*" syn match libertyxdrComment "//.*"
syn match libertyxdrIdentifier "\<[[:alpha:]][[:alnum:]_]*\>" syn match libertyxdrIdentifier "\<[[:alpha:]][[:alnum:]_]*\>"
syn match libertyxdrNumber "\<0\>\|\(-\|\<\)[1-9][[:digit:]]*\>" syn match libertyxdrNumber "\<0\>\|\(-\|\<\)[1-9][[:digit:]]*\>"
syn keyword libertyxdrKeyword const enum struct union switch case syn keyword libertyxdrKeyword const enum struct union switch case default
syn keyword libertyxdrType bool u8 u16 u32 u64 i8 i16 i32 i64 string void syn keyword libertyxdrType bool u8 u16 u32 u64 i8 i16 i32 i64 string void
let b:current_syntax = "libertyxdr" let b:current_syntax = "libertyxdr"

View File

@@ -25,5 +25,7 @@ struct Struct {
union Onion switch (Enum tag) { union Onion switch (Enum tag) {
case NOTHING: case NOTHING:
void; void;
default:
void;
} o; } o;
}; };

View File

@@ -1,6 +1,6 @@
# lxdrgen.awk: an XDR-derived code generator for network protocols. # lxdrgen.awk: an XDR-derived code generator for network protocols.
# #
# Copyright (c) 2022 - 2023, Přemysl Eric Janouch <p@janouch.name> # Copyright (c) 2022 - 2025, Přemysl Eric Janouch <p@janouch.name>
# SPDX-License-Identifier: 0BSD # SPDX-License-Identifier: 0BSD
# #
# Usage: env LC_ALL=C awk -f lxdrgen.awk -f lxdrgen-{c,go,mjs}.awk \ # Usage: env LC_ALL=C awk -f lxdrgen.awk -f lxdrgen-{c,go,mjs}.awk \
@@ -218,7 +218,7 @@ function defstruct( name, d, cg) {
} }
function defunion( name, tag, tagtype, tagvalue, cg, scg, d, a, i, function defunion( name, tag, tagtype, tagvalue, cg, scg, d, a, i,
unseen, exhaustive) { unseen, defaulted, exhaustive) {
delete cg[0] delete cg[0]
delete scg[0] delete scg[0]
delete d[0] delete d[0]
@@ -249,9 +249,22 @@ function defunion( name, tag, tagtype, tagvalue, cg, scg, d, a, i,
if (!unseen[tagvalue]--) if (!unseen[tagvalue]--)
fatal("no such value or duplicate case: " tagtype "." tagvalue) fatal("no such value or duplicate case: " tagtype "." tagvalue)
codegen_struct_tag(tag, scg) codegen_struct_tag(tag, scg)
} else if (accept("default")) {
if (tagvalue)
codegen_union_struct(name, tagvalue, cg, scg)
expect(accept(":"))
if (defaulted)
fatal("duplicate default")
tagvalue = ""
defaulted = 1
} else if (tagvalue) { } else if (tagvalue) {
if (readfield(d)) if (readfield(d))
codegen_struct_field(d, scg) codegen_struct_field(d, scg)
} else if (defaulted) {
if (readfield(d))
fatal("default must not contain fields")
} else { } else {
fatal("union fields must fall under a case") fatal("union fields must fall under a case")
} }
@@ -259,11 +272,17 @@ function defunion( name, tag, tagtype, tagvalue, cg, scg, d, a, i,
if (tagvalue) if (tagvalue)
codegen_union_struct(name, tagvalue, cg, scg) codegen_union_struct(name, tagvalue, cg, scg)
# Unseen cases are simply not recognized/allowed. # Unseen cases are only recognized/allowed when default is present.
exhaustive = 1 exhaustive = 1
for (i in unseen) for (i in unseen)
if (i && unseen[i]) if (i && unseen[i]) {
exhaustive = 0 if (defaulted) {
codegen_struct_tag(tag, scg)
codegen_union_struct(name, i, cg, scg)
} else {
exhaustive = 0
}
}
Types[name] = "union" Types[name] = "union"
codegen_union(name, cg, exhaustive) codegen_union(name, cg, exhaustive)

View File

@@ -38,5 +38,5 @@ if (WITH_CURSES)
target_link_libraries (wdye PUBLIC ${CURSES_LIBRARIES}) target_link_libraries (wdye PUBLIC ${CURSES_LIBRARIES})
endif () endif ()
add_test (NAME simple COMMAND wdye "${PROJECT_SOURCE_DIR}/test.lua") add_test (NAME wdye COMMAND wdye "${PROJECT_SOURCE_DIR}/test.lua")
include (CTest) include (CTest)

View File

@@ -890,10 +890,11 @@ environ_map_serialize (struct str_map *env, struct strv *envv)
static int static int
spawn_protected (lua_State *L) spawn_protected (lua_State *L)
{ {
struct spawn_context *ctx = lua_touserdata (L, 1); struct spawn_context *ctx = lua_touserdata (L, lua_upvalueindex (1));
luaL_checktype (L, 1, LUA_TTABLE);
// Step 1: Prepare process environment. // Step 1: Prepare process environment.
if (xlua_getfield (L, 2, "environ", LUA_TTABLE, true)) if (xlua_getfield (L, 1, "environ", LUA_TTABLE, true))
{ {
environ_map_update (&ctx->env, L); environ_map_update (&ctx->env, L);
lua_pop (L, 1); lua_pop (L, 1);
@@ -913,11 +914,11 @@ spawn_protected (lua_State *L)
#endif #endif
// Step 3: Prepare process command line. // Step 3: Prepare process command line.
size_t argc = lua_rawlen (L, 2); size_t argc = lua_rawlen (L, 1);
for (size_t i = 1; i <= argc; i++) for (size_t i = 1; i <= argc; i++)
{ {
lua_pushinteger (L, i); lua_pushinteger (L, i);
lua_rawget (L, 2); lua_rawget (L, 1);
const char *arg = lua_tostring (L, -1); const char *arg = lua_tostring (L, -1);
if (!arg) if (!arg)
return luaL_error (L, "spawn arguments must be strings"); return luaL_error (L, "spawn arguments must be strings");
@@ -1004,23 +1005,24 @@ spawn_protected (lua_State *L)
static int static int
xlua_spawn (lua_State *L) xlua_spawn (lua_State *L)
{ {
luaL_checktype (L, 1, LUA_TTABLE);
lua_pushcfunction (L, xlua_error_handler); lua_pushcfunction (L, xlua_error_handler);
lua_pushcfunction (L, spawn_protected); lua_insert (L, 1);
struct spawn_context ctx = {};
lua_pushlightuserdata (L, &ctx);
lua_pushcclosure (L, spawn_protected, 1);
lua_insert (L, 2);
// There are way too many opportunities for Lua to throw, // There are way too many opportunities for Lua to throw,
// so maintain a context to clean up in one go. // so maintain a context to clean up in one go.
struct spawn_context ctx = spawn_context_make (); ctx = spawn_context_make ();
lua_pushlightuserdata (L, &ctx); int result = lua_pcall (L, lua_gettop (L) - 2, 1, 1);
lua_rotate (L, 1, -1);
int result = lua_pcall (L, 2, 1, -4);
spawn_context_free (&ctx); spawn_context_free (&ctx);
if (result) if (result)
return lua_error (L); return lua_error (L);
// Remove the error handler ("good programming practice"). // Remove the error handler ("good programming practice").
lua_remove (L, -2); lua_remove (L, 1);
return 1; return 1;
} }
@@ -1376,9 +1378,9 @@ xlua_panic (lua_State *L)
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
if (argc != 2) if (argc < 2)
{ {
fprintf (stderr, "Usage: %s program.lua\n", argv[0]); fprintf (stderr, "Usage: %s program.lua [args...]\n", argv[0]);
return 1; return 1;
} }
@@ -1399,16 +1401,20 @@ main (int argc, char *argv[])
luaL_setfuncs (g.L, xlua_pattern_table, 0); luaL_setfuncs (g.L, xlua_pattern_table, 0);
lua_pop (g.L, 1); lua_pop (g.L, 1);
const char *path = argv[1]; luaL_checkstack (g.L, argc, NULL);
lua_pushcfunction (g.L, xlua_error_handler); lua_pushcfunction (g.L, xlua_error_handler);
if (luaL_loadfile (g.L, path) if (luaL_loadfile (g.L, strcmp (argv[1], "-") ? argv[1] : NULL))
|| lua_pcall (g.L, 0, 0, -2)) goto error;
{ for (int i = 2; i < argc; i++)
print_error ("%s", lua_tostring (g.L, -1)); lua_pushstring (g.L, argv[i]);
lua_pop (g.L, 1); if (lua_pcall (g.L, argc - 2, 0, 1))
lua_close (g.L); goto error;
return 1;
}
lua_close (g.L); lua_close (g.L);
return 0; return 0;
error:
print_error ("%s", lua_tostring (g.L, -1));
lua_close (g.L);
return 1;
} }