Add hexN output mode

Adds support for hexN mode where N is a number in the range 1 to 4096
which defines how many hex values will be printed before a line break.

In short, it defines the width of the hex output.

In this mode, if timestamps are enabled they will be added to each hex
line.
This commit is contained in:
Martin Lund 2024-04-27 15:22:41 +02:00
parent 4113a072c2
commit 42ff234204
5 changed files with 151 additions and 22 deletions

View file

@ -119,7 +119,7 @@ Options:
-n, --no-reconnect Do not reconnect -n, --no-reconnect Do not reconnect
-e, --local-echo Enable local echo -e, --local-echo Enable local echo
--input-mode normal|hex|line Select input mode (default: normal) --input-mode normal|hex|line Select input mode (default: normal)
--output-mode normal|hex Select output mode (default: normal) --output-mode normal|hex|hexN Select output mode (default: normal, N <= 4096)
-t, --timestamp Enable line timestamp -t, --timestamp Enable line timestamp
--timestamp-format <format> Set timestamp format (default: 24hour) --timestamp-format <format> Set timestamp format (default: 24hour)
--timestamp-timeout <ms> Set timestamp timeout (default: 200) --timestamp-timeout <ms> Set timestamp timeout (default: 200)

View file

@ -248,9 +248,14 @@ editing feature supported in this mode is backspace.
Default value is "normal". Default value is "normal".
.TP .TP
.BR " \-\-output\-mode " normal|hex .BR " \-\-output\-mode " normal|hex|hexN
Set output mode. In hex mode each incoming byte is printed out as a 1 byte hex value. Set output mode.
In hex mode each incoming byte is printed out as a 1 byte hex value.
In hexN mode, N is a number less than or equal to 4096 which defines how many
hex values will be printed before a line break.
Default value is "normal". Default value is "normal".

View file

@ -20,6 +20,7 @@
*/ */
#include "config.h" #include "config.h"
#include <regex.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <string.h> #include <string.h>
@ -41,6 +42,8 @@
#include "log.h" #include "log.h"
#include "script.h" #include "script.h"
#define HEX_N_VALUE_MAX 4096
enum opt_t enum opt_t
{ {
OPT_NONE, OPT_NONE,
@ -114,6 +117,7 @@ struct option_t option =
.exclude_devices = NULL, .exclude_devices = NULL,
.exclude_drivers = NULL, .exclude_drivers = NULL,
.exclude_tids = NULL, .exclude_tids = NULL,
.hex_n_value = 0,
}; };
void print_help(char *argv[]) void print_help(char *argv[])
@ -140,7 +144,7 @@ void print_help(char *argv[])
printf(" -n, --no-reconnect Do not reconnect\n"); printf(" -n, --no-reconnect Do not reconnect\n");
printf(" -e, --local-echo Enable local echo\n"); printf(" -e, --local-echo Enable local echo\n");
printf(" --input-mode normal|hex|line Select input mode (default: normal)\n"); printf(" --input-mode normal|hex|line Select input mode (default: normal)\n");
printf(" --output-mode normal|hex Select output mode (default: normal)\n"); printf(" --output-mode normal|hex|hexN Select output mode (default: normal, N <= %d)\n", HEX_N_VALUE_MAX);
printf(" -t, --timestamp Enable line timestamp\n"); printf(" -t, --timestamp Enable line timestamp\n");
printf(" --timestamp-format <format> Set timestamp format (default: 24hour)\n"); printf(" --timestamp-format <format> Set timestamp format (default: 24hour)\n");
printf(" --timestamp-timeout <ms> Set timestamp timeout (default: 200)\n"); printf(" --timestamp-timeout <ms> Set timestamp timeout (default: 200)\n");
@ -268,6 +272,61 @@ void line_pulse_duration_option_parse(const char *arg)
free(buffer); free(buffer);
} }
// Function to parse the input string
int parse_hexN_string(const char *input_string)
{
regmatch_t match[2]; // One for entire match, one for the optional N
int n_value = 0;
regex_t regex;
int ret;
// Compile the regular expression to match "hex" and optionally capture N
ret = regcomp(&regex, "^hex([0-9]+)?$", REG_EXTENDED);
if (ret)
{
tio_error_printf("Could not compile regex\n");
exit(EXIT_FAILURE);
}
// Execute the regular expression
ret = regexec(&regex, input_string, 2, match, 0);
if (!ret)
{
// If there is a match, extract the N value if present
if (match[1].rm_so != -1)
{
char n_value_str[32]; // Assume max 32 digits for the numerical value
strncpy(n_value_str, input_string + match[1].rm_so, match[1].rm_eo - match[1].rm_so);
n_value_str[match[1].rm_eo - match[1].rm_so] = '\0'; // Null-terminate the string
n_value = atoi(n_value_str);
if ((n_value > HEX_N_VALUE_MAX) || (n_value == 0))
{
n_value = -1;
}
}
else
{
n_value = 0;
}
}
else if (ret == REG_NOMATCH)
{
n_value = -1;
}
else
{
char msgbuf[100];
regerror(ret, &regex, msgbuf, sizeof(msgbuf));
tio_error_printf("Regex match failed: %s\n", msgbuf);
exit(EXIT_FAILURE);
}
regfree(&regex);
return n_value;
}
input_mode_t input_mode_option_parse(const char *arg) input_mode_t input_mode_option_parse(const char *arg)
{ {
if (strcmp("normal", arg) == 0) if (strcmp("normal", arg) == 0)
@ -291,12 +350,15 @@ input_mode_t input_mode_option_parse(const char *arg)
output_mode_t output_mode_option_parse(const char *arg) output_mode_t output_mode_option_parse(const char *arg)
{ {
int n = 0;
if (strcmp("normal", arg) == 0) if (strcmp("normal", arg) == 0)
{ {
return OUTPUT_MODE_NORMAL; return OUTPUT_MODE_NORMAL;
} }
else if (strcmp("hex", arg) == 0) else if ((n = parse_hexN_string(arg)) != -1)
{ {
option.hex_n_value = n;
return OUTPUT_MODE_HEX; return OUTPUT_MODE_HEX;
} }
else else

View file

@ -94,6 +94,7 @@ struct option_t
const char *exclude_devices; const char *exclude_devices;
const char *exclude_drivers; const char *exclude_drivers;
const char *exclude_tids; const char *exclude_tids;
int hex_n_value;
}; };
extern struct option_t option; extern struct option_t option;

View file

@ -2086,7 +2086,7 @@ int tty_connect(void)
char line_buffer[BUFSIZ] = {}; char line_buffer[BUFSIZ] = {};
static bool first = true; static bool first = true;
int status; int status;
bool next_timestamp = false; bool do_timestamp = false;
char* now = NULL; char* now = NULL;
unsigned int line_index = 0; unsigned int line_index = 0;
static char previous_char[2] = {}; static char previous_char[2] = {};
@ -2128,7 +2128,7 @@ int tty_connect(void)
if (option.timestamp) if (option.timestamp)
{ {
next_timestamp = true; do_timestamp = true;
} }
/* Manage print output mode */ /* Manage print output mode */
@ -2260,7 +2260,7 @@ int tty_connect(void)
rx_total += bytes_read; rx_total += bytes_read;
// Manage timeout based timestamping in hex mode // Manage timeout based timestamping in hex mode
if (option.output_mode == OUTPUT_MODE_HEX) if ((option.output_mode == OUTPUT_MODE_HEX) && (option.hex_n_value == 0))
{ {
if (option.timestamp != TIMESTAMP_NONE) if (option.timestamp != TIMESTAMP_NONE)
{ {
@ -2276,7 +2276,7 @@ int tty_connect(void)
{ {
log_printf("\r\n[%s] ", now); log_printf("\r\n[%s] ", now);
} }
next_timestamp = false; do_timestamp = false;
} }
} }
tval_before = tval_now; tval_before = tval_now;
@ -2286,24 +2286,85 @@ int tty_connect(void)
/* Process input byte by byte */ /* Process input byte by byte */
for (int i=0; i<bytes_read; i++) for (int i=0; i<bytes_read; i++)
{ {
static unsigned long count = 0;
input_char = input_buffer[i]; input_char = input_buffer[i];
/* Print timestamp on new line if enabled */ /* Handle timestamps */
if (option.output_mode == OUTPUT_MODE_NORMAL) switch (option.output_mode)
{ {
if ((next_timestamp && input_char != '\n' && input_char != '\r')) case OUTPUT_MODE_NORMAL:
{ // Support timestamp per line
now = timestamp_current_time(); if ((do_timestamp && input_char != '\n' && input_char != '\r'))
if (now)
{ {
ansi_printf_raw("[%s] ", now); now = timestamp_current_time();
if (option.log) if (now)
{ {
log_printf("[%s] ", now); ansi_printf_raw("[%s] ", now);
if (option.log)
{
log_printf("[%s] ", now);
}
do_timestamp = false;
} }
next_timestamp = false;
} }
} break;
case OUTPUT_MODE_HEX:
// Support hexN mode
if (option.hex_n_value > 0)
{
static bool first = true;
if ((count % option.hex_n_value) == 0)
{
if (option.timestamp != TIMESTAMP_NONE)
{
now = timestamp_current_time();
if (first)
{
ansi_printf_raw("[%s] ", now);
if (option.log)
{
log_printf("[%s] ", now);
}
first = false;
}
else
{
ansi_printf_raw("\r\n[%s] ", now);
if (option.log)
{
log_printf("\n[%s] ", now);
}
}
}
else
{
if (first)
{
// Do nothing
}
else
{
putchar('\r');
putchar('\n');
if (option.log)
{
log_putc('\n');
}
first = false;
}
}
}
}
count++;
break;
default:
tio_error_printf("Unknown outut mode");
exit(EXIT_FAILURE);
break;
} }
/* Convert MSB to LSB bit order */ /* Convert MSB to LSB bit order */
@ -2324,7 +2385,7 @@ int tty_connect(void)
print('\n'); print('\n');
if (option.timestamp) if (option.timestamp)
{ {
next_timestamp = true; do_timestamp = true;
} }
} }
else if ((input_char == '\f') && (map_i_ff_escc) && (!map_o_msblsb)) else if ((input_char == '\f') && (map_i_ff_escc) && (!map_o_msblsb))
@ -2350,7 +2411,7 @@ int tty_connect(void)
if (input_char == '\n' && option.timestamp) if (input_char == '\n' && option.timestamp)
{ {
next_timestamp = true; do_timestamp = true;
} }
} }
} }