Update tcsgrep.
This commit is contained in:
parent
f9238f7e26
commit
18265e1fe5
|
@ -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,59 +101,63 @@ 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
|
||||
|
@ -158,6 +165,9 @@ main(int argc, char **argv)
|
|||
{
|
||||
struct tcsgrep_ctx ctx = {
|
||||
.prog_name = argv[0],
|
||||
.out_file = stdout,
|
||||
.err_file = stderr,
|
||||
.in_fd = STDIN_FILENO,
|
||||
.timeout = -1,
|
||||
.limit = DEFAULT_MAX_BUFFER_LEN,
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue