varlink: parse comments too

This commit is contained in:
Lennart Poettering
2024-06-17 09:20:21 +02:00
parent fbb69c0306
commit ce2d2260c9
2 changed files with 94 additions and 10 deletions
+79 -10
View File
@@ -657,8 +657,10 @@ static int varlink_idl_subparse_token(
static int varlink_idl_subparse_comment(
const char **p,
unsigned *line,
unsigned *column) {
unsigned *column,
char **ret) {
_cleanup_free_ char *comment = NULL;
size_t l;
assert(p);
@@ -667,9 +669,30 @@ static int varlink_idl_subparse_comment(
assert(column);
l = strcspn(*p, NEWLINE);
if (!utf8_is_valid_n(*p, l))
return varlink_idl_log(SYNTHETIC_ERRNO(EBADMSG), "%u:%u: Comment is not valid UTF-8.", *line, *column);
if (ret) {
/* Remove a single space as prefix of a comment, if one is specified. This is because we
* generally expect comments to be formatted as "# foobar" rather than "#foobar", and will
* ourselves format them that way. We accept the comments without the space too however. We
* will not strip more than one space, to allow indented comment blocks. */
if (**p == ' ')
comment = strndup(*p + 1, l - 1);
else
comment = strndup(*p, l);
if (!comment)
return -ENOMEM;
}
advance_line_column(*p, l + 1, line, column);
*p += l;
if (ret)
*ret = TAKE_PTR(comment);
return 1;
}
@@ -856,7 +879,7 @@ static int varlink_idl_subparse_struct_or_enum(
return varlink_idl_log(SYNTHETIC_ERRNO(EBADMSG), "%u:%u: Unexpected token '%s'.", *line, *column, token);
state = STATE_NAME;
allowed_delimiters = ")";
allowed_delimiters = ")#";
allowed_chars = VALID_CHARS_IDENTIFIER;
break;
@@ -865,7 +888,23 @@ static int varlink_idl_subparse_struct_or_enum(
if (!token)
return varlink_idl_log(SYNTHETIC_ERRNO(EBADMSG), "%u:%u: Premature EOF.", *line, *column);
if (streq(token, ")"))
else if (streq(token, "#")) {
_cleanup_free_ char *comment = NULL;
r = varlink_idl_subparse_comment(p, line, column, &comment);
if (r < 0)
return r;
r = varlink_symbol_realloc(symbol, *n_fields + 1);
if (r < 0)
return r;
VarlinkField *field = (*symbol)->fields + (*n_fields)++;
*field = (VarlinkField) {
.name = TAKE_PTR(comment),
.field_type = _VARLINK_FIELD_COMMENT,
};
} else if (streq(token, ")"))
state = STATE_DONE;
else {
field_name = TAKE_PTR(token);
@@ -929,7 +968,7 @@ static int varlink_idl_subparse_struct_or_enum(
if (streq(token, ",")) {
state = STATE_NAME;
allowed_delimiters = NULL;
allowed_delimiters = "#";
allowed_chars = VALID_CHARS_IDENTIFIER;
} else {
assert(streq(token, ")"));
@@ -947,7 +986,7 @@ static int varlink_idl_subparse_struct_or_enum(
return varlink_idl_log(SYNTHETIC_ERRNO(EBADMSG), "%u:%u: Premature EOF.", *line, *column);
if (streq(token, ",")) {
state = STATE_NAME;
allowed_delimiters = NULL;
allowed_delimiters = "#";
allowed_chars = VALID_CHARS_IDENTIFIER;
} else if (streq(token, ")"))
state = STATE_DONE;
@@ -1062,9 +1101,24 @@ int varlink_idl_parse(
if (!token)
return varlink_idl_log(SYNTHETIC_ERRNO(EBADMSG), "%u:%u: Premature EOF.", *line, *column);
if (streq(token, "#")) {
r = varlink_idl_subparse_comment(&text, line, column);
_cleanup_free_ char *comment = NULL;
r = varlink_idl_subparse_comment(&text, line, column, &comment);
if (r < 0)
return r;
r = varlink_interface_realloc(&interface, n_symbols + 1);
if (r < 0)
return r;
r = varlink_symbol_realloc(&symbol, 0);
if (r < 0)
return r;
symbol->symbol_type = _VARLINK_INTERFACE_COMMENT;
symbol->name = TAKE_PTR(comment);
interface->symbols[n_symbols++] = TAKE_PTR(symbol);
} else if (streq(token, "interface")) {
state = STATE_INTERFACE;
allowed_delimiters = NULL;
@@ -1074,9 +1128,6 @@ int varlink_idl_parse(
break;
case STATE_INTERFACE:
assert(!interface);
assert(n_symbols == 0);
if (!token)
return varlink_idl_log(SYNTHETIC_ERRNO(EBADMSG), "%u:%u: Premature EOF.", *line, *column);
@@ -1084,7 +1135,9 @@ int varlink_idl_parse(
if (r < 0)
return r;
assert(!interface->name);
interface->name = TAKE_PTR(token);
state = STATE_PRE_SYMBOL;
allowed_delimiters = "#";
allowed_chars = VALID_CHARS_RESERVED;
@@ -1097,9 +1150,25 @@ int varlink_idl_parse(
}
if (streq(token, "#")) {
r = varlink_idl_subparse_comment(&text, line, column);
_cleanup_free_ char *comment = NULL;
r = varlink_idl_subparse_comment(&text, line, column, &comment);
if (r < 0)
return r;
r = varlink_interface_realloc(&interface, n_symbols + 1);
if (r < 0)
return r;
assert(!symbol);
r = varlink_symbol_realloc(&symbol, 0);
if (r < 0)
return r;
symbol->symbol_type = _VARLINK_SYMBOL_COMMENT;
symbol->name = TAKE_PTR(comment);
interface->symbols[n_symbols++] = TAKE_PTR(symbol);
} else if (streq(token, "method")) {
state = STATE_METHOD;
allowed_chars = VALID_CHARS_IDENTIFIER;
+15
View File
@@ -123,6 +123,21 @@ static void test_parse_format_one(const VarlinkInterface *iface) {
assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
assert_se(varlink_idl_consistent(parsed, LOG_ERR) >= 0);
assert_se(varlink_idl_format(parsed, &text2) >= 0);
ASSERT_STREQ(text, text2);
text = mfree(text);
text2 = mfree(text2);
parsed = varlink_interface_free(parsed);
/* Do the same thing, but aggressively line break, and make sure this is roundtrippable as well */
assert_se(varlink_idl_dump(stdout, /* use_colors=*/ true, 23, iface) >= 0);
assert_se(varlink_idl_consistent(iface, LOG_ERR) >= 0);
assert_se(varlink_idl_format_full(iface, 23, &text) >= 0);
assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
assert_se(varlink_idl_consistent(parsed, LOG_ERR) >= 0);
assert_se(varlink_idl_format_full(parsed, 23, &text2) >= 0);
ASSERT_STREQ(text, text2);
}