mirror of https://github.com/nirenjan/libx52.git
feat(libx52io): Add _from_str and from_str_nocase APIs
This change add APIs to convert the string forms of the axis and button names back to their corresponding enum identifiers. This is effectively built such that a roundtrip of _to_str and _from_str will return the same input. The _nocase variants handle case insensitive matching of the names by folding of the ASCII alphabets A-Z and a-z only, so it doesn't depend on localization.profile-support
parent
a3d9708d1e
commit
d8cc745d2d
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "libx52io.h"
|
||||
#include "gettext.h"
|
||||
|
||||
|
|
@ -16,6 +17,28 @@
|
|||
* on one to the enumeration definitions.
|
||||
*/
|
||||
|
||||
/* Locale-independent: only ASCII A–Z fold with a–z; digits and underscore unchanged */
|
||||
static int x52io_ascii_strcasecmp(const char *a, const char *b)
|
||||
{
|
||||
for (;;) {
|
||||
unsigned char ca = (unsigned char)*a++;
|
||||
unsigned char cb = (unsigned char)*b++;
|
||||
|
||||
if (ca >= 'A' && ca <= 'Z') {
|
||||
ca = (unsigned char)(ca - 'A' + 'a');
|
||||
}
|
||||
if (cb >= 'A' && cb <= 'Z') {
|
||||
cb = (unsigned char)(cb - 'A' + 'a');
|
||||
}
|
||||
if (ca != cb) {
|
||||
return (int)ca - (int)cb;
|
||||
}
|
||||
if (ca == '\0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* String mapping for axis */
|
||||
static const char * _x52io_axis_str[LIBX52IO_AXIS_MAX] = {
|
||||
[LIBX52IO_AXIS_X] = "ABS_X",
|
||||
|
|
@ -92,6 +115,78 @@ const char * libx52io_button_to_str(libx52io_button button)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int libx52io_axis_from_str(const char *str, libx52io_axis *axis)
|
||||
{
|
||||
libx52io_axis i;
|
||||
|
||||
if (!str || !axis) {
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
for (i = LIBX52IO_AXIS_X; i < LIBX52IO_AXIS_MAX; i++) {
|
||||
if (strcmp(str, _x52io_axis_str[i]) == 0) {
|
||||
*axis = i;
|
||||
return LIBX52IO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
int libx52io_button_from_str(const char *str, libx52io_button *button)
|
||||
{
|
||||
libx52io_button b;
|
||||
|
||||
if (!str || !button) {
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
for (b = LIBX52IO_BTN_TRIGGER; b < LIBX52IO_BUTTON_MAX; b++) {
|
||||
if (strcmp(str, _x52io_button_str[b]) == 0) {
|
||||
*button = b;
|
||||
return LIBX52IO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
int libx52io_axis_from_str_nocase(const char *str, libx52io_axis *axis)
|
||||
{
|
||||
libx52io_axis i;
|
||||
|
||||
if (!str || !axis) {
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
for (i = LIBX52IO_AXIS_X; i < LIBX52IO_AXIS_MAX; i++) {
|
||||
if (x52io_ascii_strcasecmp(str, _x52io_axis_str[i]) == 0) {
|
||||
*axis = i;
|
||||
return LIBX52IO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
int libx52io_button_from_str_nocase(const char *str, libx52io_button *button)
|
||||
{
|
||||
libx52io_button b;
|
||||
|
||||
if (!str || !button) {
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
for (b = LIBX52IO_BTN_TRIGGER; b < LIBX52IO_BUTTON_MAX; b++) {
|
||||
if (x52io_ascii_strcasecmp(str, _x52io_button_str[b]) == 0) {
|
||||
*button = b;
|
||||
return LIBX52IO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
/* Error buffer used for building custom error strings */
|
||||
static char error_buffer[256];
|
||||
|
||||
|
|
|
|||
|
|
@ -434,6 +434,62 @@ LIBX52IO_API const char *libx52io_axis_to_str(libx52io_axis axis);
|
|||
*/
|
||||
LIBX52IO_API const char *libx52io_button_to_str(libx52io_button button);
|
||||
|
||||
/**
|
||||
* @brief Parse the string representation of an axis.
|
||||
*
|
||||
* Accepts tokens as returned by \ref libx52io_axis_to_str (e.g. \c ABS_X).
|
||||
*
|
||||
* @param[in] str NUL-terminated axis name
|
||||
* @param[out] axis Receives the axis ID on success
|
||||
*
|
||||
* @returns \ref LIBX52IO_SUCCESS if \a str was recognized,
|
||||
* \ref LIBX52IO_ERROR_INVALID if \a str or \a axis is NULL or \a str is unknown.
|
||||
*/
|
||||
LIBX52IO_API int libx52io_axis_from_str(const char *str, libx52io_axis *axis);
|
||||
|
||||
/**
|
||||
* @brief Parse the string representation of a button.
|
||||
*
|
||||
* Accepts tokens as returned by \ref libx52io_button_to_str (e.g. \c BTN_FIRE).
|
||||
*
|
||||
* @param[in] str NUL-terminated button name
|
||||
* @param[out] button Receives the button ID on success
|
||||
*
|
||||
* @returns \ref LIBX52IO_SUCCESS if \a str was recognized,
|
||||
* \ref LIBX52IO_ERROR_INVALID if \a str or \a button is NULL or \a str is unknown.
|
||||
*/
|
||||
LIBX52IO_API int libx52io_button_from_str(const char *str, libx52io_button *button);
|
||||
|
||||
/**
|
||||
* @brief Parse an axis name with ASCII case-insensitive matching.
|
||||
*
|
||||
* Like \ref libx52io_axis_from_str, but treats ASCII letters \c A– \c Z the same
|
||||
* as \c a– \c z. Digits, underscore, and NUL must match exactly. Matching is
|
||||
* not locale-dependent.
|
||||
*
|
||||
* @param[in] str NUL-terminated axis name
|
||||
* @param[out] axis Receives the axis ID on success
|
||||
*
|
||||
* @returns \ref LIBX52IO_SUCCESS if \a str was recognized,
|
||||
* \ref LIBX52IO_ERROR_INVALID if \a str or \a axis is NULL or \a str is unknown.
|
||||
*/
|
||||
LIBX52IO_API int libx52io_axis_from_str_nocase(const char *str, libx52io_axis *axis);
|
||||
|
||||
/**
|
||||
* @brief Parse a button name with ASCII case-insensitive matching.
|
||||
*
|
||||
* Like \ref libx52io_button_from_str, but treats ASCII letters \c A– \c Z the same
|
||||
* as \c a– \c z. Digits, underscore, and NUL must match exactly. Matching is
|
||||
* not locale-dependent.
|
||||
*
|
||||
* @param[in] str NUL-terminated button name
|
||||
* @param[out] button Receives the button ID on success
|
||||
*
|
||||
* @returns \ref LIBX52IO_SUCCESS if \a str was recognized,
|
||||
* \ref LIBX52IO_ERROR_INVALID if \a str or \a button is NULL or \a str is unknown.
|
||||
*/
|
||||
LIBX52IO_API int libx52io_button_from_str_nocase(const char *str, libx52io_button *button);
|
||||
|
||||
/**
|
||||
* @brief Get the vendor ID of the connected X52 device.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
libx52io_version = '1.0.0'
|
||||
libx52io_version = '1.1.0'
|
||||
|
||||
libx52io_files = files(
|
||||
'io_core.c',
|
||||
|
|
@ -37,4 +37,11 @@ test_parser = executable('test-parser', 'test_parser.c', libx52io_files,
|
|||
)
|
||||
test('test-parser', test_parser, protocol: 'tap')
|
||||
|
||||
test_io_strings = executable('test-io-strings', 'test_io_strings.c', libx52io_files,
|
||||
build_by_default: false,
|
||||
dependencies: [dep_cmocka, dep_hidapi, dep_intl],
|
||||
include_directories: [includes],
|
||||
)
|
||||
test('test-io-strings', test_io_strings, protocol: 'tap')
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Saitek X52 IO driver - io string parse tests
|
||||
*
|
||||
* Copyright (C) 2012-2020 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
|
||||
#include "libx52io.h"
|
||||
|
||||
static void lower_ascii_only(char *dst, const char *src)
|
||||
{
|
||||
for (; *src; src++, dst++) {
|
||||
unsigned char c = (unsigned char)*src;
|
||||
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
c = (unsigned char)(c - 'A' + 'a');
|
||||
}
|
||||
*dst = (char)c;
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
static void test_axis_round_trip(void **state)
|
||||
{
|
||||
libx52io_axis a;
|
||||
libx52io_axis out;
|
||||
|
||||
(void)state;
|
||||
|
||||
for (a = LIBX52IO_AXIS_X; a < LIBX52IO_AXIS_MAX; a++) {
|
||||
const char *s = libx52io_axis_to_str(a);
|
||||
|
||||
assert_non_null(s);
|
||||
assert_int_equal(LIBX52IO_SUCCESS, libx52io_axis_from_str(s, &out));
|
||||
assert_int_equal(a, out);
|
||||
assert_ptr_equal(s, libx52io_axis_to_str(out));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_button_round_trip(void **state)
|
||||
{
|
||||
libx52io_button b;
|
||||
libx52io_button out;
|
||||
|
||||
(void)state;
|
||||
|
||||
for (b = LIBX52IO_BTN_TRIGGER; b < LIBX52IO_BUTTON_MAX; b++) {
|
||||
const char *s = libx52io_button_to_str(b);
|
||||
|
||||
assert_non_null(s);
|
||||
assert_int_equal(LIBX52IO_SUCCESS, libx52io_button_from_str(s, &out));
|
||||
assert_int_equal(b, out);
|
||||
assert_ptr_equal(s, libx52io_button_to_str(out));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_axis_from_str_invalid(void **state)
|
||||
{
|
||||
libx52io_axis out;
|
||||
|
||||
(void)state;
|
||||
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str("", &out));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str("ABS_", &out));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str("ABS_XX", &out));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str("abs_x", &out));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str("BTN_FIRE", &out));
|
||||
}
|
||||
|
||||
static void test_button_from_str_invalid(void **state)
|
||||
{
|
||||
libx52io_button out;
|
||||
|
||||
(void)state;
|
||||
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str("", &out));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str("BTN_", &out));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID,
|
||||
libx52io_button_from_str("BTN_FIRE_EXTRA", &out));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str("btn_fire", &out));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str("ABS_X", &out));
|
||||
}
|
||||
|
||||
static void test_from_str_null_args(void **state)
|
||||
{
|
||||
libx52io_axis ax;
|
||||
libx52io_button btn;
|
||||
|
||||
(void)state;
|
||||
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str(NULL, &ax));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str("ABS_X", NULL));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str(NULL, &btn));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str("BTN_A", NULL));
|
||||
}
|
||||
|
||||
static void test_axis_from_str_nocase(void **state)
|
||||
{
|
||||
libx52io_axis a;
|
||||
libx52io_axis out;
|
||||
char buf[64];
|
||||
|
||||
(void)state;
|
||||
|
||||
for (a = LIBX52IO_AXIS_X; a < LIBX52IO_AXIS_MAX; a++) {
|
||||
const char *s = libx52io_axis_to_str(a);
|
||||
|
||||
assert_non_null(s);
|
||||
lower_ascii_only(buf, s);
|
||||
assert_int_equal(LIBX52IO_SUCCESS, libx52io_axis_from_str_nocase(buf, &out));
|
||||
assert_int_equal(a, out);
|
||||
}
|
||||
|
||||
assert_int_equal(LIBX52IO_SUCCESS,
|
||||
libx52io_axis_from_str_nocase("aBs_hAtX", &out));
|
||||
assert_int_equal(LIBX52IO_AXIS_HATX, out);
|
||||
}
|
||||
|
||||
static void test_button_from_str_nocase(void **state)
|
||||
{
|
||||
libx52io_button b;
|
||||
libx52io_button out;
|
||||
char buf[64];
|
||||
|
||||
(void)state;
|
||||
|
||||
for (b = LIBX52IO_BTN_TRIGGER; b < LIBX52IO_BUTTON_MAX; b++) {
|
||||
const char *s = libx52io_button_to_str(b);
|
||||
|
||||
assert_non_null(s);
|
||||
lower_ascii_only(buf, s);
|
||||
assert_int_equal(LIBX52IO_SUCCESS, libx52io_button_from_str_nocase(buf, &out));
|
||||
assert_int_equal(b, out);
|
||||
}
|
||||
|
||||
assert_int_equal(LIBX52IO_SUCCESS,
|
||||
libx52io_button_from_str_nocase("BtN_t1_dN", &out));
|
||||
assert_int_equal(LIBX52IO_BTN_T1_DN, out);
|
||||
}
|
||||
|
||||
static void test_from_str_nocase_invalid(void **state)
|
||||
{
|
||||
libx52io_axis ax;
|
||||
libx52io_button btn;
|
||||
|
||||
(void)state;
|
||||
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str_nocase("", &ax));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str_nocase("abs_xx", &ax));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str_nocase("", &btn));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID,
|
||||
libx52io_button_from_str_nocase("btn_fire_extra", &btn));
|
||||
}
|
||||
|
||||
static void test_from_str_nocase_null_args(void **state)
|
||||
{
|
||||
libx52io_axis ax;
|
||||
libx52io_button btn;
|
||||
|
||||
(void)state;
|
||||
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str_nocase(NULL, &ax));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_axis_from_str_nocase("abs_x", NULL));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str_nocase(NULL, &btn));
|
||||
assert_int_equal(LIBX52IO_ERROR_INVALID, libx52io_button_from_str_nocase("btn_a", NULL));
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_axis_round_trip),
|
||||
cmocka_unit_test(test_button_round_trip),
|
||||
cmocka_unit_test(test_axis_from_str_invalid),
|
||||
cmocka_unit_test(test_button_from_str_invalid),
|
||||
cmocka_unit_test(test_from_str_null_args),
|
||||
cmocka_unit_test(test_axis_from_str_nocase),
|
||||
cmocka_unit_test(test_button_from_str_nocase),
|
||||
cmocka_unit_test(test_from_str_nocase_invalid),
|
||||
cmocka_unit_test(test_from_str_nocase_null_args),
|
||||
};
|
||||
|
||||
cmocka_set_message_output(CM_OUTPUT_TAP);
|
||||
cmocka_run_group_tests(tests, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: libx52 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n"
|
||||
"POT-Creation-Date: 2026-04-02 23:18-0700\n"
|
||||
"POT-Creation-Date: 2026-04-02 23:32-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -17,11 +17,11 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: libx52/x52_strerror.c:23 libx52io/io_strings.c:101 vkm/vkm_common.c:25
|
||||
#: libx52/x52_strerror.c:23 libx52io/io_strings.c:196 vkm/vkm_common.c:25
|
||||
msgid "Success"
|
||||
msgstr ""
|
||||
|
||||
#: libx52/x52_strerror.c:24 libx52io/io_strings.c:102
|
||||
#: libx52/x52_strerror.c:24 libx52io/io_strings.c:197
|
||||
msgid "Initialization failure"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ msgstr ""
|
|||
msgid "System call interrupted"
|
||||
msgstr ""
|
||||
|
||||
#: libx52/x52_strerror.c:66 libx52io/io_strings.c:125 vkm/vkm_common.c:52
|
||||
#: libx52/x52_strerror.c:66 libx52io/io_strings.c:220 vkm/vkm_common.c:52
|
||||
#, c-format
|
||||
msgid "Unknown error %d"
|
||||
msgstr ""
|
||||
|
|
@ -213,23 +213,23 @@ msgstr ""
|
|||
msgid "Unknown LED ID %d"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:103
|
||||
#: libx52io/io_strings.c:198
|
||||
msgid "No device"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:104
|
||||
#: libx52io/io_strings.c:199
|
||||
msgid "Invalid arguments"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:105
|
||||
#: libx52io/io_strings.c:200
|
||||
msgid "Connection failure"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:106
|
||||
#: libx52io/io_strings.c:201
|
||||
msgid "I/O error"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:107
|
||||
#: libx52io/io_strings.c:202
|
||||
msgid "Read timeout"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
18
po/xx_PL.po
18
po/xx_PL.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: libx52 0.2.3\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n"
|
||||
"POT-Creation-Date: 2026-04-02 23:18-0700\n"
|
||||
"POT-Creation-Date: 2026-04-02 23:32-0700\n"
|
||||
"PO-Revision-Date: 2026-04-01 20:50-0700\n"
|
||||
"Last-Translator: Nirenjan Krishnan <nirenjan@gmail.com>\n"
|
||||
"Language-Team: Dummy Language for testing i18n\n"
|
||||
|
|
@ -17,11 +17,11 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 3.4.2\n"
|
||||
|
||||
#: libx52/x52_strerror.c:23 libx52io/io_strings.c:101 vkm/vkm_common.c:25
|
||||
#: libx52/x52_strerror.c:23 libx52io/io_strings.c:196 vkm/vkm_common.c:25
|
||||
msgid "Success"
|
||||
msgstr "Uccesssay"
|
||||
|
||||
#: libx52/x52_strerror.c:24 libx52io/io_strings.c:102
|
||||
#: libx52/x52_strerror.c:24 libx52io/io_strings.c:197
|
||||
msgid "Initialization failure"
|
||||
msgstr "Initializationay ailurefay"
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ msgstr "Ipepay erroray"
|
|||
msgid "System call interrupted"
|
||||
msgstr "Ystemsay allcay interrupteday"
|
||||
|
||||
#: libx52/x52_strerror.c:66 libx52io/io_strings.c:125 vkm/vkm_common.c:52
|
||||
#: libx52/x52_strerror.c:66 libx52io/io_strings.c:220 vkm/vkm_common.c:52
|
||||
#, c-format
|
||||
msgid "Unknown error %d"
|
||||
msgstr "Unknownay erroray %d"
|
||||
|
|
@ -213,23 +213,23 @@ msgstr "Ottlethray"
|
|||
msgid "Unknown LED ID %d"
|
||||
msgstr "Unknownay EDLay IDay %d"
|
||||
|
||||
#: libx52io/io_strings.c:103
|
||||
#: libx52io/io_strings.c:198
|
||||
msgid "No device"
|
||||
msgstr "Onay eviceday"
|
||||
|
||||
#: libx52io/io_strings.c:104
|
||||
#: libx52io/io_strings.c:199
|
||||
msgid "Invalid arguments"
|
||||
msgstr "Invaliday argumentsay"
|
||||
|
||||
#: libx52io/io_strings.c:105
|
||||
#: libx52io/io_strings.c:200
|
||||
msgid "Connection failure"
|
||||
msgstr "Onnectioncay ailurefay"
|
||||
|
||||
#: libx52io/io_strings.c:106
|
||||
#: libx52io/io_strings.c:201
|
||||
msgid "I/O error"
|
||||
msgstr "I/O erroray"
|
||||
|
||||
#: libx52io/io_strings.c:107
|
||||
#: libx52io/io_strings.c:202
|
||||
msgid "Read timeout"
|
||||
msgstr "Eadray imeouttay"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue