expr: move op_type/value_type_to_string functions to ast
Generally the enum-to-string function should appear where the enum is defined. Signed-off-by: Ran Benita <ran234@gmail.com>master
parent
b9c87eb710
commit
d3ddcf70e8
|
@ -1248,7 +1248,7 @@ HandleActionDef(ExprDef * def,
|
||||||
|
|
||||||
if (def->op != EXPR_ACTION_DECL) {
|
if (def->op != EXPR_ACTION_DECL) {
|
||||||
log_err(keymap->ctx, "Expected an action definition, found %s\n",
|
log_err(keymap->ctx, "Expected an action definition, found %s\n",
|
||||||
exprOpText(def->op));
|
expr_op_type_to_string(def->op));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
str = xkb_atom_text(keymap->ctx, def->value.action.name);
|
str = xkb_atom_text(keymap->ctx, def->value.action.name);
|
||||||
|
|
|
@ -651,7 +651,7 @@ FreeXkbFile(XkbFile *file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *stmt_type_strings[_STMT_NUM_VALUES] = {
|
static const char *stmt_type_strings[_STMT_NUM_VALUES] = {
|
||||||
[STMT_UNKNOWN] = "unknown statement",
|
[STMT_UNKNOWN] = "unknown statement",
|
||||||
[STMT_INCLUDE] = "include statement",
|
[STMT_INCLUDE] = "include statement",
|
||||||
[STMT_KEYCODE] = "key name definition",
|
[STMT_KEYCODE] = "key name definition",
|
||||||
|
@ -669,9 +669,54 @@ const char *stmt_type_strings[_STMT_NUM_VALUES] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
StmtTypeToString(enum stmt_type type)
|
stmt_type_to_string(enum stmt_type type)
|
||||||
{
|
{
|
||||||
if (type >= _STMT_NUM_VALUES)
|
if (type >= _STMT_NUM_VALUES)
|
||||||
type = STMT_UNKNOWN;
|
return NULL;
|
||||||
return stmt_type_strings[type];
|
return stmt_type_strings[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *expr_op_type_strings[_EXPR_NUM_VALUES] = {
|
||||||
|
[EXPR_VALUE] = "literal",
|
||||||
|
[EXPR_IDENT] = "identifier",
|
||||||
|
[EXPR_ACTION_DECL] = "action declaration",
|
||||||
|
[EXPR_FIELD_REF] = "field reference",
|
||||||
|
[EXPR_ARRAY_REF] = "array reference",
|
||||||
|
[EXPR_KEYSYM_LIST] = "list of keysyms",
|
||||||
|
[EXPR_ACTION_LIST] = "list of actions",
|
||||||
|
[EXPR_ADD] = "addition",
|
||||||
|
[EXPR_SUBTRACT] = "subtraction",
|
||||||
|
[EXPR_MULTIPLY] = "multiplication",
|
||||||
|
[EXPR_DIVIDE] = "division",
|
||||||
|
[EXPR_ASSIGN] = "assignment",
|
||||||
|
[EXPR_NOT] = "logical negation",
|
||||||
|
[EXPR_NEGATE] = "arithmetic negation",
|
||||||
|
[EXPR_INVERT] = "bitwise inversion",
|
||||||
|
[EXPR_UNARY_PLUS] = "unary plus",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
expr_op_type_to_string(enum expr_op_type type)
|
||||||
|
{
|
||||||
|
if (type >= _EXPR_NUM_VALUES)
|
||||||
|
return NULL;
|
||||||
|
return expr_op_type_strings[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *expr_value_type_strings[_EXPR_TYPE_NUM_VALUES] = {
|
||||||
|
[EXPR_TYPE_UNKNOWN] = "unknown",
|
||||||
|
[EXPR_TYPE_BOOLEAN] = "boolean",
|
||||||
|
[EXPR_TYPE_INT] = "int",
|
||||||
|
[EXPR_TYPE_STRING] = "string",
|
||||||
|
[EXPR_TYPE_ACTION] = "action",
|
||||||
|
[EXPR_TYPE_KEYNAME] = "keyname",
|
||||||
|
[EXPR_TYPE_SYMBOLS] = "symbols",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
expr_value_type_to_string(enum expr_value_type type)
|
||||||
|
{
|
||||||
|
if (type >= _EXPR_TYPE_NUM_VALUES)
|
||||||
|
return NULL;
|
||||||
|
return expr_value_type_strings[type];
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ enum stmt_type {
|
||||||
STMT_GROUP_COMPAT,
|
STMT_GROUP_COMPAT,
|
||||||
STMT_INDICATOR_MAP,
|
STMT_INDICATOR_MAP,
|
||||||
STMT_INDICATOR_NAME,
|
STMT_INDICATOR_NAME,
|
||||||
|
|
||||||
_STMT_NUM_VALUES
|
_STMT_NUM_VALUES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,10 +54,12 @@ enum expr_value_type {
|
||||||
EXPR_TYPE_ACTION,
|
EXPR_TYPE_ACTION,
|
||||||
EXPR_TYPE_KEYNAME,
|
EXPR_TYPE_KEYNAME,
|
||||||
EXPR_TYPE_SYMBOLS,
|
EXPR_TYPE_SYMBOLS,
|
||||||
|
|
||||||
|
_EXPR_TYPE_NUM_VALUES
|
||||||
};
|
};
|
||||||
|
|
||||||
enum expr_op_type {
|
enum expr_op_type {
|
||||||
EXPR_VALUE = 0,
|
EXPR_VALUE,
|
||||||
EXPR_IDENT,
|
EXPR_IDENT,
|
||||||
EXPR_ACTION_DECL,
|
EXPR_ACTION_DECL,
|
||||||
EXPR_FIELD_REF,
|
EXPR_FIELD_REF,
|
||||||
|
@ -72,6 +75,8 @@ enum expr_op_type {
|
||||||
EXPR_NEGATE,
|
EXPR_NEGATE,
|
||||||
EXPR_INVERT,
|
EXPR_INVERT,
|
||||||
EXPR_UNARY_PLUS,
|
EXPR_UNARY_PLUS,
|
||||||
|
|
||||||
|
_EXPR_NUM_VALUES
|
||||||
};
|
};
|
||||||
|
|
||||||
enum merge_mode {
|
enum merge_mode {
|
||||||
|
@ -81,6 +86,15 @@ enum merge_mode {
|
||||||
MERGE_REPLACE,
|
MERGE_REPLACE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
stmt_type_to_string(enum stmt_type type);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
expr_op_type_to_string(enum expr_op_type type);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
expr_value_type_to_string(enum expr_value_type type);
|
||||||
|
|
||||||
typedef struct _ParseCommon {
|
typedef struct _ParseCommon {
|
||||||
enum stmt_type type;
|
enum stmt_type type;
|
||||||
struct _ParseCommon *next;
|
struct _ParseCommon *next;
|
||||||
|
|
|
@ -975,7 +975,7 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge)
|
||||||
default:
|
default:
|
||||||
log_err(info->keymap->ctx,
|
log_err(info->keymap->ctx,
|
||||||
"Interpretation files may not include other types; "
|
"Interpretation files may not include other types; "
|
||||||
"Ignoring %s\n", StmtTypeToString(stmt->type));
|
"Ignoring %s\n", stmt_type_to_string(stmt->type));
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,98 +32,6 @@ typedef bool (*IdentLookupFunc)(struct xkb_context *ctx, const void *priv,
|
||||||
xkb_atom_t field, enum expr_value_type type,
|
xkb_atom_t field, enum expr_value_type type,
|
||||||
unsigned int *val_rtrn);
|
unsigned int *val_rtrn);
|
||||||
|
|
||||||
const char *
|
|
||||||
exprOpText(enum expr_op_type op)
|
|
||||||
{
|
|
||||||
static char buf[32];
|
|
||||||
|
|
||||||
switch (op) {
|
|
||||||
case EXPR_VALUE:
|
|
||||||
strcpy(buf, "literal");
|
|
||||||
break;
|
|
||||||
case EXPR_IDENT:
|
|
||||||
strcpy(buf, "identifier");
|
|
||||||
break;
|
|
||||||
case EXPR_ACTION_DECL:
|
|
||||||
strcpy(buf, "action declaration");
|
|
||||||
break;
|
|
||||||
case EXPR_FIELD_REF:
|
|
||||||
strcpy(buf, "field reference");
|
|
||||||
break;
|
|
||||||
case EXPR_ARRAY_REF:
|
|
||||||
strcpy(buf, "array reference");
|
|
||||||
break;
|
|
||||||
case EXPR_KEYSYM_LIST:
|
|
||||||
strcpy(buf, "list of keysyms");
|
|
||||||
break;
|
|
||||||
case EXPR_ACTION_LIST:
|
|
||||||
strcpy(buf, "list of actions");
|
|
||||||
break;
|
|
||||||
case EXPR_ADD:
|
|
||||||
strcpy(buf, "addition");
|
|
||||||
break;
|
|
||||||
case EXPR_SUBTRACT:
|
|
||||||
strcpy(buf, "subtraction");
|
|
||||||
break;
|
|
||||||
case EXPR_MULTIPLY:
|
|
||||||
strcpy(buf, "multiplication");
|
|
||||||
break;
|
|
||||||
case EXPR_DIVIDE:
|
|
||||||
strcpy(buf, "division");
|
|
||||||
break;
|
|
||||||
case EXPR_ASSIGN:
|
|
||||||
strcpy(buf, "assignment");
|
|
||||||
break;
|
|
||||||
case EXPR_NOT:
|
|
||||||
strcpy(buf, "logical not");
|
|
||||||
break;
|
|
||||||
case EXPR_NEGATE:
|
|
||||||
strcpy(buf, "arithmetic negation");
|
|
||||||
break;
|
|
||||||
case EXPR_INVERT:
|
|
||||||
strcpy(buf, "bitwise inversion");
|
|
||||||
break;
|
|
||||||
case EXPR_UNARY_PLUS:
|
|
||||||
strcpy(buf, "unary plus");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
snprintf(buf, sizeof(buf), "illegal(%d)", op);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
exprValueTypeText(enum expr_value_type type)
|
|
||||||
{
|
|
||||||
static char buf[20];
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case EXPR_TYPE_UNKNOWN:
|
|
||||||
strcpy(buf, "unknown");
|
|
||||||
break;
|
|
||||||
case EXPR_TYPE_BOOLEAN:
|
|
||||||
strcpy(buf, "boolean");
|
|
||||||
break;
|
|
||||||
case EXPR_TYPE_INT:
|
|
||||||
strcpy(buf, "int");
|
|
||||||
break;
|
|
||||||
case EXPR_TYPE_STRING:
|
|
||||||
strcpy(buf, "string");
|
|
||||||
break;
|
|
||||||
case EXPR_TYPE_ACTION:
|
|
||||||
strcpy(buf, "action");
|
|
||||||
break;
|
|
||||||
case EXPR_TYPE_KEYNAME:
|
|
||||||
strcpy(buf, "keyname");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
snprintf(buf, sizeof(buf), "illegal(%d)", type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
|
ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
const char **elem_rtrn, const char **field_rtrn,
|
const char **elem_rtrn, const char **field_rtrn,
|
||||||
|
@ -224,7 +132,7 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
if (expr->value_type != EXPR_TYPE_BOOLEAN) {
|
if (expr->value_type != EXPR_TYPE_BOOLEAN) {
|
||||||
log_err(ctx,
|
log_err(ctx,
|
||||||
"Found constant of type %s where boolean was expected\n",
|
"Found constant of type %s where boolean was expected\n",
|
||||||
exprValueTypeText(expr->value_type));
|
expr_value_type_to_string(expr->value_type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*set_rtrn = !!expr->value.ival;
|
*set_rtrn = !!expr->value.ival;
|
||||||
|
@ -270,7 +178,7 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
case EXPR_NEGATE:
|
case EXPR_NEGATE:
|
||||||
case EXPR_UNARY_PLUS:
|
case EXPR_UNARY_PLUS:
|
||||||
log_err(ctx, "%s of boolean values not permitted\n",
|
log_err(ctx, "%s of boolean values not permitted\n",
|
||||||
exprOpText(expr->op));
|
expr_op_type_to_string(expr->op));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -293,7 +201,7 @@ ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
if (expr->value_type != EXPR_TYPE_INT) {
|
if (expr->value_type != EXPR_TYPE_INT) {
|
||||||
log_err(ctx,
|
log_err(ctx,
|
||||||
"Found constant of type %s where an int was expected\n",
|
"Found constant of type %s where an int was expected\n",
|
||||||
exprValueTypeText(expr->value_type));
|
expr_value_type_to_string(expr->value_type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +289,7 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
if (expr->value_type != EXPR_TYPE_INT) {
|
if (expr->value_type != EXPR_TYPE_INT) {
|
||||||
log_err(ctx,
|
log_err(ctx,
|
||||||
"Found constant of type %s where an int was expected\n",
|
"Found constant of type %s where an int was expected\n",
|
||||||
exprValueTypeText(expr->value_type));
|
expr_value_type_to_string(expr->value_type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,7 +481,7 @@ ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
case EXPR_VALUE:
|
case EXPR_VALUE:
|
||||||
if (expr->value_type != EXPR_TYPE_STRING) {
|
if (expr->value_type != EXPR_TYPE_STRING) {
|
||||||
log_err(ctx, "Found constant of type %s, expected a string\n",
|
log_err(ctx, "Found constant of type %s, expected a string\n",
|
||||||
exprValueTypeText(expr->value_type));
|
expr_value_type_to_string(expr->value_type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,7 +508,8 @@ ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
case EXPR_INVERT:
|
case EXPR_INVERT:
|
||||||
case EXPR_NOT:
|
case EXPR_NOT:
|
||||||
case EXPR_UNARY_PLUS:
|
case EXPR_UNARY_PLUS:
|
||||||
log_err(ctx, "%s of strings not permitted\n", exprOpText(expr->op));
|
log_err(ctx, "%s of strings not permitted\n",
|
||||||
|
expr_op_type_to_string(expr->op));
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -618,7 +527,7 @@ ExprResolveKeyName(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
case EXPR_VALUE:
|
case EXPR_VALUE:
|
||||||
if (expr->value_type != EXPR_TYPE_KEYNAME) {
|
if (expr->value_type != EXPR_TYPE_KEYNAME) {
|
||||||
log_err(ctx, "Found constant of type %s, expected a key name\n",
|
log_err(ctx, "Found constant of type %s, expected a key name\n",
|
||||||
exprValueTypeText(expr->value_type));
|
expr_value_type_to_string(expr->value_type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
strncpy(name, expr->value.keyName, XkbKeyNameLength);
|
strncpy(name, expr->value.keyName, XkbKeyNameLength);
|
||||||
|
@ -645,7 +554,7 @@ ExprResolveKeyName(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
case EXPR_NOT:
|
case EXPR_NOT:
|
||||||
case EXPR_UNARY_PLUS:
|
case EXPR_UNARY_PLUS:
|
||||||
log_err(ctx, "%s of key name values not permitted\n",
|
log_err(ctx, "%s of key name values not permitted\n",
|
||||||
exprOpText(expr->op));
|
expr_op_type_to_string(expr->op));
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -661,7 +570,7 @@ ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
{
|
{
|
||||||
if (expr->op != EXPR_IDENT) {
|
if (expr->op != EXPR_IDENT) {
|
||||||
log_err(ctx, "Found a %s where an enumerated value was expected\n",
|
log_err(ctx, "Found a %s where an enumerated value was expected\n",
|
||||||
exprOpText(expr->op));
|
expr_op_type_to_string(expr->op));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,7 +605,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
if (expr->value_type != EXPR_TYPE_INT) {
|
if (expr->value_type != EXPR_TYPE_INT) {
|
||||||
log_err(ctx,
|
log_err(ctx,
|
||||||
"Found constant of type %s where a mask was expected\n",
|
"Found constant of type %s where a mask was expected\n",
|
||||||
exprValueTypeText(expr->value_type));
|
expr_value_type_to_string(expr->value_type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*val_rtrn = (unsigned int) expr->value.ival;
|
*val_rtrn = (unsigned int) expr->value.ival;
|
||||||
|
|
|
@ -32,9 +32,6 @@ typedef struct _LookupEntry {
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
} LookupEntry;
|
} LookupEntry;
|
||||||
|
|
||||||
const char *
|
|
||||||
exprOpText(enum expr_op_type op);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
|
ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
|
||||||
const char **elem_rtrn, const char **field_rtrn,
|
const char **elem_rtrn, const char **field_rtrn,
|
||||||
|
|
|
@ -844,7 +844,7 @@ HandleKeycodesFile(KeyNamesInfo *info, XkbFile *file, enum merge_mode merge)
|
||||||
default:
|
default:
|
||||||
log_err(info->ctx,
|
log_err(info->ctx,
|
||||||
"Keycode files may define key and indicator names only; "
|
"Keycode files may define key and indicator names only; "
|
||||||
"Ignoring %s\n", StmtTypeToString(stmt->type));
|
"Ignoring %s\n", stmt_type_to_string(stmt->type));
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -874,7 +874,8 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
|
||||||
log_err(info->keymap->ctx,
|
log_err(info->keymap->ctx,
|
||||||
"Expected a list of symbols, found %s; "
|
"Expected a list of symbols, found %s; "
|
||||||
"Ignoring symbols for group %u of %s\n",
|
"Ignoring symbols for group %u of %s\n",
|
||||||
exprOpText(value->op), ndx + 1, LongKeyNameText(keyi->name));
|
expr_op_type_to_string(value->op), ndx + 1,
|
||||||
|
LongKeyNameText(keyi->name));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!darray_empty(keyi->syms[ndx])) {
|
if (!darray_empty(keyi->syms[ndx])) {
|
||||||
|
@ -1072,7 +1073,8 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
|
||||||
log_err(info->keymap->ctx,
|
log_err(info->keymap->ctx,
|
||||||
"Expected a virtual modifier mask, found %s; "
|
"Expected a virtual modifier mask, found %s; "
|
||||||
"Ignoring virtual modifiers definition for key %s\n",
|
"Ignoring virtual modifiers definition for key %s\n",
|
||||||
exprOpText(value->op), LongKeyNameText(keyi->name));
|
expr_op_type_to_string(value->op),
|
||||||
|
LongKeyNameText(keyi->name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (istreq(field, "locking") ||
|
else if (istreq(field, "locking") ||
|
||||||
|
@ -1434,7 +1436,7 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
|
||||||
default:
|
default:
|
||||||
log_err(info->keymap->ctx,
|
log_err(info->keymap->ctx,
|
||||||
"Interpretation files may not include other types; "
|
"Interpretation files may not include other types; "
|
||||||
"Ignoring %s\n", StmtTypeToString(stmt->type));
|
"Ignoring %s\n", stmt_type_to_string(stmt->type));
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -831,7 +831,7 @@ HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
|
||||||
default:
|
default:
|
||||||
log_err(info->keymap->ctx,
|
log_err(info->keymap->ctx,
|
||||||
"Key type files may not include other declarations; "
|
"Key type files may not include other declarations; "
|
||||||
"Ignoring %s\n", StmtTypeToString(stmt->type));
|
"Ignoring %s\n", stmt_type_to_string(stmt->type));
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,9 +67,6 @@ UpdateModifiersFromCompat(struct xkb_keymap *keymap);
|
||||||
bool
|
bool
|
||||||
LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn);
|
LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn);
|
||||||
|
|
||||||
const char *
|
|
||||||
StmtTypeToString(enum stmt_type type);
|
|
||||||
|
|
||||||
/***====================================================================***/
|
/***====================================================================***/
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
|
|
Loading…
Reference in New Issue