Update tcsgrep.

This commit is contained in:
CismonX 2021-01-22 12:49:05 +08:00
parent f9238f7e26
commit 18265e1fe5
Signed by: cismonx
GPG Key ID: 3094873E29A482FB
1 changed files with 47 additions and 37 deletions

View File

@ -63,6 +63,9 @@ struct tcsgrep_sequence {
struct tcsgrep_ctx {
char const *prog_name;
FILE *out_file;
FILE *err_file;
int in_fd;
int timeout;
int limit;
bool purge_long_seqs;
@ -73,7 +76,7 @@ struct tcsgrep_ctx {
static inline void
print_error(struct tcsgrep_ctx const *ctx, char const *msg)
{
fprintf(stderr, "%s: [error] %s.\n", ctx->prog_name, msg);
fprintf(ctx->err_file, "%s: [error] %s.\n", ctx->prog_name, msg);
}
static inline bool
@ -89,7 +92,7 @@ parse_int(char const *str, int *dest)
}
static inline void
print_char(int ch)
print_char(struct tcsgrep_ctx const *ctx, int ch)
{
static char const *ascii_table[] = {
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
@ -98,68 +101,75 @@ print_char(int ch)
"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
};
if (ch == ' ') {
printf(" SP");
fprintf(ctx->out_file, " SP");
} else if (isprint(ch)) {
printf(" %c", ch);
fprintf(ctx->out_file, " %c", ch);
} else if (ch == 0x7f) {
printf(" DEL");
fprintf(ctx->out_file, " DEL");
} else if (!iscntrl(ch)) {
printf(" \\x%02x", (unsigned char)ch);
fprintf(ctx->out_file, " \\x%02x", (unsigned char)ch);
} else {
printf(" %s", ascii_table[ch]);
fprintf(ctx->out_file, " %s", ascii_table[ch]);
}
}
static void
print_generic_seq(char const *header, union ctlseqs_value *result, bool newline)
print_generic_seq(struct tcsgrep_ctx const *ctx, char const *header, union ctlseqs_value const *result, bool newline)
{
size_t length = result[0].len;
char const *seq = result[1].str;
printf("%s %zu", header, length);
fprintf(ctx->out_file, "%s %zu", header, length);
for (size_t idx = 0; idx < length; ++idx) {
print_char((unsigned)seq[idx]);
print_char(ctx, (unsigned)seq[idx]);
}
if (newline) {
printf("\n");
fprintf(ctx->out_file, "\n");
}
}
static void
print_matching_seq(struct tcsgrep_sequence *seq, union ctlseqs_value *result, bool verbose)
{
print_matching_seq(
struct tcsgrep_ctx const *ctx,
struct tcsgrep_sequence const *seq,
union ctlseqs_value const *result,
bool verbose
) {
if (verbose) {
print_generic_seq("OK", result, false);
print_generic_seq(ctx, "OK", result, false);
result += 2;
} else {
printf("OK");
fprintf(ctx->out_file, "OK");
}
printf(" %s", seq->name);
fprintf(ctx->out_file, " %s", seq->name);
for (int idx = 0; idx < 8; ++idx) {
char placeholder = seq->args[idx];
switch (placeholder) {
case 0x0e: // CTLSEQS_PH_NUM
printf(" %lu", result[idx].num);
fprintf(ctx->out_file, " %lu", result[idx].num);
break;
case 0x10: // CTLSEQS_PH_STR
printf(" %.*s", (int)result[idx].len, result[idx + 1].str);
fprintf(ctx->out_file, " %.*s", (int)result[idx].len, result[idx + 1].str);
break;
case 0x0f: // CTLSEQS_PH_NUMS
for (size_t i = 1; i <= result[idx].len; ++i) {
printf(" %lu", result[idx + i].num);
fprintf(ctx->out_file, " %lu", result[idx + i].num);
}
break;
}
}
printf("\n");
fprintf(ctx->out_file, "\n");
}
int
main(int argc, char **argv)
{
struct tcsgrep_ctx ctx = {
.prog_name = argv[0],
.timeout = -1,
.limit = DEFAULT_MAX_BUFFER_LEN,
.prog_name = argv[0],
.out_file = stdout,
.err_file = stderr,
.in_fd = STDIN_FILENO,
.timeout = -1,
.limit = DEFAULT_MAX_BUFFER_LEN,
};
int opt;
@ -190,12 +200,12 @@ main(int argc, char **argv)
}
}
int flags = fcntl(STDIN_FILENO, F_GETFL);
int flags = fcntl(ctx.in_fd, F_GETFL);
if (flags == -1) {
print_error(&ctx, "failed to get file status flags");
return 1;
}
if (fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK) == -1) {
if (fcntl(ctx.in_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
print_error(&ctx, "failed to set file status flags");
return 1;
}
@ -379,7 +389,7 @@ main(int argc, char **argv)
}
static union ctlseqs_value result[4096];
struct ctlseqs_reader_options reader_options = {
.fd = STDIN_FILENO,
.fd = ctx.in_fd,
.maxlen = ctx.limit,
.result = result,
.flags = ctx.verbose ? CTLSEQS_READER_SAVE_MATCHED_SEQS : 0,
@ -390,14 +400,14 @@ main(int argc, char **argv)
}
struct termios old_termios;
if (tcgetattr(STDIN_FILENO, &old_termios) != 0) {
if (tcgetattr(ctx.in_fd, &old_termios) != 0) {
ctx.not_tty = true;
} else {
struct termios new_termios = old_termios;
new_termios.c_cc[VMIN] = 0;
new_termios.c_cc[VTIME] = 0;
new_termios.c_lflag &= ~(ICANON | ISIG | ECHO);
if (tcsetattr(STDIN_FILENO, TCSANOW, &new_termios) != 0) {
if (tcsetattr(ctx.in_fd, TCSANOW, &new_termios) != 0) {
print_error(&ctx, "failed to set terminal attributes");
return 1;
}
@ -412,25 +422,25 @@ main(int argc, char **argv)
status = 1;
goto terminate;
case CTLSEQS_TIMEOUT:
printf("TIMEOUT\n");
fprintf(ctx.out_file, "TIMEOUT\n");
status = 1;
goto terminate;
case CTLSEQS_INTR:
printf("INTR\n");
fprintf(ctx.out_file, "INTR\n");
break;
case CTLSEQS_EOF:
printf("EOF\n");
fprintf(ctx.out_file, "EOF\n");
goto terminate;
case CTLSEQS_PARTIAL:
if (ctx.verbose) {
print_generic_seq("PARTIAL", result, true);
print_generic_seq(&ctx, "PARTIAL", result, true);
}
break;
case CTLSEQS_NOMATCH:
print_generic_seq("NOMATCH", result, true);
print_generic_seq(&ctx, "NOMATCH", result, true);
break;
case CTLSEQS_NOMEM:
print_generic_seq("NOMEM", result, true);
print_generic_seq(&ctx, "NOMEM", result, true);
if (ctx.purge_long_seqs) {
ctlseqs_purge(reader, result[0].len);
break;
@ -439,13 +449,13 @@ main(int argc, char **argv)
goto terminate;
}
case CTLSEQS_NOSEQ:
print_generic_seq("NOSEQ", result, true);
print_generic_seq(&ctx, "NOSEQ", result, true);
if (!ctx.not_tty && result[1].str[0] == 0x04) {
goto terminate;
}
break;
default:
print_matching_seq(&seqs[retval], result, ctx.verbose);
print_matching_seq(&ctx, &seqs[retval], result, ctx.verbose);
break;
}
}
@ -454,7 +464,7 @@ main(int argc, char **argv)
ctlseqs_matcher_free(matcher);
ctlseqs_reader_free(reader);
if (!ctx.not_tty) {
tcsetattr(STDIN_FILENO, TCSANOW, &old_termios);
tcsetattr(ctx.in_fd, TCSANOW, &old_termios);
}
return status;
}