sd-varlink: Expose sd_varlink_idl_parse()

We're planning to do code generation based on the systemd varlink
APIs. To simplify this, let's expose the IDL parser, so we can use
it to do code generation instead of having to write our own IDL
parser.
This commit is contained in:
Daan De Meyer
2025-05-19 15:19:24 +02:00
parent 34f714349b
commit d94c24e9cc
7 changed files with 29 additions and 27 deletions
+2 -2
View File
@@ -14,7 +14,7 @@
#include "varlink-idl-util.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
_cleanup_(varlink_interface_freep) sd_varlink_interface *vi = NULL;
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *vi = NULL;
_cleanup_free_ char *str = NULL, *dump = NULL;
int r;
@@ -25,7 +25,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
assert_se(str = memdup_suffix0(data, size));
r = varlink_idl_parse(str, /* ret_line= */ NULL, /* column= */ NULL, &vi);
r = sd_varlink_idl_parse(str, /* ret_line= */ NULL, /* column= */ NULL, &vi);
if (r < 0) {
log_debug_errno(r, "Failed to parse varlink interface definition: %m");
return 0;
+2
View File
@@ -1072,6 +1072,8 @@ global:
sd_varlink_get_input_fd;
sd_varlink_get_n_fds;
sd_varlink_get_output_fd;
sd_varlink_idl_parse;
sd_varlink_interface_free;
sd_varlink_reset_fds;
sd_varlink_server_listen_name;
} LIBSYSTEMD_257;
+3 -3
View File
@@ -588,7 +588,7 @@ static sd_varlink_symbol* varlink_symbol_free(sd_varlink_symbol *symbol) {
return mfree(symbol);
}
sd_varlink_interface* varlink_interface_free(sd_varlink_interface *interface) {
_public_ sd_varlink_interface* sd_varlink_interface_free(sd_varlink_interface *interface) {
if (!interface)
return NULL;
@@ -1139,13 +1139,13 @@ static int varlink_idl_resolve_types(sd_varlink_interface *interface) {
return 0;
}
int varlink_idl_parse(
_public_ int sd_varlink_idl_parse(
const char *text,
unsigned *reterr_line,
unsigned *reterr_column,
sd_varlink_interface **ret) {
_cleanup_(varlink_interface_freep) sd_varlink_interface *interface = NULL;
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *interface = NULL;
_cleanup_(varlink_symbol_freep) sd_varlink_symbol *symbol = NULL;
enum {
STATE_PRE_INTERFACE,
@@ -6,10 +6,6 @@
#include "memory-util.h"
int varlink_idl_parse(const char *text, unsigned *ret_line, unsigned *ret_column, sd_varlink_interface **ret);
sd_varlink_interface* varlink_interface_free(sd_varlink_interface *interface);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_varlink_interface*, varlink_interface_free);
bool varlink_idl_field_name_is_valid(const char *name);
bool varlink_idl_symbol_name_is_valid(const char *name);
bool varlink_idl_interface_name_is_valid(const char *name);
+4
View File
@@ -221,6 +221,10 @@ int sd_varlink_idl_dump(FILE *f, const sd_varlink_interface *interface, sd_varli
int sd_varlink_idl_format_full(const sd_varlink_interface *interface, sd_varlink_idl_format_flags_t flags, size_t cols, char **ret);
int sd_varlink_idl_format(const sd_varlink_interface *interface, char **ret);
int sd_varlink_idl_parse(const char *text, unsigned *reterr_line, unsigned *reterr_column, sd_varlink_interface **ret);
sd_varlink_interface* sd_varlink_interface_free(sd_varlink_interface *interface);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_varlink_interface, sd_varlink_interface_free);
_SD_END_DECLARATIONS;
#endif
+14 -14
View File
@@ -129,7 +129,7 @@ static SD_VARLINK_DEFINE_INTERFACE(
&vl_error_ErrorTest);
static void test_parse_format_one(const sd_varlink_interface *iface) {
_cleanup_(varlink_interface_freep) sd_varlink_interface *parsed = NULL;
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *parsed = NULL;
_cleanup_free_ char *text = NULL, *text2 = NULL;
assert_se(iface);
@@ -137,7 +137,7 @@ static void test_parse_format_one(const sd_varlink_interface *iface) {
assert_se(sd_varlink_idl_dump(stdout, iface, SD_VARLINK_IDL_FORMAT_COLOR, /* cols= */ SIZE_MAX) >= 0);
assert_se(varlink_idl_consistent(iface, LOG_ERR) >= 0);
assert_se(sd_varlink_idl_format(iface, &text) >= 0);
assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
assert_se(sd_varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
assert_se(varlink_idl_consistent(parsed, LOG_ERR) >= 0);
assert_se(sd_varlink_idl_format(parsed, &text2) >= 0);
@@ -145,13 +145,13 @@ static void test_parse_format_one(const sd_varlink_interface *iface) {
text = mfree(text);
text2 = mfree(text2);
parsed = varlink_interface_free(parsed);
parsed = sd_varlink_interface_free(parsed);
/* Do the same thing, but aggressively line break, and make sure this is roundtrippable as well */
assert_se(sd_varlink_idl_dump(stdout, iface, SD_VARLINK_IDL_FORMAT_COLOR, 23) >= 0);
assert_se(varlink_idl_consistent(iface, LOG_ERR) >= 0);
assert_se(sd_varlink_idl_format_full(iface, 0, 23, &text) >= 0);
assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
assert_se(sd_varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
assert_se(varlink_idl_consistent(parsed, LOG_ERR) >= 0);
assert_se(sd_varlink_idl_format_full(parsed, 0, 23, &text2) >= 0);
@@ -213,7 +213,7 @@ TEST(parse_format) {
}
TEST(parse) {
_cleanup_(varlink_interface_freep) sd_varlink_interface *parsed = NULL;
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *parsed = NULL;
/* This one has (nested) enonymous enums and structs */
static const char text[] =
@@ -222,13 +222,13 @@ TEST(parse) {
"type Barstruct ( a : (x, y, z), b : (x : int), c: (f, ff, fff), d: object, e : (sub : (subsub: (subsubsub: string, subsubsub2: (iii, ooo)))))"
;
assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
assert_se(sd_varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
test_parse_format_one(parsed);
assert_se(varlink_idl_parse("interface org.freedesktop.Foo\n"
"type Foo (b: bool, c: foo, c: int)", NULL, NULL, NULL) == -ENETUNREACH); /* unresolved type */
assert_se(varlink_idl_parse("interface org.freedesktop.Foo\n"
"type Foo ()", NULL, NULL, NULL) == -EBADMSG); /* empty struct/enum */
assert_se(sd_varlink_idl_parse("interface org.freedesktop.Foo\n"
"type Foo (b: bool, c: foo, c: int)", NULL, NULL, NULL) == -ENETUNREACH); /* unresolved type */
assert_se(sd_varlink_idl_parse("interface org.freedesktop.Foo\n"
"type Foo ()", NULL, NULL, NULL) == -EBADMSG); /* empty struct/enum */
}
TEST(interface_name_is_valid) {
@@ -300,7 +300,7 @@ TEST(qualified_symbol_name_is_valid) {
TEST(validate_json) {
_cleanup_(varlink_interface_freep) sd_varlink_interface *parsed = NULL;
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *parsed = NULL;
/* This one has (nested) enonymous enums and structs */
static const char text[] =
@@ -311,7 +311,7 @@ TEST(validate_json) {
"#paff\n"
"b:int, c:?bool, d:[]int, e:?[string]bool, f:?(piff, paff), g:(f:float) ) -> ()\n";
assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
assert_se(sd_varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
test_parse_format_one(parsed);
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
@@ -330,7 +330,7 @@ TEST(validate_json) {
}
static int test_recursive_one(unsigned depth) {
_cleanup_(varlink_interface_freep) sd_varlink_interface *parsed = NULL;
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *parsed = NULL;
_cleanup_free_ char *pre = NULL, *post = NULL, *text = NULL;
static const char header[] =
"interface recursive.test\n"
@@ -346,7 +346,7 @@ static int test_recursive_one(unsigned depth) {
if (!text)
return log_oom();
return varlink_idl_parse(text, NULL, NULL, &parsed);
return sd_varlink_idl_parse(text, NULL, NULL, &parsed);
}
TEST(recursive) {
+4 -4
View File
@@ -449,7 +449,7 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
{ "description", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, SD_JSON_MANDATORY },
{}
};
_cleanup_(varlink_interface_freep) sd_varlink_interface *vi = NULL;
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *vi = NULL;
const char *description = NULL;
unsigned line = 0, column = 0;
@@ -461,7 +461,7 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
print_separator();
/* Try to parse the returned description, so that we can add syntax highlighting */
r = varlink_idl_parse(ASSERT_PTR(description), &line, &column, &vi);
r = sd_varlink_idl_parse(ASSERT_PTR(description), &line, &column, &vi);
if (r < 0) {
if (list_methods)
return log_error_errno(r, "Failed to parse returned interface description at %u:%u: %m", line, column);
@@ -818,7 +818,7 @@ static int verb_call(int argc, char *argv[], void *userdata) {
}
static int verb_validate_idl(int argc, char *argv[], void *userdata) {
_cleanup_(varlink_interface_freep) sd_varlink_interface *vi = NULL;
_cleanup_(sd_varlink_interface_freep) sd_varlink_interface *vi = NULL;
_cleanup_free_ char *text = NULL;
const char *fname;
unsigned line = 1, column = 1;
@@ -838,7 +838,7 @@ static int verb_validate_idl(int argc, char *argv[], void *userdata) {
fname = "<stdin>";
}
r = varlink_idl_parse(text, &line, &column, &vi);
r = sd_varlink_idl_parse(text, &line, &column, &vi);
if (r == -EBADMSG)
return log_error_errno(r, "%s:%u:%u: Bad syntax.", fname, line, column);
if (r == -ENETUNREACH)