Cleanup parsing of mapping flags

This commit is contained in:
Martin Lund 2024-06-02 14:26:39 +02:00
parent 563c4fa6ea
commit 8014ef68c0
6 changed files with 186 additions and 152 deletions

View file

@ -215,7 +215,13 @@ static void config_parse_keys(GKeyFile *key_file, char *group)
config_get_string(key_file, group, "log-file", &option.log_filename, NULL);
config_get_bool(key_file, group, "log-append", &option.log_append);
config_get_bool(key_file, group, "log-strip", &option.log_strip);
config_get_string(key_file, group, "map", &option.map, NULL);
config_get_string(key_file, group, "map", &string, NULL);
if (string != NULL)
{
option_parse_mappings(string);
g_free((void *)string);
string = NULL;
}
config_get_string(key_file, group, "color", &string, NULL);
if (string != NULL)
{

View file

@ -85,7 +85,6 @@ struct option_t option =
.local_echo = false,
.timestamp = TIMESTAMP_NONE,
.socket = NULL,
.map = "",
.color = 256, // Bold
.input_mode = INPUT_MODE_NORMAL,
.output_mode = OUTPUT_MODE_NORMAL,
@ -109,6 +108,17 @@ struct option_t option =
.hex_n_value = 0,
.vt100 = false,
.exec = NULL,
.map_i_nl_cr = false,
.map_i_cr_nl = false,
.map_ign_cr = false,
.map_i_ff_escc = false,
.map_i_nl_crnl = false,
.map_o_cr_nl = false,
.map_o_nl_crnl = false,
.map_o_del_bs = false,
.map_o_ltu = false,
.map_o_nulbrk = false,
.map_o_msblsb = false,
};
void option_print_help(char *argv[])
@ -692,6 +702,90 @@ void option_parse_script_run(const char *arg, script_run_t *script_run)
}
}
void option_parse_mappings(const char *map)
{
bool token_found = true;
char *token = NULL;
char *buffer;
if (map == NULL)
{
return;
}
/* Parse any specified input or output mappings */
buffer = strdup(map);
while (token_found == true)
{
if (token == NULL)
{
token = strtok(buffer,",");
}
else
{
token = strtok(NULL, ",");
}
if (token != NULL)
{
if (strcmp(token,"INLCR") == 0)
{
option.map_i_nl_cr = true;
}
else if (strcmp(token,"IGNCR") == 0)
{
option.map_ign_cr = true;
}
else if (strcmp(token,"ICRNL") == 0)
{
option.map_i_cr_nl = true;
}
else if (strcmp(token,"OCRNL") == 0)
{
option.map_o_cr_nl = true;
}
else if (strcmp(token,"ODELBS") == 0)
{
option.map_o_del_bs = true;
}
else if (strcmp(token,"IFFESCC") == 0)
{
option.map_i_ff_escc = true;
}
else if (strcmp(token,"INLCRNL") == 0)
{
option.map_i_nl_crnl = true;
}
else if (strcmp(token, "ONLCRNL") == 0)
{
option.map_o_nl_crnl = true;
}
else if (strcmp(token, "OLTU") == 0)
{
option.map_o_ltu = true;
}
else if (strcmp(token, "ONULBRK") == 0)
{
option.map_o_nulbrk = true;
}
else if (strcmp(token, "MSB2LSB") == 0)
{
option.map_o_msblsb = true;
}
else
{
printf("Error: Unknown mapping flag %s\n", token);
exit(EXIT_FAILURE);
}
}
else
{
token_found = false;
}
}
free(buffer);
}
void options_print()
{
tio_printf(" Device: %s", device_name);
@ -928,7 +1022,7 @@ void options_parse(int argc, char *argv[])
break;
case 'm':
option.map = optarg;
option_parse_mappings(optarg);
break;
case 'c':

View file

@ -69,7 +69,6 @@ struct option_t
timestamp_t timestamp;
char *log_filename;
char *log_directory;
char *map;
char *socket;
int color;
input_mode_t input_mode;
@ -94,6 +93,17 @@ struct option_t
int hex_n_value;
bool vt100;
char *exec;
bool map_i_nl_cr;
bool map_i_cr_nl;
bool map_ign_cr;
bool map_i_ff_escc;
bool map_i_nl_crnl;
bool map_o_cr_nl;
bool map_o_nl_crnl;
bool map_o_del_bs;
bool map_o_ltu;
bool map_o_nulbrk;
bool map_o_msblsb;
};
extern struct option_t option;
@ -119,3 +129,5 @@ const char *option_auto_connect_state_to_string(auto_connect_t strategy);
void option_parse_timestamp(const char *arg, timestamp_t *timestamp);
const char* option_timestamp_format_to_string(timestamp_t timestamp);
void option_parse_mappings(const char *map);

View file

@ -343,20 +343,20 @@ bool socket_handle_input(fd_set *rdfs, char *output_char)
}
/* If INLCR is set, a received NL character shall be translated into a CR character */
if (*output_char == '\n' && map_i_nl_cr)
if (*output_char == '\n' && option.map_i_nl_cr)
{
*output_char = '\r';
}
else if (*output_char == '\r')
{
/* If IGNCR is set, a received CR character shall be ignored (not read). */
if (map_ign_cr)
if (option.map_ign_cr)
{
return false;
}
/* If IGNCR is not set and ICRNL is set, a received CR character shall be translated into an NL character. */
if (map_i_cr_nl)
if (option.map_i_cr_nl)
{
*output_char = '\n';
}

195
src/tty.c
View file

@ -153,9 +153,6 @@ const char random_array[] =
};
bool interactive_mode = true;
bool map_i_nl_cr = false;
bool map_i_cr_nl = false;
bool map_ign_cr = false;
char key_hit = 0xff;
@ -167,14 +164,6 @@ static bool connected = false;
static bool standard_baudrate = true;
static void (*print)(char c);
static int device_fd;
static bool map_i_ff_escc = false;
static bool map_i_nl_crnl = false;
static bool map_o_cr_nl = false;
static bool map_o_nl_crnl = false;
static bool map_o_del_bs = false;
static bool map_o_ltu = false;
static bool map_o_nulbrk = false;
static bool map_o_msblsb = false;
static char hex_chars[2];
static unsigned char hex_char_index = 0;
static char tty_buffer[BUFSIZ*2];
@ -259,7 +248,7 @@ ssize_t tty_write(int fd, const void *buffer, size_t count)
ssize_t retval = 0, bytes_written = 0;
size_t i;
if (map_o_ltu)
if (option.map_o_ltu)
{
// Convert lower case to upper case
for (i = 0; i<count; i++)
@ -632,28 +621,28 @@ void tty_output_mode_set(output_mode_t mode)
static void mappings_print(void)
{
if (map_i_cr_nl || map_ign_cr || map_i_ff_escc || map_i_nl_cr ||
map_i_nl_crnl || map_o_cr_nl || map_o_del_bs || map_o_nl_crnl ||
map_o_ltu || map_o_nulbrk || map_o_msblsb)
if (option.map_i_cr_nl || option.map_ign_cr || option.map_i_ff_escc ||
option.map_i_nl_cr || option.map_i_nl_crnl || option.map_o_cr_nl ||
option.map_o_del_bs || option.map_o_nl_crnl || option.map_o_ltu ||
option.map_o_nulbrk || option.map_o_msblsb)
{
tio_printf(" Mappings:%s%s%s%s%s%s%s%s%s%s%s",
map_i_cr_nl ? " ICRNL" : "",
map_ign_cr ? " IGNCR" : "",
map_i_ff_escc ? " IFFESCC" : "",
map_i_nl_cr ? " INLCR" : "",
map_i_nl_crnl ? " INLCRNL" : "",
map_o_cr_nl ? " OCRNL" : "",
map_o_del_bs ? " ODELBS" : "",
map_o_nl_crnl ? " ONLCRNL" : "",
map_o_ltu ? " OLTU" : "",
map_o_nulbrk ? " ONULBRK" : "",
map_o_msblsb ? " MSB2LSB" : "");
option.map_i_cr_nl ? " ICRNL" : "",
option.map_ign_cr ? " IGNCR" : "",
option.map_i_ff_escc ? " IFFESCC" : "",
option.map_i_nl_cr ? " INLCR" : "",
option.map_i_nl_crnl ? " INLCRNL" : "",
option.map_o_cr_nl ? " OCRNL" : "",
option.map_o_del_bs ? " ODELBS" : "",
option.map_o_nl_crnl ? " ONLCRNL" : "",
option.map_o_ltu ? " OLTU" : "",
option.map_o_nulbrk ? " ONULBRK" : "",
option.map_o_msblsb ? " MSB2LSB" : "");
}
else
{
tio_printf(" Mappings: none");
}
}
void handle_command_sequence(char input_char, char *output_char, bool *forward)
@ -761,50 +750,50 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
{
case KEY_0:
tio.c_iflag ^= ICRNL;
map_i_cr_nl = !map_i_cr_nl;
tio_printf("ICRNL is %s", map_i_cr_nl ? "set" : "unset");
option.map_i_cr_nl = !option.map_i_cr_nl;
tio_printf("ICRNL is %s", option.map_i_cr_nl ? "set" : "unset");
break;
case KEY_1:
tio.c_iflag ^= IGNCR;
map_ign_cr = !map_ign_cr;
tio_printf("IGNCR is %s", map_ign_cr ? "set" : "unset");
option.map_ign_cr = !option.map_ign_cr;
tio_printf("IGNCR is %s", option.map_ign_cr ? "set" : "unset");
break;
case KEY_2:
map_i_ff_escc = !map_i_ff_escc;
tio_printf("IFFESCC is %s", map_i_ff_escc ? "set" : "unset");
option.map_i_ff_escc = !option.map_i_ff_escc;
tio_printf("IFFESCC is %s", option.map_i_ff_escc ? "set" : "unset");
break;
case KEY_3:
tio.c_iflag ^= INLCR;
map_i_nl_cr = !map_i_nl_cr;
tio_printf("INLCR is %s", map_i_nl_cr ? "set" : "unset");
option.map_i_nl_cr = !option.map_i_nl_cr;
tio_printf("INLCR is %s", option.map_i_nl_cr ? "set" : "unset");
break;
case KEY_4:
map_i_nl_crnl = !map_i_nl_crnl;
tio_printf("INLCRNL is %s", map_i_nl_crnl ? "set" : "unset");
option.map_i_nl_crnl = !option.map_i_nl_crnl;
tio_printf("INLCRNL is %s", option.map_i_nl_crnl ? "set" : "unset");
break;
case KEY_5:
map_o_cr_nl = !map_o_cr_nl;
tio_printf("OCRNL is %s", map_o_cr_nl ? "set" : "unset");
option.map_o_cr_nl = !option.map_o_cr_nl;
tio_printf("OCRNL is %s", option.map_o_cr_nl ? "set" : "unset");
break;
case KEY_6:
map_o_del_bs = !map_o_del_bs;
tio_printf("ODELBS is %s", map_o_del_bs ? "set" : "unset");
option.map_o_del_bs = !option.map_o_del_bs;
tio_printf("ODELBS is %s", option.map_o_del_bs ? "set" : "unset");
break;
case KEY_7:
map_o_nl_crnl = !map_o_nl_crnl;
tio_printf("ONLCRNL is %s", map_o_nl_crnl ? "set" : "unset");
option.map_o_nl_crnl = !option.map_o_nl_crnl;
tio_printf("ONLCRNL is %s", option.map_o_nl_crnl ? "set" : "unset");
break;
case KEY_8:
map_o_ltu = !map_o_ltu;
tio_printf("OLTU is %s", map_o_ltu ? "set" : "unset");
option.map_o_ltu = !option.map_o_ltu;
tio_printf("OLTU is %s", option.map_o_ltu ? "set" : "unset");
break;
case KEY_9:
map_o_nulbrk = !map_o_nulbrk;
tio_printf("ONULBRK is %s", map_o_nulbrk ? "set" : "unset");
option.map_o_nulbrk = !option.map_o_nulbrk;
tio_printf("ONULBRK is %s", option.map_o_nulbrk ? "set" : "unset");
break;
case KEY_A:
map_o_msblsb = !map_o_msblsb;
tio_printf("MSB2LSB is %s", map_o_msblsb ? "set" : "unset");
option.map_o_msblsb = !option.map_o_msblsb;
tio_printf("MSB2LSB is %s", option.map_o_msblsb ? "set" : "unset");
break;
default:
tio_error_print("Invalid input");
@ -995,27 +984,27 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
/* Change mapping of characters on input or output */
tio_printf("Please enter which mapping to set or unset:");
tio_printf(" (0) ICRNL: %s mapping CR to NL on input (unless IGNCR is set)",
map_i_cr_nl ? "Unset" : "Set");
option.map_i_cr_nl ? "Unset" : "Set");
tio_printf(" (1) IGNCR: %s ignoring CR on input",
map_ign_cr ? "Unset" : "Set");
option.map_ign_cr ? "Unset" : "Set");
tio_printf(" (2) IFFESCC: %s mapping FF to ESC-c on input",
map_i_ff_escc ? "Unset" : "Set");
option.map_i_ff_escc ? "Unset" : "Set");
tio_printf(" (3) INLCR: %s mapping NL to CR on input",
map_i_nl_cr ? "Unset" : "Set");
option.map_i_nl_cr ? "Unset" : "Set");
tio_printf(" (4) INLCRNL: %s mapping NL to CR-NL on input",
map_i_nl_cr ? "Unset" : "Set");
option.map_i_nl_cr ? "Unset" : "Set");
tio_printf(" (5) OCRNL: %s mapping CR to NL on output",
map_o_cr_nl ? "Unset" : "Set");
option.map_o_cr_nl ? "Unset" : "Set");
tio_printf(" (6) ODELBS: %s mapping DEL to BS on output",
map_o_del_bs ? "Unset" : "Set");
option.map_o_del_bs ? "Unset" : "Set");
tio_printf(" (7) ONLCRNL: %s mapping NL to CR-NL on output",
map_o_nl_crnl ? "Unset" : "Set");
option.map_o_nl_crnl ? "Unset" : "Set");
tio_printf(" (8) OLTU: %s mapping lowercase to uppercase on output",
map_o_ltu ? "Unset" : "Set");
option.map_o_ltu ? "Unset" : "Set");
tio_printf(" (9) ONULBRK: %s mapping NUL to send break signal on output",
map_o_nulbrk ? "Unset" : "Set");
option.map_o_nulbrk ? "Unset" : "Set");
tio_printf(" (a) MSB2LSB: %s mapping MSB bit order to LSB on output",
map_o_msblsb ? "Unset" : "Set");
option.map_o_msblsb ? "Unset" : "Set");
// Process next input character as sub command
sub_command = SUBCOMMAND_MAP;
@ -1210,9 +1199,6 @@ void stdout_configure(void)
void tty_configure(void)
{
bool token_found = true;
char *token = NULL;
char *buffer;
int status;
speed_t baudrate;
@ -1364,80 +1350,19 @@ void tty_configure(void)
tio.c_cc[VTIME] = 0; // Inter-character timer unused
tio.c_cc[VMIN] = 1; // Blocking read until 1 character received
/* Configure any specified input or output mappings */
buffer = strdup(option.map);
while (token_found == true)
{
if (token == NULL)
{
token = strtok(buffer,",");
}
else
{
token = strtok(NULL, ",");
}
if (token != NULL)
{
if (strcmp(token,"INLCR") == 0)
/* Configure input mappings */
if (option.map_i_nl_cr)
{
tio.c_iflag |= INLCR;
map_i_nl_cr = true;
}
else if (strcmp(token,"IGNCR") == 0)
if (option.map_ign_cr)
{
tio.c_iflag |= IGNCR;
map_ign_cr = true;
}
else if (strcmp(token,"ICRNL") == 0)
if (option.map_i_cr_nl)
{
tio.c_iflag |= ICRNL;
map_i_cr_nl = true;
}
else if (strcmp(token,"OCRNL") == 0)
{
map_o_cr_nl = true;
}
else if (strcmp(token,"ODELBS") == 0)
{
map_o_del_bs = true;
}
else if (strcmp(token,"IFFESCC") == 0)
{
map_i_ff_escc = true;
}
else if (strcmp(token,"INLCRNL") == 0)
{
map_i_nl_crnl = true;
}
else if (strcmp(token, "ONLCRNL") == 0)
{
map_o_nl_crnl = true;
}
else if (strcmp(token, "OLTU") == 0)
{
map_o_ltu = true;
}
else if (strcmp(token, "ONULBRK") == 0)
{
map_o_nulbrk = true;
}
else if (strcmp(token, "MSB2LSB") == 0)
{
map_o_msblsb = true;
}
else
{
printf("Error: Unknown mapping flag %s\n", token);
exit(EXIT_FAILURE);
}
}
else
{
token_found = false;
}
}
free(buffer);
}
static bool is_serial_device(const char *format, ...)
@ -2184,17 +2109,17 @@ void forward_to_tty(int fd, char output_char)
int status;
/* Map output character */
if ((output_char == 127) && (map_o_del_bs))
if ((output_char == 127) && (option.map_o_del_bs))
{
output_char = '\b';
}
if ((output_char == '\r') && (map_o_cr_nl))
if ((output_char == '\r') && (option.map_o_cr_nl))
{
output_char = '\n';
}
/* Map newline character */
if ((output_char == '\n' || output_char == '\r') && (map_o_nl_crnl))
if ((output_char == '\n' || output_char == '\r') && (option.map_o_nl_crnl))
{
const char *crlf = "\r\n";
@ -2221,7 +2146,7 @@ void forward_to_tty(int fd, char output_char)
{
/* Send output to tty device */
optional_local_echo(output_char);
if ((output_char == 0) && (map_o_nulbrk))
if ((output_char == 0) && (option.map_o_nulbrk))
{
status = tcsendbreak(fd, 0);
}
@ -2556,7 +2481,7 @@ int tty_connect(void)
}
/* Convert MSB to LSB bit order */
if (map_o_msblsb)
if (option.map_o_msblsb)
{
char ch = input_char;
input_char = 0;
@ -2567,7 +2492,7 @@ int tty_connect(void)
}
/* Map input character */
if ((input_char == '\n') && (map_i_nl_crnl) && (!map_o_msblsb))
if ((input_char == '\n') && (option.map_i_nl_crnl) && (!option.map_o_msblsb))
{
print('\r');
print('\n');
@ -2576,7 +2501,7 @@ int tty_connect(void)
do_timestamp = true;
}
}
else if ((input_char == '\f') && (map_i_ff_escc) && (!map_o_msblsb))
else if ((input_char == '\f') && (option.map_i_ff_escc) && (!option.map_o_msblsb))
{
print('\e');
print('c');

View file

@ -71,9 +71,6 @@ typedef struct
extern const char *device_name;
extern bool interactive_mode;
extern bool map_i_nl_cr;
extern bool map_i_cr_nl;
extern bool map_ign_cr;
void stdout_configure(void);
void stdin_configure(void);