sync code with last improvements from OpenBSD

This commit is contained in:
purplerain 2023-09-15 18:33:02 +00:00
parent 66d94126c9
commit 8b897ac235
Signed by: purplerain
GPG Key ID: F42C07F07E2E35B7
18 changed files with 560 additions and 1276 deletions

View File

@ -116,6 +116,8 @@
/** timeout in millisec to wait for write to unblock, packets dropped after.*/ /** timeout in millisec to wait for write to unblock, packets dropped after.*/
#define SEND_BLOCKED_WAIT_TIMEOUT 200 #define SEND_BLOCKED_WAIT_TIMEOUT 200
/** max number of times to wait for write to unblock, packets dropped after.*/
#define SEND_BLOCKED_MAX_RETRY 5
/** Let's make timestamping code cleaner and redefine SO_TIMESTAMP* */ /** Let's make timestamping code cleaner and redefine SO_TIMESTAMP* */
#ifndef SO_TIMESTAMP #ifndef SO_TIMESTAMP
@ -402,9 +404,10 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAENOBUFS ||
WSAGetLastError() == WSAEWOULDBLOCK) { WSAGetLastError() == WSAEWOULDBLOCK) {
#endif #endif
int retries = 0;
/* if we set the fd blocking, other threads suddenly /* if we set the fd blocking, other threads suddenly
* have a blocking fd that they operate on */ * have a blocking fd that they operate on */
while(sent == -1 && ( while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && (
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
errno == EAGAIN || errno == EINTR || errno == EAGAIN || errno == EINTR ||
# ifdef EWOULDBLOCK # ifdef EWOULDBLOCK
@ -419,6 +422,13 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
#endif #endif
)) { )) {
#if defined(HAVE_POLL) || defined(USE_WINSOCK) #if defined(HAVE_POLL) || defined(USE_WINSOCK)
int send_nobufs = (
#ifndef USE_WINSOCK
errno == ENOBUFS
#else
WSAGetLastError() == WSAENOBUFS
#endif
);
struct pollfd p; struct pollfd p;
int pret; int pret;
memset(&p, 0, sizeof(p)); memset(&p, 0, sizeof(p));
@ -457,8 +467,48 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
log_err("poll udp out failed: %s", log_err("poll udp out failed: %s",
sock_strerror(errno)); sock_strerror(errno));
return 0; return 0;
} else if((pret < 0 &&
#ifndef USE_WINSOCK
errno == ENOBUFS
#else
WSAGetLastError() == WSAENOBUFS
#endif
) || (send_nobufs && retries > 0)) {
/* ENOBUFS, and poll returned without
* a timeout. Or the retried send call
* returned ENOBUFS. It is good to
* wait a bit for the error to clear. */
/* The timeout is 20*(2^(retries+1)),
* it increases exponentially, starting
* at 40 msec. After 5 tries, 1240 msec
* have passed in total, when poll
* returned the error, and 1200 msec
* when send returned the errors. */
#ifndef USE_WINSOCK
pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
#else
pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
#endif
if(pret < 0 &&
#ifndef USE_WINSOCK
errno != EAGAIN && errno != EINTR &&
# ifdef EWOULDBLOCK
errno != EWOULDBLOCK &&
# endif
errno != ENOBUFS
#else
WSAGetLastError() != WSAEINPROGRESS &&
WSAGetLastError() != WSAEINTR &&
WSAGetLastError() != WSAENOBUFS &&
WSAGetLastError() != WSAEWOULDBLOCK
#endif
) {
log_err("poll udp out timer failed: %s",
sock_strerror(errno));
}
} }
#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ #endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */
retries++;
if (!is_connected) { if (!is_connected) {
sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), sent = sendto(c->fd, (void*)sldns_buffer_begin(packet),
sldns_buffer_remaining(packet), 0, sldns_buffer_remaining(packet), 0,
@ -665,7 +715,8 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAENOBUFS ||
WSAGetLastError() == WSAEWOULDBLOCK) { WSAGetLastError() == WSAEWOULDBLOCK) {
#endif #endif
while(sent == -1 && ( int retries = 0;
while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && (
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
errno == EAGAIN || errno == EINTR || errno == EAGAIN || errno == EINTR ||
# ifdef EWOULDBLOCK # ifdef EWOULDBLOCK
@ -680,6 +731,13 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
#endif #endif
)) { )) {
#if defined(HAVE_POLL) || defined(USE_WINSOCK) #if defined(HAVE_POLL) || defined(USE_WINSOCK)
int send_nobufs = (
#ifndef USE_WINSOCK
errno == ENOBUFS
#else
WSAGetLastError() == WSAENOBUFS
#endif
);
struct pollfd p; struct pollfd p;
int pret; int pret;
memset(&p, 0, sizeof(p)); memset(&p, 0, sizeof(p));
@ -718,8 +776,48 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
log_err("poll udp out failed: %s", log_err("poll udp out failed: %s",
sock_strerror(errno)); sock_strerror(errno));
return 0; return 0;
} else if((pret < 0 &&
#ifndef USE_WINSOCK
errno == ENOBUFS
#else
WSAGetLastError() == WSAENOBUFS
#endif
) || (send_nobufs && retries > 0)) {
/* ENOBUFS, and poll returned without
* a timeout. Or the retried send call
* returned ENOBUFS. It is good to
* wait a bit for the error to clear. */
/* The timeout is 20*(2^(retries+1)),
* it increases exponentially, starting
* at 40 msec. After 5 tries, 1240 msec
* have passed in total, when poll
* returned the error, and 1200 msec
* when send returned the errors. */
#ifndef USE_WINSOCK
pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
#else
pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1));
#endif
if(pret < 0 &&
#ifndef USE_WINSOCK
errno != EAGAIN && errno != EINTR &&
# ifdef EWOULDBLOCK
errno != EWOULDBLOCK &&
# endif
errno != ENOBUFS
#else
WSAGetLastError() != WSAEINPROGRESS &&
WSAGetLastError() != WSAEINTR &&
WSAGetLastError() != WSAENOBUFS &&
WSAGetLastError() != WSAEWOULDBLOCK
#endif
) {
log_err("poll udp out timer failed: %s",
sock_strerror(errno));
}
} }
#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ #endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */
retries++;
sent = sendmsg(c->fd, &msg, 0); sent = sendmsg(c->fd, &msg, 0);
} }
} }

View File

@ -1,4 +1,4 @@
# $OpenBSD: bsd.regress.mk,v 1.25 2022/12/09 09:30:54 tb Exp $ # $OpenBSD: bsd.regress.mk,v 1.26 2023/09/15 07:13:35 tb Exp $
# Documented in bsd.regress.mk(5) # Documented in bsd.regress.mk(5)
# No man pages for regression tests. # No man pages for regression tests.
@ -21,7 +21,7 @@ all: regress
REGRESS_LOG?=/dev/null REGRESS_LOG?=/dev/null
REGRESS_SKIP_TARGETS?= REGRESS_SKIP_TARGETS?=
REGRESS_SKIP_SLOW?=no REGRESS_SKIP_SLOW?=no
REGRESS_FAIL_EARLY?=no REGRESS_FAIL_EARLY?=yes
.if ! ${REGRESS_LOG:M/*} .if ! ${REGRESS_LOG:M/*}
ERRORS += "Fatal: REGRESS_LOG=${REGRESS_LOG} is not an absolute path" ERRORS += "Fatal: REGRESS_LOG=${REGRESS_LOG} is not an absolute path"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kern_clockintr.c,v 1.52 2023/09/14 22:27:09 cheloha Exp $ */ /* $OpenBSD: kern_clockintr.c,v 1.53 2023/09/15 11:48:49 deraadt Exp $ */
/* /*
* Copyright (c) 2003 Dale Rahn <drahn@openbsd.org> * Copyright (c) 2003 Dale Rahn <drahn@openbsd.org>
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@ -355,9 +355,10 @@ clockintr_cancel(struct clockintr *cl)
} }
struct clockintr * struct clockintr *
clockintr_establish(struct cpu_info *ci, clockintr_establish(void *vci,
void (*func)(struct clockintr *, void *, void *), void *arg) void (*func)(struct clockintr *, void *, void *), void *arg)
{ {
struct cpu_info *ci = vci;
struct clockintr *cl; struct clockintr *cl;
struct clockintr_queue *cq = &ci->ci_queue; struct clockintr_queue *cq = &ci->ci_queue;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clockintr.h,v 1.16 2023/09/14 22:07:11 cheloha Exp $ */ /* $OpenBSD: clockintr.h,v 1.17 2023/09/15 11:48:48 deraadt Exp $ */
/* /*
* Copyright (c) 2020-2022 Scott Cheloha <cheloha@openbsd.org> * Copyright (c) 2020-2022 Scott Cheloha <cheloha@openbsd.org>
* *
@ -128,7 +128,7 @@ void clockintr_trigger(void);
uint64_t clockintr_advance(struct clockintr *, uint64_t); uint64_t clockintr_advance(struct clockintr *, uint64_t);
uint64_t clockintr_advance_random(struct clockintr *, uint64_t, uint32_t); uint64_t clockintr_advance_random(struct clockintr *, uint64_t, uint32_t);
void clockintr_cancel(struct clockintr *); void clockintr_cancel(struct clockintr *);
struct clockintr *clockintr_establish(struct cpu_info *, struct clockintr *clockintr_establish(void *,
void (*)(struct clockintr *, void *, void *), void *); void (*)(struct clockintr *, void *, void *), void *);
void clockintr_stagger(struct clockintr *, uint64_t, uint32_t, uint32_t); void clockintr_stagger(struct clockintr *, uint64_t, uint32_t, uint32_t);
void clockqueue_init(struct clockintr_queue *); void clockqueue_init(struct clockintr_queue *);

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: awk.1,v 1.63 2021/11/08 06:46:22 jmc Exp $ .\" $OpenBSD: awk.1,v 1.64 2023/09/15 15:07:08 jsg Exp $
.\" .\"
.\" Copyright (C) Lucent Technologies 1997 .\" Copyright (C) Lucent Technologies 1997
.\" All Rights Reserved .\" All Rights Reserved
@ -22,7 +22,7 @@
.\" ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF .\" ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
.\" THIS SOFTWARE. .\" THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: November 8 2021 $ .Dd $Mdocdate: September 15 2023 $
.Dt AWK 1 .Dt AWK 1
.Os .Os
.Sh NAME .Sh NAME
@ -1001,8 +1001,8 @@ No others do.
.%A P. J. Weinberger .%A P. J. Weinberger
.%T The AWK Programming Language .%T The AWK Programming Language
.%I Addison-Wesley .%I Addison-Wesley
.%D 1988 .%D 2024
.%O ISBN 0-201-07981-X .%O ISBN 0-13-826972-6
.Re .Re
.Sh STANDARDS .Sh STANDARDS
The The

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cfg.c,v 1.86 2022/06/20 07:59:37 nicm Exp $ */ /* $OpenBSD: cfg.c,v 1.87 2023/09/15 06:31:49 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -67,6 +67,7 @@ start_cfg(void)
{ {
struct client *c; struct client *c;
u_int i; u_int i;
int flags = 0;
/* /*
* Configuration files are loaded without a client, so commands are run * Configuration files are loaded without a client, so commands are run
@ -84,19 +85,17 @@ start_cfg(void)
cmdq_append(c, cfg_item); cmdq_append(c, cfg_item);
} }
for (i = 0; i < cfg_nfiles; i++) { if (cfg_quiet)
if (cfg_quiet) flags = CMD_PARSE_QUIET;
load_cfg(cfg_files[i], c, NULL, CMD_PARSE_QUIET, NULL); for (i = 0; i < cfg_nfiles; i++)
else load_cfg(cfg_files[i], c, NULL, NULL, flags, NULL);
load_cfg(cfg_files[i], c, NULL, 0, NULL);
}
cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL)); cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL));
} }
int int
load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags, load_cfg(const char *path, struct client *c, struct cmdq_item *item,
struct cmdq_item **new_item) struct cmd_find_state *current, int flags, struct cmdq_item **new_item)
{ {
FILE *f; FILE *f;
struct cmd_parse_input pi; struct cmd_parse_input pi;
@ -135,7 +134,7 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
} }
if (item != NULL) if (item != NULL)
state = cmdq_copy_state(cmdq_get_state(item)); state = cmdq_copy_state(cmdq_get_state(item), current);
else else
state = cmdq_new_state(NULL, NULL, 0); state = cmdq_new_state(NULL, NULL, 0);
cmdq_add_format(state, "current_file", "%s", pi.file); cmdq_add_format(state, "current_file", "%s", pi.file);
@ -155,8 +154,8 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
int int
load_cfg_from_buffer(const void *buf, size_t len, const char *path, load_cfg_from_buffer(const void *buf, size_t len, const char *path,
struct client *c, struct cmdq_item *item, int flags, struct client *c, struct cmdq_item *item, struct cmd_find_state *current,
struct cmdq_item **new_item) int flags, struct cmdq_item **new_item)
{ {
struct cmd_parse_input pi; struct cmd_parse_input pi;
struct cmd_parse_result *pr; struct cmd_parse_result *pr;
@ -187,7 +186,7 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
} }
if (item != NULL) if (item != NULL)
state = cmdq_copy_state(cmdq_get_state(item)); state = cmdq_copy_state(cmdq_get_state(item), current);
else else
state = cmdq_new_state(NULL, NULL, 0); state = cmdq_new_state(NULL, NULL, 0);
cmdq_add_format(state, "current_file", "%s", pi.file); cmdq_add_format(state, "current_file", "%s", pi.file);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cmd-queue.c,v 1.114 2023/02/05 21:15:32 nicm Exp $ */ /* $OpenBSD: cmd-queue.c,v 1.115 2023/09/15 06:31:49 nicm Exp $ */
/* /*
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -237,8 +237,10 @@ cmdq_link_state(struct cmdq_state *state)
/* Make a copy of a state. */ /* Make a copy of a state. */
struct cmdq_state * struct cmdq_state *
cmdq_copy_state(struct cmdq_state *state) cmdq_copy_state(struct cmdq_state *state, struct cmd_find_state *current)
{ {
if (current != NULL)
return (cmdq_new_state(current, &state->event, state->flags));
return (cmdq_new_state(&state->current, &state->event, state->flags)); return (cmdq_new_state(&state->current, &state->event, state->flags));
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cmd-source-file.c,v 1.53 2021/08/23 11:04:21 nicm Exp $ */ /* $OpenBSD: cmd-source-file.c,v 1.54 2023/09/15 06:31:49 nicm Exp $ */
/* /*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
@ -36,8 +36,10 @@ const struct cmd_entry cmd_source_file_entry = {
.name = "source-file", .name = "source-file",
.alias = "source", .alias = "source",
.args = { "Fnqv", 1, -1, NULL }, .args = { "t:Fnqv", 1, -1, NULL },
.usage = "[-Fnqv] path ...", .usage = "[-Fnqv] " CMD_TARGET_PANE_USAGE " path ...",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
.flags = 0, .flags = 0,
.exec = cmd_source_file_exec .exec = cmd_source_file_exec
@ -93,6 +95,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
size_t bsize = EVBUFFER_LENGTH(buffer); size_t bsize = EVBUFFER_LENGTH(buffer);
u_int n; u_int n;
struct cmdq_item *new_item; struct cmdq_item *new_item;
struct cmd_find_state *target = cmdq_get_target(item);
if (!closed) if (!closed)
return; return;
@ -101,7 +104,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
cmdq_error(item, "%s: %s", path, strerror(error)); cmdq_error(item, "%s: %s", path, strerror(error));
else if (bsize != 0) { else if (bsize != 0) {
if (load_cfg_from_buffer(bdata, bsize, path, c, cdata->after, if (load_cfg_from_buffer(bdata, bsize, path, c, cdata->after,
cdata->flags, &new_item) < 0) target, cdata->flags, &new_item) < 0)
cdata->retval = CMD_RETURN_ERROR; cdata->retval = CMD_RETURN_ERROR;
else if (new_item != NULL) else if (new_item != NULL)
cdata->after = new_item; cdata->after = new_item;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: input.c,v 1.220 2023/08/23 08:30:07 nicm Exp $ */ /* $OpenBSD: input.c,v 1.222 2023/09/15 06:31:49 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -169,6 +169,7 @@ static void input_csi_dispatch_rm(struct input_ctx *);
static void input_csi_dispatch_rm_private(struct input_ctx *); static void input_csi_dispatch_rm_private(struct input_ctx *);
static void input_csi_dispatch_sm(struct input_ctx *); static void input_csi_dispatch_sm(struct input_ctx *);
static void input_csi_dispatch_sm_private(struct input_ctx *); static void input_csi_dispatch_sm_private(struct input_ctx *);
static void input_csi_dispatch_sm_graphics(struct input_ctx *);
static void input_csi_dispatch_winops(struct input_ctx *); static void input_csi_dispatch_winops(struct input_ctx *);
static void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *); static void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
static void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *); static void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
@ -203,7 +204,7 @@ enum input_esc_type {
INPUT_ESC_SCSG0_ON, INPUT_ESC_SCSG0_ON,
INPUT_ESC_SCSG1_OFF, INPUT_ESC_SCSG1_OFF,
INPUT_ESC_SCSG1_ON, INPUT_ESC_SCSG1_ON,
INPUT_ESC_ST, INPUT_ESC_ST
}; };
/* Escape command table. */ /* Escape command table. */
@ -259,11 +260,12 @@ enum input_csi_type {
INPUT_CSI_SGR, INPUT_CSI_SGR,
INPUT_CSI_SM, INPUT_CSI_SM,
INPUT_CSI_SM_PRIVATE, INPUT_CSI_SM_PRIVATE,
INPUT_CSI_SM_GRAPHICS,
INPUT_CSI_SU, INPUT_CSI_SU,
INPUT_CSI_TBC, INPUT_CSI_TBC,
INPUT_CSI_VPA, INPUT_CSI_VPA,
INPUT_CSI_WINOPS, INPUT_CSI_WINOPS,
INPUT_CSI_XDA, INPUT_CSI_XDA
}; };
/* Control (CSI) command table. */ /* Control (CSI) command table. */
@ -283,6 +285,7 @@ static const struct input_table_entry input_csi_table[] = {
{ 'M', "", INPUT_CSI_DL }, { 'M', "", INPUT_CSI_DL },
{ 'P', "", INPUT_CSI_DCH }, { 'P', "", INPUT_CSI_DCH },
{ 'S', "", INPUT_CSI_SU }, { 'S', "", INPUT_CSI_SU },
{ 'S', "?", INPUT_CSI_SM_GRAPHICS },
{ 'T', "", INPUT_CSI_SD }, { 'T', "", INPUT_CSI_SD },
{ 'X', "", INPUT_CSI_ECH }, { 'X', "", INPUT_CSI_ECH },
{ 'Z', "", INPUT_CSI_CBT }, { 'Z', "", INPUT_CSI_CBT },
@ -306,7 +309,7 @@ static const struct input_table_entry input_csi_table[] = {
{ 'r', "", INPUT_CSI_DECSTBM }, { 'r', "", INPUT_CSI_DECSTBM },
{ 's', "", INPUT_CSI_SCP }, { 's', "", INPUT_CSI_SCP },
{ 't', "", INPUT_CSI_WINOPS }, { 't', "", INPUT_CSI_WINOPS },
{ 'u', "", INPUT_CSI_RCP }, { 'u', "", INPUT_CSI_RCP }
}; };
/* Input transition. */ /* Input transition. */
@ -1595,6 +1598,9 @@ input_csi_dispatch(struct input_ctx *ictx)
case INPUT_CSI_SM_PRIVATE: case INPUT_CSI_SM_PRIVATE:
input_csi_dispatch_sm_private(ictx); input_csi_dispatch_sm_private(ictx);
break; break;
case INPUT_CSI_SM_GRAPHICS:
input_csi_dispatch_sm_graphics(ictx);
break;
case INPUT_CSI_SU: case INPUT_CSI_SU:
n = input_get(ictx, 0, 1, 1); n = input_get(ictx, 0, 1, 1);
if (n != -1) if (n != -1)
@ -1827,6 +1833,12 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
} }
} }
/* Handle CSI graphics SM. */
static void
input_csi_dispatch_sm_graphics(__unused struct input_ctx *ictx)
{
}
/* Handle CSI window operations. */ /* Handle CSI window operations. */
static void static void
input_csi_dispatch_winops(struct input_ctx *ictx) input_csi_dispatch_winops(struct input_ctx *ictx)
@ -1834,6 +1846,7 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
struct screen_write_ctx *sctx = &ictx->ctx; struct screen_write_ctx *sctx = &ictx->ctx;
struct screen *s = sctx->s; struct screen *s = sctx->s;
struct window_pane *wp = ictx->wp; struct window_pane *wp = ictx->wp;
struct window *w = wp->window;
u_int x = screen_size_x(s), y = screen_size_y(s); u_int x = screen_size_x(s), y = screen_size_y(s);
int n, m; int n, m;
@ -1847,8 +1860,6 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
case 7: case 7:
case 11: case 11:
case 13: case 13:
case 14:
case 19:
case 20: case 20:
case 21: case 21:
case 24: case 24:
@ -1866,6 +1877,21 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
if (input_get(ictx, m, 0, -1) == -1) if (input_get(ictx, m, 0, -1) == -1)
return; return;
break; break;
case 14:
input_reply(ictx, "\033[4;%u;%ut", y * w->ypixel, x * w->xpixel);
break;
case 15:
input_reply(ictx, "\033[5;%u;%ut", y * w->ypixel, x * w->xpixel);
break;
case 16:
input_reply(ictx, "\033[6;%u;%ut", w->ypixel, w->xpixel);
break;
case 18:
input_reply(ictx, "\033[8;%u;%ut", y, x);
break;
case 19:
input_reply(ictx, "\033[9;%u;%ut", y, x);
break;
case 22: case 22:
m++; m++;
switch (input_get(ictx, m, 0, -1)) { switch (input_get(ictx, m, 0, -1)) {
@ -1893,9 +1919,6 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
break; break;
} }
break; break;
case 18:
input_reply(ictx, "\033[8;%u;%ut", y, x);
break;
default: default:
log_debug("%s: unknown '%c'", __func__, ictx->ch); log_debug("%s: unknown '%c'", __func__, ictx->ch);
break; break;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: screen-write.c,v 1.221 2023/09/14 13:01:35 nicm Exp $ */ /* $OpenBSD: screen-write.c,v 1.222 2023/09/15 15:49:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -32,8 +32,8 @@ static void screen_write_collect_flush(struct screen_write_ctx *, int,
const char *); const char *);
static int screen_write_overwrite(struct screen_write_ctx *, static int screen_write_overwrite(struct screen_write_ctx *,
struct grid_cell *, u_int); struct grid_cell *, u_int);
static const struct grid_cell *screen_write_combine(struct screen_write_ctx *, static int screen_write_combine(struct screen_write_ctx *,
const struct utf8_data *, u_int *, u_int *); const struct grid_cell *);
struct screen_write_citem { struct screen_write_citem {
u_int x; u_int x;
@ -1742,7 +1742,6 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
if (ci->used == 0) if (ci->used == 0)
return; return;
ctx->flags &= ~SCREEN_WRITE_COMBINE;
before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used, before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used,
&wrapped); &wrapped);
@ -1841,65 +1840,22 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
struct grid_cell copy; const struct utf8_data *ud = &gc->data;
const struct utf8_data *ud = &gc->data, *previous = NULL, *combine;
struct grid_line *gl; struct grid_line *gl;
struct grid_cell_entry *gce; struct grid_cell_entry *gce;
struct grid_cell tmp_gc, now_gc; struct grid_cell tmp_gc, now_gc;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sx = screen_size_x(s), sy = screen_size_y(s); u_int sx = screen_size_x(s), sy = screen_size_y(s);
u_int width = ud->width, xx, last, cx, cy; u_int width = ud->width, xx, not_wrap;
int selected, skip = 1; int selected, skip = 1;
/* Ignore padding cells. */ /* Ignore padding cells. */
if (gc->flags & GRID_FLAG_PADDING) if (gc->flags & GRID_FLAG_PADDING)
return; return;
/* Check if this cell needs to be combined with the previous cell. */ /* Get the previous cell to check for combining. */
if (ctx->flags & SCREEN_WRITE_COMBINE) if (screen_write_combine(ctx, gc) != 0)
previous = &ctx->previous;
switch (utf8_try_combined(ud, previous, &combine, &width)) {
case UTF8_DISCARD_NOW:
log_debug("%s: UTF8_DISCARD_NOW (width %u)", __func__, width);
ctx->flags &= ~SCREEN_WRITE_COMBINE;
return; return;
case UTF8_WRITE_NOW:
log_debug("%s: UTF8_WRITE_NOW (width %u)", __func__, width);
ctx->flags &= ~SCREEN_WRITE_COMBINE;
break;
case UTF8_COMBINE_NOW:
log_debug("%s: UTF8_COMBINE_NOW (width %u)", __func__, width);
screen_write_collect_flush(ctx, 0, __func__);
gc = screen_write_combine(ctx, combine, &xx, &cx);
if (gc != NULL) {
cx = s->cx; cy = s->cy;
screen_write_set_cursor(ctx, xx, s->cy);
screen_write_initctx(ctx, &ttyctx, 0);
ttyctx.cell = gc;
tty_write(tty_cmd_cell, &ttyctx);
s->cx = cx; s->cy = cy;
}
ctx->flags &= ~SCREEN_WRITE_COMBINE;
return;
case UTF8_WRITE_MAYBE_COMBINE:
log_debug("%s: UTF8_WRITE_MAYBE_COMBINE (width %u)", __func__,
width);
utf8_copy(&ctx->previous, ud);
ctx->flags |= SCREEN_WRITE_COMBINE;
break;
case UTF8_DISCARD_MAYBE_COMBINE:
log_debug("%s: UTF8_DISCARD_MAYBE_COMBINE (width %u)", __func__,
width);
utf8_copy(&ctx->previous, ud);
ctx->flags |= SCREEN_WRITE_COMBINE;
return;
}
if (width != ud->width) {
memcpy(&copy, gc, sizeof copy);
copy.data.width = width;
gc = &copy;
}
ud = NULL;
/* Flush any existing scrolling. */ /* Flush any existing scrolling. */
screen_write_collect_flush(ctx, 1, __func__); screen_write_collect_flush(ctx, 1, __func__);
@ -1991,11 +1947,11 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* Move the cursor. If not wrapping, stick at the last character and * Move the cursor. If not wrapping, stick at the last character and
* replace it. * replace it.
*/ */
last = !(s->mode & MODE_WRAP); not_wrap = !(s->mode & MODE_WRAP);
if (s->cx <= sx - last - width) if (s->cx <= sx - not_wrap - width)
screen_write_set_cursor(ctx, s->cx + width, -1); screen_write_set_cursor(ctx, s->cx + width, -1);
else else
screen_write_set_cursor(ctx, sx - last, -1); screen_write_set_cursor(ctx, sx - not_wrap, -1);
/* Create space for character in insert mode. */ /* Create space for character in insert mode. */
if (s->mode & MODE_INSERT) { if (s->mode & MODE_INSERT) {
@ -2015,65 +1971,98 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
} }
} }
/* Combine a UTF-8 zero-width character onto the previous. */ /* Combine a UTF-8 zero-width character onto the previous if necessary. */
static const struct grid_cell * static int
screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud, screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
u_int *xx, u_int *cx)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid *gd = s->grid; struct grid *gd = s->grid;
static struct grid_cell gc; const struct utf8_data *ud = &gc->data;
u_int n, width; u_int n, cx = s->cx, cy = s->cy;
struct grid_cell last;
struct tty_ctx ttyctx;
int force_wide = 0, zero_width = 0;
/* Can't combine if at 0. */ /*
if (s->cx == 0) { * Is this character which makes no sense without being combined? If
*xx = 0; * this is true then flag it here and discard the character (return 1)
return (NULL); * if we cannot combine it.
*/
if (utf8_is_zwj(ud))
zero_width = 1;
else if (utf8_is_vs(ud))
zero_width = force_wide = 1;
else if (ud->width == 0)
zero_width = 1;
/* Cannot combine empty character or at left. */
if (ud->size < 2 || cx == 0)
return (zero_width);
log_debug("%s: character %.*s at %u,%u (width %u)", __func__,
(int)ud->size, ud->data, cx, cy, ud->width);
/* Find the cell to combine with. */
n = 1;
grid_view_get_cell(gd, cx - n, cy, &last);
if (cx != 1 && (last.flags & GRID_FLAG_PADDING)) {
n = 2;
grid_view_get_cell(gd, cx - n, cy, &last);
} }
*xx = s->cx; if (n != last.data.width || (last.flags & GRID_FLAG_PADDING))
return (zero_width);
/* Empty data is out. */ /*
if (ud->size == 0) * Check if we need to combine characters. This could be zero width
fatalx("UTF-8 data empty"); * (zet above), a modifier character (with an existing Unicode
* character) or a previous ZWJ.
/* Retrieve the previous cell. */ */
for (n = 1; n <= s->cx; n++) { if (!zero_width) {
grid_view_get_cell(gd, s->cx - n, s->cy, &gc); if (utf8_is_modifier(ud)) {
if (~gc.flags & GRID_FLAG_PADDING) if (last.data.size < 2)
break; return (0);
force_wide = 1;
} else if (!utf8_has_zwj(&last.data))
return (0);
} }
if (n > s->cx)
return (NULL);
/* Check there is enough space. */ /* Combining; flush any pending output. */
if (gc.data.size + ud->size > sizeof gc.data.data) screen_write_collect_flush(ctx, 0, __func__);
return (NULL);
(*xx) -= n;
log_debug("%s: %.*s onto %.*s at %u,%u (width %u)", __func__, log_debug("%s: %.*s -> %.*s at %u,%u (offset %u, width %u)", __func__,
(int)ud->size, ud->data, (int)gc.data.size, gc.data.data, *xx, (int)ud->size, ud->data, (int)last.data.size, last.data.data,
s->cy, gc.data.width); cx - n, cy, n, last.data.width);
/* Append the data. */ /* Append the data. */
memcpy(gc.data.data + gc.data.size, ud->data, ud->size); memcpy(last.data.data + last.data.size, ud->data, ud->size);
gc.data.size += ud->size; last.data.size += ud->size;
width = gc.data.width;
/* If this is U+FE0F VARIATION SELECTOR-16, force the width to 2. */ /* Force the width to 2 for modifiers and variation selector. */
if (gc.data.width == 1 && if (last.data.width == 1 && force_wide) {
ud->size == 3 && last.data.width = 2;
memcmp(ud->data, "\357\270\217", 3) == 0) { n = 2;
grid_view_set_padding(gd, (*xx) + 1, s->cy); cx++;
gc.data.width = 2; } else
width += 2; force_wide = 0;
}
/* Set the new cell. */ /* Set the new cell. */
grid_view_set_cell(gd, *xx, s->cy, &gc); grid_view_set_cell(gd, cx - n, cy, &last);
if (force_wide)
grid_view_set_padding(gd, cx, cy);
*cx = (*xx) + width; /*
log_debug("%s: character at %u; cursor at %u", __func__, *xx, *cx); * Redraw the combined cell. If forcing the cell to width 2, reset the
return (&gc); * cached cursor position in the tty, since we don't really know
* whether the terminal thought the character was width 1 or width 2
* and what it is going to do now.
*/
screen_write_set_cursor(ctx, cx - n, cy);
screen_write_initctx(ctx, &ttyctx, 0);
ttyctx.cell = &last;
ttyctx.num = force_wide; /* reset cached cursor position */
tty_write(tty_cmd_cell, &ttyctx);
screen_write_set_cursor(ctx, cx, cy);
return (1);
} }
/* /*

View File

@ -1,4 +1,4 @@
/* $OpenBSD: server.c,v 1.204 2023/09/01 14:29:11 nicm Exp $ */ /* $OpenBSD: server.c,v 1.205 2023/09/15 15:49:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -205,7 +205,6 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
fatal("pledge failed"); fatal("pledge failed");
input_key_build(); input_key_build();
utf8_build_combined();
RB_INIT(&windows); RB_INIT(&windows);
RB_INIT(&all_window_panes); RB_INIT(&all_window_panes);
TAILQ_INIT(&clients); TAILQ_INIT(&clients);

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: tmux.1,v 1.931 2023/09/02 09:17:23 nicm Exp $ .\" $OpenBSD: tmux.1,v 1.932 2023/09/15 06:31:49 nicm Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\" .\"
@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: September 2 2023 $ .Dd $Mdocdate: September 15 2023 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@ -1546,6 +1546,7 @@ show debugging information about jobs and terminals.
.Tg source .Tg source
.It Xo Ic source-file .It Xo Ic source-file
.Op Fl Fnqv .Op Fl Fnqv
.Op Fl t Ar target-pane
.Ar path ... .Ar path ...
.Xc .Xc
.D1 Pq alias: Ic source .D1 Pq alias: Ic source

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1209 2023/09/02 20:03:10 nicm Exp $ */ /* $OpenBSD: tmux.h,v 1.1211 2023/09/15 15:49:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -30,6 +30,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <termios.h> #include <termios.h>
#include <wchar.h>
#include "tmux-protocol.h" #include "tmux-protocol.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -619,15 +620,6 @@ enum utf8_state {
UTF8_ERROR UTF8_ERROR
}; };
/* UTF-8 combine state. */
enum utf8_combine_state {
UTF8_DISCARD_NOW, /* discard immediately */
UTF8_WRITE_NOW, /* do not combine, write immediately */
UTF8_COMBINE_NOW, /* combine immediately */
UTF8_WRITE_MAYBE_COMBINE, /* write but try to combine the next */
UTF8_DISCARD_MAYBE_COMBINE /* discard but try to combine the next */
};
/* Colour flags. */ /* Colour flags. */
#define COLOUR_FLAG_256 0x01000000 #define COLOUR_FLAG_256 0x01000000
#define COLOUR_FLAG_RGB 0x02000000 #define COLOUR_FLAG_RGB 0x02000000
@ -900,7 +892,6 @@ struct screen_write_ctx {
int flags; int flags;
#define SCREEN_WRITE_SYNC 0x1 #define SCREEN_WRITE_SYNC 0x1
#define SCREEN_WRITE_COMBINE 0x2
screen_write_init_ctx_cb init_ctx_cb; screen_write_init_ctx_cb init_ctx_cb;
void *arg; void *arg;
@ -908,7 +899,6 @@ struct screen_write_ctx {
struct screen_write_citem *item; struct screen_write_citem *item;
u_int scrolled; u_int scrolled;
u_int bg; u_int bg;
struct utf8_data previous;
}; };
/* Box border lines option. */ /* Box border lines option. */
@ -2102,10 +2092,11 @@ extern char **cfg_files;
extern u_int cfg_nfiles; extern u_int cfg_nfiles;
extern int cfg_quiet; extern int cfg_quiet;
void start_cfg(void); void start_cfg(void);
int load_cfg(const char *, struct client *, struct cmdq_item *, int, int load_cfg(const char *, struct client *, struct cmdq_item *,
struct cmdq_item **); struct cmd_find_state *, int, struct cmdq_item **);
int load_cfg_from_buffer(const void *, size_t, const char *, int load_cfg_from_buffer(const void *, size_t, const char *,
struct client *, struct cmdq_item *, int, struct cmdq_item **); struct client *, struct cmdq_item *, struct cmd_find_state *,
int, struct cmdq_item **);
void printflike(1, 2) cfg_add_cause(const char *, ...); void printflike(1, 2) cfg_add_cause(const char *, ...);
void cfg_print_causes(struct cmdq_item *); void cfg_print_causes(struct cmdq_item *);
void cfg_show_causes(struct session *); void cfg_show_causes(struct session *);
@ -2551,7 +2542,8 @@ struct cmd_parse_result *cmd_parse_from_arguments(struct args_value *, u_int,
struct cmdq_state *cmdq_new_state(struct cmd_find_state *, struct key_event *, struct cmdq_state *cmdq_new_state(struct cmd_find_state *, struct key_event *,
int); int);
struct cmdq_state *cmdq_link_state(struct cmdq_state *); struct cmdq_state *cmdq_link_state(struct cmdq_state *);
struct cmdq_state *cmdq_copy_state(struct cmdq_state *); struct cmdq_state *cmdq_copy_state(struct cmdq_state *,
struct cmd_find_state *);
void cmdq_free_state(struct cmdq_state *); void cmdq_free_state(struct cmdq_state *);
void printflike(3, 4) cmdq_add_format(struct cmdq_state *, const char *, void printflike(3, 4) cmdq_add_format(struct cmdq_state *, const char *,
const char *, ...); const char *, ...);
@ -3275,6 +3267,8 @@ u_int session_group_attached_count(struct session_group *);
void session_renumber_windows(struct session *); void session_renumber_windows(struct session *);
/* utf8.c */ /* utf8.c */
enum utf8_state utf8_towc (const struct utf8_data *, wchar_t *);
int utf8_in_table(wchar_t, const wchar_t *, u_int);
utf8_char utf8_build_one(u_char); utf8_char utf8_build_one(u_char);
enum utf8_state utf8_from_data(const struct utf8_data *, utf8_char *); enum utf8_state utf8_from_data(const struct utf8_data *, utf8_char *);
void utf8_to_data(utf8_char, struct utf8_data *); void utf8_to_data(utf8_char, struct utf8_data *);
@ -3297,10 +3291,10 @@ char *utf8_rpadcstr(const char *, u_int);
int utf8_cstrhas(const char *, const struct utf8_data *); int utf8_cstrhas(const char *, const struct utf8_data *);
/* utf8-combined.c */ /* utf8-combined.c */
void utf8_build_combined(void); int utf8_has_zwj(const struct utf8_data *);
int utf8_try_combined(const struct utf8_data *, int utf8_is_zwj(const struct utf8_data *);
const struct utf8_data *, const struct utf8_data **, int utf8_is_vs(const struct utf8_data *);
u_int *width); int utf8_is_modifier(const struct utf8_data *);
/* procname.c */ /* procname.c */
char *get_proc_name(int, char *); char *get_proc_name(int, char *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tty.c,v 1.434 2023/09/02 20:03:10 nicm Exp $ */ /* $OpenBSD: tty.c,v 1.435 2023/09/15 15:49:05 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -2091,6 +2091,9 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette, tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,
ctx->s->hyperlinks); ctx->s->hyperlinks);
if (ctx->num == 1)
tty_invalidate(tty);
} }
void void

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $OpenBSD: utf8.c,v 1.63 2023/09/01 14:29:11 nicm Exp $ */ /* $OpenBSD: utf8.c,v 1.64 2023/09/15 15:49:05 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@ -23,10 +23,174 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <vis.h> #include <vis.h>
#include <wchar.h>
#include "tmux.h" #include "tmux.h"
static const wchar_t utf8_force_wide[] = {
0x0261D,
0x026F9,
0x0270A,
0x0270B,
0x0270C,
0x0270D,
0x1F1E6,
0x1F1E7,
0x1F1E8,
0x1F1E9,
0x1F1EA,
0x1F1EB,
0x1F1EC,
0x1F1ED,
0x1F1EE,
0x1F1EF,
0x1F1F0,
0x1F1F1,
0x1F1F2,
0x1F1F3,
0x1F1F4,
0x1F1F5,
0x1F1F6,
0x1F1F7,
0x1F1F8,
0x1F1F9,
0x1F1FA,
0x1F1FB,
0x1F1FC,
0x1F1FD,
0x1F1FE,
0x1F1FF,
0x1F385,
0x1F3C2,
0x1F3C3,
0x1F3C4,
0x1F3C7,
0x1F3CA,
0x1F3CB,
0x1F3CC,
0x1F3FB,
0x1F3FC,
0x1F3FD,
0x1F3FE,
0x1F3FF,
0x1F442,
0x1F443,
0x1F446,
0x1F447,
0x1F448,
0x1F449,
0x1F44A,
0x1F44B,
0x1F44C,
0x1F44D,
0x1F44E,
0x1F44F,
0x1F450,
0x1F466,
0x1F467,
0x1F468,
0x1F469,
0x1F46B,
0x1F46C,
0x1F46D,
0x1F46E,
0x1F470,
0x1F471,
0x1F472,
0x1F473,
0x1F474,
0x1F475,
0x1F476,
0x1F477,
0x1F478,
0x1F47C,
0x1F481,
0x1F482,
0x1F483,
0x1F485,
0x1F486,
0x1F487,
0x1F48F,
0x1F491,
0x1F4AA,
0x1F574,
0x1F575,
0x1F57A,
0x1F590,
0x1F595,
0x1F596,
0x1F645,
0x1F646,
0x1F647,
0x1F64B,
0x1F64C,
0x1F64D,
0x1F64E,
0x1F64F,
0x1F6A3,
0x1F6B4,
0x1F6B5,
0x1F6B6,
0x1F6C0,
0x1F6CC,
0x1F90C,
0x1F90F,
0x1F918,
0x1F919,
0x1F91A,
0x1F91B,
0x1F91C,
0x1F91D,
0x1F91E,
0x1F91F,
0x1F926,
0x1F930,
0x1F931,
0x1F932,
0x1F933,
0x1F934,
0x1F935,
0x1F936,
0x1F937,
0x1F938,
0x1F939,
0x1F93D,
0x1F93E,
0x1F977,
0x1F9B5,
0x1F9B6,
0x1F9B8,
0x1F9B9,
0x1F9BB,
0x1F9CD,
0x1F9CE,
0x1F9CF,
0x1F9D1,
0x1F9D2,
0x1F9D3,
0x1F9D4,
0x1F9D5,
0x1F9D6,
0x1F9D7,
0x1F9D8,
0x1F9D9,
0x1F9DA,
0x1F9DB,
0x1F9DC,
0x1F9DD,
0x1FAC3,
0x1FAC4,
0x1FAC5,
0x1FAF0,
0x1FAF1,
0x1FAF2,
0x1FAF3,
0x1FAF4,
0x1FAF5,
0x1FAF6,
0x1FAF7,
0x1FAF8
};
struct utf8_item { struct utf8_item {
RB_ENTRY(utf8_item) index_entry; RB_ENTRY(utf8_item) index_entry;
u_int index; u_int index;
@ -123,6 +287,28 @@ utf8_put_item(const u_char *data, size_t size, u_int *index)
return (0); return (0);
} }
static int
utf8_table_cmp(const void *vp1, const void *vp2)
{
const wchar_t *wc1 = vp1, *wc2 = vp2;
if (*wc1 < *wc2)
return (-1);
if (*wc1 > *wc2)
return (1);
return (0);
}
/* Check if character in table. */
int
utf8_in_table(wchar_t find, const wchar_t *table, u_int count)
{
wchar_t *found;
found = bsearch(&find, table, count, sizeof *table, utf8_table_cmp);
return (found != NULL);
}
/* Get UTF-8 character from data. */ /* Get UTF-8 character from data. */
enum utf8_state enum utf8_state
utf8_from_data(const struct utf8_data *ud, utf8_char *uc) utf8_from_data(const struct utf8_data *ud, utf8_char *uc)
@ -217,16 +403,13 @@ utf8_width(struct utf8_data *ud, int *width)
{ {
wchar_t wc; wchar_t wc;
switch (mbtowc(&wc, ud->data, ud->size)) { if (utf8_towc(ud, &wc) != UTF8_DONE)
case -1:
log_debug("UTF-8 %.*s, mbtowc() %d", (int)ud->size, ud->data,
errno);
mbtowc(NULL, NULL, MB_CUR_MAX);
return (UTF8_ERROR);
case 0:
return (UTF8_ERROR); return (UTF8_ERROR);
if (utf8_in_table(wc, utf8_force_wide, nitems(utf8_force_wide))) {
*width = 2;
return (UTF8_DONE);
} }
log_debug("UTF-8 %.*s is %05X", (int)ud->size, ud->data, (u_int)wc);
*width = wcwidth(wc); *width = wcwidth(wc);
log_debug("wcwidth(%05X) returned %d", (u_int)wc, *width); log_debug("wcwidth(%05X) returned %d", (u_int)wc, *width);
if (*width < 0) { if (*width < 0) {
@ -241,6 +424,23 @@ utf8_width(struct utf8_data *ud, int *width)
return (UTF8_ERROR); return (UTF8_ERROR);
} }
/* Convert UTF-8 character to wide character. */
enum utf8_state
utf8_towc(const struct utf8_data *ud, wchar_t *wc)
{
switch (mbtowc(wc, ud->data, ud->size)) {
case -1:
log_debug("UTF-8 %.*s, mbtowc() %d", (int)ud->size, ud->data,
errno);
mbtowc(NULL, NULL, MB_CUR_MAX);
return (UTF8_ERROR);
case 0:
return (UTF8_ERROR);
}
log_debug("UTF-8 %.*s is %05X", (int)ud->size, ud->data, (u_int)*wc);
return (UTF8_DONE);
}
/* /*
* Open UTF-8 sequence. * Open UTF-8 sequence.
* *

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: btrace.8,v 1.8 2022/12/22 19:53:24 kn Exp $ .\" $OpenBSD: btrace.8,v 1.9 2023/09/15 10:56:46 claudio Exp $
.\" .\"
.\" Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org> .\" Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org>
.\" .\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: December 22 2022 $ .Dd $Mdocdate: September 15 2023 $
.Dt BTRACE 8 .Dt BTRACE 8
.Os .Os
.Sh NAME .Sh NAME
@ -24,6 +24,7 @@
.Nm btrace .Nm btrace
.Op Fl lnv .Op Fl lnv
.Op Fl e Ar program | Ar file .Op Fl e Ar program | Ar file
.Op Fl p Ar file
.Op Ar argument ... .Op Ar argument ...
.Sh DESCRIPTION .Sh DESCRIPTION
The The
@ -47,6 +48,12 @@ List all available probes.
.It Fl n .It Fl n
No action. No action.
Parse the program and then exit. Parse the program and then exit.
.It Fl p Ar file
Load symbols from
.Ar file
to convert
.Va ustack
addresses into function names.
.It Fl v .It Fl v
Verbose mode. Verbose mode.
Causes Causes

View File

@ -1,4 +1,4 @@
/* $OpenBSD: btrace.c,v 1.77 2023/09/13 13:47:58 mpi Exp $ */ /* $OpenBSD: btrace.c,v 1.78 2023/09/15 10:59:02 claudio Exp $ */
/* /*
* Copyright (c) 2019 - 2023 Martin Pieuchot <mpi@openbsd.org> * Copyright (c) 2019 - 2023 Martin Pieuchot <mpi@openbsd.org>
@ -233,8 +233,8 @@ main(int argc, char *argv[])
__dead void __dead void
usage(void) usage(void)
{ {
fprintf(stderr, "usage: %s [-lnv] [-e program | file] [argument ...]\n", fprintf(stderr, "usage: %s [-lnv] [-e program | file] [-p file] "
getprogname()); "[argument ...]\n", getprogname());
exit(1); exit(1);
} }