Refactor code.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
b2c5b019cc
commit
e45395bbdf
|
@ -25,8 +25,10 @@ autoscan.log
|
|||
compile
|
||||
config.*
|
||||
configure
|
||||
configure~
|
||||
configure.scan
|
||||
install-sh
|
||||
m4/
|
||||
Makefile
|
||||
Makefile.in
|
||||
missing
|
||||
|
@ -37,4 +39,5 @@ stamp-h1
|
|||
|
||||
# build
|
||||
*.o
|
||||
build/
|
||||
ctlseqs-*.tar.gz
|
||||
|
|
50
INSTALL.md
50
INSTALL.md
|
@ -1,38 +1,36 @@
|
|||
<!--
|
||||
Copyright (C) 2020,2021 CismonX <admin@cismon.net>
|
||||
|
||||
Copying and distribution of this file, with or without modification, are
|
||||
permitted in any medium without royalty, provided the copyright notice and
|
||||
this notice are preserved. This file is offered as-is, without any warranty.
|
||||
Copyright (C) 2020,2021 CismonX <admin@cismon.net>
|
||||
|
||||
Copying and distribution of this file, with or without modification, are
|
||||
permitted in any medium without royalty, provided the copyright notice and
|
||||
this notice are preserved. This file is offered as-is, without any warranty.
|
||||
-->
|
||||
|
||||
# Installing ctlseqs
|
||||
Installing ctlseqs
|
||||
==================
|
||||
|
||||
## Copy Code to Your Project
|
||||
Copy Code to Your Project
|
||||
-------------------------
|
||||
|
||||
The code of ctlseqs is simple, and can be used out-of-the-box. Just copy
|
||||
[ctlseqs.h](include/ctlseqs.h) and [ctlseqs.c](src/ctlseqs.c) to your project
|
||||
and build it alongside with other code.
|
||||
The code of ctlseqs is simple, and can be used out-of-the-box. Just copy
|
||||
ctlseqs.h and ctlseqs.c to your project and build it with other code.
|
||||
|
||||
Requires an ISO C99 and POSIX.1-2001 compliant C implementation.
|
||||
Requires an ISO C99 and POSIX.1-2001 compliant C implementation.
|
||||
|
||||
## Build and Install From Source
|
||||
Build and Install From Source
|
||||
-----------------------------
|
||||
|
||||
Alternatively, ctlseqs can be built into a shared/static library with
|
||||
GNU Autotools (Autoconf, Automake, Libtool and Autoconf Archive).
|
||||
Alternatively, ctlseqs can be built into a shared/static library with
|
||||
GNU Autotools (Autoconf, Automake, Libtool and Autoconf Archive).
|
||||
|
||||
```shell
|
||||
autoreconf --install
|
||||
./configure
|
||||
make
|
||||
```
|
||||
autoreconf --install
|
||||
./configure
|
||||
make
|
||||
|
||||
Optionally, you can run tests (requires DejaGnu) and install the library.
|
||||
Optionally, you can run tests (requires DejaGnu) and install the library.
|
||||
|
||||
```shell
|
||||
make check
|
||||
make install
|
||||
```
|
||||
make check
|
||||
make install
|
||||
|
||||
Unix man pages are not automatically installed with `make install`, and should
|
||||
be installed manually with `make install-man`.
|
||||
Unix man pages are not automatically installed with `make install`, and
|
||||
should be installed manually with `make install-man`.
|
||||
|
|
|
@ -6,4 +6,6 @@
|
|||
# this notice are preserved. This file is offered as-is, without any warranty.
|
||||
#
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = include src doc man tests examples
|
||||
|
|
35
README.md
35
README.md
|
@ -1,25 +1,28 @@
|
|||
<!--
|
||||
Copyright (C) 2020,2021 CismonX <admin@cismon.net>
|
||||
|
||||
Copying and distribution of this file, with or without modification, are
|
||||
permitted in any medium without royalty, provided the copyright notice and
|
||||
this notice are preserved. This file is offered as-is, without any warranty.
|
||||
Copyright (C) 2020,2021 CismonX <admin@cismon.net>
|
||||
|
||||
Copying and distribution of this file, with or without modification, are
|
||||
permitted in any medium without royalty, provided the copyright notice and
|
||||
this notice are preserved. This file is offered as-is, without any warranty.
|
||||
-->
|
||||
|
||||
# ctlseqs
|
||||
ctlseqs
|
||||
=======
|
||||
|
||||
[![Build Status](https://shields.io/drone/build/CismonX/ctlseqs?server=https%3A%2F%2Fdrone.cismon.net)](https://drone.cismon.net/CismonX/ctlseqs)
|
||||
[![License](https://img.shields.io/badge/license-GPL--3.0--or--later-blue.svg)](COPYING)
|
||||
[![Savannah](https://img.shields.io/badge/hosted_on-Savannah-pink)](https://sv.gnu.org/p/ctlseqs)
|
||||
The ctlseqs library provides C API for handling ECMA-35/ECMA-48 compatible
|
||||
control functions, which is commonly used for communication between terminal
|
||||
emulators and text-based programs.
|
||||
|
||||
## About
|
||||
ctlseqs is free software, licensed under the terms of the GNU General Public
|
||||
License, either version 3, or any later version of the license. See COPYING
|
||||
for details.
|
||||
|
||||
The ctlseqs library provides C API for handling ECMA-35/ECMA-48 compatible control functions,
|
||||
which is commonly used for communication between terminal emulators and text-based programs.
|
||||
See INSTALL.md for instructions on how to build and install ctlseqs.
|
||||
|
||||
## Getting Started
|
||||
Visit the [project homepage] for documentation, mailing lists, releases,
|
||||
and everything else about ctlseqs.
|
||||
|
||||
For installation instructions, see [INSTALL.md](INSTALL.md).
|
||||
|
||||
Documentation of the library can be read [online](https://nongnu.org/ctlseqs/manual), or read with `info ctlseqs` after installation.
|
||||
Unix man pages are also available.
|
||||
<!-- Reference Links -->
|
||||
|
||||
[project homepage]: https://savannah.nongnu.org/projects/ctlseqs
|
||||
|
|
41
configure.ac
41
configure.ac
|
@ -1,24 +1,25 @@
|
|||
dnl
|
||||
dnl Copyright (C) 2020,2021 CismonX <admin@cismon.net>
|
||||
dnl
|
||||
dnl Copying and distribution of this file, with or without modification, are
|
||||
dnl permitted in any medium without royalty, provided the copyright notice and
|
||||
dnl this notice are preserved. This file is offered as-is, without any warranty.
|
||||
dnl Copying and distribution of this file, with or without modification,
|
||||
dnl are permitted in any medium without royalty,
|
||||
dnl provided the copyright notice and this notice are preserved.
|
||||
dnl This file is offered as-is, without any warranty.
|
||||
dnl
|
||||
|
||||
AC_PREREQ([2.60])
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([ctlseqs], [0.1.0], [bug-report@cismon.net])
|
||||
AC_CONFIG_SRCDIR([src/ctlseqs.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AM_INIT_AUTOMAKE([foreign info-in-builddir])
|
||||
AM_EXTRA_RECURSIVE_TARGETS([install-man uninstall-man])
|
||||
LT_PREREQ([2.4.0])
|
||||
LT_PREREQ([2.4.2])
|
||||
LT_INIT
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CXX
|
||||
AC_PROG_AWK
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
|
@ -28,12 +29,14 @@ AC_PROG_MAKE_SET
|
|||
m4_ifdef([AX_GCC_BUILTIN], [
|
||||
AX_GCC_BUILTIN(__builtin_expect)
|
||||
AX_GCC_BUILTIN(__builtin_unreachable)
|
||||
])
|
||||
m4_ifdef([AX_GCC_FUNC_ATTRIBUTE], [
|
||||
AX_GCC_FUNC_ATTRIBUTE(cold)
|
||||
AX_GCC_FUNC_ATTRIBUTE(hot)
|
||||
])
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([fcntl.h limits.h stddef.h stdlib.h string.h sys/ioctl.h termios.h unistd.h])
|
||||
AC_CHECK_HEADERS([fcntl.h sys/ioctl.h termios.h unistd.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_CHECK_HEADER_STDBOOL
|
||||
|
@ -42,13 +45,23 @@ AC_TYPE_SIZE_T
|
|||
AC_TYPE_SSIZE_T
|
||||
|
||||
# Checks for library functions.
|
||||
AC_CHECK_FUNCS([memset strtoul])
|
||||
AC_FUNC_MALLOC
|
||||
AC_FUNC_REALLOC
|
||||
AC_CHECK_FUNCS([strtol strtoul tcgetattr tcsetattr ioctl])
|
||||
|
||||
# Specify libtool library version.
|
||||
m4_define([CTLSEQS_LT_CURRENT], [0])
|
||||
m4_define([CTLSEQS_LT_REVISION], [0])
|
||||
m4_define([CTLSEQS_LT_CUR], [0])
|
||||
m4_define([CTLSEQS_LT_REV], [0])
|
||||
m4_define([CTLSEQS_LT_AGE], [0])
|
||||
AC_SUBST([CTLSEQS_LT_VERSION], [CTLSEQS_LT_CURRENT:CTLSEQS_LT_REVISION:CTLSEQS_LT_AGE])
|
||||
AC_SUBST([CTLSEQS_LT_VERSION], [CTLSEQS_LT_CUR:CTLSEQS_LT_REV:CTLSEQS_LT_AGE])
|
||||
|
||||
AC_CONFIG_FILES([Makefile include/Makefile doc/Makefile man/Makefile src/Makefile tests/Makefile examples/Makefile])
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
include/Makefile
|
||||
doc/Makefile
|
||||
man/Makefile
|
||||
src/Makefile
|
||||
tests/Makefile
|
||||
examples/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
# this notice are preserved. This file is offered as-is, without any warranty.
|
||||
#
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
noinst_PROGRAMS = sixdraw
|
||||
sixdraw_SOURCES = sixdraw.c
|
||||
sixdraw_LDADD = $(top_builddir)/src/libctlseqs.la
|
||||
noinst_PROGRAMS = sixdraw
|
||||
sixdraw_CPPFLAGS = -I$(top_srcdir)/include
|
||||
sixdraw_SOURCES = sixdraw.c
|
||||
sixdraw_LDADD = $(top_builddir)/src/libctlseqs.la
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* sixdraw.c - draw lines on your terminal
|
||||
* sixdraw.c - draw on your terminal
|
||||
*
|
||||
* Requires sixel graphics and 1016 mouse mode to run on your terminal.
|
||||
* These features are not widely supported. To save yourself from trouble,
|
||||
|
@ -48,9 +48,8 @@
|
|||
# define DEFAULT_TIMEOUT_MILLIS 500
|
||||
#endif // !DEFAULT_TIMEOUT_MILLIS
|
||||
|
||||
#define DECRQM_UNREC 0
|
||||
#define DECRQM_SET 1
|
||||
#define DECRQM_RST 2
|
||||
#define DECRQM_SET 1
|
||||
#define DECRQM_RST 2
|
||||
|
||||
#define DECTCEM 25
|
||||
#define DECSDM 80
|
||||
|
@ -126,7 +125,11 @@ terminate(struct sixdraw_ctx *ctx)
|
|||
|
||||
// Restore original sixel mode.
|
||||
if (ctx->sixel_scroll) {
|
||||
fprintf(ctx->out_file, ctx->legacy_xterm ? CTLSEQS_DECRST("%d") : CTLSEQS_DECSET("%d"), DECSDM);
|
||||
fprintf(
|
||||
ctx->out_file,
|
||||
ctx->legacy_xterm ? CTLSEQS_DECRST("%d") : CTLSEQS_DECSET("%d"),
|
||||
DECSDM
|
||||
);
|
||||
}
|
||||
|
||||
// Restore original terminal modes.
|
||||
|
@ -168,7 +171,9 @@ decrqm(struct sixdraw_ctx *ctx, unsigned mode, char const *name)
|
|||
print_error(ctx, "failed to get %s status", name);
|
||||
return false;
|
||||
}
|
||||
if (result[0].num != mode || result[1].num == DECRQM_UNREC) {
|
||||
if ( result[0].num != mode
|
||||
|| (result[1].num != DECRQM_SET && result[1].num != DECRQM_RST)
|
||||
) {
|
||||
print_error(ctx, "%s status not recognizable", name);
|
||||
return false;
|
||||
}
|
||||
|
@ -250,7 +255,8 @@ init(struct sixdraw_ctx *ctx, int argc, char **argv)
|
|||
break;
|
||||
case '?':
|
||||
default:
|
||||
fprintf(ctx->out_file, "%s\n", "Usage: sixdraw [-t timeout] [-c line-color]");
|
||||
fprintf(ctx->out_file, "%s\n",
|
||||
"Usage: sixdraw [-t timeout] [-c line-color]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +270,8 @@ init(struct sixdraw_ctx *ctx, int argc, char **argv)
|
|||
char const *patterns[] = {
|
||||
CTLSEQS_RESP_PRIMARY_DA(CTLSEQS_PH_NUMS),
|
||||
CTLSEQS_RESP_DECRQM(CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
CTLSEQS_RESP_SGR_MOUSE(CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, "M"),
|
||||
CTLSEQS_RESP_SGR_MOUSE(
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, "M"),
|
||||
CTLSEQS_RESP_XTVERSION(CTLSEQS_PH_STR),
|
||||
};
|
||||
struct ctlseqs_matcher_options matcher_options = {
|
||||
|
@ -339,7 +346,7 @@ prepare(struct sixdraw_ctx *ctx)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check terminal support for sixel graphics and DEC locator.
|
||||
// Check terminal support for sixel graphics.
|
||||
fprintf(ctx->out_file, CTLSEQS_PRIMARY_DA());
|
||||
ssize_t retval;
|
||||
do {
|
||||
|
@ -384,9 +391,14 @@ prepare(struct sixdraw_ctx *ctx)
|
|||
}
|
||||
// Before patch #369, XTerm implemented DECSDM incorrectly.
|
||||
// See https://invisible-island.net/xterm/xterm.log.html#xterm_369
|
||||
ctx->sixel_scroll = result[1].num == (ctx->legacy_xterm ? DECRQM_RST : DECRQM_SET);
|
||||
ctx->sixel_scroll
|
||||
= result[1].num == (ctx->legacy_xterm ? DECRQM_RST : DECRQM_SET);
|
||||
if (ctx->sixel_scroll) {
|
||||
fprintf(ctx->out_file, ctx->legacy_xterm ? CTLSEQS_DECSET("%d") : CTLSEQS_DECRST("%d"), DECSDM);
|
||||
fprintf(
|
||||
ctx->out_file,
|
||||
ctx->legacy_xterm ? CTLSEQS_DECSET("%d") : CTLSEQS_DECRST("%d"),
|
||||
DECSDM
|
||||
);
|
||||
}
|
||||
|
||||
// Enable button event tracking mode.
|
||||
|
@ -418,9 +430,14 @@ prepare(struct sixdraw_ctx *ctx)
|
|||
|
||||
// Build the immutable part of sixel sequence.
|
||||
ctx->sixel_init_size = sizeof(SIXEL_SEQ_HEAD) - 1;
|
||||
ctx->sixel_init_size += sprintf(sixel_seq + ctx->sixel_init_size, "%u;%u#0;2;%d;%d;%d#0",
|
||||
ctx->ch_width, ctx->ch_height, ((ctx->line_color >> 16) & 0xFF) * 100 / 0xFF,
|
||||
((ctx->line_color >> 8) & 0xFF) * 100 / 0xFF, ((ctx->line_color >> 0) & 0xFF) * 100 / 0xFF);
|
||||
ctx->sixel_init_size += sprintf(
|
||||
sixel_seq + ctx->sixel_init_size,
|
||||
"%u;%u#0;2;%d;%d;%d#0",
|
||||
ctx->ch_width, ctx->ch_height,
|
||||
((ctx->line_color >> 16) & 0xFF) * 100 / 0xFF,
|
||||
((ctx->line_color >> 8) & 0xFF) * 100 / 0xFF,
|
||||
((ctx->line_color >> 0) & 0xFF) * 100 / 0xFF
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -428,27 +445,34 @@ prepare(struct sixdraw_ctx *ctx)
|
|||
static bool
|
||||
draw(struct sixdraw_ctx *ctx)
|
||||
{
|
||||
fprintf(ctx->out_file, CTLSEQS_CUP("%d", "1") "Canvas size: %ux%u. Line color: #%06X.",
|
||||
ctx->rows - 1, ctx->canvas_width, ctx->canvas_height, ctx->line_color);
|
||||
fprintf(ctx->out_file, CTLSEQS_CUP("%d", "1") "Usage: Draw with mouse. Press Ctrl+C to exit.", ctx->rows);
|
||||
fprintf(
|
||||
ctx->out_file,
|
||||
CTLSEQS_CUP("%d", "1") "Canvas size: %ux%u. Line color: #%06X.",
|
||||
ctx->rows - 1, ctx->canvas_width, ctx->canvas_height, ctx->line_color
|
||||
);
|
||||
fprintf(
|
||||
ctx->out_file,
|
||||
CTLSEQS_CUP("%d", "1") "Usage: Draw with mouse. Press Ctrl+C to exit.",
|
||||
ctx->rows
|
||||
);
|
||||
|
||||
union ctlseqs_value *result = ctx->result;
|
||||
while (true) {
|
||||
switch (ctlseqs_read(ctx->reader, ctx->matcher, -1)) {
|
||||
case 2: // CTLSEQS_RESP_SGR_MOUSE
|
||||
// Pixel coordinates start at 1 instead of 0.
|
||||
print_sixel_dot(ctx, result[1].num - 1, result[2].num - 1);
|
||||
break;
|
||||
case CTLSEQS_NOSEQ:
|
||||
// Press Ctrl+C to exit.
|
||||
if (result[1].str[0] == 0x03) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case CTLSEQS_ERROR:
|
||||
case CTLSEQS_NOMEM:
|
||||
case CTLSEQS_EOF:
|
||||
return false;
|
||||
case 2: // CTLSEQS_RESP_SGR_MOUSE
|
||||
// Pixel coordinates start at 1 instead of 0.
|
||||
print_sixel_dot(ctx, result[1].num - 1, result[2].num - 1);
|
||||
break;
|
||||
case CTLSEQS_NOSEQ:
|
||||
// Press Ctrl+C to exit.
|
||||
if (result[1].str[0] == 0x03) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case CTLSEQS_ERROR:
|
||||
case CTLSEQS_NOMEM:
|
||||
case CTLSEQS_EOF:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* ctlseqs.h - helper library for control sequences
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
|
||||
*
|
||||
*
|
||||
* This file is part of the ctlseqs library.
|
||||
*
|
||||
* ctlseqs is free software: you can redistribute it and/or modify
|
||||
|
@ -30,89 +30,166 @@
|
|||
|
||||
/* C0 Control Functions */
|
||||
|
||||
#define CTLSEQS_NUL "\x00" // Null
|
||||
#define CTLSEQS_SOH "\x01" // Start of Heading
|
||||
#define CTLSEQS_STX "\x02" // Start of Text
|
||||
#define CTLSEQS_ETX "\x03" // End of Text
|
||||
#define CTLSEQS_EOT "\x04" // End of Transmission
|
||||
#define CTLSEQS_ENQ "\x05" // Enquiry
|
||||
#define CTLSEQS_ACK "\x06" // Acknowledge
|
||||
#define CTLSEQS_BEL "\x07" // Bell
|
||||
#define CTLSEQS_BS "\x08" // Backspace
|
||||
#define CTLSEQS_HT "\x09" // Horizontal Tab
|
||||
#define CTLSEQS_LF "\x0a" // Line Feed
|
||||
#define CTLSEQS_VT "\x0b" // Vertical Tab
|
||||
#define CTLSEQS_FF "\x0c" // Form Feed or New Page
|
||||
#define CTLSEQS_CR "\x0d" // Carriage Return
|
||||
#define CTLSEQS_SO "\x0e" // Shift Out
|
||||
#define CTLSEQS_SI "\x0f" // Shift In
|
||||
#define CTLSEQS_DLE "\x10" // Data Link Escape
|
||||
#define CTLSEQS_DC1 "\x11" // Device Control 1
|
||||
#define CTLSEQS_DC2 "\x12" // Device Control 2
|
||||
#define CTLSEQS_DC3 "\x13" // Device Control 3
|
||||
#define CTLSEQS_DC4 "\x14" // Device Control 4
|
||||
#define CTLSEQS_NAK "\x15" // Negative Acknowledgement
|
||||
#define CTLSEQS_SYN "\x16" // Synchronous Idle
|
||||
#define CTLSEQS_ETB "\x17" // End of Transmission Block
|
||||
#define CTLSEQS_CAN "\x18" // Cancel
|
||||
#define CTLSEQS_EM "\x19" // End of Medium
|
||||
#define CTLSEQS_SUB "\x1a" // Substitute
|
||||
#define CTLSEQS_ESC "\x1b" // Escape
|
||||
#define CTLSEQS_FS "\x1c" // File Separator
|
||||
#define CTLSEQS_GS "\x1d" // Group Separator
|
||||
#define CTLSEQS_RS "\x1e" // Record Separator
|
||||
#define CTLSEQS_US "\x1f" // Unit Separator
|
||||
#define CTLSEQS_SP "\x20" // Space
|
||||
#define CTLSEQS_DEL "\x7f" // Delete
|
||||
// Null
|
||||
#define CTLSEQS_NUL "\x00"
|
||||
// Start of Heading
|
||||
#define CTLSEQS_SOH "\x01"
|
||||
// Start of Text
|
||||
#define CTLSEQS_STX "\x02"
|
||||
// End of Text
|
||||
#define CTLSEQS_ETX "\x03"
|
||||
// End of Transmission
|
||||
#define CTLSEQS_EOT "\x04"
|
||||
// Enquiry
|
||||
#define CTLSEQS_ENQ "\x05"
|
||||
// Acknowledge
|
||||
#define CTLSEQS_ACK "\x06"
|
||||
// Bell
|
||||
#define CTLSEQS_BEL "\x07"
|
||||
// Backspace
|
||||
#define CTLSEQS_BS "\x08"
|
||||
// Horizontal Tab
|
||||
#define CTLSEQS_HT "\x09"
|
||||
// Line Feed
|
||||
#define CTLSEQS_LF "\x0a"
|
||||
// Vertical Tab
|
||||
#define CTLSEQS_VT "\x0b"
|
||||
// Form Feed or New Page
|
||||
#define CTLSEQS_FF "\x0c"
|
||||
// Carriage Return
|
||||
#define CTLSEQS_CR "\x0d"
|
||||
// Shift Out
|
||||
#define CTLSEQS_SO "\x0e"
|
||||
// Shift In
|
||||
#define CTLSEQS_SI "\x0f"
|
||||
// Data Link Escape
|
||||
#define CTLSEQS_DLE "\x10"
|
||||
// Device Control 1
|
||||
#define CTLSEQS_DC1 "\x11"
|
||||
// Device Control 2
|
||||
#define CTLSEQS_DC2 "\x12"
|
||||
// Device Control 3
|
||||
#define CTLSEQS_DC3 "\x13"
|
||||
// Device Control 4
|
||||
#define CTLSEQS_DC4 "\x14"
|
||||
// Negative Acknowledgement
|
||||
#define CTLSEQS_NAK "\x15"
|
||||
// Synchronous Idle
|
||||
#define CTLSEQS_SYN "\x16"
|
||||
// End of Transmission Block
|
||||
#define CTLSEQS_ETB "\x17"
|
||||
// Cancel
|
||||
#define CTLSEQS_CAN "\x18"
|
||||
// End of Medium
|
||||
#define CTLSEQS_EM "\x19"
|
||||
// Substitute
|
||||
#define CTLSEQS_SUB "\x1a"
|
||||
// Escape
|
||||
#define CTLSEQS_ESC "\x1b"
|
||||
// File Separator
|
||||
#define CTLSEQS_FS "\x1c"
|
||||
// Group Separator
|
||||
#define CTLSEQS_GS "\x1d"
|
||||
// Record Separator
|
||||
#define CTLSEQS_RS "\x1e"
|
||||
// Unit Separator
|
||||
#define CTLSEQS_US "\x1f"
|
||||
// Space
|
||||
#define CTLSEQS_SP "\x20"
|
||||
// Delete
|
||||
#define CTLSEQS_DEL "\x7f"
|
||||
|
||||
/* C1 Control Functions (2-character 7-bit representation) */
|
||||
|
||||
#define CTLSEQS_BPH CTLSEQS_ESC "B" // Break Permitted Here
|
||||
#define CTLSEQS_NBH CTLSEQS_ESC "C" // No Break Here
|
||||
#define CTLSEQS_IND CTLSEQS_ESC "D" // Index
|
||||
#define CTLSEQS_NEL CTLSEQS_ESC "E" // Next Line
|
||||
#define CTLSEQS_SSA CTLSEQS_ESC "F" // Start of Selected Area
|
||||
#define CTLSEQS_ESA CTLSEQS_ESC "G" // End of Selected Area
|
||||
#define CTLSEQS_HTS CTLSEQS_ESC "H" // Character Tabulation Set
|
||||
#define CTLSEQS_VTS CTLSEQS_ESC "J" // Line Tabulation Set
|
||||
#define CTLSEQS_PLD CTLSEQS_ESC "K" // Partial Line Forward
|
||||
#define CTLSEQS_PLU CTLSEQS_ESC "L" // Partial Line Backward
|
||||
#define CTLSEQS_RI CTLSEQS_ESC "M" // Reverse Index
|
||||
#define CTLSEQS_SS2 CTLSEQS_ESC "N" // Single Shift 2
|
||||
#define CTLSEQS_SS3 CTLSEQS_ESC "O" // Single Shift 3
|
||||
#define CTLSEQS_DCS CTLSEQS_ESC "P" // Device Control String
|
||||
#define CYLSEQS_PU1 CTLSEQS_ESC "Q" // Private Use 1
|
||||
#define CYLSEQS_PU2 CTLSEQS_ESC "R" // Private Use 2
|
||||
#define CYLSEQS_STS CTLSEQS_ESC "S" // Set Transmit State
|
||||
#define CTLSEQS_CCH CTLSEQS_ESC "T" // Cancel Character
|
||||
#define CTLSEQS_MW CTLSEQS_ESC "U" // Message Waiting
|
||||
#define CTLSEQS_SPA CTLSEQS_ESC "V" // Start of Guarded Area
|
||||
#define CTLSEQS_EPA CTLSEQS_ESC "W" // End of Guarded Area
|
||||
#define CTLSEQS_SOS CTLSEQS_ESC "X" // Start of String
|
||||
#define CTLSEQS_HTJ CTLSEQS_ESC "Y" // Character Tabulation with Justification
|
||||
#define CYLSEQS_SCI CTLSEQS_ESC "Z" // Single Character Introducer
|
||||
#define CTLSEQS_CSI CTLSEQS_ESC "[" // Control Sequence Introducer
|
||||
#define CTLSEQS_ST CTLSEQS_ESC "\\" // String Terminator
|
||||
#define CTLSEQS_OSC CTLSEQS_ESC "]" // Operating System Command
|
||||
#define CTLSEQS_PM CTLSEQS_ESC "^" // Privacy Message
|
||||
#define CTLSEQS_APC CTLSEQS_ESC "_" // Application Program Command
|
||||
// Break Permitted Here
|
||||
#define CTLSEQS_BPH CTLSEQS_ESC "B"
|
||||
// No Break Here
|
||||
#define CTLSEQS_NBH CTLSEQS_ESC "C"
|
||||
// Index
|
||||
#define CTLSEQS_IND CTLSEQS_ESC "D"
|
||||
// Next Line
|
||||
#define CTLSEQS_NEL CTLSEQS_ESC "E"
|
||||
// Start of Selected Area
|
||||
#define CTLSEQS_SSA CTLSEQS_ESC "F"
|
||||
// End of Selected Area
|
||||
#define CTLSEQS_ESA CTLSEQS_ESC "G"
|
||||
// Character Tabulation Set
|
||||
#define CTLSEQS_HTS CTLSEQS_ESC "H"
|
||||
// Line Tabulation Set
|
||||
#define CTLSEQS_VTS CTLSEQS_ESC "J"
|
||||
// Partial Line Forward
|
||||
#define CTLSEQS_PLD CTLSEQS_ESC "K"
|
||||
// Partial Line Backward
|
||||
#define CTLSEQS_PLU CTLSEQS_ESC "L"
|
||||
// Reverse Index
|
||||
#define CTLSEQS_RI CTLSEQS_ESC "M"
|
||||
// Single Shift 2
|
||||
#define CTLSEQS_SS2 CTLSEQS_ESC "N"
|
||||
// Single Shift 3
|
||||
#define CTLSEQS_SS3 CTLSEQS_ESC "O"
|
||||
// Device Control String
|
||||
#define CTLSEQS_DCS CTLSEQS_ESC "P"
|
||||
// Private Use 1
|
||||
#define CTLSEQS_PU1 CTLSEQS_ESC "Q"
|
||||
// Private Use 2
|
||||
#define CTLSEQS_PU2 CTLSEQS_ESC "R"
|
||||
// Set Transmit State
|
||||
#define CTLSEQS_STS CTLSEQS_ESC "S"
|
||||
// Cancel Character
|
||||
#define CTLSEQS_CCH CTLSEQS_ESC "T"
|
||||
// Message Waiting
|
||||
#define CTLSEQS_MW CTLSEQS_ESC "U"
|
||||
// Start of Guarded Area
|
||||
#define CTLSEQS_SPA CTLSEQS_ESC "V"
|
||||
// End of Guarded Area
|
||||
#define CTLSEQS_EPA CTLSEQS_ESC "W"
|
||||
// Start of String
|
||||
#define CTLSEQS_SOS CTLSEQS_ESC "X"
|
||||
// Character Tabulation with Justification
|
||||
#define CTLSEQS_HTJ CTLSEQS_ESC "Y"
|
||||
// Single Character Introducer
|
||||
#define CTLSEQS_SCI CTLSEQS_ESC "Z"
|
||||
// Control Sequence Introducer
|
||||
#define CTLSEQS_CSI CTLSEQS_ESC "["
|
||||
// String Terminator
|
||||
#define CTLSEQS_ST CTLSEQS_ESC "\\"
|
||||
// Operating System Command
|
||||
#define CTLSEQS_OSC CTLSEQS_ESC "]"
|
||||
// Privacy Message
|
||||
#define CTLSEQS_PM CTLSEQS_ESC "^"
|
||||
// Application Program Command
|
||||
#define CTLSEQS_APC CTLSEQS_ESC "_"
|
||||
|
||||
/* Controls beginning with ESC */
|
||||
|
||||
#define CTLSEQS_S7C1T() CTLSEQS_ESC " F" // 7-bit controls
|
||||
#define CTLSEQS_S8C1T() CTLSEQS_ESC " G" // 8-bit controls
|
||||
#define CTLSEQS_DECDHL_TOP() CTLSEQS_ESC "#3" // DEC double-height line, top half
|
||||
#define CTLSEQS_DECDHL_BOTOM() CTLSEQS_ESC "#4" // DEC double-height line, bottom half
|
||||
#define CTLSEQS_DECSWL() CTLSEQS_ESC "#5" // DEC single-width line
|
||||
#define CTLSEQS_DECDWL() CTLSEQS_ESC "#6" // DEC double-width line
|
||||
#define CTLSEQS_DECALN() CTLSEQS_ESC "#8" // DEC Screen Alignment Test
|
||||
#define CTLSEQS_DECBI() CTLSEQS_ESC "6" // Back Index
|
||||
#define CTLSEQS_DECSC() CTLSEQS_ESC "7" // Save Cursor
|
||||
#define CTLSEQS_DECRC() CTLSEQS_ESC "8" // Restore Cursor
|
||||
#define CTLSEQS_DECFI() CTLSEQS_ESC "9" // Forward Index
|
||||
#define CTLSEQS_DECKPAM() CTLSEQS_ESC "=" // Application Keypad
|
||||
#define CTLSEQS_DECKPNM() CTLSEQS_ESC ">" // Normal Keypad
|
||||
#define CTLSEQS_RIS() CTLSEQS_ESC "c" // Full Reset
|
||||
// 7-bit controls
|
||||
#define CTLSEQS_S7C1T() CTLSEQS_ESC " F"
|
||||
// 8-bit controls
|
||||
#define CTLSEQS_S8C1T() CTLSEQS_ESC " G"
|
||||
// DEC double-height line, top half
|
||||
#define CTLSEQS_DECDHL_TOP() CTLSEQS_ESC "#3"
|
||||
// DEC double-height line, bottom half
|
||||
#define CTLSEQS_DECDHL_BOTOM() CTLSEQS_ESC "#4"
|
||||
// DEC single-width line
|
||||
#define CTLSEQS_DECSWL() CTLSEQS_ESC "#5"
|
||||
// DEC double-width line
|
||||
#define CTLSEQS_DECDWL() CTLSEQS_ESC "#6"
|
||||
// DEC Screen Alignment Test
|
||||
#define CTLSEQS_DECALN() CTLSEQS_ESC "#8"
|
||||
// Back Index
|
||||
#define CTLSEQS_DECBI() CTLSEQS_ESC "6"
|
||||
// Save Cursor
|
||||
#define CTLSEQS_DECSC() CTLSEQS_ESC "7"
|
||||
// Restore Cursor
|
||||
#define CTLSEQS_DECRC() CTLSEQS_ESC "8"
|
||||
// Forward Index
|
||||
#define CTLSEQS_DECFI() CTLSEQS_ESC "9"
|
||||
// Application Keypad
|
||||
#define CTLSEQS_DECKPAM() CTLSEQS_ESC "="
|
||||
// Normal Keypad
|
||||
#define CTLSEQS_DECKPNM() CTLSEQS_ESC ">"
|
||||
// Full Reset
|
||||
#define CTLSEQS_RIS() CTLSEQS_ESC "c"
|
||||
|
||||
/* Device-Control functions */
|
||||
|
||||
|
@ -172,11 +249,13 @@
|
|||
// Scroll up $n Lines
|
||||
#define CTLSEQS_SU(n) CTLSEQS_CSI n "S"
|
||||
// Set or request graphics attribute
|
||||
#define CTLSEQS_XTSMGRAPHICS(i1, i2, is) CTLSEQS_CSI "?" i1 ";" i2 ";" is "S"
|
||||
#define CTLSEQS_XTSMGRAPHICS(i1, i2, is) \
|
||||
CTLSEQS_CSI "?" i1 ";" i2 ";" is "S"
|
||||
// Scroll Down $n Line(s)
|
||||
#define CTLSEQS_SD(n) CTLSEQS_CSI n "T"
|
||||
// Initiate highlight mouse tracking
|
||||
#define CTLSEQS_XTHIMOUSE(f, x, y, fr, lr) CTLSEQS_CSI f ";" x ";" y ";" fr ";" lr "T"
|
||||
#define CTLSEQS_XTHIMOUSE(f, x, y, fr, lr) \
|
||||
CTLSEQS_CSI f ";" x ";" y ";" fr ";" lr "T"
|
||||
// Reset title mode features to default value
|
||||
#define CTLSEQS_XTRMTITLE(is) CTLSEQS_CSI ">" is "T"
|
||||
// Erase $n Character(s)
|
||||
|
@ -211,7 +290,7 @@
|
|||
#define CTLSEQS_MC(i) CTLSEQS_CSI i "i"
|
||||
// Media Copy, DEC-specific
|
||||
#define CTLSEQS_MC_DEC(i) CTLSEQS_CSI "?" i "i"
|
||||
// Reset Mode
|
||||
// Reset Mode
|
||||
#define CTLSEQS_RM(i) CTLSEQS_CSI i "l"
|
||||
// DEC Private Mode Reset
|
||||
#define CTLSEQS_DECRST(i) CTLSEQS_CSI "?" i "l"
|
||||
|
@ -248,7 +327,8 @@
|
|||
// Restore DEC Private Mode Values
|
||||
#define CTLSEQS_XTRESTORE(is) CTLSEQS_CSI "?" is "r"
|
||||
// Change Attributes in Rectangular Area
|
||||
#define CTLSEQS_DECCARA(t, l, b, r, i) CTLSEQS_CSI t ";" l ";" b ";" r ";" i "$r"
|
||||
#define CTLSEQS_DECCARA(t, l, b, r, i) \
|
||||
CTLSEQS_CSI t ";" l ";" b ";" r ";" i "$r"
|
||||
// Save cursor
|
||||
#define CTLSEQS_SCOSC() CTLSEQS_CSI "s"
|
||||
// Set left and right margins
|
||||
|
@ -262,39 +342,47 @@
|
|||
// Set warning-bell volume
|
||||
#define CTLSEQS_DECSWBV(i) CTLSEQS_CSI i " t"
|
||||
// Reverse Attributes in Rectangular Area
|
||||
#define CTLSEQS_DECRARA(t, l, b, r, i) CTLSEQS_CSI t ";" l ";" b ";" r ";" i "$t"
|
||||
#define CTLSEQS_DECRARA(t, l, b, r, i) \
|
||||
CTLSEQS_CSI t ";" l ";" b ";" r ";" i "$t"
|
||||
// Restore cursor
|
||||
#define CTLSEQS_SCORC() CTLSEQS_CSI "u"
|
||||
// Set margin-bell volume
|
||||
#define CTLSEQS_DECSMBV(i) CTLSEQS_CSI i " u"
|
||||
// Copy Rectangular Area
|
||||
#define CTLSEQS_DECCRA(t, l, b, r, sp, dt, dl, dp) CTLSEQS_CSI t ";" l ";" b ";" r ";" sp ";" dt ";" dl ";" dp "$v"
|
||||
#define CTLSEQS_DECCRA(t, l, b, r, sp, dt, dl, dp) \
|
||||
CTLSEQS_CSI t ";" l ";" b ";" r ";" sp ";" dt ";" dl ";" dp "$v"
|
||||
// Request presentation state report
|
||||
#define CTLSEQS_DECRQPSR(i) CTLSEQS_CSI i "$w"
|
||||
// Enable Filter Rectangle
|
||||
#define CTLSEQS_DECEFR(t, l, b, r) CTLSEQS_CSI t ";" l ";" b ";" r "'w"
|
||||
#define CTLSEQS_DECEFR(t, l, b, r) \
|
||||
CTLSEQS_CSI t ";" l ";" b ";" r "'w"
|
||||
// Request Terminal Parameters
|
||||
#define CTLSEQS_DECREQTPARM(i) CTLSEQS_CSI i "x"
|
||||
// Select Attribute Change Extent
|
||||
#define CTLSEQS_DECSACE(i) CTLSEQS_CSI i "*x"
|
||||
// Fill Rectangular Area
|
||||
#define CTLSEQS_DECFRA(c, t, l, b, r) CTLSEQS_CSI c ";" t ";" l ";" b ";" r "$x"
|
||||
#define CTLSEQS_DECFRA(c, t, l, b, r) \
|
||||
CTLSEQS_CSI c ";" t ";" l ";" b ";" r "$x"
|
||||
// Select checksum extension
|
||||
#define CTLSEQS_XTCHECKSUM(i) CTLSEQS_CSI i "#y"
|
||||
// Request Checksum of Rectangular Area
|
||||
#define CTLSEQS_DECRQCRA(id, p, t, l, b, r) CTLSEQS_CSI id ";" p ";" t ";" l ";" b ";" r "*y"
|
||||
#define CTLSEQS_DECRQCRA(id, p, t, l, b, r) \
|
||||
CTLSEQS_CSI id ";" p ";" t ";" l ";" b ";" r "*y"
|
||||
// Enable Locator Reporting
|
||||
#define CTLSEQS_DECELR(i1, i2) CTLSEQS_CSI i1 ";" i2 "'z"
|
||||
// Erase Rectangular Area
|
||||
#define CTLSEQS_DECERA(t, l, b, r) CTLSEQS_CSI t ";" l ";" b ";" r "$z"
|
||||
#define CTLSEQS_DECERA(t, l, b, r) \
|
||||
CTLSEQS_CSI t ";" l ";" b ";" r "$z"
|
||||
// Select Locator Events
|
||||
#define CTLSEQS_DECSLE(is) CTLSEQS_CSI is "'{"
|
||||
// Push video attributes onto stack
|
||||
#define CTLSEQS_XTPUSHSGR(is) CTLSEQS_CSI is "#{"
|
||||
// Selective Erase Rectangular Area
|
||||
#define CTLSEQS_DECSERA(t, l, b, r) CTLSEQS_CSI t ";" l ";" b ";" r "${"
|
||||
#define CTLSEQS_DECSERA(t, l, b, r) \
|
||||
CTLSEQS_CSI t ";" l ";" b ";" r "${"
|
||||
// Report selected graphic rendition
|
||||
#define CTLSEQS_XTREPORTSGR(t, l, b, r) CTLSEQS_CSI t ";" l ";" b ";" r "$|"
|
||||
#define CTLSEQS_XTREPORTSGR(t, l, b, r) \
|
||||
CTLSEQS_CSI t ";" l ";" b ";" r "$|"
|
||||
// Select columns per page
|
||||
#define CTLSEQS_DECSCPP(i) CTLSEQS_CSI i "$|"
|
||||
// Request Locator Position
|
||||
|
@ -324,7 +412,8 @@
|
|||
// Primary DA response message
|
||||
#define CTLSEQS_RESP_PRIMARY_DA(ns) CTLSEQS_CSI "?" ns "c"
|
||||
// Secondary DA response message
|
||||
#define CTLSEQS_RESP_SECONDARY_DA(n1, n2, n3) CTLSEQS_CSI ">" n1 ";" n2 ";" n3 "c"
|
||||
#define CTLSEQS_RESP_SECONDARY_DA(n1, n2, n3) \
|
||||
CTLSEQS_CSI ">" n1 ";" n2 ";" n3 "c"
|
||||
// DECLRP response message
|
||||
#define CTLSEQS_RESP_DECXCPR(n1, n2) CTLSEQS_CSI "?" n1 ";" n2 "R"
|
||||
// DSR response message
|
||||
|
@ -342,34 +431,58 @@
|
|||
// DECRQCRA response message
|
||||
#define CTLSEQS_RESP_DECRQCRA(n, s) CTLSEQS_DCS n "!~" s CTLSEQS_ST
|
||||
// DECRQLP response message
|
||||
#define CTLSEQS_RESP_DECRQLP(e, b, row, col, p) CTLSEQS_CSI e ";" b ";" row ";" col ";" p "&w"
|
||||
#define CTLSEQS_RESP_DECRQLP(e, b, row, col, p) \
|
||||
CTLSEQS_CSI e ";" b ";" row ";" col ";" p "&w"
|
||||
// Mouse response in SGR mouse mode
|
||||
#define CTLSEQS_RESP_SGR_MOUSE(n, col, row, c) CTLSEQS_CSI "<" n ";" col ";" row c
|
||||
#define CTLSEQS_RESP_SGR_MOUSE(n, col, row, c) \
|
||||
CTLSEQS_CSI "<" n ";" col ";" row c
|
||||
|
||||
/// PC-Style Function Keys
|
||||
|
||||
#define CTLSEQS_KEY_UP() CTLSEQS_CSI "A" // Up arrow key
|
||||
#define CTLSEQS_KEY_DOWN() CTLSEQS_CSI "B" // Down arrow key
|
||||
#define CTLSEQS_KEY_RIGHT() CTLSEQS_CSI "C" // Right arrow key
|
||||
#define CTLSEQS_KEY_LEFT() CTLSEQS_CSI "D" // Left arrow key
|
||||
#define CTLSEQS_KEY_HOME() CTLSEQS_CSI "H" // Home key
|
||||
#define CTLSEQS_KEY_END() CTLSEQS_CSI "F" // End key
|
||||
#define CTLSEQS_KEY_INSERT() CTLSEQS_CSI "2~" // Insert key
|
||||
#define CTLSEQS_KEY_DELETE() CTLSEQS_CSI "3~" // Delete key
|
||||
#define CTLSEQS_KEY_PGUP() CTLSEQS_CSI "5~" // Page Up key
|
||||
#define CTLSEQS_KEY_PGDN() CTLSEQS_CSI "6~" // Page Down key
|
||||
#define CTLSEQS_KEY_F1() CTLSEQS_SS3 "P" // F1 key
|
||||
#define CTLSEQS_KEY_F2() CTLSEQS_SS3 "Q" // F2 key
|
||||
#define CTLSEQS_KEY_F3() CTLSEQS_SS3 "R" // F3 key
|
||||
#define CTLSEQS_KEY_F4() CTLSEQS_SS3 "S" // F4 key
|
||||
#define CTLSEQS_KEY_F5() CTLSEQS_CSI "15~" // F5 key
|
||||
#define CTLSEQS_KEY_F6() CTLSEQS_CSI "17~" // F6 key
|
||||
#define CTLSEQS_KEY_F7() CTLSEQS_CSI "18~" // F7 key
|
||||
#define CTLSEQS_KEY_F8() CTLSEQS_CSI "19~" // F8 key
|
||||
#define CTLSEQS_KEY_F9() CTLSEQS_CSI "20~" // F9 key
|
||||
#define CTLSEQS_KEY_F10() CTLSEQS_CSI "21~" // F10 key
|
||||
#define CTLSEQS_KEY_F11() CTLSEQS_CSI "23~" // F11 key
|
||||
#define CTLSEQS_KEY_F12() CTLSEQS_CSI "24~" // F12 key
|
||||
// Up arrow key
|
||||
#define CTLSEQS_KEY_UP() CTLSEQS_CSI "A"
|
||||
// Down arrow key
|
||||
#define CTLSEQS_KEY_DOWN() CTLSEQS_CSI "B"
|
||||
// Right arrow key
|
||||
#define CTLSEQS_KEY_RIGHT() CTLSEQS_CSI "C"
|
||||
// Left arrow key
|
||||
#define CTLSEQS_KEY_LEFT() CTLSEQS_CSI "D"
|
||||
// Home key
|
||||
#define CTLSEQS_KEY_HOME() CTLSEQS_CSI "H"
|
||||
// End key
|
||||
#define CTLSEQS_KEY_END() CTLSEQS_CSI "F"
|
||||
// Insert key
|
||||
#define CTLSEQS_KEY_INSERT() CTLSEQS_CSI "2~"
|
||||
// Delete key
|
||||
#define CTLSEQS_KEY_DELETE() CTLSEQS_CSI "3~"
|
||||
// Page Up key
|
||||
#define CTLSEQS_KEY_PGUP() CTLSEQS_CSI "5~"
|
||||
// Page Down key
|
||||
#define CTLSEQS_KEY_PGDN() CTLSEQS_CSI "6~"
|
||||
// F1 key
|
||||
#define CTLSEQS_KEY_F1() CTLSEQS_SS3 "P"
|
||||
// F2 key
|
||||
#define CTLSEQS_KEY_F2() CTLSEQS_SS3 "Q"
|
||||
// F3 key
|
||||
#define CTLSEQS_KEY_F3() CTLSEQS_SS3 "R"
|
||||
// F4 key
|
||||
#define CTLSEQS_KEY_F4() CTLSEQS_SS3 "S"
|
||||
// F5 key
|
||||
#define CTLSEQS_KEY_F5() CTLSEQS_CSI "15~"
|
||||
// F6 key
|
||||
#define CTLSEQS_KEY_F6() CTLSEQS_CSI "17~"
|
||||
// F7 key
|
||||
#define CTLSEQS_KEY_F7() CTLSEQS_CSI "18~"
|
||||
// F8 key
|
||||
#define CTLSEQS_KEY_F8() CTLSEQS_CSI "19~"
|
||||
// F9 key
|
||||
#define CTLSEQS_KEY_F9() CTLSEQS_CSI "20~"
|
||||
// F10 key
|
||||
#define CTLSEQS_KEY_F10() CTLSEQS_CSI "21~"
|
||||
// F11 key
|
||||
#define CTLSEQS_KEY_F11() CTLSEQS_CSI "23~"
|
||||
// F12 key
|
||||
#define CTLSEQS_KEY_F12() CTLSEQS_CSI "24~"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include <cstddef>
|
||||
|
@ -381,19 +494,29 @@
|
|||
|
||||
/* Placeholders */
|
||||
|
||||
#define CTLSEQS_PH_NUM "\x0e" // CSI Parameter Bytes, numbers only
|
||||
#define CTLSEQS_PH_NUMS "\x0f" // CSI Parameter Bytes, multiple numbers separated by semicolon
|
||||
#define CTLSEQS_PH_STR "\x10" // String, printable characters only
|
||||
#define CTLSEQS_PH_CMDSTR "\x11" // Command String
|
||||
#define CTLSEQS_PH_CSI_PARAM "\x12" // CSI Parameter Bytes
|
||||
#define CTLSEQS_PH_CSI_INTMD "\x13" // CSI Intermediate Bytes
|
||||
#define CTLSEQS_PH_HEXNUM "\x14" // Printable characters representing a hexadecimal number
|
||||
#define CTLSEQS_PH_CHRSTR "\x15" // Character String
|
||||
// CSI Parameter Bytes, numbers only
|
||||
#define CTLSEQS_PH_NUM "\x0e"
|
||||
// CSI Parameter Bytes, multiple numbers separated by semicolon
|
||||
#define CTLSEQS_PH_NUMS "\x0f"
|
||||
// String, printable characters only
|
||||
#define CTLSEQS_PH_STR "\x10"
|
||||
// Command String
|
||||
#define CTLSEQS_PH_CMDSTR "\x11"
|
||||
// CSI Parameter Bytes
|
||||
#define CTLSEQS_PH_CSI_PARAM "\x12"
|
||||
// CSI Intermediate Bytes
|
||||
#define CTLSEQS_PH_CSI_INTMD "\x13"
|
||||
// Printable characters representing a hexadecimal number
|
||||
#define CTLSEQS_PH_HEXNUM "\x14"
|
||||
// Character String
|
||||
#define CTLSEQS_PH_CHRSTR "\x15"
|
||||
|
||||
/* Reader option flags */
|
||||
|
||||
#define CTLSEQS_READER_NO_POLL (1 << 0) // Do not poll() before read()
|
||||
#define CTLSEQS_READER_SAVE_MATCHED_SEQS (1 << 1) // Save successfully matched sequence to buffer
|
||||
// Do not poll() before read()
|
||||
#define CTLSEQS_READER_NO_POLL (1 << 0)
|
||||
// Save successfully matched sequence to buffer
|
||||
#define CTLSEQS_READER_SAVE_MATCHED_SEQS (1 << 1)
|
||||
|
||||
/* Function return status codes */
|
||||
|
||||
|
@ -439,28 +562,50 @@ struct ctlseqs_matcher *
|
|||
ctlseqs_matcher_init();
|
||||
|
||||
int
|
||||
ctlseqs_matcher_config(struct ctlseqs_matcher *matcher, struct ctlseqs_matcher_options const *options);
|
||||
ctlseqs_matcher_config(
|
||||
struct ctlseqs_matcher *matcher,
|
||||
struct ctlseqs_matcher_options const *options
|
||||
);
|
||||
|
||||
void
|
||||
ctlseqs_matcher_free(struct ctlseqs_matcher *matcher);
|
||||
ctlseqs_matcher_free(
|
||||
struct ctlseqs_matcher *matcher
|
||||
);
|
||||
|
||||
ssize_t
|
||||
ctlseqs_match(struct ctlseqs_matcher const *matcher, char const *str, size_t str_len, union ctlseqs_value *result);
|
||||
ctlseqs_match(
|
||||
struct ctlseqs_matcher const *matcher,
|
||||
char const *str,
|
||||
size_t str_len,
|
||||
union ctlseqs_value *result
|
||||
);
|
||||
|
||||
struct ctlseqs_reader *
|
||||
ctlseqs_reader_init();
|
||||
|
||||
int
|
||||
ctlseqs_reader_config(struct ctlseqs_reader *reader, struct ctlseqs_reader_options const *options);
|
||||
ctlseqs_reader_config(
|
||||
struct ctlseqs_reader *reader,
|
||||
struct ctlseqs_reader_options const *options
|
||||
);
|
||||
|
||||
ssize_t
|
||||
ctlseqs_read(struct ctlseqs_reader *reader, struct ctlseqs_matcher const *matcher, int timeout);
|
||||
ctlseqs_read(
|
||||
struct ctlseqs_reader *reader,
|
||||
struct ctlseqs_matcher const *matcher,
|
||||
int timeout
|
||||
);
|
||||
|
||||
void
|
||||
ctlseqs_purge(struct ctlseqs_reader *reader, size_t nbytes);
|
||||
ctlseqs_purge(
|
||||
struct ctlseqs_reader *reader,
|
||||
size_t nbytes
|
||||
);
|
||||
|
||||
void
|
||||
ctlseqs_reader_free(struct ctlseqs_reader *reader);
|
||||
ctlseqs_reader_free(
|
||||
struct ctlseqs_reader *reader
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
# this notice are preserved. This file is offered as-is, without any warranty.
|
||||
#
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
AM_LDFLAGS = -version-info $(CTLSEQS_LT_VERSION)
|
||||
|
||||
lib_LTLIBRARIES = libctlseqs.la
|
||||
libctlseqs_la_SOURCES = ctlseqs.c
|
||||
lib_LTLIBRARIES = libctlseqs.la
|
||||
libctlseqs_la_CPPFLAGS = -I$(top_srcdir)/include
|
||||
libctlseqs_la_SOURCES = ctlseqs.c
|
||||
libctlseqs_la_LDFLAGS = -version-info $(CTLSEQS_LT_VERSION)
|
||||
|
|
384
src/ctlseqs.c
384
src/ctlseqs.c
|
@ -159,142 +159,196 @@ struct ctlseqs_reader {
|
|||
};
|
||||
|
||||
ctlseqs_hot static inline int
|
||||
ctlseqs_poll(struct pollfd *pollfd, int timeout)
|
||||
{
|
||||
ctlseqs_poll(
|
||||
struct pollfd *pollfd,
|
||||
int timeout
|
||||
) {
|
||||
int nevents = poll(pollfd, 1, timeout);
|
||||
if (nevents == -1) {
|
||||
return errno == EINTR ? CTLSEQS_INTR : CTLSEQS_ERROR;
|
||||
}
|
||||
if (nevents == 0) {
|
||||
switch (nevents) {
|
||||
case 0:
|
||||
return CTLSEQS_TIMEOUT;
|
||||
case 1:
|
||||
if (ctlseqs_likely(pollfd->revents & POLLIN)) {
|
||||
return CTLSEQS_OK;
|
||||
} else if (pollfd->revents & POLLHUP) {
|
||||
return CTLSEQS_EOF;
|
||||
} else {
|
||||
return CTLSEQS_ERROR;
|
||||
}
|
||||
default:
|
||||
if (errno == EINTR) {
|
||||
return CTLSEQS_INTR;
|
||||
} else {
|
||||
return CTLSEQS_ERROR;
|
||||
}
|
||||
}
|
||||
if (ctlseqs_likely(pollfd->revents & POLLIN)) {
|
||||
return CTLSEQS_OK;
|
||||
}
|
||||
return pollfd->revents & POLLHUP ? CTLSEQS_EOF : CTLSEQS_ERROR;
|
||||
}
|
||||
|
||||
ctlseqs_hot static inline int
|
||||
ctlseqs_do_read(struct ctlseqs_reader *reader)
|
||||
{
|
||||
ctlseqs_do_read(
|
||||
struct ctlseqs_reader *reader
|
||||
) {
|
||||
size_t offset = reader->buf_start + reader->last_idx;
|
||||
ssize_t nbytes = read(reader->pollfd.fd, reader->rbuf + offset, reader->readlen - offset);
|
||||
if (ctlseqs_unlikely(nbytes == -1)) {
|
||||
ssize_t nbytes = read(
|
||||
reader->pollfd.fd,
|
||||
reader->rbuf + offset,
|
||||
reader->readlen - offset
|
||||
);
|
||||
switch (nbytes) {
|
||||
case -1:
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return CTLSEQS_TIMEOUT;
|
||||
} else if (errno == EINTR) {
|
||||
return CTLSEQS_INTR;
|
||||
} else {
|
||||
return CTLSEQS_ERROR;
|
||||
}
|
||||
return errno == EINTR ? CTLSEQS_INTR : CTLSEQS_ERROR;
|
||||
}
|
||||
if (ctlseqs_unlikely(nbytes == 0)) {
|
||||
case 0:
|
||||
return CTLSEQS_EOF;
|
||||
default:
|
||||
reader->buf_end += nbytes;
|
||||
return CTLSEQS_OK;
|
||||
}
|
||||
reader->buf_end += nbytes;
|
||||
return CTLSEQS_OK;
|
||||
}
|
||||
|
||||
ctlseqs_hot static enum ctlseqs_state
|
||||
ctlseqs_state_transition(enum ctlseqs_state state, char ch)
|
||||
{
|
||||
ctlseqs_state_transition(
|
||||
enum ctlseqs_state state,
|
||||
char ch
|
||||
) {
|
||||
switch (state) {
|
||||
case ctlseqs_state_none:
|
||||
return ch == 0x1b ? ctlseqs_state_esc : ctlseqs_state_err;
|
||||
case ctlseqs_state_esc:
|
||||
switch (ch) {
|
||||
case '[':
|
||||
return ctlseqs_state_csi;
|
||||
case 'N':
|
||||
case 'O':
|
||||
return ctlseqs_state_ss;
|
||||
case 'P':
|
||||
case ']':
|
||||
case '_':
|
||||
case '^':
|
||||
return ctlseqs_state_cmdstr;
|
||||
case 'X':
|
||||
return ctlseqs_state_ctlstr;
|
||||
default:
|
||||
return (ch >= ' ' && ch <= '~') ? ctlseqs_state_done : ctlseqs_state_err;
|
||||
}
|
||||
case ctlseqs_state_csi:
|
||||
if (ch >= '0' && ch <= '?') {
|
||||
return state;
|
||||
} else if (ch >= ' ' && ch <= '/') {
|
||||
return ctlseqs_state_csi_intmd;
|
||||
}
|
||||
return (ch >= '@' && ch <= '~') ? ctlseqs_state_done : ctlseqs_state_err;
|
||||
case ctlseqs_state_csi_intmd:
|
||||
if (ch >= ' ' && ch <= '/') {
|
||||
return state;
|
||||
}
|
||||
return (ch >= '@' && ch <= '~') ? ctlseqs_state_done : ctlseqs_state_err;
|
||||
case ctlseqs_state_cmdstr:
|
||||
if (ch == 0x1b) {
|
||||
return ctlseqs_state_str_end;
|
||||
} else if (ch < 0x08 || ch > '~' || (ch > 0x0d && ch < ' ')) {
|
||||
case ctlseqs_state_none:
|
||||
if (ch == 0x1b) {
|
||||
return ctlseqs_state_esc;
|
||||
} else {
|
||||
return ctlseqs_state_err;
|
||||
}
|
||||
case ctlseqs_state_esc:
|
||||
switch (ch) {
|
||||
case '[':
|
||||
return ctlseqs_state_csi;
|
||||
case 'N':
|
||||
case 'O':
|
||||
return ctlseqs_state_ss;
|
||||
case 'P':
|
||||
case ']':
|
||||
case '_':
|
||||
case '^':
|
||||
return ctlseqs_state_cmdstr;
|
||||
case 'X':
|
||||
return ctlseqs_state_ctlstr;
|
||||
default:
|
||||
if (ch >= ' ' && ch <= '~') {
|
||||
return ctlseqs_state_done;
|
||||
} else {
|
||||
return ctlseqs_state_err;
|
||||
}
|
||||
}
|
||||
case ctlseqs_state_csi:
|
||||
if (ch >= '0' && ch <= '?') {
|
||||
return state;
|
||||
case ctlseqs_state_ss:
|
||||
return (ch >= ' ' && ch <= '~') ? ctlseqs_state_done : ctlseqs_state_err;
|
||||
case ctlseqs_state_ctlstr:
|
||||
return ch == 0x1b ? ctlseqs_state_str_end : state;
|
||||
case ctlseqs_state_str_end:
|
||||
return ch == '\\' ? ctlseqs_state_done : ctlseqs_state_err;
|
||||
default:
|
||||
ctlseqs_unreachable();
|
||||
} else if (ch >= ' ' && ch <= '/') {
|
||||
return ctlseqs_state_csi_intmd;
|
||||
} else if (ch >= '@' && ch <= '~') {
|
||||
return ctlseqs_state_done;
|
||||
} else {
|
||||
return ctlseqs_state_err;
|
||||
}
|
||||
case ctlseqs_state_csi_intmd:
|
||||
if (ch >= ' ' && ch <= '/') {
|
||||
return state;
|
||||
} else if (ch >= '@' && ch <= '~') {
|
||||
return ctlseqs_state_done;
|
||||
} else {
|
||||
return ctlseqs_state_err;
|
||||
}
|
||||
case ctlseqs_state_cmdstr:
|
||||
if (ch == 0x1b) {
|
||||
return ctlseqs_state_str_end;
|
||||
} else if (ch < 0x08 || ch > '~' || (ch > 0x0d && ch < ' ')) {
|
||||
return ctlseqs_state_err;
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
case ctlseqs_state_ss:
|
||||
if (ch >= ' ' && ch <= '~') {
|
||||
return ctlseqs_state_done;
|
||||
} else {
|
||||
return ctlseqs_state_err;
|
||||
}
|
||||
case ctlseqs_state_ctlstr:
|
||||
if (ch == 0x1b) {
|
||||
return ctlseqs_state_str_end;
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
case ctlseqs_state_str_end:
|
||||
if (ch == '\\') {
|
||||
return ctlseqs_state_done;
|
||||
} else {
|
||||
return ctlseqs_state_err;
|
||||
}
|
||||
default:
|
||||
ctlseqs_unreachable();
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
ctlseqs_hot static char const *
|
||||
ctlseqs_fetch_value(char const *seq, int type, union ctlseqs_value **buf)
|
||||
{
|
||||
ctlseqs_fetch_value(
|
||||
char const *seq,
|
||||
int type,
|
||||
union ctlseqs_value **buf
|
||||
) {
|
||||
size_t cnt;
|
||||
unsigned long num;
|
||||
char *endptr = NULL;
|
||||
union ctlseqs_value *buf_val = *buf;
|
||||
switch (type) {
|
||||
case ctlseqs_ph_num:
|
||||
CTLSEQS_VALUE_NUM(10);
|
||||
case ctlseqs_ph_nums:
|
||||
for (cnt = 1; ; ++cnt) {
|
||||
errno = 0;
|
||||
num = strtoul(seq, &endptr, 10);
|
||||
if (errno || seq == endptr) {
|
||||
return NULL;
|
||||
}
|
||||
buf_val[cnt].num = num;
|
||||
if (endptr[0] != ';') {
|
||||
break;
|
||||
}
|
||||
seq = endptr + 1;
|
||||
case ctlseqs_ph_num:
|
||||
CTLSEQS_VALUE_NUM(10);
|
||||
case ctlseqs_ph_nums:
|
||||
for (cnt = 1; ; ++cnt) {
|
||||
errno = 0;
|
||||
num = strtoul(seq, &endptr, 10);
|
||||
if (errno || seq == endptr) {
|
||||
return NULL;
|
||||
}
|
||||
buf_val[0].len = cnt;
|
||||
*buf += cnt + 1;
|
||||
return endptr;
|
||||
case ctlseqs_ph_str:
|
||||
CTLSEQS_VALUE_STR(num < ' ' || num > '~');
|
||||
case ctlseqs_ph_cmdstr:
|
||||
CTLSEQS_VALUE_STR(num < 0x08 || num > '~' || (num > 0x0d && num < ' '));
|
||||
case ctlseqs_ph_csi_param:
|
||||
CTLSEQS_VALUE_STR(num < '0' || num > '?');
|
||||
case ctlseqs_ph_csi_intmd:
|
||||
CTLSEQS_VALUE_STR(num < ' ' || num > '/');
|
||||
case ctlseqs_ph_hexnum:
|
||||
CTLSEQS_VALUE_NUM(16);
|
||||
case ctlseqs_ph_chrstr:
|
||||
CTLSEQS_VALUE_STR(num > 0x7f);
|
||||
default:
|
||||
ctlseqs_unreachable();
|
||||
return NULL;
|
||||
buf_val[cnt].num = num;
|
||||
if (endptr[0] != ';') {
|
||||
break;
|
||||
}
|
||||
seq = endptr + 1;
|
||||
}
|
||||
buf_val[0].len = cnt;
|
||||
*buf += cnt + 1;
|
||||
return endptr;
|
||||
case ctlseqs_ph_str:
|
||||
CTLSEQS_VALUE_STR(num < ' ' || num > '~');
|
||||
case ctlseqs_ph_cmdstr:
|
||||
CTLSEQS_VALUE_STR(num < 0x08 || num > '~' || num > 0x0d && num < ' ');
|
||||
case ctlseqs_ph_csi_param:
|
||||
CTLSEQS_VALUE_STR(num < '0' || num > '?');
|
||||
case ctlseqs_ph_csi_intmd:
|
||||
CTLSEQS_VALUE_STR(num < ' ' || num > '/');
|
||||
case ctlseqs_ph_hexnum:
|
||||
CTLSEQS_VALUE_NUM(16);
|
||||
case ctlseqs_ph_chrstr:
|
||||
CTLSEQS_VALUE_STR(num > 0x7f);
|
||||
default:
|
||||
ctlseqs_unreachable();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ctlseqs_hot static ssize_t
|
||||
ctlseqs_match_pattern(struct ctlseqs_matcher const *matcher, struct ctlseqs_match_args const *args)
|
||||
{
|
||||
ctlseqs_match_pattern(
|
||||
struct ctlseqs_matcher const *matcher,
|
||||
struct ctlseqs_match_args const *args
|
||||
) {
|
||||
struct ctlseqs_trie_node const *old_node, empty_node = { 0 };
|
||||
struct ctlseqs_match_ctx match_stack[matcher->match_stack_size], match_ctx = {
|
||||
struct ctlseqs_match_ctx match_stack[matcher->match_stack_size];
|
||||
struct ctlseqs_match_ctx match_ctx = {
|
||||
.node = matcher == NULL ? &empty_node : &matcher->root,
|
||||
.seq = args->seq + 1,
|
||||
.result = args->result + (args->save_seq ? 2 : 0),
|
||||
|
@ -303,13 +357,14 @@ ctlseqs_match_pattern(struct ctlseqs_matcher const *matcher, struct ctlseqs_matc
|
|||
while (true) {
|
||||
match_ctx.value = match_ctx.node->value;
|
||||
if (match_ctx.value == -1) {
|
||||
match_character:
|
||||
match_ctx.node = match_ctx.node->children[(unsigned)match_ctx.seq++[0]];
|
||||
match_character:
|
||||
match_ctx.node
|
||||
= match_ctx.node->children[(unsigned)match_ctx.seq++[0]];
|
||||
if (match_ctx.node == NULL) {
|
||||
break;
|
||||
}
|
||||
} else if (match_ctx.value < -1) {
|
||||
match_placeholder:
|
||||
match_placeholder:
|
||||
old_node = match_ctx.node;
|
||||
match_ctx.node = match_ctx.node->children[-match_ctx.value];
|
||||
struct ctlseqs_trie_node *next_node = match_ctx.node->next;
|
||||
|
@ -319,7 +374,11 @@ ctlseqs_match_pattern(struct ctlseqs_matcher const *matcher, struct ctlseqs_matc
|
|||
.seq = match_ctx.seq,
|
||||
.result = match_ctx.result,
|
||||
};
|
||||
match_ctx.seq = ctlseqs_fetch_value(match_ctx.seq, -match_ctx.value, &match_ctx.result);
|
||||
match_ctx.seq = ctlseqs_fetch_value(
|
||||
match_ctx.seq,
|
||||
-match_ctx.value,
|
||||
&match_ctx.result
|
||||
);
|
||||
if (match_ctx.seq == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -340,8 +399,10 @@ ctlseqs_match_pattern(struct ctlseqs_matcher const *matcher, struct ctlseqs_matc
|
|||
}
|
||||
|
||||
ctlseqs_hot static inline ssize_t
|
||||
ctlseqs_do_match(struct ctlseqs_matcher const *matcher, struct ctlseqs_match_args *args)
|
||||
{
|
||||
ctlseqs_do_match(
|
||||
struct ctlseqs_matcher const *matcher,
|
||||
struct ctlseqs_match_args *args
|
||||
) {
|
||||
ssize_t retval = CTLSEQS_PARTIAL;
|
||||
char const *seq = args->seq;
|
||||
size_t idx, len = args->seq_len;
|
||||
|
@ -374,8 +435,10 @@ ctlseqs_do_match(struct ctlseqs_matcher const *matcher, struct ctlseqs_match_arg
|
|||
}
|
||||
|
||||
ctlseqs_hot static ssize_t
|
||||
ctlseqs_reader_match(struct ctlseqs_reader *reader, struct ctlseqs_matcher const *matcher)
|
||||
{
|
||||
ctlseqs_reader_match(
|
||||
struct ctlseqs_reader *reader,
|
||||
struct ctlseqs_matcher const *matcher
|
||||
) {
|
||||
struct ctlseqs_match_args args = {
|
||||
.seq = reader->rbuf + reader->buf_start,
|
||||
.seq_len = reader->buf_end - reader->buf_start,
|
||||
|
@ -387,17 +450,25 @@ ctlseqs_reader_match(struct ctlseqs_reader *reader, struct ctlseqs_matcher const
|
|||
ssize_t retval = ctlseqs_do_match(matcher, &args);
|
||||
if (retval == CTLSEQS_PARTIAL) {
|
||||
reader->last_idx = args.result_idx;
|
||||
if (ctlseqs_unlikely(reader->buf_start + args.result_idx == reader->readlen)) {
|
||||
if (ctlseqs_unlikely(
|
||||
reader->buf_start + args.result_idx == reader->readlen
|
||||
)) {
|
||||
// Buffer is full but a match is still pending.
|
||||
// This may happen when the reader's maxlen option is not large enough to hold a sequence,
|
||||
// This may happen when the reader's maxlen option is not
|
||||
// large enough to hold a sequence,
|
||||
// or when the the sequences are produced faster than consumed.
|
||||
if (reader->buf_start > reader->readlen / 2) {
|
||||
memcpy(reader->rbuf, reader->rbuf + reader->buf_start, args.result_idx);
|
||||
memcpy(
|
||||
reader->rbuf,
|
||||
reader->rbuf + reader->buf_start,
|
||||
args.result_idx
|
||||
);
|
||||
reader->buf_start = 0;
|
||||
reader->buf_end = args.result_idx;
|
||||
} else {
|
||||
// We could memmove() here, but having a buffer no larger than twice the size of a sequence
|
||||
// is hardly what a normal program would desire.
|
||||
// We could memmove() here, but having a buffer no larger than
|
||||
// twice the size of a sequence is hardly what a normal program
|
||||
// would desire.
|
||||
retval = CTLSEQS_NOMEM;
|
||||
}
|
||||
}
|
||||
|
@ -409,7 +480,11 @@ ctlseqs_reader_match(struct ctlseqs_reader *reader, struct ctlseqs_matcher const
|
|||
reader->buf_end = 0;
|
||||
}
|
||||
}
|
||||
reader->state = args.state >= ctlseqs_state_done ? ctlseqs_state_none : args.state;
|
||||
if (args.state >= ctlseqs_state_done) {
|
||||
reader->state = ctlseqs_state_none;
|
||||
} else {
|
||||
reader->state = args.state;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -428,10 +503,13 @@ ctlseqs_matcher_init()
|
|||
}
|
||||
|
||||
int
|
||||
ctlseqs_matcher_config(struct ctlseqs_matcher *matcher, struct ctlseqs_matcher_options const *options)
|
||||
{
|
||||
ctlseqs_matcher_config(
|
||||
struct ctlseqs_matcher *matcher,
|
||||
struct ctlseqs_matcher_options const *options
|
||||
) {
|
||||
size_t node_idx = 0, max_format_size = 0;
|
||||
struct ctlseqs_trie_node *node_pool = matcher->node_pools[matcher->pool_idx];
|
||||
struct ctlseqs_trie_node *node_pool
|
||||
= matcher->node_pools[matcher->pool_idx];
|
||||
matcher->root = (struct ctlseqs_trie_node) { .value = -1 };
|
||||
for (size_t i = 0; i < options->npatterns; ++i) {
|
||||
char const *pattern = options->patterns[i];
|
||||
|
@ -452,10 +530,14 @@ ctlseqs_matcher_config(struct ctlseqs_matcher *matcher, struct ctlseqs_matcher_o
|
|||
continue;
|
||||
}
|
||||
if (ctlseqs_unlikely(++node_idx >= matcher->pool_size)) {
|
||||
if (ctlseqs_unlikely(matcher->pool_idx >= CTLSEQS_TRIE_NODE_POOL_MAX_NUM - 1)) {
|
||||
if (ctlseqs_unlikely(
|
||||
matcher->pool_idx >= CTLSEQS_TRIE_NODE_POOL_MAX_NUM - 1
|
||||
)) {
|
||||
return CTLSEQS_NOMEM;
|
||||
}
|
||||
node_pool = malloc(sizeof(struct ctlseqs_trie_node) * matcher->pool_size * 2);
|
||||
node_pool = malloc(
|
||||
sizeof(struct ctlseqs_trie_node) * matcher->pool_size * 2
|
||||
);
|
||||
if (ctlseqs_unlikely(node_pool == NULL)) {
|
||||
return CTLSEQS_NOMEM;
|
||||
}
|
||||
|
@ -464,16 +546,23 @@ ctlseqs_matcher_config(struct ctlseqs_matcher *matcher, struct ctlseqs_matcher_o
|
|||
matcher->pool_size *= 2;
|
||||
}
|
||||
old_node->children[ch] = node = node_pool + node_idx;
|
||||
ssize_t placeholder;
|
||||
if (ch < ctlseqs_ph_begin || ch >= ctlseqs_ph_end) {
|
||||
placeholder = 0;
|
||||
} else {
|
||||
placeholder = ch;
|
||||
}
|
||||
*node = (struct ctlseqs_trie_node) {
|
||||
.value = -1, // Value -1 indicates that there's no match on current node.
|
||||
.placeholder = ch < ctlseqs_ph_begin || ch >= ctlseqs_ph_end ? 0 : ch,
|
||||
// Value -1 indicates that there's no match on current node.
|
||||
.value = -1,
|
||||
.placeholder = placeholder,
|
||||
};
|
||||
if (node->placeholder == 0) {
|
||||
if (placeholder == 0) {
|
||||
continue;
|
||||
}
|
||||
if (old_node->value < -1) {
|
||||
// Node with multiple placeholders contains negated offset of the child node
|
||||
// which is the head of the linked list.
|
||||
// Node with multiple placeholders contains negated offset of
|
||||
// the child node which is the head of the linked list.
|
||||
node->next = old_node->children[-old_node->value];
|
||||
}
|
||||
old_node->value = -ch;
|
||||
|
@ -484,8 +573,12 @@ ctlseqs_matcher_config(struct ctlseqs_matcher *matcher, struct ctlseqs_matcher_o
|
|||
}
|
||||
|
||||
ctlseqs_hot ssize_t
|
||||
ctlseqs_match(struct ctlseqs_matcher const *matcher, char const *str, size_t str_len, union ctlseqs_value *result)
|
||||
{
|
||||
ctlseqs_match(
|
||||
struct ctlseqs_matcher const *matcher,
|
||||
char const *str,
|
||||
size_t str_len,
|
||||
union ctlseqs_value *result
|
||||
) {
|
||||
struct ctlseqs_match_args args = {
|
||||
.seq = str,
|
||||
.seq_len = str_len,
|
||||
|
@ -493,7 +586,7 @@ ctlseqs_match(struct ctlseqs_matcher const *matcher, char const *str, size_t str
|
|||
.save_seq = true,
|
||||
};
|
||||
ssize_t retval;
|
||||
try_match:
|
||||
try_match:
|
||||
retval = ctlseqs_do_match(matcher, &args);
|
||||
if (retval == CTLSEQS_NOSEQ) {
|
||||
size_t result_len = args.result[0].len;
|
||||
|
@ -507,8 +600,9 @@ ctlseqs_match(struct ctlseqs_matcher const *matcher, char const *str, size_t str
|
|||
}
|
||||
|
||||
ctlseqs_cold void
|
||||
ctlseqs_matcher_free(struct ctlseqs_matcher *matcher)
|
||||
{
|
||||
ctlseqs_matcher_free(
|
||||
struct ctlseqs_matcher *matcher
|
||||
) {
|
||||
if (ctlseqs_likely(matcher != NULL)) {
|
||||
for (size_t idx = 1; idx <= matcher->pool_idx; ++idx) {
|
||||
free(matcher->node_pools[idx]);
|
||||
|
@ -528,8 +622,10 @@ ctlseqs_reader_init()
|
|||
}
|
||||
|
||||
int
|
||||
ctlseqs_reader_config(struct ctlseqs_reader *reader, struct ctlseqs_reader_options const *options)
|
||||
{
|
||||
ctlseqs_reader_config(
|
||||
struct ctlseqs_reader *reader,
|
||||
struct ctlseqs_reader_options const *options
|
||||
) {
|
||||
size_t const readlen = options->maxlen;
|
||||
if (reader->readlen != readlen) {
|
||||
if (readlen < reader->buf_end) {
|
||||
|
@ -553,8 +649,11 @@ ctlseqs_reader_config(struct ctlseqs_reader *reader, struct ctlseqs_reader_optio
|
|||
}
|
||||
|
||||
ctlseqs_hot ssize_t
|
||||
ctlseqs_read(struct ctlseqs_reader *reader, struct ctlseqs_matcher const *matcher, int timeout)
|
||||
{
|
||||
ctlseqs_read(
|
||||
struct ctlseqs_reader *reader,
|
||||
struct ctlseqs_matcher const *matcher,
|
||||
int timeout
|
||||
) {
|
||||
ssize_t result;
|
||||
// Whether we have read more than we could match in the preview call.
|
||||
if (reader->state == ctlseqs_state_none && reader->buf_start != 0) {
|
||||
|
@ -571,14 +670,20 @@ ctlseqs_read(struct ctlseqs_reader *reader, struct ctlseqs_matcher const *matche
|
|||
}
|
||||
result = ctlseqs_do_read(reader);
|
||||
if (ctlseqs_unlikely(result < 0)) {
|
||||
return reader->state == ctlseqs_state_none ? result : CTLSEQS_PARTIAL;
|
||||
if (reader->state == ctlseqs_state_none) {
|
||||
return result;
|
||||
} else {
|
||||
return CTLSEQS_PARTIAL;
|
||||
}
|
||||
}
|
||||
return ctlseqs_reader_match(reader, matcher);
|
||||
}
|
||||
|
||||
void
|
||||
ctlseqs_purge(struct ctlseqs_reader *reader, size_t nbytes)
|
||||
{
|
||||
ctlseqs_purge(
|
||||
struct ctlseqs_reader *reader,
|
||||
size_t nbytes
|
||||
) {
|
||||
if (ctlseqs_unlikely(nbytes == 0)) {
|
||||
return;
|
||||
}
|
||||
|
@ -592,8 +697,9 @@ ctlseqs_purge(struct ctlseqs_reader *reader, size_t nbytes)
|
|||
}
|
||||
|
||||
ctlseqs_cold void
|
||||
ctlseqs_reader_free(struct ctlseqs_reader *reader)
|
||||
{
|
||||
ctlseqs_reader_free(
|
||||
struct ctlseqs_reader *reader
|
||||
) {
|
||||
if (ctlseqs_likely(reader != NULL)) {
|
||||
free(reader->rbuf);
|
||||
free(reader);
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
#
|
||||
|
||||
AUTOMAKE_OPTIONS = dejagnu
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
EXTRA_DIST = ctlseqs/*.exp init.exp
|
||||
|
||||
noinst_PROGRAMS = tcsgrep
|
||||
tcsgrep_SOURCES = tcsgrep.c
|
||||
tcsgrep_LDADD = $(top_builddir)/src/libctlseqs.la
|
||||
noinst_PROGRAMS = tcsgrep
|
||||
tcsgrep_CPPFLAGS = -I$(top_srcdir)/include
|
||||
tcsgrep_SOURCES = tcsgrep.c
|
||||
tcsgrep_LDADD = $(top_builddir)/src/libctlseqs.la
|
||||
|
||||
RUNTESTDEFAULTFLAGS = TCSGREP_BIN=$(srcdir)/tcsgrep
|
||||
RUNTESTDEFAULTFLAGS = TCSGREP_BIN=$(builddir)/tcsgrep
|
||||
EXTRA_DEJAGNU_SITE_CONFIG = $(srcdir)/init.exp
|
||||
|
|
|
@ -12,16 +12,19 @@ set timeout 2
|
|||
set n1 [ random_int ]
|
||||
set n2 [ random_int ]
|
||||
set n3 [ random_int ]
|
||||
set n1_len [ string length $n1 ]
|
||||
|
||||
set input { }
|
||||
lappend input "$CSI$n1;${n2}H"
|
||||
lappend input "$DCS$n1;$n2|$n3$ST"
|
||||
lappend input "$CSI<?${n1}Z"
|
||||
set input [ list \
|
||||
"$CSI$n1;${n2}H" \
|
||||
"$DCS$n1;$n2|$n3$ST" \
|
||||
"$CSI<?${n1}Z" \
|
||||
]
|
||||
|
||||
set output { }
|
||||
lappend output "OK CUP $n1 $n2"
|
||||
lappend output "OK DECUDK $n1 $n2 $n3"
|
||||
lappend output "NOMATCH [ expr [ string length $n1 ] + 5 ] ESC \[ < ? [ split $n1 {} ] Z"
|
||||
set output [ list \
|
||||
"OK CUP $n1 $n2" \
|
||||
"OK DECUDK $n1 $n2 $n3" \
|
||||
"NOMATCH [ expr { $n1_len + 5 } ] ESC \[ < ? [ split $n1 {} ] Z" \
|
||||
]
|
||||
|
||||
tcsgrep_start
|
||||
|
||||
|
|
|
@ -26,9 +26,10 @@ expect {
|
|||
}
|
||||
|
||||
for { set i 0 } { $i < $nlen } { incr i } {
|
||||
set substr [ string range $n1 0 $i ]
|
||||
send [ string index $n1 $i ]
|
||||
expect {
|
||||
-ex "PARTIAL [ expr $i + 3 ] ESC \[ [ split [ string range $n1 0 $i ] {} ]\n" {
|
||||
-ex "PARTIAL [ expr { $i + 3 } ] ESC \[ [ split $substr {} ]\n" {
|
||||
pass "pass"
|
||||
}
|
||||
default {
|
||||
|
@ -40,7 +41,7 @@ for { set i 0 } { $i < $nlen } { incr i } {
|
|||
|
||||
send "p"
|
||||
expect {
|
||||
-ex "NOMATCH [ expr $nlen + 3 ] ESC \[ [ split $n1 {} ] p\n" {
|
||||
-ex "NOMATCH [ expr { $nlen + 3 } ] ESC \[ [ split $n1 {} ] p\n" {
|
||||
pass "pass"
|
||||
}
|
||||
default {
|
||||
|
|
|
@ -31,7 +31,7 @@ proc tcsgrep_start args {
|
|||
|
||||
proc tcsgrep_stop { } {
|
||||
global spawn_id
|
||||
send \x04
|
||||
send "\x04"
|
||||
expect {
|
||||
-ex "NOSEQ 1 EOT\n" { }
|
||||
default {
|
||||
|
@ -46,5 +46,5 @@ proc tcsgrep_stop { } {
|
|||
|
||||
proc random_int { } {
|
||||
set num [ exec od -An -td -N4 /dev/urandom ]
|
||||
return [ expr abs(int($num)) ]
|
||||
return [ expr { abs(int($num)) } ]
|
||||
}
|
||||
|
|
204
tests/tcsgrep.c
204
tests/tcsgrep.c
|
@ -50,8 +50,8 @@
|
|||
#define DEFARGS_(nargs, ...) CONCAT_(nargs)(__VA_ARGS__)
|
||||
|
||||
#define DEFSEQ_NOARGS(name) { #name, CTLSEQS_##name(), "" }
|
||||
#define DEFSEQ(name, ...) \
|
||||
{ #name, CTLSEQS_##name(__VA_ARGS__), DEFARGS_(COUNT_ARGS_(__VA_ARGS__), __VA_ARGS__) }
|
||||
#define DEFSEQ(name, ...) { #name, CTLSEQS_##name(__VA_ARGS__), \
|
||||
DEFARGS_(COUNT_ARGS_(__VA_ARGS__), __VA_ARGS__) }
|
||||
|
||||
#define DEFAULT_MAX_BUFFER_LEN 4096
|
||||
|
||||
|
@ -74,14 +74,18 @@ struct tcsgrep_ctx {
|
|||
};
|
||||
|
||||
static inline void
|
||||
print_error(struct tcsgrep_ctx const *ctx, char const *msg)
|
||||
{
|
||||
print_error(
|
||||
struct tcsgrep_ctx const *ctx,
|
||||
char const *msg
|
||||
) {
|
||||
fprintf(ctx->err_file, "%s: [error] %s.\n", ctx->prog_name, msg);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
parse_int(char const *str, int *dest)
|
||||
{
|
||||
parse_int(
|
||||
char const *str,
|
||||
int *dest
|
||||
) {
|
||||
errno = 0;
|
||||
unsigned long result = strtoul(str, NULL, 10);
|
||||
if (errno || result > 4096) {
|
||||
|
@ -92,8 +96,10 @@ parse_int(char const *str, int *dest)
|
|||
}
|
||||
|
||||
static inline void
|
||||
print_char(struct tcsgrep_ctx const *ctx, int ch)
|
||||
{
|
||||
print_char(
|
||||
struct tcsgrep_ctx const *ctx,
|
||||
int ch
|
||||
) {
|
||||
static char const *ascii_table[] = {
|
||||
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
|
||||
"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
|
||||
|
@ -114,8 +120,12 @@ print_char(struct tcsgrep_ctx const *ctx, int ch)
|
|||
}
|
||||
|
||||
static void
|
||||
print_generic_seq(struct tcsgrep_ctx const *ctx, char const *header, union ctlseqs_value const *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;
|
||||
fprintf(ctx->out_file, "%s %zu", header, length);
|
||||
|
@ -129,9 +139,9 @@ print_generic_seq(struct tcsgrep_ctx const *ctx, char const *header, union ctlse
|
|||
|
||||
static void
|
||||
print_matching_seq(
|
||||
struct tcsgrep_ctx const *ctx,
|
||||
struct tcsgrep_ctx const *ctx,
|
||||
struct tcsgrep_sequence const *seq,
|
||||
union ctlseqs_value const *result,
|
||||
union ctlseqs_value const *result,
|
||||
bool verbose
|
||||
) {
|
||||
if (verbose) {
|
||||
|
@ -148,7 +158,8 @@ print_matching_seq(
|
|||
fprintf(ctx->out_file, " %lu", result[idx].num);
|
||||
break;
|
||||
case 0x10: // CTLSEQS_PH_STR
|
||||
fprintf(ctx->out_file, " %.*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) {
|
||||
|
@ -161,8 +172,10 @@ print_matching_seq(
|
|||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
main(
|
||||
int argc,
|
||||
char **argv
|
||||
) {
|
||||
struct tcsgrep_ctx ctx = {
|
||||
.prog_name = argv[0],
|
||||
.out_file = stdout,
|
||||
|
@ -175,28 +188,29 @@ main(int argc, char **argv)
|
|||
int opt;
|
||||
while (-1 != (opt = getopt(argc, argv, "t:l:pv"))) {
|
||||
switch (opt) {
|
||||
case 't':
|
||||
if (!parse_int(optarg, &ctx.timeout)) {
|
||||
print_error(&ctx, "invalid timeout option");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (!parse_int(optarg, &ctx.limit)) {
|
||||
print_error(&ctx, "invalid limit option");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
ctx.purge_long_seqs = true;
|
||||
break;
|
||||
case 'v':
|
||||
ctx.verbose = true;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
fprintf(ctx.out_file, "%s\n", "Usage: tcsgrep [-t timeout] [-l limit] [-pv]");
|
||||
case 't':
|
||||
if (!parse_int(optarg, &ctx.timeout)) {
|
||||
print_error(&ctx, "invalid timeout option");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (!parse_int(optarg, &ctx.limit)) {
|
||||
print_error(&ctx, "invalid limit option");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
ctx.purge_long_seqs = true;
|
||||
break;
|
||||
case 'v':
|
||||
ctx.verbose = true;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
fprintf(ctx.out_file, "%s\n",
|
||||
"Usage: tcsgrep [-t timeout] [-l limit] [-pv]");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +271,8 @@ main(int argc, char **argv)
|
|||
DEFSEQ(SU, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTSMGRAPHICS, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(SD, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTHIMOUSE, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTHIMOUSE, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTRMTITLE, CTLSEQS_PH_STR),
|
||||
DEFSEQ(ECH, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(CBT, CTLSEQS_PH_NUM),
|
||||
|
@ -293,34 +308,43 @@ main(int argc, char **argv)
|
|||
DEFSEQ(DECSCA, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECSTBM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTRESTORE, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(DECCARA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECCARA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ_NOARGS(SCOSC),
|
||||
DEFSEQ(DECSLRM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTSAVE, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(XTWINOPS, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(XTSMTITLE, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(DECSWBV, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECRARA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECRARA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ_NOARGS(SCORC),
|
||||
DEFSEQ(DECSMBV, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECCRA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECCRA,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECRQPSR, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECEFR, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECEFR,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECREQTPARM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECEFR, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECEFR,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECREQTPARM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECSACE, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECFRA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTCHECKSUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECRQCRA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
DEFSEQ(DECFRA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTCHECKSUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECRQCRA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECELR, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECERA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECERA,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECSLE, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(XTPUSHSGR, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(DECSERA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTREPORTSGR, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECSERA,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(XTREPORTSGR,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(DECSCPP, CTLSEQS_PH_NUM),
|
||||
DEFSEQ_NOARGS(DECRQLP),
|
||||
DEFSEQ(DECSNLS, CTLSEQS_PH_NUM),
|
||||
|
@ -332,7 +356,8 @@ main(int argc, char **argv)
|
|||
DEFSEQ(RESP_XTGETXRES, CTLSEQS_PH_NUM, CTLSEQS_PH_STR),
|
||||
DEFSEQ(RESP_XTGETTCAP, CTLSEQS_PH_NUM, CTLSEQS_PH_STR),
|
||||
DEFSEQ(RESP_PRIMARY_DA, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(RESP_SECONDARY_DA, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(RESP_SECONDARY_DA,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(RESP_DECXCPR, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(RESP_DSR, CTLSEQS_PH_NUMS),
|
||||
DEFSEQ(RESP_DECRQM_ANSI, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
|
@ -341,7 +366,8 @@ main(int argc, char **argv)
|
|||
DEFSEQ(RESP_DECCIR, CTLSEQS_PH_STR),
|
||||
DEFSEQ(RESP_DECTABSR, CTLSEQS_PH_STR),
|
||||
DEFSEQ(RESP_DECRQCRA, CTLSEQS_PH_NUM, CTLSEQS_PH_STR),
|
||||
DEFSEQ(RESP_DECRQLP, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ(RESP_DECRQLP, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM,
|
||||
CTLSEQS_PH_NUM, CTLSEQS_PH_NUM),
|
||||
DEFSEQ_NOARGS(KEY_UP),
|
||||
DEFSEQ_NOARGS(KEY_DOWN),
|
||||
DEFSEQ_NOARGS(KEY_RIGHT),
|
||||
|
@ -413,50 +439,50 @@ main(int argc, char **argv)
|
|||
while (true) {
|
||||
ssize_t retval = ctlseqs_read(reader, matcher, ctx.timeout);
|
||||
switch (retval) {
|
||||
case CTLSEQS_ERROR:
|
||||
print_error(&ctx, "unexpected error");
|
||||
case CTLSEQS_ERROR:
|
||||
print_error(&ctx, "unexpected error");
|
||||
status = 1;
|
||||
goto terminate;
|
||||
case CTLSEQS_TIMEOUT:
|
||||
fprintf(ctx.out_file, "TIMEOUT\n");
|
||||
status = 1;
|
||||
goto terminate;
|
||||
case CTLSEQS_INTR:
|
||||
fprintf(ctx.out_file, "INTR\n");
|
||||
break;
|
||||
case CTLSEQS_EOF:
|
||||
fprintf(ctx.out_file, "EOF\n");
|
||||
goto terminate;
|
||||
case CTLSEQS_PARTIAL:
|
||||
if (ctx.verbose) {
|
||||
print_generic_seq(&ctx, "PARTIAL", result, true);
|
||||
}
|
||||
break;
|
||||
case CTLSEQS_NOMATCH:
|
||||
print_generic_seq(&ctx, "NOMATCH", result, true);
|
||||
break;
|
||||
case CTLSEQS_NOMEM:
|
||||
print_generic_seq(&ctx, "NOMEM", result, true);
|
||||
if (ctx.purge_long_seqs) {
|
||||
ctlseqs_purge(reader, result[0].len);
|
||||
break;
|
||||
} else {
|
||||
status = 1;
|
||||
goto terminate;
|
||||
case CTLSEQS_TIMEOUT:
|
||||
fprintf(ctx.out_file, "TIMEOUT\n");
|
||||
status = 1;
|
||||
}
|
||||
case CTLSEQS_NOSEQ:
|
||||
print_generic_seq(&ctx, "NOSEQ", result, true);
|
||||
if (!ctx.not_tty && result[1].str[0] == 0x04) {
|
||||
goto terminate;
|
||||
case CTLSEQS_INTR:
|
||||
fprintf(ctx.out_file, "INTR\n");
|
||||
break;
|
||||
case CTLSEQS_EOF:
|
||||
fprintf(ctx.out_file, "EOF\n");
|
||||
goto terminate;
|
||||
case CTLSEQS_PARTIAL:
|
||||
if (ctx.verbose) {
|
||||
print_generic_seq(&ctx, "PARTIAL", result, true);
|
||||
}
|
||||
break;
|
||||
case CTLSEQS_NOMATCH:
|
||||
print_generic_seq(&ctx, "NOMATCH", result, true);
|
||||
break;
|
||||
case CTLSEQS_NOMEM:
|
||||
print_generic_seq(&ctx, "NOMEM", result, true);
|
||||
if (ctx.purge_long_seqs) {
|
||||
ctlseqs_purge(reader, result[0].len);
|
||||
break;
|
||||
} else {
|
||||
status = 1;
|
||||
goto terminate;
|
||||
}
|
||||
case CTLSEQS_NOSEQ:
|
||||
print_generic_seq(&ctx, "NOSEQ", result, true);
|
||||
if (!ctx.not_tty && result[1].str[0] == 0x04) {
|
||||
goto terminate;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
print_matching_seq(&ctx, &seqs[retval], result, ctx.verbose);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
print_matching_seq(&ctx, &seqs[retval], result, ctx.verbose);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
terminate:
|
||||
terminate:
|
||||
ctlseqs_matcher_free(matcher);
|
||||
ctlseqs_reader_free(reader);
|
||||
if (!ctx.not_tty) {
|
||||
|
|
Loading…
Reference in New Issue