jcs's openbsd hax
openbsd
1/* $OpenBSD: visbuf.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */
2
3/****************************************************************************
4 * Copyright 2019-2021,2023 Thomas E. Dickey *
5 * Copyright 2001-2016,2017 Free Software Foundation, Inc. *
6 * *
7 * Permission is hereby granted, free of charge, to any person obtaining a *
8 * copy of this software and associated documentation files (the *
9 * "Software"), to deal in the Software without restriction, including *
10 * without limitation the rights to use, copy, modify, merge, publish, *
11 * distribute, distribute with modifications, sublicense, and/or sell *
12 * copies of the Software, and to permit persons to whom the Software is *
13 * furnished to do so, subject to the following conditions: *
14 * *
15 * The above copyright notice and this permission notice shall be included *
16 * in all copies or substantial portions of the Software. *
17 * *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
21 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
24 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
25 * *
26 * Except as contained in this notice, the name(s) of the above copyright *
27 * holders shall not be used in advertising or otherwise to promote the *
28 * sale, use or other dealings in this Software without prior written *
29 * authorization. *
30 ****************************************************************************/
31
32/****************************************************************************
33 * Author: Thomas E. Dickey 1996-on *
34 * and: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
35 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
36 ****************************************************************************/
37
38/*
39 * visbuf.c - Tracing/Debugging support routines
40 */
41
42#define NEED_NCURSES_CH_T
43#include <curses.priv.h>
44
45#include <tic.h>
46#include <ctype.h>
47
48MODULE_ID("$Id: visbuf.c,v 1.2 2023/10/17 09:52:09 nicm Exp $")
49
50#define NUM_VISBUFS 4
51
52#define NormalLen(len) (size_t) (((size_t)(len) + 1) * 4)
53#define WideLen(len) (size_t) (((size_t)(len) + 1) * 4 * (size_t) MB_CUR_MAX)
54
55#ifdef TRACE
56static const char d_quote[] = StringOf(D_QUOTE);
57static const char l_brace[] = StringOf(L_BRACE);
58static const char r_brace[] = StringOf(R_BRACE);
59#endif
60
61#if USE_STRING_HACKS && HAVE_SNPRINTF
62#define VisChar(tp, chr, limit) _nc_vischar(tp, chr, limit)
63#define LIMIT_ARG ,size_t limit
64#else
65#define VisChar(tp, chr, limit) _nc_vischar(tp, chr)
66#define LIMIT_ARG /* nothing */
67#endif
68
69static char *
70_nc_vischar(char *tp, unsigned c LIMIT_ARG)
71{
72 if (tp == NULL) {
73 return NULL;
74 } else if (c == '"' || c == '\\') {
75 *tp++ = '\\';
76 *tp++ = (char) c;
77 } else if (is7bits((int) c) && (isgraph((int) c) || c == ' ')) {
78 *tp++ = (char) c;
79 } else if (c == '\n') {
80 *tp++ = '\\';
81 *tp++ = 'n';
82 } else if (c == '\r') {
83 *tp++ = '\\';
84 *tp++ = 'r';
85 } else if (c == '\b') {
86 *tp++ = '\\';
87 *tp++ = 'b';
88 } else if (c == '\t') {
89 *tp++ = '\\';
90 *tp++ = 't';
91 } else if (c == '\033') {
92 *tp++ = '\\';
93 *tp++ = 'e';
94 } else if (UChar(c) == 0x7f) {
95 *tp++ = '\\';
96 *tp++ = '^';
97 *tp++ = '?';
98 } else if (is7bits(c) && iscntrl(UChar(c))) {
99 *tp++ = '\\';
100 *tp++ = '^';
101 *tp++ = (char) ('@' + c);
102 } else {
103 _nc_SPRINTF(tp, _nc_SLIMIT(limit)
104 "\\%03lo", (unsigned long) ChCharOf(c));
105 tp += strlen(tp);
106 }
107 *tp = 0;
108 return tp;
109}
110
111static const char *
112_nc_visbuf2n(int bufnum, const char *buf, int len)
113{
114 const char *vbuf = 0;
115 char *tp;
116 int count;
117
118 if (buf == 0)
119 return ("(null)");
120 if (buf == CANCELLED_STRING)
121 return ("(cancelled)");
122
123 if (len < 0)
124 len = (int) strlen(buf);
125
126 count = len;
127#ifdef TRACE
128 vbuf = tp = _nc_trace_buf(bufnum, NormalLen(len));
129#else
130 {
131 static char *mybuf[NUM_VISBUFS];
132 int c;
133
134 if (bufnum < 0) {
135 for (c = 0; c < NUM_VISBUFS; ++c) {
136 FreeAndNull(mybuf[c]);
137 }
138 tp = 0;
139 } else {
140 mybuf[bufnum] = typeRealloc(char, NormalLen(len), mybuf[bufnum]);
141 vbuf = tp = mybuf[bufnum];
142 }
143 }
144#endif
145 if (tp != 0) {
146 int c;
147
148 *tp++ = D_QUOTE;
149 while ((--count >= 0) && (c = *buf++) != '\0') {
150 tp = VisChar(tp, UChar(c), NormalLen(len));
151 }
152 *tp++ = D_QUOTE;
153 *tp = '\0';
154 } else {
155 vbuf = ("(_nc_visbuf2n failed)");
156 }
157 return (vbuf);
158}
159
160NCURSES_EXPORT(const char *)
161_nc_visbuf2(int bufnum, const char *buf)
162{
163 return _nc_visbuf2n(bufnum, buf, -1);
164}
165
166NCURSES_EXPORT(const char *)
167_nc_visbuf(const char *buf)
168{
169 return _nc_visbuf2(0, buf);
170}
171
172NCURSES_EXPORT(const char *)
173_nc_visbufn(const char *buf, int len)
174{
175 return _nc_visbuf2n(0, buf, len);
176}
177
178#ifdef TRACE
179#if USE_WIDEC_SUPPORT
180
181#if defined(USE_TERMLIB)
182#define _nc_wchstrlen _my_wchstrlen
183static int
184_nc_wchstrlen(const cchar_t *s)
185{
186 int result = 0;
187 while (CharOf(s[result]) != L'\0') {
188 result++;
189 }
190 return result;
191}
192#endif
193
194static const char *
195_nc_viswbuf2n(int bufnum, const wchar_t *buf, int len)
196{
197 const char *vbuf;
198 char *tp;
199 int count;
200
201 if (buf == 0)
202 return ("(null)");
203
204 if (len < 0)
205 len = (int) wcslen(buf);
206
207 count = len;
208#ifdef TRACE
209 vbuf = tp = _nc_trace_buf(bufnum, WideLen(len));
210#else
211 {
212 static char *mybuf[NUM_VISBUFS];
213 mybuf[bufnum] = typeRealloc(char, WideLen(len), mybuf[bufnum]);
214 vbuf = tp = mybuf[bufnum];
215 }
216#endif
217 if (tp != 0) {
218 wchar_t c;
219
220 *tp++ = D_QUOTE;
221 while ((--count >= 0) && (c = *buf++) != '\0') {
222 char temp[CCHARW_MAX + 80];
223 int j = wctomb(temp, c), k;
224 if (j <= 0) {
225 _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
226 "\\u%08X", (unsigned) c);
227 j = (int) strlen(temp);
228 }
229 for (k = 0; k < j; ++k) {
230 tp = VisChar(tp, UChar(temp[k]), WideLen(len));
231 }
232 }
233 *tp++ = D_QUOTE;
234 *tp = '\0';
235 } else {
236 vbuf = ("(_nc_viswbuf2n failed)");
237 }
238 return (vbuf);
239}
240
241NCURSES_EXPORT(const char *)
242_nc_viswbuf2(int bufnum, const wchar_t *buf)
243{
244 return _nc_viswbuf2n(bufnum, buf, -1);
245}
246
247NCURSES_EXPORT(const char *)
248_nc_viswbuf(const wchar_t *buf)
249{
250 return _nc_viswbuf2(0, buf);
251}
252
253NCURSES_EXPORT(const char *)
254_nc_viswbufn(const wchar_t *buf, int len)
255{
256 return _nc_viswbuf2n(0, buf, len);
257}
258
259/* this special case is used for wget_wstr() */
260NCURSES_EXPORT(const char *)
261_nc_viswibuf(const wint_t *buf)
262{
263 static wchar_t *mybuf;
264 static unsigned mylen;
265 unsigned n;
266
267 for (n = 0; buf[n] != 0; ++n) {
268 ; /* empty */
269 }
270 if (mylen < ++n) {
271 mylen = n + 80;
272 if (mybuf != 0)
273 mybuf = typeRealloc(wchar_t, mylen, mybuf);
274 else
275 mybuf = typeMalloc(wchar_t, mylen);
276 }
277 if (mybuf != 0) {
278 for (n = 0; buf[n] != 0; ++n) {
279 mybuf[n] = (wchar_t) buf[n];
280 }
281 mybuf[n] = L'\0';
282 }
283
284 return _nc_viswbuf2(0, mybuf);
285}
286#endif /* USE_WIDEC_SUPPORT */
287
288/* use these functions for displaying parts of a line within a window */
289NCURSES_EXPORT(const char *)
290_nc_viscbuf2(int bufnum, const NCURSES_CH_T *buf, int len)
291{
292 char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ);
293
294 if (result != 0) {
295 int first = 0;
296
297#if USE_WIDEC_SUPPORT
298 if (len < 0)
299 len = _nc_wchstrlen(buf);
300#endif /* USE_WIDEC_SUPPORT */
301
302 /*
303 * Display one or more strings followed by attributes.
304 */
305 while (first < len) {
306 attr_t attr = AttrOf(buf[first]);
307 int last = len - 1;
308 int j;
309
310 for (j = first + 1; j < len; ++j) {
311 if (!SameAttrOf(buf[j], buf[first])) {
312 last = j - 1;
313 break;
314 }
315 }
316
317 (void) _nc_trace_bufcat(bufnum, l_brace);
318 (void) _nc_trace_bufcat(bufnum, d_quote);
319 for (j = first; j <= last; ++j) {
320 const char *found = _nc_altcharset_name(attr, (chtype)
321 CharOf(buf[j]));
322 if (found != 0) {
323 (void) _nc_trace_bufcat(bufnum, found);
324 attr &= ~A_ALTCHARSET;
325 } else
326#if USE_WIDEC_SUPPORT
327 if (!isWidecExt(buf[j])) {
328 PUTC_DATA;
329
330 for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) {
331 int k;
332 char temp[80];
333
334 PUTC_ch = buf[j].chars[PUTC_i];
335 if (PUTC_ch == L'\0') {
336 if (PUTC_i == 0)
337 (void) _nc_trace_bufcat(bufnum, "\\000");
338 break;
339 }
340 PUTC_INIT;
341 PUTC_n = (int) wcrtomb(PUTC_buf,
342 buf[j].chars[PUTC_i], &PUT_st);
343 if (PUTC_n <= 0 || buf[j].chars[PUTC_i] > 255) {
344 _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
345 "{%d:\\u%lx}",
346 _nc_wacs_width(buf[j].chars[PUTC_i]),
347 (unsigned long) buf[j].chars[PUTC_i]);
348 (void) _nc_trace_bufcat(bufnum, temp);
349 break;
350 }
351 for (k = 0; k < PUTC_n; k++) {
352 VisChar(temp, UChar(PUTC_buf[k]), sizeof(temp));
353 (void) _nc_trace_bufcat(bufnum, temp);
354 }
355 }
356 }
357#else
358 {
359 char temp[80];
360 VisChar(temp, UChar(buf[j]), sizeof(temp));
361 (void) _nc_trace_bufcat(bufnum, temp);
362 }
363#endif /* USE_WIDEC_SUPPORT */
364 }
365 (void) _nc_trace_bufcat(bufnum, d_quote);
366 if (attr != A_NORMAL) {
367 (void) _nc_trace_bufcat(bufnum, " | ");
368 (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr));
369 }
370 result = _nc_trace_bufcat(bufnum, r_brace);
371 first = last + 1;
372 }
373 }
374 return result;
375}
376
377NCURSES_EXPORT(const char *)
378_nc_viscbuf(const NCURSES_CH_T *buf, int len)
379{
380 return _nc_viscbuf2(0, buf, len);
381}
382#endif /* TRACE */