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