Compare commits

...

7 Commits

Author SHA1 Message Date
7566f9af82 liberty: comment on pthread_cancel
All checks were successful
Alpine 3.21 Success
OpenBSD 7.6 Success
2025-09-21 18:59:16 +02:00
7425355d01 liberty-xui: fix a new Fontconfig warning
All checks were successful
Alpine 3.21 Success
OpenBSD 7.6 Success
2025-08-02 18:22:00 +02:00
d8f785eae5 liberty-xdg: don't crash on missing X11 atoms
All checks were successful
Alpine 3.21 Success
OpenBSD 7.6 Success
They can be missing in bare configurations, such as Sway + XWayland.
2025-06-04 21:54:04 +02:00
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
8 changed files with 78 additions and 40 deletions

View File

@@ -86,24 +86,30 @@ xdg_xsettings_update (struct xdg_xsettings *self, Display *dpy)
// TODO: We're supposed to lock the server.
// TODO: We're supposed to trap X errors.
char *selection = xstrdup_printf ("_XSETTINGS_S%d", DefaultScreen (dpy));
Window owner
= XGetSelectionOwner (dpy, XInternAtom (dpy, selection, True));
Atom selection_atom = XInternAtom (dpy, selection, True);
free (selection);
if (!selection_atom)
return;
Window owner = XGetSelectionOwner (dpy, selection_atom);
if (!owner)
return;
Atom xsettings_atom = XInternAtom (dpy, "_XSETTINGS_SETTINGS", True);
if (!xsettings_atom)
return;
Atom actual_type = None;
int actual_format = 0;
unsigned long nitems = 0, bytes_after = 0;
unsigned char *buffer = NULL;
Atom xsettings = XInternAtom (dpy, "_XSETTINGS_SETTINGS", True);
int status = XGetWindowProperty (dpy,
owner,
xsettings,
xsettings_atom,
0L,
LONG_MAX,
False,
xsettings,
xsettings_atom,
&actual_type,
&actual_format,
&nitems,
@@ -112,7 +118,7 @@ xdg_xsettings_update (struct xdg_xsettings *self, Display *dpy)
if (status != Success || !buffer)
return;
if (actual_type != xsettings
if (actual_type != xsettings_atom
|| actual_format != 8
|| nitems < 12)
goto fail;

View File

@@ -1884,6 +1884,8 @@ x11_init (struct poller *poller, struct attrs *app_attrs, size_t app_attrs_len)
if (!(g_xui.dpy = XkbOpenDisplay
(NULL, &g_xui.xkb_base_event_code, NULL, NULL, NULL, NULL)))
exit_fatal ("cannot open display");
if (!XftInit (NULL))
print_warning ("Fontconfig initialization failed");
if (!XftDefaultHasRender (g_xui.dpy))
exit_fatal ("XRender is not supported");
if (!(g_xui.x11_im = XOpenIM (g_xui.dpy, NULL, NULL, NULL)))
@@ -1912,8 +1914,6 @@ x11_init (struct poller *poller, struct attrs *app_attrs, size_t app_attrs_len)
g_xui.x11_xsettings = xdg_xsettings_make ();
xdg_xsettings_update (&g_xui.x11_xsettings, g_xui.dpy);
if (!FcInit ())
print_warning ("Fontconfig initialization failed");
if (!(g_xui.xft_fonts = x11_font_open (0)))
exit_fatal ("cannot open a font");

View File

@@ -1209,7 +1209,10 @@ async_make (struct async_manager *manager)
}
/// Only allowed from the main thread once the job has been started but before
/// the results have been dispatched
/// the results have been dispatched.
///
/// Note that it may in practice lead to memory leakage, although that's
/// an implementation issue: https://eissing.org/icing/posts/rip_pthread_cancel/
static void
async_cancel (struct async *self)
{

View File

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

View File

@@ -8,7 +8,7 @@ syn region libertyxdrBlockComment start=+/[*]+ end=+[*]/+
syn match libertyxdrComment "//.*"
syn match libertyxdrIdentifier "\<[[:alpha:]][[:alnum:]_]*\>"
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
let b:current_syntax = "libertyxdr"

View File

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

View File

@@ -1,6 +1,6 @@
# 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
#
# 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,
unseen, exhaustive) {
unseen, defaulted, exhaustive) {
delete cg[0]
delete scg[0]
delete d[0]
@@ -249,9 +249,22 @@ function defunion( name, tag, tagtype, tagvalue, cg, scg, d, a, i,
if (!unseen[tagvalue]--)
fatal("no such value or duplicate case: " tagtype "." tagvalue)
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) {
if (readfield(d))
codegen_struct_field(d, scg)
} else if (defaulted) {
if (readfield(d))
fatal("default must not contain fields")
} else {
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)
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
for (i in unseen)
if (i && unseen[i])
exhaustive = 0
if (i && unseen[i]) {
if (defaulted) {
codegen_struct_tag(tag, scg)
codegen_union_struct(name, i, cg, scg)
} else {
exhaustive = 0
}
}
Types[name] = "union"
codegen_union(name, cg, exhaustive)

View File

@@ -890,10 +890,11 @@ environ_map_serialize (struct str_map *env, struct strv *envv)
static int
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.
if (xlua_getfield (L, 2, "environ", LUA_TTABLE, true))
if (xlua_getfield (L, 1, "environ", LUA_TTABLE, true))
{
environ_map_update (&ctx->env, L);
lua_pop (L, 1);
@@ -913,11 +914,11 @@ spawn_protected (lua_State *L)
#endif
// 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++)
{
lua_pushinteger (L, i);
lua_rawget (L, 2);
lua_rawget (L, 1);
const char *arg = lua_tostring (L, -1);
if (!arg)
return luaL_error (L, "spawn arguments must be strings");
@@ -1004,23 +1005,24 @@ spawn_protected (lua_State *L)
static int
xlua_spawn (lua_State *L)
{
luaL_checktype (L, 1, LUA_TTABLE);
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,
// so maintain a context to clean up in one go.
struct spawn_context ctx = spawn_context_make ();
lua_pushlightuserdata (L, &ctx);
lua_rotate (L, 1, -1);
int result = lua_pcall (L, 2, 1, -4);
ctx = spawn_context_make ();
int result = lua_pcall (L, lua_gettop (L) - 2, 1, 1);
spawn_context_free (&ctx);
if (result)
return lua_error (L);
// Remove the error handler ("good programming practice").
lua_remove (L, -2);
lua_remove (L, 1);
return 1;
}
@@ -1376,9 +1378,9 @@ xlua_panic (lua_State *L)
int
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;
}
@@ -1399,16 +1401,20 @@ main (int argc, char *argv[])
luaL_setfuncs (g.L, xlua_pattern_table, 0);
lua_pop (g.L, 1);
const char *path = argv[1];
luaL_checkstack (g.L, argc, NULL);
lua_pushcfunction (g.L, xlua_error_handler);
if (luaL_loadfile (g.L, path)
|| lua_pcall (g.L, 0, 0, -2))
{
print_error ("%s", lua_tostring (g.L, -1));
lua_pop (g.L, 1);
lua_close (g.L);
return 1;
}
if (luaL_loadfile (g.L, strcmp (argv[1], "-") ? argv[1] : NULL))
goto error;
for (int i = 2; i < argc; i++)
lua_pushstring (g.L, argv[i]);
if (lua_pcall (g.L, argc - 2, 0, 1))
goto error;
lua_close (g.L);
return 0;
error:
print_error ("%s", lua_tostring (g.L, -1));
lua_close (g.L);
return 1;
}