mirror of
https://github.com/systemd/systemd
synced 2024-10-01 13:55:20 +00:00
varlink: add concept for embedding comments into IDL structures
This commit is contained in:
parent
aca093018c
commit
fbb69c0306
|
@ -5,6 +5,7 @@
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
|
#include "utf8.h"
|
||||||
#include "varlink-idl.h"
|
#include "varlink-idl.h"
|
||||||
|
|
||||||
#define DEPTH_MAX 64U
|
#define DEPTH_MAX 64U
|
||||||
|
@ -15,13 +16,63 @@ enum {
|
||||||
COLOR_IDENTIFIER,
|
COLOR_IDENTIFIER,
|
||||||
COLOR_MARKS, /* [], ->, ?, … */
|
COLOR_MARKS, /* [], ->, ?, … */
|
||||||
COLOR_RESET,
|
COLOR_RESET,
|
||||||
|
COLOR_COMMENT,
|
||||||
_COLOR_MAX,
|
_COLOR_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define varlink_idl_log(error, format, ...) log_debug_errno(error, "Varlink-IDL: " format, ##__VA_ARGS__)
|
#define varlink_idl_log(error, format, ...) log_debug_errno(error, "Varlink-IDL: " format, ##__VA_ARGS__)
|
||||||
#define varlink_idl_log_full(level, error, format, ...) log_full_errno(level, error, "Varlink-IDL: " format, ##__VA_ARGS__)
|
#define varlink_idl_log_full(level, error, format, ...) log_full_errno(level, error, "Varlink-IDL: " format, ##__VA_ARGS__)
|
||||||
|
|
||||||
static int varlink_idl_format_all_fields(FILE *f, const VarlinkSymbol *symbol, VarlinkFieldDirection direction, const char *indent, const char *const colors[static _COLOR_MAX]);
|
static int varlink_idl_format_all_fields(FILE *f, const VarlinkSymbol *symbol, VarlinkFieldDirection direction, const char *indent, const char *const colors[static _COLOR_MAX], size_t cols);
|
||||||
|
|
||||||
|
static int varlink_idl_format_comment(
|
||||||
|
FILE *f,
|
||||||
|
const char *text,
|
||||||
|
const char *indent,
|
||||||
|
const char *const colors[static _COLOR_MAX],
|
||||||
|
size_t cols) {
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(f);
|
||||||
|
assert(colors);
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
/* If text is NULL, output an empty but commented line */
|
||||||
|
fputs(strempty(indent), f);
|
||||||
|
fputs(colors[COLOR_COMMENT], f);
|
||||||
|
fputs("#", f);
|
||||||
|
fputs(colors[COLOR_RESET], f);
|
||||||
|
fputs("\n", f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
|
r = strv_split_full(&l, text, NEWLINE, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to split comment string: %m");
|
||||||
|
|
||||||
|
size_t indent_width = utf8_console_width(indent);
|
||||||
|
size_t max_width = indent_width < cols ? cols - indent_width : 0;
|
||||||
|
if (max_width < 10)
|
||||||
|
max_width = 10;
|
||||||
|
|
||||||
|
_cleanup_strv_free_ char **broken = NULL;
|
||||||
|
r = strv_rebreak_lines(l, max_width, &broken);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to rebreak lines in comment: %m");
|
||||||
|
|
||||||
|
STRV_FOREACH(i, broken) {
|
||||||
|
fputs(strempty(indent), f);
|
||||||
|
fputs(colors[COLOR_COMMENT], f);
|
||||||
|
fputs("# ", f);
|
||||||
|
fputs(*i, f);
|
||||||
|
fputs(colors[COLOR_RESET], f);
|
||||||
|
fputs("\n", f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int varlink_idl_format_enum_values(
|
static int varlink_idl_format_enum_values(
|
||||||
FILE *f,
|
FILE *f,
|
||||||
|
@ -65,10 +116,12 @@ static int varlink_idl_format_field(
|
||||||
FILE *f,
|
FILE *f,
|
||||||
const VarlinkField *field,
|
const VarlinkField *field,
|
||||||
const char *indent,
|
const char *indent,
|
||||||
const char *const colors[static _COLOR_MAX]) {
|
const char *const colors[static _COLOR_MAX],
|
||||||
|
size_t cols) {
|
||||||
|
|
||||||
assert(f);
|
assert(f);
|
||||||
assert(field);
|
assert(field);
|
||||||
|
assert(field->field_type != _VARLINK_FIELD_COMMENT);
|
||||||
|
|
||||||
fputs(strempty(indent), f);
|
fputs(strempty(indent), f);
|
||||||
fputs(colors[COLOR_IDENTIFIER], f);
|
fputs(colors[COLOR_IDENTIFIER], f);
|
||||||
|
@ -146,7 +199,7 @@ static int varlink_idl_format_field(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VARLINK_STRUCT:
|
case VARLINK_STRUCT:
|
||||||
return varlink_idl_format_all_fields(f, ASSERT_PTR(field->symbol), VARLINK_REGULAR, indent, colors);
|
return varlink_idl_format_all_fields(f, ASSERT_PTR(field->symbol), VARLINK_REGULAR, indent, colors, cols);
|
||||||
|
|
||||||
case VARLINK_ENUM:
|
case VARLINK_ENUM:
|
||||||
return varlink_idl_format_enum_values(f, ASSERT_PTR(field->symbol), indent, colors);
|
return varlink_idl_format_enum_values(f, ASSERT_PTR(field->symbol), indent, colors);
|
||||||
|
@ -163,7 +216,8 @@ static int varlink_idl_format_all_fields(
|
||||||
const VarlinkSymbol *symbol,
|
const VarlinkSymbol *symbol,
|
||||||
VarlinkFieldDirection filter_direction,
|
VarlinkFieldDirection filter_direction,
|
||||||
const char *indent,
|
const char *indent,
|
||||||
const char *const colors[static _COLOR_MAX]) {
|
const char *const colors[static _COLOR_MAX],
|
||||||
|
size_t cols) {
|
||||||
|
|
||||||
_cleanup_free_ char *indent2 = NULL;
|
_cleanup_free_ char *indent2 = NULL;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
@ -179,6 +233,9 @@ static int varlink_idl_format_all_fields(
|
||||||
|
|
||||||
for (const VarlinkField *field = symbol->fields; field->field_type != _VARLINK_FIELD_TYPE_END_MARKER; field++) {
|
for (const VarlinkField *field = symbol->fields; field->field_type != _VARLINK_FIELD_TYPE_END_MARKER; field++) {
|
||||||
|
|
||||||
|
if (field->field_type == _VARLINK_FIELD_COMMENT) /* skip comments at first */
|
||||||
|
continue;
|
||||||
|
|
||||||
if (field->field_direction != filter_direction)
|
if (field->field_direction != filter_direction)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -188,7 +245,27 @@ static int varlink_idl_format_all_fields(
|
||||||
} else
|
} else
|
||||||
fputs(",\n", f);
|
fputs(",\n", f);
|
||||||
|
|
||||||
r = varlink_idl_format_field(f, field, indent2, colors);
|
/* We found a field we want to output. In this case, output all immediately preceeding
|
||||||
|
* comments first. First, find the first comment in the series before. */
|
||||||
|
const VarlinkField *start_comment = NULL;
|
||||||
|
for (const VarlinkField *c1 = field; c1 > symbol->fields; c1--) {
|
||||||
|
const VarlinkField *c0 = c1 - 1;
|
||||||
|
|
||||||
|
if (c0->field_type != _VARLINK_FIELD_COMMENT)
|
||||||
|
break;
|
||||||
|
|
||||||
|
start_comment = c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_comment) {
|
||||||
|
for (const VarlinkField *c = start_comment; c < field; c++) {
|
||||||
|
r = varlink_idl_format_comment(f, ASSERT_PTR(c->name), indent2, colors, cols);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = varlink_idl_format_field(f, field, indent2, colors, cols);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +284,8 @@ static int varlink_idl_format_all_fields(
|
||||||
static int varlink_idl_format_symbol(
|
static int varlink_idl_format_symbol(
|
||||||
FILE *f,
|
FILE *f,
|
||||||
const VarlinkSymbol *symbol,
|
const VarlinkSymbol *symbol,
|
||||||
const char *const colors[static _COLOR_MAX]) {
|
const char *const colors[static _COLOR_MAX],
|
||||||
|
size_t cols) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(f);
|
assert(f);
|
||||||
|
@ -232,7 +310,7 @@ static int varlink_idl_format_symbol(
|
||||||
fputs(symbol->name, f);
|
fputs(symbol->name, f);
|
||||||
fputs(colors[COLOR_RESET], f);
|
fputs(colors[COLOR_RESET], f);
|
||||||
|
|
||||||
r = varlink_idl_format_all_fields(f, symbol, VARLINK_REGULAR, /* indent= */ NULL, colors);
|
r = varlink_idl_format_all_fields(f, symbol, VARLINK_REGULAR, /* indent= */ NULL, colors, cols);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VARLINK_METHOD:
|
case VARLINK_METHOD:
|
||||||
|
@ -242,7 +320,7 @@ static int varlink_idl_format_symbol(
|
||||||
fputs(symbol->name, f);
|
fputs(symbol->name, f);
|
||||||
fputs(colors[COLOR_RESET], f);
|
fputs(colors[COLOR_RESET], f);
|
||||||
|
|
||||||
r = varlink_idl_format_all_fields(f, symbol, VARLINK_INPUT, /* indent= */ NULL, colors);
|
r = varlink_idl_format_all_fields(f, symbol, VARLINK_INPUT, /* indent= */ NULL, colors, cols);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -250,7 +328,7 @@ static int varlink_idl_format_symbol(
|
||||||
fputs(" -> ", f);
|
fputs(" -> ", f);
|
||||||
fputs(colors[COLOR_RESET], f);
|
fputs(colors[COLOR_RESET], f);
|
||||||
|
|
||||||
r = varlink_idl_format_all_fields(f, symbol, VARLINK_OUTPUT, /* indent= */ NULL, colors);
|
r = varlink_idl_format_all_fields(f, symbol, VARLINK_OUTPUT, /* indent= */ NULL, colors, cols);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VARLINK_ERROR:
|
case VARLINK_ERROR:
|
||||||
|
@ -260,7 +338,7 @@ static int varlink_idl_format_symbol(
|
||||||
fputs(symbol->name, f);
|
fputs(symbol->name, f);
|
||||||
fputs(colors[COLOR_RESET], f);
|
fputs(colors[COLOR_RESET], f);
|
||||||
|
|
||||||
r = varlink_idl_format_all_fields(f, symbol, VARLINK_REGULAR, /* indent= */ NULL, colors);
|
r = varlink_idl_format_all_fields(f, symbol, VARLINK_REGULAR, /* indent= */ NULL, colors, cols);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -277,7 +355,8 @@ static int varlink_idl_format_all_symbols(
|
||||||
FILE *f,
|
FILE *f,
|
||||||
const VarlinkInterface *interface,
|
const VarlinkInterface *interface,
|
||||||
VarlinkSymbolType filter_type,
|
VarlinkSymbolType filter_type,
|
||||||
const char *const colors[static _COLOR_MAX]) {
|
const char *const colors[static _COLOR_MAX],
|
||||||
|
size_t cols) {
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -289,9 +368,38 @@ static int varlink_idl_format_all_symbols(
|
||||||
if ((*symbol)->symbol_type != filter_type)
|
if ((*symbol)->symbol_type != filter_type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if ((*symbol)->symbol_type == _VARLINK_INTERFACE_COMMENT) {
|
||||||
|
/* Interface comments we'll output directly. */
|
||||||
|
r = varlink_idl_format_comment(f, ASSERT_PTR((*symbol)->name), /* indent= */ NULL, colors, cols);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
fputs("\n", f);
|
fputs("\n", f);
|
||||||
|
|
||||||
r = varlink_idl_format_symbol(f, *symbol, colors);
|
/* Symbol comments we'll only output if we are outputing the symbol they belong to. Scan
|
||||||
|
* backwards for symbol comments. */
|
||||||
|
const VarlinkSymbol *const*start_comment = NULL;
|
||||||
|
for (const VarlinkSymbol *const*c1 = symbol; c1 > interface->symbols; c1--) {
|
||||||
|
const VarlinkSymbol *const *c0 = c1 - 1;
|
||||||
|
|
||||||
|
if ((*c0)->symbol_type != _VARLINK_SYMBOL_COMMENT)
|
||||||
|
break;
|
||||||
|
|
||||||
|
start_comment = c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Found one or more comments, output them now */
|
||||||
|
if (start_comment)
|
||||||
|
for (const VarlinkSymbol *const*c = start_comment; c < symbol; c++) {
|
||||||
|
r = varlink_idl_format_comment(f, ASSERT_PTR((*c)->name), /* indent= */ NULL, colors, cols);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = varlink_idl_format_symbol(f, *symbol, colors, cols);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -299,17 +407,18 @@ static int varlink_idl_format_all_symbols(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int varlink_idl_dump(FILE *f, int use_colors, const VarlinkInterface *interface) {
|
int varlink_idl_dump(FILE *f, int use_colors, size_t cols, const VarlinkInterface *interface) {
|
||||||
static const char* const color_table[_COLOR_MAX] = {
|
static const char* const color_table[_COLOR_MAX] = {
|
||||||
[COLOR_SYMBOL_TYPE] = ANSI_HIGHLIGHT_GREEN,
|
[COLOR_SYMBOL_TYPE] = ANSI_HIGHLIGHT_GREEN,
|
||||||
[COLOR_FIELD_TYPE] = ANSI_HIGHLIGHT_BLUE,
|
[COLOR_FIELD_TYPE] = ANSI_HIGHLIGHT_BLUE,
|
||||||
[COLOR_IDENTIFIER] = ANSI_NORMAL,
|
[COLOR_IDENTIFIER] = ANSI_NORMAL,
|
||||||
[COLOR_MARKS] = ANSI_HIGHLIGHT_MAGENTA,
|
[COLOR_MARKS] = ANSI_HIGHLIGHT_MAGENTA,
|
||||||
[COLOR_RESET] = ANSI_NORMAL,
|
[COLOR_RESET] = ANSI_NORMAL,
|
||||||
|
[COLOR_COMMENT] = ANSI_GREY,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* const color_off[_COLOR_MAX] = {
|
static const char* const color_off[_COLOR_MAX] = {
|
||||||
"", "", "", "", "",
|
"", "", "", "", "", "",
|
||||||
};
|
};
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
@ -324,6 +433,11 @@ int varlink_idl_dump(FILE *f, int use_colors, const VarlinkInterface *interface)
|
||||||
|
|
||||||
const char *const *colors = use_colors ? color_table : color_off;
|
const char *const *colors = use_colors ? color_table : color_off;
|
||||||
|
|
||||||
|
/* First output interface comments */
|
||||||
|
r = varlink_idl_format_all_symbols(f, interface, _VARLINK_INTERFACE_COMMENT, colors, cols);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
fputs(colors[COLOR_SYMBOL_TYPE], f);
|
fputs(colors[COLOR_SYMBOL_TYPE], f);
|
||||||
fputs("interface ", f);
|
fputs("interface ", f);
|
||||||
fputs(colors[COLOR_IDENTIFIER], f);
|
fputs(colors[COLOR_IDENTIFIER], f);
|
||||||
|
@ -331,8 +445,15 @@ int varlink_idl_dump(FILE *f, int use_colors, const VarlinkInterface *interface)
|
||||||
fputs(colors[COLOR_RESET], f);
|
fputs(colors[COLOR_RESET], f);
|
||||||
fputs("\n", f);
|
fputs("\n", f);
|
||||||
|
|
||||||
|
/* Then output all symbols, ordered by symbol type */
|
||||||
for (VarlinkSymbolType t = 0; t < _VARLINK_SYMBOL_TYPE_MAX; t++) {
|
for (VarlinkSymbolType t = 0; t < _VARLINK_SYMBOL_TYPE_MAX; t++) {
|
||||||
r = varlink_idl_format_all_symbols(f, interface, t, colors);
|
|
||||||
|
/* Interface comments we already have output above. Symbol comments are output when the
|
||||||
|
* symbol they belong to are output, hence filter both here. */
|
||||||
|
if (IN_SET(t, _VARLINK_SYMBOL_COMMENT, _VARLINK_INTERFACE_COMMENT))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
r = varlink_idl_format_all_symbols(f, interface, t, colors, cols);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -340,14 +461,14 @@ int varlink_idl_dump(FILE *f, int use_colors, const VarlinkInterface *interface)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int varlink_idl_format(const VarlinkInterface *interface, char **ret) {
|
int varlink_idl_format_full(const VarlinkInterface *interface, size_t cols, char **ret) {
|
||||||
_cleanup_(memstream_done) MemStream memstream = {};
|
_cleanup_(memstream_done) MemStream memstream = {};
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!memstream_init(&memstream))
|
if (!memstream_init(&memstream))
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = varlink_idl_dump(memstream.f, /* use_colors= */ false, interface);
|
r = varlink_idl_dump(memstream.f, /* use_colors= */ false, cols, interface);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -1201,6 +1322,10 @@ bool varlink_idl_interface_name_is_valid(const char *name) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool varlink_idl_comment_is_valid(const char *comment) {
|
||||||
|
return utf8_is_valid(comment);
|
||||||
|
}
|
||||||
|
|
||||||
static int varlink_idl_symbol_consistent(const VarlinkInterface *interface, const VarlinkSymbol *symbol, int level);
|
static int varlink_idl_symbol_consistent(const VarlinkInterface *interface, const VarlinkSymbol *symbol, int level);
|
||||||
|
|
||||||
static int varlink_idl_field_consistent(
|
static int varlink_idl_field_consistent(
|
||||||
|
@ -1293,6 +1418,9 @@ static int varlink_idl_field_consistent(
|
||||||
static bool varlink_symbol_is_empty(const VarlinkSymbol *symbol) {
|
static bool varlink_symbol_is_empty(const VarlinkSymbol *symbol) {
|
||||||
assert(symbol);
|
assert(symbol);
|
||||||
|
|
||||||
|
if (IN_SET(symbol->symbol_type, _VARLINK_SYMBOL_COMMENT, _VARLINK_INTERFACE_COMMENT))
|
||||||
|
return true;
|
||||||
|
|
||||||
return symbol->fields[0].field_type == _VARLINK_FIELD_TYPE_END_MARKER;
|
return symbol->fields[0].field_type == _VARLINK_FIELD_TYPE_END_MARKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1316,7 +1444,18 @@ static int varlink_idl_symbol_consistent(
|
||||||
if (IN_SET(symbol->symbol_type, VARLINK_STRUCT_TYPE, VARLINK_ENUM_TYPE) && varlink_symbol_is_empty(symbol))
|
if (IN_SET(symbol->symbol_type, VARLINK_STRUCT_TYPE, VARLINK_ENUM_TYPE) && varlink_symbol_is_empty(symbol))
|
||||||
return varlink_idl_log_full(level, SYNTHETIC_ERRNO(EUCLEAN), "Symbol '%s' is empty, refusing.", symbol_name);
|
return varlink_idl_log_full(level, SYNTHETIC_ERRNO(EUCLEAN), "Symbol '%s' is empty, refusing.", symbol_name);
|
||||||
|
|
||||||
|
if (IN_SET(symbol->symbol_type, _VARLINK_SYMBOL_COMMENT, _VARLINK_INTERFACE_COMMENT))
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (const VarlinkField *field = symbol->fields; field->field_type != _VARLINK_FIELD_TYPE_END_MARKER; field++) {
|
for (const VarlinkField *field = symbol->fields; field->field_type != _VARLINK_FIELD_TYPE_END_MARKER; field++) {
|
||||||
|
|
||||||
|
if (field->field_type == _VARLINK_FIELD_COMMENT) {
|
||||||
|
if (!varlink_idl_comment_is_valid(field->name))
|
||||||
|
return varlink_idl_log_full(level, SYNTHETIC_ERRNO(EUCLEAN), "Comment in symbol '%s' not valid, refusing.", symbol_name);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Set **name_set = field->field_direction == VARLINK_OUTPUT ? &output_set : &input_set; /* for the method case we need two separate sets, otherwise we use the same */
|
Set **name_set = field->field_direction == VARLINK_OUTPUT ? &output_set : &input_set; /* for the method case we need two separate sets, otherwise we use the same */
|
||||||
|
|
||||||
if (!varlink_idl_field_name_is_valid(field->name))
|
if (!varlink_idl_field_name_is_valid(field->name))
|
||||||
|
@ -1347,6 +1486,12 @@ int varlink_idl_consistent(const VarlinkInterface *interface, int level) {
|
||||||
|
|
||||||
for (const VarlinkSymbol *const *symbol = interface->symbols; *symbol; symbol++) {
|
for (const VarlinkSymbol *const *symbol = interface->symbols; *symbol; symbol++) {
|
||||||
|
|
||||||
|
if (IN_SET((*symbol)->symbol_type, _VARLINK_SYMBOL_COMMENT, _VARLINK_INTERFACE_COMMENT)) {
|
||||||
|
if (!varlink_idl_comment_is_valid((*symbol)->name))
|
||||||
|
return varlink_idl_log_full(level, SYNTHETIC_ERRNO(EUCLEAN), "Comment in interface '%s' not valid, refusing.", interface->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!varlink_idl_symbol_name_is_valid((*symbol)->name))
|
if (!varlink_idl_symbol_name_is_valid((*symbol)->name))
|
||||||
return varlink_idl_log_full(level, SYNTHETIC_ERRNO(EUCLEAN), "Symbol name '%s' is not valid, refusing.", strempty((*symbol)->name));
|
return varlink_idl_log_full(level, SYNTHETIC_ERRNO(EUCLEAN), "Symbol name '%s' is not valid, refusing.", strempty((*symbol)->name));
|
||||||
|
|
||||||
|
@ -1407,6 +1552,9 @@ static int varlink_idl_validate_field_element_type(const VarlinkField *field, sd
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case _VARLINK_FIELD_COMMENT:
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -1418,6 +1566,7 @@ static int varlink_idl_validate_field(const VarlinkField *field, sd_json_variant
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(field);
|
assert(field);
|
||||||
|
assert(field->field_type != _VARLINK_FIELD_COMMENT);
|
||||||
|
|
||||||
if (!v || sd_json_variant_is_null(v)) {
|
if (!v || sd_json_variant_is_null(v)) {
|
||||||
|
|
||||||
|
@ -1449,7 +1598,6 @@ static int varlink_idl_validate_field(const VarlinkField *field, sd_json_variant
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
r = varlink_idl_validate_field_element_type(field, v);
|
r = varlink_idl_validate_field_element_type(field, v);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -1462,6 +1610,7 @@ static int varlink_idl_validate_symbol(const VarlinkSymbol *symbol, sd_json_vari
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(symbol);
|
assert(symbol);
|
||||||
|
assert(!IN_SET(symbol->symbol_type, _VARLINK_SYMBOL_COMMENT, _VARLINK_INTERFACE_COMMENT));
|
||||||
|
|
||||||
if (!v) {
|
if (!v) {
|
||||||
if (bad_field)
|
if (bad_field)
|
||||||
|
@ -1537,6 +1686,10 @@ static int varlink_idl_validate_symbol(const VarlinkSymbol *symbol, sd_json_vari
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case _VARLINK_SYMBOL_COMMENT:
|
||||||
|
case _VARLINK_INTERFACE_COMMENT:
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -1579,6 +1732,7 @@ const VarlinkSymbol* varlink_idl_find_symbol(
|
||||||
|
|
||||||
assert(interface);
|
assert(interface);
|
||||||
assert(type < _VARLINK_SYMBOL_TYPE_MAX);
|
assert(type < _VARLINK_SYMBOL_TYPE_MAX);
|
||||||
|
assert(!IN_SET(type, _VARLINK_SYMBOL_COMMENT, _VARLINK_INTERFACE_COMMENT));
|
||||||
|
|
||||||
if (isempty(name))
|
if (isempty(name))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1603,9 +1757,13 @@ const VarlinkField* varlink_idl_find_field(
|
||||||
if (isempty(name))
|
if (isempty(name))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (const VarlinkField *field = symbol->fields; field->field_type != _VARLINK_FIELD_TYPE_END_MARKER; field++)
|
for (const VarlinkField *field = symbol->fields; field->field_type != _VARLINK_FIELD_TYPE_END_MARKER; field++) {
|
||||||
|
if (field->field_type == _VARLINK_FIELD_COMMENT)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (streq_ptr(field->name, name))
|
if (streq_ptr(field->name, name))
|
||||||
return field;
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ typedef enum VarlinkSymbolType {
|
||||||
VARLINK_STRUCT_TYPE,
|
VARLINK_STRUCT_TYPE,
|
||||||
VARLINK_METHOD,
|
VARLINK_METHOD,
|
||||||
VARLINK_ERROR,
|
VARLINK_ERROR,
|
||||||
|
_VARLINK_INTERFACE_COMMENT, /* Not really a symbol, just a comment about the interface */
|
||||||
|
_VARLINK_SYMBOL_COMMENT, /* Not really a symbol, just a comment about a symbol */
|
||||||
_VARLINK_SYMBOL_TYPE_MAX,
|
_VARLINK_SYMBOL_TYPE_MAX,
|
||||||
_VARLINK_SYMBOL_TYPE_INVALID = -EINVAL,
|
_VARLINK_SYMBOL_TYPE_INVALID = -EINVAL,
|
||||||
} VarlinkSymbolType;
|
} VarlinkSymbolType;
|
||||||
|
@ -35,6 +37,7 @@ typedef enum VarlinkFieldType {
|
||||||
VARLINK_STRING,
|
VARLINK_STRING,
|
||||||
VARLINK_OBJECT,
|
VARLINK_OBJECT,
|
||||||
VARLINK_ENUM_VALUE,
|
VARLINK_ENUM_VALUE,
|
||||||
|
_VARLINK_FIELD_COMMENT, /* Not really a field, just a comment about a field*/
|
||||||
_VARLINK_FIELD_TYPE_MAX,
|
_VARLINK_FIELD_TYPE_MAX,
|
||||||
_VARLINK_FIELD_TYPE_INVALID = -EINVAL,
|
_VARLINK_FIELD_TYPE_INVALID = -EINVAL,
|
||||||
} VarlinkFieldType;
|
} VarlinkFieldType;
|
||||||
|
@ -103,6 +106,9 @@ struct VarlinkInterface {
|
||||||
#define VARLINK_DEFINE_ENUM_VALUE(_name) \
|
#define VARLINK_DEFINE_ENUM_VALUE(_name) \
|
||||||
{ .name = #_name, .field_type = VARLINK_ENUM_VALUE }
|
{ .name = #_name, .field_type = VARLINK_ENUM_VALUE }
|
||||||
|
|
||||||
|
#define VARLINK_FIELD_COMMENT(text) \
|
||||||
|
{ .name = "" text, .field_type = _VARLINK_FIELD_COMMENT }
|
||||||
|
|
||||||
#define VARLINK_DEFINE_METHOD(_name, ...) \
|
#define VARLINK_DEFINE_METHOD(_name, ...) \
|
||||||
const VarlinkSymbol vl_method_ ## _name = { \
|
const VarlinkSymbol vl_method_ ## _name = { \
|
||||||
.name = #_name, \
|
.name = #_name, \
|
||||||
|
@ -137,8 +143,24 @@ struct VarlinkInterface {
|
||||||
.symbols = { __VA_ARGS__ __VA_OPT__(,) NULL}, \
|
.symbols = { __VA_ARGS__ __VA_OPT__(,) NULL}, \
|
||||||
}
|
}
|
||||||
|
|
||||||
int varlink_idl_dump(FILE *f, int use_colors, const VarlinkInterface *interface);
|
#define VARLINK_SYMBOL_COMMENT(text) \
|
||||||
int varlink_idl_format(const VarlinkInterface *interface, char **ret);
|
&(const VarlinkSymbol) { \
|
||||||
|
.name = "" text, \
|
||||||
|
.symbol_type = _VARLINK_SYMBOL_COMMENT, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VARLINK_INTERFACE_COMMENT(text) \
|
||||||
|
&(const VarlinkSymbol) { \
|
||||||
|
.name = "" text, \
|
||||||
|
.symbol_type = _VARLINK_INTERFACE_COMMENT, \
|
||||||
|
}
|
||||||
|
|
||||||
|
int varlink_idl_dump(FILE *f, int use_colors, size_t cols, const VarlinkInterface *interface);
|
||||||
|
int varlink_idl_format_full(const VarlinkInterface *interface, size_t cols, char **ret);
|
||||||
|
|
||||||
|
static inline int varlink_idl_format(const VarlinkInterface *interface, char **ret) {
|
||||||
|
return varlink_idl_format_full(interface, SIZE_MAX, ret);
|
||||||
|
}
|
||||||
|
|
||||||
int varlink_idl_parse(const char *text, unsigned *ret_line, unsigned *ret_column, VarlinkInterface **ret);
|
int varlink_idl_parse(const char *text, unsigned *ret_line, unsigned *ret_column, VarlinkInterface **ret);
|
||||||
VarlinkInterface* varlink_interface_free(VarlinkInterface *interface);
|
VarlinkInterface* varlink_interface_free(VarlinkInterface *interface);
|
||||||
|
|
|
@ -117,7 +117,7 @@ static void test_parse_format_one(const VarlinkInterface *iface) {
|
||||||
|
|
||||||
assert_se(iface);
|
assert_se(iface);
|
||||||
|
|
||||||
assert_se(varlink_idl_dump(stdout, /* use_colors=*/ true, iface) >= 0);
|
assert_se(varlink_idl_dump(stdout, /* use_colors=*/ true, /* cols= */ SIZE_MAX, iface) >= 0);
|
||||||
assert_se(varlink_idl_consistent(iface, LOG_ERR) >= 0);
|
assert_se(varlink_idl_consistent(iface, LOG_ERR) >= 0);
|
||||||
assert_se(varlink_idl_format(iface, &text) >= 0);
|
assert_se(varlink_idl_format(iface, &text) >= 0);
|
||||||
assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
|
assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0);
|
||||||
|
|
|
@ -392,7 +392,7 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pager_open(arg_pager_flags);
|
pager_open(arg_pager_flags);
|
||||||
r = varlink_idl_dump(stdout, /* use_colors= */ -1, vi);
|
r = varlink_idl_dump(stdout, /* use_colors= */ -1, on_tty() ? columns() : SIZE_MAX, vi);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to format parsed interface description: %m");
|
return log_error_errno(r, "Failed to format parsed interface description: %m");
|
||||||
}
|
}
|
||||||
|
@ -628,7 +628,7 @@ static int verb_validate_idl(int argc, char *argv[], void *userdata) {
|
||||||
|
|
||||||
pager_open(arg_pager_flags);
|
pager_open(arg_pager_flags);
|
||||||
|
|
||||||
r = varlink_idl_dump(stdout, /* use_colors= */ -1, vi);
|
r = varlink_idl_dump(stdout, /* use_colors= */ -1, on_tty() ? columns() : SIZE_MAX, vi);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to format parsed interface description: %m");
|
return log_error_errno(r, "Failed to format parsed interface description: %m");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue