Bug Summary

File:src/usr.bin/tset/../tic/dump_entry.c
Warning:line 1135, column 6
Value stored to 'len' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dump_entry.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/tset/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/tset/../../lib/libcurses -I /usr/src/usr.bin/tset/../tic -I /usr/src/usr.bin/tset -I . -D HAVE_GETTTYNAM -D HAVE_TTYENT_H -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/tset/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/tset/../tic/dump_entry.c
1/* $OpenBSD: dump_entry.c,v 1.20 2017/05/11 19:13:17 millert Exp $ */
2
3/****************************************************************************
4 * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. *
5 * *
6 * Permission is hereby granted, free of charge, to any person obtaining a *
7 * copy of this software and associated documentation files (the *
8 * "Software"), to deal in the Software without restriction, including *
9 * without limitation the rights to use, copy, modify, merge, publish, *
10 * distribute, distribute with modifications, sublicense, and/or sell *
11 * copies of the Software, and to permit persons to whom the Software is *
12 * furnished to do so, subject to the following conditions: *
13 * *
14 * The above copyright notice and this permission notice shall be included *
15 * in all copies or substantial portions of the Software. *
16 * *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
20 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
23 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
24 * *
25 * Except as contained in this notice, the name(s) of the above copyright *
26 * holders shall not be used in advertising or otherwise to promote the *
27 * sale, use or other dealings in this Software without prior written *
28 * authorization. *
29 ****************************************************************************/
30
31/****************************************************************************
32 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
33 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
34 * and: Thomas E. Dickey 1996 on *
35 ****************************************************************************/
36
37#define __INTERNAL_CAPS_VISIBLE
38#include <progs.priv.h>
39
40#include "dump_entry.h"
41#include "termsort.c" /* this C file is generated */
42#include <parametrized.h> /* so is this */
43
44MODULE_ID("$Id: dump_entry.c,v 1.20 2017/05/11 19:13:17 millert Exp $")
45
46#define INDENT8 8
47#define DISCARD(string)string = (char *)0 string = ABSENT_STRING(char *)0
48#define PRINTF(void) printf (void) printf
49
50#define OkIndex(index,array)((int)(index) >= 0 && (int)(index) < (int) (sizeof
(array)/sizeof(array[0])))
((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array)(sizeof(array)/sizeof(array[0])))
51
52typedef struct {
53 char *text;
54 size_t used;
55 size_t size;
56} DYNBUF;
57
58static int tversion; /* terminfo version */
59static int outform; /* output format to use */
60static int sortmode; /* sort mode to use */
61static int width = 60; /* max line width for listings */
62static int column; /* current column, limited by 'width' */
63static int oldcol; /* last value of column before wrap */
64static bool_Bool pretty; /* true if we format if-then-else strings */
65
66static char *save_sgr;
67
68static DYNBUF outbuf;
69static DYNBUF tmpbuf;
70
71/* indirection pointers for implementing sort and display modes */
72static const PredIdx *bool_indirect, *num_indirect, *str_indirect;
73static NCURSES_CONSTconst char *const *bool_names;
74static NCURSES_CONSTconst char *const *num_names;
75static NCURSES_CONSTconst char *const *str_names;
76
77static const char *separator, *trailer;
78
79/* cover various ports and variants of terminfo */
80#define V_ALLCAPS0 0 /* all capabilities (SVr4, XSI, ncurses) */
81#define V_SVR11 1 /* SVR1, Ultrix */
82#define V_HPUX2 2 /* HP/UX */
83#define V_AIX3 3 /* AIX */
84#define V_BSD4 4 /* BSD */
85
86#if NCURSES_XNAMES1
87#define OBSOLETE(n)(!_nc_user_definable && (n[0] == 'O' && n[1] ==
'T'))
(!_nc_user_definable && (n[0] == 'O' && n[1] == 'T'))
88#else
89#define OBSOLETE(n)(!_nc_user_definable && (n[0] == 'O' && n[1] ==
'T'))
(n[0] == 'O' && n[1] == 'T')
90#endif
91
92#define isObsolete(f,n)((f == 0 || f == 1) && (!_nc_user_definable &&
(n[0] == 'O' && n[1] == 'T')))
((f == F_TERMINFO0 || f == F_VARIABLE1) && OBSOLETE(n)(!_nc_user_definable && (n[0] == 'O' && n[1] ==
'T'))
)
93
94#if NCURSES_XNAMES1
95#define BoolIndirect(j)((j >= 44) ? (j) : ((sortmode == 1) ? j : bool_indirect[j]
))
((j >= BOOLCOUNT44) ? (j) : ((sortmode == S_NOSORT1) ? j : bool_indirect[j]))
96#define NumIndirect(j)((j >= 39) ? (j) : ((sortmode == 1) ? j : num_indirect[j])
)
((j >= NUMCOUNT39) ? (j) : ((sortmode == S_NOSORT1) ? j : num_indirect[j]))
97#define StrIndirect(j)((j >= 414) ? (j) : ((sortmode == 1) ? j : str_indirect[j]
))
((j >= STRCOUNT414) ? (j) : ((sortmode == S_NOSORT1) ? j : str_indirect[j]))
98#else
99#define BoolIndirect(j)((j >= 44) ? (j) : ((sortmode == 1) ? j : bool_indirect[j]
))
((sortmode == S_NOSORT1) ? (j) : bool_indirect[j])
100#define NumIndirect(j)((j >= 39) ? (j) : ((sortmode == 1) ? j : num_indirect[j])
)
((sortmode == S_NOSORT1) ? (j) : num_indirect[j])
101#define StrIndirect(j)((j >= 414) ? (j) : ((sortmode == 1) ? j : str_indirect[j]
))
((sortmode == S_NOSORT1) ? (j) : str_indirect[j])
102#endif
103
104static void
105strncpy_DYN(DYNBUF * dst, const char *src, size_t need)
106{
107 size_t want = need + dst->used + 1;
108 if (want > dst->size) {
109 dst->size += (want + 1024); /* be generous */
110 dst->text = typeRealloc(char, dst->size, dst->text)(char *)_nc_doalloc(dst->text, (dst->size)*sizeof(char)
)
;
111 }
112 (void) strncpy(dst->text + dst->used, src, need);
113 dst->used += need;
114 dst->text[dst->used] = 0;
115}
116
117static void
118strcpy_DYN(DYNBUF * dst, const char *src)
119{
120 if (src == 0) {
121 dst->used = 0;
122 strcpy_DYN(dst, "");
123 } else {
124 strncpy_DYN(dst, src, strlen(src));
125 }
126}
127
128#if NO_LEAKS0
129static void
130free_DYN(DYNBUF * p)
131{
132 if (p->text != 0)
133 free(p->text);
134 p->text = 0;
135 p->size = 0;
136 p->used = 0;
137}
138
139void
140_nc_leaks_dump_entry(void)
141{
142 free_DYN(&outbuf);
143 free_DYN(&tmpbuf);
144}
145#endif
146
147#define NameTrans(check,result)if (((int)(np->nte_index) >= 0 && (int)(np->
nte_index) < (int) (sizeof(check)/sizeof(check[0]))) &&
check[np->nte_index]) return (result[np->nte_index])
\
148 if (OkIndex(np->nte_index, check)((int)(np->nte_index) >= 0 && (int)(np->nte_index
) < (int) (sizeof(check)/sizeof(check[0])))
\
149 && check[np->nte_index]) \
150 return (result[np->nte_index])
151
152NCURSES_CONSTconst char *
153nametrans(const char *name)
154/* translate a capability name from termcap to terminfo */
155{
156 const struct name_table_entry *np;
157
158 if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0)
159 switch (np->nte_type) {
160 case BOOLEAN0:
161 NameTrans(bool_from_termcap, boolcodes)if (((int)(np->nte_index) >= 0 && (int)(np->
nte_index) < (int) (sizeof(bool_from_termcap)/sizeof(bool_from_termcap
[0]))) && bool_from_termcap[np->nte_index]) return
(boolcodes[np->nte_index])
;
162 break;
163
164 case NUMBER1:
165 NameTrans(num_from_termcap, numcodes)if (((int)(np->nte_index) >= 0 && (int)(np->
nte_index) < (int) (sizeof(num_from_termcap)/sizeof(num_from_termcap
[0]))) && num_from_termcap[np->nte_index]) return (
numcodes[np->nte_index])
;
166 break;
167
168 case STRING2:
169 NameTrans(str_from_termcap, strcodes)if (((int)(np->nte_index) >= 0 && (int)(np->
nte_index) < (int) (sizeof(str_from_termcap)/sizeof(str_from_termcap
[0]))) && str_from_termcap[np->nte_index]) return (
strcodes[np->nte_index])
;
170 break;
171 }
172
173 return (0);
174}
175
176void
177dump_init(const char *version, int mode, int sort, int twidth, int traceval,
178 bool_Bool formatted)
179/* set up for entry display */
180{
181 width = twidth;
182 pretty = formatted;
183
184 /* versions */
185 if (version == 0)
186 tversion = V_ALLCAPS0;
187 else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1")
188 || !strcmp(version, "Ultrix"))
189 tversion = V_SVR11;
190 else if (!strcmp(version, "HP"))
191 tversion = V_HPUX2;
192 else if (!strcmp(version, "AIX"))
193 tversion = V_AIX3;
194 else if (!strcmp(version, "BSD"))
195 tversion = V_BSD4;
196 else
197 tversion = V_ALLCAPS0;
198
199 /* implement display modes */
200 switch (outform = mode) {
201 case F_LITERAL4:
202 case F_TERMINFO0:
203 bool_names = boolnames;
204 num_names = numnames;
205 str_names = strnames;
206 separator = twidth ? ", " : ",";
207 trailer = "\n\t";
208 break;
209
210 case F_VARIABLE1:
211 bool_names = boolfnames;
212 num_names = numfnames;
213 str_names = strfnames;
214 separator = twidth ? ", " : ",";
215 trailer = "\n\t";
216 break;
217
218 case F_TERMCAP2:
219 case F_TCONVERR3:
220 bool_names = boolcodes;
221 num_names = numcodes;
222 str_names = strcodes;
223 separator = ":";
224 trailer = "\\\n\t:";
225 break;
226 }
227
228 /* implement sort modes */
229 switch (sortmode = sort) {
230 case S_NOSORT1:
231 if (traceval)
232 (void) fprintf(stderr(&__sF[2]),
233 "%s: sorting by term structure order\n", _nc_progname);
234 break;
235
236 case S_TERMINFO2:
237 if (traceval)
238 (void) fprintf(stderr(&__sF[2]),
239 "%s: sorting by terminfo name order\n", _nc_progname);
240 bool_indirect = bool_terminfo_sort;
241 num_indirect = num_terminfo_sort;
242 str_indirect = str_terminfo_sort;
243 break;
244
245 case S_VARIABLE3:
246 if (traceval)
247 (void) fprintf(stderr(&__sF[2]),
248 "%s: sorting by C variable order\n", _nc_progname);
249 bool_indirect = bool_variable_sort;
250 num_indirect = num_variable_sort;
251 str_indirect = str_variable_sort;
252 break;
253
254 case S_TERMCAP4:
255 if (traceval)
256 (void) fprintf(stderr(&__sF[2]),
257 "%s: sorting by termcap name order\n", _nc_progname);
258 bool_indirect = bool_termcap_sort;
259 num_indirect = num_termcap_sort;
260 str_indirect = str_termcap_sort;
261 break;
262 }
263
264 if (traceval)
265 (void) fprintf(stderr(&__sF[2]),
266 "%s: width = %d, tversion = %d, outform = %d\n",
267 _nc_progname, width, tversion, outform);
268}
269
270static TERMTYPE *cur_type;
271
272static int
273dump_predicate(PredType type, PredIdx idx)
274/* predicate function to use for ordinary decompilation */
275{
276 switch (type) {
277 case BOOLEAN0:
278 return (cur_type->Booleans[idx] == FALSE0)
279 ? FAIL-1 : cur_type->Booleans[idx];
280
281 case NUMBER1:
282 return (cur_type->Numbers[idx] == ABSENT_NUMERIC(-1))
283 ? FAIL-1 : cur_type->Numbers[idx];
284
285 case STRING2:
286 return (cur_type->Strings[idx] != ABSENT_STRING(char *)0)
287 ? (int) TRUE1 : FAIL-1;
288 }
289
290 return (FALSE0); /* pacify compiler */
291}
292
293static void set_obsolete_termcaps(TERMTYPE *tp);
294
295/* is this the index of a function key string? */
296#define FNKEY(i)(((i)>= 65 && (i)<= 75) || ((i)>= 216 &&
(i)<= 268))
(((i)>= 65 && (i)<= 75) || ((i)>= 216 && (i)<= 268))
297
298/*
299 * If we configure with a different Caps file, the offsets into the arrays
300 * will change. So we use an address expression.
301 */
302#define BOOL_IDX(name)(PredType) (&(name) - &(tp-> Booleans[0])) (PredType) (&(name) - &(CURtp-> Booleans[0]))
303#define NUM_IDX(name)(PredType) (&(name) - &(tp-> Numbers[0])) (PredType) (&(name) - &(CURtp-> Numbers[0]))
304#define STR_IDX(name)(PredType) (&(name) - &(tp-> Strings[0])) (PredType) (&(name) - &(CURtp-> Strings[0]))
305
306static bool_Bool
307version_filter(PredType type, PredIdx idx)
308/* filter out capabilities we may want to suppress */
309{
310 switch (tversion) {
311 case V_ALLCAPS0: /* SVr4, XSI Curses */
312 return (TRUE1);
313
314 case V_SVR11: /* System V Release 1, Ultrix */
315 switch (type) {
316 case BOOLEAN0:
317 return ((idx <= BOOL_IDX(xon_xoff)(PredType) (&(tp-> Booleans[20]) - &(tp-> Booleans
[0]))
) ? TRUE1 : FALSE0);
318 case NUMBER1:
319 return ((idx <= NUM_IDX(width_status_line)(PredType) (&(tp-> Numbers[7]) - &(tp-> Numbers
[0]))
) ? TRUE1 : FALSE0);
320 case STRING2:
321 return ((idx <= STR_IDX(prtr_non)(PredType) (&(tp-> Strings[144]) - &(tp-> Strings
[0]))
) ? TRUE1 : FALSE0);
322 }
323 break;
324
325 case V_HPUX2: /* Hewlett-Packard */
326 switch (type) {
327 case BOOLEAN0:
328 return ((idx <= BOOL_IDX(xon_xoff)(PredType) (&(tp-> Booleans[20]) - &(tp-> Booleans
[0]))
) ? TRUE1 : FALSE0);
329 case NUMBER1:
330 return ((idx <= NUM_IDX(label_width)(PredType) (&(tp-> Numbers[10]) - &(tp-> Numbers
[0]))
) ? TRUE1 : FALSE0);
331 case STRING2:
332 if (idx <= STR_IDX(prtr_non)(PredType) (&(tp-> Strings[144]) - &(tp-> Strings
[0]))
)
333 return (TRUE1);
334 else if (FNKEY(idx)(((idx)>= 65 && (idx)<= 75) || ((idx)>= 216 &&
(idx)<= 268))
) /* function keys */
335 return (TRUE1);
336 else if (idx == STR_IDX(plab_norm)(PredType) (&(tp-> Strings[147]) - &(tp-> Strings
[0]))
337 || idx == STR_IDX(label_on)(PredType) (&(tp-> Strings[156]) - &(tp-> Strings
[0]))
338 || idx == STR_IDX(label_off)(PredType) (&(tp-> Strings[157]) - &(tp-> Strings
[0]))
)
339 return (TRUE1);
340 else
341 return (FALSE0);
342 }
343 break;
344
345 case V_AIX3: /* AIX */
346 switch (type) {
347 case BOOLEAN0:
348 return ((idx <= BOOL_IDX(xon_xoff)(PredType) (&(tp-> Booleans[20]) - &(tp-> Booleans
[0]))
) ? TRUE1 : FALSE0);
349 case NUMBER1:
350 return ((idx <= NUM_IDX(width_status_line)(PredType) (&(tp-> Numbers[7]) - &(tp-> Numbers
[0]))
) ? TRUE1 : FALSE0);
351 case STRING2:
352 if (idx <= STR_IDX(prtr_non)(PredType) (&(tp-> Strings[144]) - &(tp-> Strings
[0]))
)
353 return (TRUE1);
354 else if (FNKEY(idx)(((idx)>= 65 && (idx)<= 75) || ((idx)>= 216 &&
(idx)<= 268))
) /* function keys */
355 return (TRUE1);
356 else
357 return (FALSE0);
358 }
359 break;
360
361#define is_termcap(type)(((int)(idx) >= 0 && (int)(idx) < (int) (sizeof
(type_from_termcap)/sizeof(type_from_termcap[0]))) &&
type_from_termcap[idx])
(OkIndex(idx, type##_from_termcap)((int)(idx) >= 0 && (int)(idx) < (int) (sizeof(
type##_from_termcap)/sizeof(type##_from_termcap[0])))
&& \
362 type##_from_termcap[idx])
363
364 case V_BSD4: /* BSD */
365 switch (type) {
366 case BOOLEAN0:
367 return is_termcap(bool)(((int)(idx) >= 0 && (int)(idx) < (int) (sizeof
(bool_from_termcap)/sizeof(bool_from_termcap[0]))) &&
bool_from_termcap[idx])
;
368 case NUMBER1:
369 return is_termcap(num)(((int)(idx) >= 0 && (int)(idx) < (int) (sizeof
(num_from_termcap)/sizeof(num_from_termcap[0]))) && num_from_termcap
[idx])
;
370 case STRING2:
371 return is_termcap(str)(((int)(idx) >= 0 && (int)(idx) < (int) (sizeof
(str_from_termcap)/sizeof(str_from_termcap[0]))) && str_from_termcap
[idx])
;
372 }
373 break;
374 }
375
376 return (FALSE0); /* pacify the compiler */
377}
378
379static void
380trim_trailing(void)
381{
382 while (outbuf.used > 0 && outbuf.text[outbuf.used - 1] == ' ')
383 outbuf.text[--outbuf.used] = '\0';
384}
385
386static void
387force_wrap(void)
388{
389 oldcol = column;
390 trim_trailing();
391 strcpy_DYN(&outbuf, trailer);
392 column = INDENT8;
393}
394
395static void
396wrap_concat(const char *src)
397{
398 unsigned need = strlen(src);
399 unsigned want = strlen(separator) + need;
400
401 if (column > INDENT8
402 && column + (int) want > width) {
403 force_wrap();
404 }
405 strcpy_DYN(&outbuf, src);
406 strcpy_DYN(&outbuf, separator);
407 column += (int) need;
408}
409
410#define IGNORE_SEP_TRAIL(first,last,sep_trail)if ((size_t)(last - first) > sizeof(sep_trail)-1 &&
!strncmp(first, sep_trail, sizeof(sep_trail)-1)) first += sizeof
(sep_trail)-2
\
411 if ((size_t)(last - first) > sizeof(sep_trail)-1 \
412 && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \
413 first += sizeof(sep_trail)-2
414
415/* Returns the nominal length of the buffer assuming it is termcap format,
416 * i.e., the continuation sequence is treated as a single character ":".
417 *
418 * There are several implementations of termcap which read the text into a
419 * fixed-size buffer. Generally they strip the newlines from the text, but may
420 * not do it until after the buffer is read. Also, "tc=" resolution may be
421 * expanded in the same buffer. This function is useful for measuring the size
422 * of the best fixed-buffer implementation; the worst case may be much worse.
423 */
424#ifdef TEST_TERMCAP_LENGTH
425static int
426termcap_length(const char *src)strlen(const char *src)
427{
428 static const char pattern[] = ":\\\n\t:";
429
430 int len = 0;
431 const char *const t = src + strlen(src);
432
433 while (*src != '\0') {
434 IGNORE_SEP_TRAIL(src, t, pattern)if ((size_t)(t - src) > sizeof(pattern)-1 && !strncmp
(src, pattern, sizeof(pattern)-1)) src += sizeof(pattern)-2
;
435 src++;
436 len++;
437 }
438 return len;
439}
440#else
441#define termcap_length(src)strlen(src) strlen(src)
442#endif
443
444static void
445indent_DYN(DYNBUF * buffer, int level)
446{
447 int n;
448
449 for (n = 0; n < level; n++)
450 strncpy_DYN(buffer, "\t", 1);
451}
452
453static bool_Bool
454has_params(const char *src)
455{
456 bool_Bool result = FALSE0;
457 int len = (int) strlen(src);
458 int n;
459 bool_Bool ifthen = FALSE0;
460 bool_Bool params = FALSE0;
461
462 for (n = 0; n < len - 1; ++n) {
463 if (!strncmp(src + n, "%p", 2)) {
464 params = TRUE1;
465 } else if (!strncmp(src + n, "%;", 2)) {
466 ifthen = TRUE1;
467 result = params;
468 break;
469 }
470 }
471 if (!ifthen) {
472 result = ((len > 50) && params);
473 }
474 return result;
475}
476
477static char *
478fmt_complex(char *src, int level)
479{
480 bool_Bool percent = FALSE0;
481 bool_Bool params = has_params(src);
482
483 while (*src != '\0') {
484 switch (*src) {
485 case '\\':
486 percent = FALSE0;
487 strncpy_DYN(&tmpbuf, src++, 1);
488 break;
489 case '%':
490 percent = TRUE1;
491 break;
492 case '?': /* "if" */
493 case 't': /* "then" */
494 case 'e': /* "else" */
495 if (percent) {
496 percent = FALSE0;
497 tmpbuf.text[tmpbuf.used - 1] = '\n';
498 /* treat a "%e" as else-if, on the same level */
499 if (*src == 'e') {
500 indent_DYN(&tmpbuf, level);
501 strncpy_DYN(&tmpbuf, "%", 1);
502 strncpy_DYN(&tmpbuf, src, 1);
503 src++;
504 params = has_params(src);
505 if (!params && *src != '\0' && *src != '%') {
506 strncpy_DYN(&tmpbuf, "\n", 1);
507 indent_DYN(&tmpbuf, level + 1);
508 }
509 } else {
510 indent_DYN(&tmpbuf, level + 1);
511 strncpy_DYN(&tmpbuf, "%", 1);
512 strncpy_DYN(&tmpbuf, src, 1);
513 if (*src++ == '?') {
514 src = fmt_complex(src, level + 1);
515 if (*src != '\0' && *src != '%') {
516 strncpy_DYN(&tmpbuf, "\n", 1);
517 indent_DYN(&tmpbuf, level + 1);
518 }
519 } else if (level == 1) {
520 _nc_warning("%%%c without %%?", *src);
521 }
522 }
523 continue;
524 }
525 break;
526 case ';': /* "endif" */
527 if (percent) {
528 percent = FALSE0;
529 if (level > 1) {
530 tmpbuf.text[tmpbuf.used - 1] = '\n';
531 indent_DYN(&tmpbuf, level);
532 strncpy_DYN(&tmpbuf, "%", 1);
533 strncpy_DYN(&tmpbuf, src++, 1);
534 return src;
535 }
536 _nc_warning("%%; without %%?");
537 }
538 break;
539 case 'p':
540 if (percent && params) {
541 tmpbuf.text[tmpbuf.used - 1] = '\n';
542 indent_DYN(&tmpbuf, level + 1);
543 strncpy_DYN(&tmpbuf, "%", 1);
544 }
545 params = FALSE0;
546 percent = FALSE0;
547 break;
548 case ' ':
549 strncpy_DYN(&tmpbuf, "\\s", 2);
550 ++src;
551 continue;
552 default:
553 percent = FALSE0;
554 break;
555 }
556 strncpy_DYN(&tmpbuf, src++, 1);
557 }
558 return src;
559}
560
561#define SAME_CAP(n,cap)(&tterm->Strings[n] == &cap) (&tterm->Strings[n] == &cap)
562#define EXTRA_CAP20 20
563
564int
565fmt_entry(TERMTYPE *tterm,
566 PredFunc pred,
567 bool_Bool content_only,
568 bool_Bool suppress_untranslatable,
569 bool_Bool infodump,
570 int numbers)
571{
572 PredIdx i, j;
573 char buffer[MAX_TERMINFO_LENGTH4096 + EXTRA_CAP20];
574 char *capability;
575 NCURSES_CONSTconst char *name;
576 int predval, len;
577 PredIdx num_bools = 0;
578 PredIdx num_values = 0;
579 PredIdx num_strings = 0;
580 bool_Bool outcount = 0;
581
582#define WRAP_CONCATwrap_concat(buffer); outcount = 1 \
583 wrap_concat(buffer); \
584 outcount = TRUE1
585
586 len = 12; /* terminfo file-header */
587
588 if (pred == 0) {
589 cur_type = tterm;
590 pred = dump_predicate;
591 }
592
593 strcpy_DYN(&outbuf, 0);
594 if (content_only) {
595 column = INDENT8; /* FIXME: workaround to prevent empty lines */
596 } else {
597 strcpy_DYN(&outbuf, tterm->term_names);
598 strcpy_DYN(&outbuf, separator);
599 column = (int) outbuf.used;
600 force_wrap();
601 }
602
603 for_each_boolean(j, tterm)for(j = 0; j < (tterm)->num_Booleans; j++) {
604 i = BoolIndirect(j)((j >= 44) ? (j) : ((sortmode == 1) ? j : bool_indirect[j]
))
;
605 name = ExtBoolname(tterm, i, bool_names)(i >= 44) ? tterm->ext_Names[(i - (tterm->num_Booleans
- tterm->ext_Booleans))] : bool_names[i]
;
606 assert(strlen(name) < sizeof(buffer) - EXTRA_CAP)((void)0);
607
608 if (!version_filter(BOOLEAN0, i))
609 continue;
610 else if (isObsolete(outform, name)((outform == 0 || outform == 1) && (!_nc_user_definable
&& (name[0] == 'O' && name[1] == 'T')))
)
611 continue;
612
613 predval = pred(BOOLEAN0, i);
614 if (predval != FAIL-1) {
615 (void) strlcpy(buffer, name, sizeof buffer);
616 if (predval <= 0)
617 (void) strlcat(buffer, "@", sizeof buffer);
618 else if (i + 1 > num_bools)
619 num_bools = i + 1;
620 WRAP_CONCATwrap_concat(buffer); outcount = 1;
621 }
622 }
623
624 if (column != INDENT8)
625 force_wrap();
626
627 for_each_number(j, tterm)for(j = 0; j < (tterm)->num_Numbers; j++) {
628 i = NumIndirect(j)((j >= 39) ? (j) : ((sortmode == 1) ? j : num_indirect[j])
)
;
629 name = ExtNumname(tterm, i, num_names)(i >= 39) ? tterm->ext_Names[(i - (tterm->num_Numbers
- tterm->ext_Numbers)) + tterm->ext_Booleans] : num_names
[i]
;
630 assert(strlen(name) < sizeof(buffer) - EXTRA_CAP)((void)0);
631
632 if (!version_filter(NUMBER1, i))
633 continue;
634 else if (isObsolete(outform, name)((outform == 0 || outform == 1) && (!_nc_user_definable
&& (name[0] == 'O' && name[1] == 'T')))
)
635 continue;
636
637 predval = pred(NUMBER1, i);
638 if (predval != FAIL-1) {
639 if (tterm->Numbers[i] < 0) {
640 snprintf(buffer, sizeof buffer, "%s@", name);
641 } else {
642 snprintf(buffer, sizeof buffer, "%s#%d", name, tterm->Numbers[i]);
643 if (i + 1 > num_values)
644 num_values = i + 1;
645 }
646 WRAP_CONCATwrap_concat(buffer); outcount = 1;
647 }
648 }
649
650 if (column != INDENT8)
651 force_wrap();
652
653 len += (int) (num_bools
654 + num_values * 2
655 + strlen(tterm->term_names) + 1);
656 if (len & 1)
657 len++;
658
659#undef CURtp->
660#define CURtp-> tterm->
661 if (outform == F_TERMCAP2) {
662 if (termcap_resettp-> Strings[395] != ABSENT_STRING(char *)0) {
663 if (init_3stringtp-> Strings[50] != ABSENT_STRING(char *)0
664 && !strcmp(init_3stringtp-> Strings[50], termcap_resettp-> Strings[395]))
665 DISCARD(init_3string)tp-> Strings[50] = (char *)0;
666
667 if (reset_2stringtp-> Strings[123] != ABSENT_STRING(char *)0
668 && !strcmp(reset_2stringtp-> Strings[123], termcap_resettp-> Strings[395]))
669 DISCARD(reset_2string)tp-> Strings[123] = (char *)0;
670 }
671 }
672
673 for_each_string(j, tterm)for(j = 0; j < (tterm)->num_Strings; j++) {
674 i = StrIndirect(j)((j >= 414) ? (j) : ((sortmode == 1) ? j : str_indirect[j]
))
;
675 name = ExtStrname(tterm, i, str_names)(i >= 414) ? tterm->ext_Names[(i - (tterm->num_Strings
- tterm->ext_Strings)) + (tterm->ext_Numbers + tterm->
ext_Booleans)] : str_names[i]
;
676 assert(strlen(name) < sizeof(buffer) - EXTRA_CAP)((void)0);
677
678 capability = tterm->Strings[i];
679
680 if (!version_filter(STRING2, i))
681 continue;
682 else if (isObsolete(outform, name)((outform == 0 || outform == 1) && (!_nc_user_definable
&& (name[0] == 'O' && name[1] == 'T')))
)
683 continue;
684
685#if NCURSES_XNAMES1
686 /*
687 * Extended names can be longer than 2 characters, but termcap programs
688 * cannot read those (filter them out).
689 */
690 if (outform == F_TERMCAP2 && (strlen(name) > 2))
691 continue;
692#endif
693
694 if (outform == F_TERMCAP2) {
695 /*
696 * Some older versions of vi want rmir/smir to be defined
697 * for ich/ich1 to work. If they're not defined, force
698 * them to be output as defined and empty.
699 */
700 if (PRESENT(insert_character)(((tp-> Strings[52]) != (char *)0) && ((tp-> Strings
[52]) != (char *)(-1)))
|| PRESENT(parm_ich)(((tp-> Strings[108]) != (char *)0) && ((tp-> Strings
[108]) != (char *)(-1)))
) {
701 if (SAME_CAP(i, enter_insert_mode)(&tterm->Strings[i] == &tp-> Strings[31])
702 && enter_insert_modetp-> Strings[31] == ABSENT_STRING(char *)0) {
703 (void) strlcpy(buffer, "im=", sizeof(buffer));
704 WRAP_CONCATwrap_concat(buffer); outcount = 1;
705 continue;
706 }
707
708 if (SAME_CAP(i, exit_insert_mode)(&tterm->Strings[i] == &tp-> Strings[42])
709 && exit_insert_modetp-> Strings[42] == ABSENT_STRING(char *)0) {
710 (void) strlcpy(buffer, "ei=", sizeof(buffer));
711 WRAP_CONCATwrap_concat(buffer); outcount = 1;
712 continue;
713 }
714 }
715 /*
716 * termcap applications such as screen will be confused if sgr0
717 * is translated to a string containing rmacs. Filter that out.
718 */
719 if (PRESENT(exit_attribute_mode)(((tp-> Strings[39]) != (char *)0) && ((tp-> Strings
[39]) != (char *)(-1)))
) {
720 if (SAME_CAP(i, exit_attribute_mode)(&tterm->Strings[i] == &tp-> Strings[39])) {
721 char *trimmed_sgr0;
722 char *my_sgr = set_attributestp-> Strings[131];
723
724 set_attributestp-> Strings[131] = save_sgr;
725
726 trimmed_sgr0 = _nc_trim_sgr0(tterm);
727 if (strcmp(capability, trimmed_sgr0))
728 capability = trimmed_sgr0;
729
730 set_attributestp-> Strings[131] = my_sgr;
731 }
732 }
733 }
734
735 predval = pred(STRING2, i);
736 buffer[0] = '\0';
737
738 if (predval != FAIL-1) {
739 if (capability != ABSENT_STRING(char *)0
740 && i + 1 > num_strings)
741 num_strings = i + 1;
742
743 if (!VALID_STRING(capability)((capability) != (char *)(-1) && (capability) != (char
*)0)
) {
744 snprintf(buffer, sizeof(buffer), "%s@", name);
745 WRAP_CONCATwrap_concat(buffer); outcount = 1;
746 } else if (outform == F_TERMCAP2 || outform == F_TCONVERR3) {
747 int params = ((i < (int) SIZEOF(parametrized)(sizeof(parametrized)/sizeof(parametrized[0])))
748 ? parametrized[i]
749 : 0);
750 char *srccap = _nc_tic_expand(capability, TRUE1, numbers);
751 char *cv = _nc_infotocap(name, srccap, params);
752
753 if (cv == 0) {
754 if (outform == F_TCONVERR3) {
755 snprintf(buffer, sizeof(buffer),
756 "%s=!!! %s WILL NOT CONVERT !!!", name, srccap);
757 } else if (suppress_untranslatable) {
758 continue;
759 } else {
760 char *d, *s = srccap;
761 snprintf(buffer, sizeof(buffer), "..%s=", name);
762 d = buffer + strlen(buffer);
763 while ((*d = *s++) != 0) { /* XXX overflow */
764 if (*d == ':') {
765 *d++ = '\\';
766 *d = ':';
767 } else if (*d == '\\') {
768 *++d = *s++;
769 }
770 d++;
771 }
772 }
773 } else {
774 snprintf(buffer, sizeof buffer, "%s=%s", name, cv);
775 }
776 len += (int) strlen(capability) + 1;
777 WRAP_CONCATwrap_concat(buffer); outcount = 1;
778 } else {
779 char *src = _nc_tic_expand(capability,
780 outform == F_TERMINFO0, numbers);
781
782 strcpy_DYN(&tmpbuf, 0);
783 strcpy_DYN(&tmpbuf, name);
784 strcpy_DYN(&tmpbuf, "=");
785 if (pretty
786 && (outform == F_TERMINFO0
787 || outform == F_VARIABLE1)) {
788 fmt_complex(src, 1);
789 } else {
790 strcpy_DYN(&tmpbuf, src);
791 }
792 len += (int) strlen(capability) + 1;
793 wrap_concat(tmpbuf.text);
794 outcount = TRUE1;
795 }
796 }
797 /* e.g., trimmed_sgr0 */
798 if (capability != tterm->Strings[i])
799 free(capability);
800 }
801 len += (int) (num_strings * 2);
802
803 /*
804 * This piece of code should be an effective inverse of the functions
805 * postprocess_terminfo() and postprocess_terminfo() in parse_entry.c.
806 * Much more work should be done on this to support dumping termcaps.
807 */
808 if (tversion == V_HPUX2) {
809 if (VALID_STRING(memory_lock)((tp-> Strings[411]) != (char *)(-1) && (tp-> Strings
[411]) != (char *)0)
) {
810 (void) snprintf(buffer, sizeof(buffer), "meml=%s", memory_locktp-> Strings[411]);
811 WRAP_CONCATwrap_concat(buffer); outcount = 1;
812 }
813 if (VALID_STRING(memory_unlock)((tp-> Strings[412]) != (char *)(-1) && (tp-> Strings
[412]) != (char *)0)
) {
814 (void) snprintf(buffer, sizeof(buffer), "memu=%s", memory_unlocktp-> Strings[412]);
815 WRAP_CONCATwrap_concat(buffer); outcount = 1;
816 }
817 } else if (tversion == V_AIX3) {
818 if (VALID_STRING(acs_chars)((tp-> Strings[146]) != (char *)(-1) && (tp-> Strings
[146]) != (char *)0)
) {
819 bool_Bool box_ok = TRUE1;
820 const char *acstrans = "lqkxjmwuvtn";
821 const char *cp;
822 char *tp, *sp, boxchars[11];
823
824 tp = boxchars;
825 for (cp = acstrans; *cp; cp++) {
826 sp = strchr(acs_charstp-> Strings[146], *cp);
827 if (sp)
828 *tp++ = sp[1];
829 else {
830 box_ok = FALSE0;
831 break;
832 }
833 }
834 tp[0] = '\0';
835
836 if (box_ok) {
837 (void) strlcpy(buffer, "box1=", sizeof(buffer));
838 (void) strlcat(buffer, _nc_tic_expand(boxchars,
839 outform == F_TERMINFO0, numbers), sizeof(buffer));
840 WRAP_CONCATwrap_concat(buffer); outcount = 1;
841 }
842 }
843 }
844
845 /*
846 * kludge: trim off trailer to avoid an extra blank line
847 * in infocmp -u output when there are no string differences
848 */
849 if (outcount) {
850 bool_Bool trimmed = FALSE0;
851 j = outbuf.used;
852 if (j >= 2
853 && outbuf.text[j - 1] == '\t'
854 && outbuf.text[j - 2] == '\n') {
855 outbuf.used -= 2;
856 trimmed = TRUE1;
857 } else if (j >= 4
858 && outbuf.text[j - 1] == ':'
859 && outbuf.text[j - 2] == '\t'
860 && outbuf.text[j - 3] == '\n'
861 && outbuf.text[j - 4] == '\\') {
862 outbuf.used -= 4;
863 trimmed = TRUE1;
864 }
865 if (trimmed) {
866 outbuf.text[outbuf.used] = '\0';
867 column = oldcol;
868 strcpy_DYN(&outbuf, " ");
869 }
870 }
871#if 0
872 fprintf(stderr(&__sF[2]), "num_bools = %d\n", num_bools);
873 fprintf(stderr(&__sF[2]), "num_values = %d\n", num_values);
874 fprintf(stderr(&__sF[2]), "num_strings = %d\n", num_strings);
875 fprintf(stderr(&__sF[2]), "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n",
876 tterm->term_names, len, outbuf.used, outbuf.text);
877#endif
878 /*
879 * Here's where we use infodump to trigger a more stringent length check
880 * for termcap-translation purposes.
881 * Return the length of the raw entry, without tc= expansions,
882 * It gives an idea of which entries are deadly to even *scan past*,
883 * as opposed to *use*.
884 */
885 return (infodump ? len : (int) termcap_length(outbuf.text)strlen(outbuf.text));
886}
887
888static bool_Bool
889kill_string(TERMTYPE *tterm, char *cap)
890{
891 unsigned n;
892 for (n = 0; n < NUM_STRINGS(tterm)(tterm)->num_Strings; ++n) {
893 if (cap == tterm->Strings[n]) {
894 tterm->Strings[n] = ABSENT_STRING(char *)0;
895 return TRUE1;
896 }
897 }
898 return FALSE0;
899}
900
901static char *
902find_string(TERMTYPE *tterm, char *name)
903{
904 PredIdx n;
905 for (n = 0; n < NUM_STRINGS(tterm)(tterm)->num_Strings; ++n) {
906 if (version_filter(STRING2, n)
907 && !strcmp(name, strnames[n])) {
908 char *cap = tterm->Strings[n];
909 if (VALID_STRING(cap)((cap) != (char *)(-1) && (cap) != (char *)0)) {
910 return cap;
911 }
912 break;
913 }
914 }
915 return ABSENT_STRING(char *)0;
916}
917
918/*
919 * This is used to remove function-key labels from a termcap entry to
920 * make it smaller.
921 */
922static int
923kill_labels(TERMTYPE *tterm, int target)
924{
925 int n;
926 int result = 0;
927 char *cap;
928 char name[10];
929
930 for (n = 0; n <= 10; ++n) {
931 snprintf(name, sizeof(name), "lf%d", n);
932 if ((cap = find_string(tterm, name)) != ABSENT_STRING(char *)0
933 && kill_string(tterm, cap)) {
934 target -= (int) (strlen(cap) + 5);
935 ++result;
936 if (target < 0)
937 break;
938 }
939 }
940 return result;
941}
942
943/*
944 * This is used to remove function-key definitions from a termcap entry to
945 * make it smaller.
946 */
947static int
948kill_fkeys(TERMTYPE *tterm, int target)
949{
950 int n;
951 int result = 0;
952 char *cap;
953 char name[10];
954
955 for (n = 60; n >= 0; --n) {
956 snprintf(name, sizeof(name), "kf%d", n);
957 if ((cap = find_string(tterm, name)) != ABSENT_STRING(char *)0
958 && kill_string(tterm, cap)) {
959 target -= (int) (strlen(cap) + 5);
960 ++result;
961 if (target < 0)
962 break;
963 }
964 }
965 return result;
966}
967
968/*
969 * Check if the given acsc string is a 1-1 mapping, i.e., just-like-vt100.
970 * Also, since this is for termcap, we only care about the line-drawing map.
971 */
972#define isLine(c)(strchr("lmkjtuvwqxn", c) != 0) (strchr("lmkjtuvwqxn", c) != 0)
973
974static bool_Bool
975one_one_mapping(const char *mapping)
976{
977 bool_Bool result = TRUE1;
978
979 if (mapping != ABSENT_STRING(char *)0) {
980 int n = 0;
981 while (mapping[n] != '\0') {
982 if (isLine(mapping[n])(strchr("lmkjtuvwqxn", mapping[n]) != 0) &&
983 mapping[n] != mapping[n + 1]) {
984 result = FALSE0;
985 break;
986 }
987 n += 2;
988 }
989 }
990 return result;
991}
992
993#define FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
\
994 fmt_entry(tterm, pred, \
995 0, \
996 suppress_untranslatable, \
997 infodump, numbers)
998
999#define SHOW_WHY(void) printf PRINTF(void) printf
1000
1001static bool_Bool
1002purged_acs(TERMTYPE *tterm)
1003{
1004 bool_Bool result = FALSE0;
1005
1006 if (VALID_STRING(acs_chars)((tp-> Strings[146]) != (char *)(-1) && (tp-> Strings
[146]) != (char *)0)
) {
1007 if (!one_one_mapping(acs_charstp-> Strings[146])) {
1008 enter_alt_charset_modetp-> Strings[25] = ABSENT_STRING(char *)0;
1009 exit_alt_charset_modetp-> Strings[38] = ABSENT_STRING(char *)0;
1010 SHOW_WHY(void) printf("# (rmacs/smacs removed for consistency)\n");
1011 }
1012 result = TRUE1;
1013 }
1014 return result;
1015}
1016
1017/*
1018 * Dump a single entry.
1019 */
1020void
1021dump_entry(TERMTYPE *tterm,
1022 bool_Bool suppress_untranslatable,
1023 bool_Bool limited,
1024 int numbers,
1025 PredFunc pred)
1026{
1027 TERMTYPE save_tterm;
1028 int len, critlen;
1029 const char *legend;
1030 bool_Bool infodump;
1031
1032 if (outform == F_TERMCAP2 || outform == F_TCONVERR3) {
1033 critlen = MAX_TERMCAP_LENGTH1023;
1034 legend = "older termcap";
1035 infodump = FALSE0;
1036 set_obsolete_termcaps(tterm);
1037 } else {
1038 critlen = MAX_TERMINFO_LENGTH4096;
1039 legend = "terminfo";
1040 infodump = TRUE1;
1041 }
1042
1043 save_sgr = set_attributestp-> Strings[131];
1044
1045 if (((len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
) > critlen)
1046 && limited) {
1047
1048 save_tterm = *tterm;
1049 if (!suppress_untranslatable) {
1050 SHOW_WHY(void) printf("# (untranslatable capabilities removed to fit entry within %d bytes)\n",
1051 critlen);
1052 suppress_untranslatable = TRUE1;
1053 }
1054 if ((len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
) > critlen) {
1055 /*
1056 * We pick on sgr because it's a nice long string capability that
1057 * is really just an optimization hack. Another good candidate is
1058 * acsc since it is both long and unused by BSD termcap.
1059 */
1060 bool_Bool changed = FALSE0;
1061
1062#if NCURSES_XNAMES1
1063 /*
1064 * Extended names are most likely function-key definitions. Drop
1065 * those first.
1066 */
1067 unsigned n;
1068 for (n = STRCOUNT414; n < NUM_STRINGS(tterm)(tterm)->num_Strings; n++) {
1069 const char *name = ExtStrname(tterm, n, strnames)(n >= 414) ? tterm->ext_Names[(n - (tterm->num_Strings
- tterm->ext_Strings)) + (tterm->ext_Numbers + tterm->
ext_Booleans)] : strnames[n]
;
1070
1071 if (VALID_STRING(tterm->Strings[n])((tterm->Strings[n]) != (char *)(-1) && (tterm->
Strings[n]) != (char *)0)
) {
1072 set_attributestp-> Strings[131] = ABSENT_STRING(char *)0;
1073 /* we remove long names anyway - only report the short */
1074 if (strlen(name) <= 2) {
1075 SHOW_WHY(void) printf("# (%s removed to fit entry within %d bytes)\n",
1076 name,
1077 critlen);
1078 }
1079 changed = TRUE1;
1080 if ((len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
) <= critlen)
1081 break;
1082 }
1083 }
1084#endif
1085 if (VALID_STRING(set_attributes)((tp-> Strings[131]) != (char *)(-1) && (tp-> Strings
[131]) != (char *)0)
) {
1086 set_attributestp-> Strings[131] = ABSENT_STRING(char *)0;
1087 SHOW_WHY(void) printf("# (sgr removed to fit entry within %d bytes)\n",
1088 critlen);
1089 changed = TRUE1;
1090 }
1091 if (!changed || ((len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
) > critlen)) {
1092 if (purged_acs(tterm)) {
1093 acs_charstp-> Strings[146] = ABSENT_STRING(char *)0;
1094 SHOW_WHY(void) printf("# (acsc removed to fit entry within %d bytes)\n",
1095 critlen);
1096 changed = TRUE1;
1097 }
1098 }
1099 if (!changed || ((len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
) > critlen)) {
1100 int oldversion = tversion;
1101
1102 tversion = V_BSD4;
1103 SHOW_WHY(void) printf("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n",
1104 critlen);
1105
1106 len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
;
1107 if (len > critlen
1108 && kill_labels(tterm, len - critlen)) {
1109 SHOW_WHY(void) printf("# (some labels capabilities suppressed to fit entry within %d bytes)\n",
1110 critlen);
1111 len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
;
1112 }
1113 if (len > critlen
1114 && kill_fkeys(tterm, len - critlen)) {
1115 SHOW_WHY(void) printf("# (some function-key capabilities suppressed to fit entry within %d bytes)\n",
1116 critlen);
1117 len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
;
1118 }
1119 if (len > critlen) {
1120 (void) fprintf(stderr(&__sF[2]),
1121 "warning: %s entry is %d bytes long\n",
1122 _nc_first_name(tterm->term_names),
1123 len);
1124 SHOW_WHY(void) printf("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
1125 len, legend);
1126 }
1127 tversion = oldversion;
1128 }
1129 set_attributestp-> Strings[131] = save_sgr;
1130 *tterm = save_tterm;
1131 }
1132 } else if (!version_filter(STRING2, STR_IDX(acs_chars)(PredType) (&(tp-> Strings[146]) - &(tp-> Strings
[0]))
)) {
1133 save_tterm = *tterm;
1134 if (purged_acs(tterm)) {
1135 len = FMT_ENTRY()fmt_entry(tterm, pred, 0, suppress_untranslatable, infodump, numbers
)
;
Value stored to 'len' is never read
1136 }
1137 *tterm = save_tterm;
1138 }
1139}
1140
1141void
1142dump_uses(const char *name, bool_Bool infodump)
1143/* dump "use=" clauses in the appropriate format */
1144{
1145 char buffer[MAX_TERMINFO_LENGTH4096];
1146
1147 if (outform == F_TERMCAP2 || outform == F_TCONVERR3)
1148 trim_trailing();
1149 (void) snprintf(buffer, sizeof(buffer), "%s%s", infodump ? "use=" : "tc=",
1150 name);
1151 wrap_concat(buffer);
1152}
1153
1154int
1155show_entry(void)
1156{
1157 trim_trailing();
1158 (void) fputs(outbuf.text, stdout(&__sF[1]));
1159 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1160 return (int) outbuf.used;
1161}
1162
1163void
1164compare_entry(void (*hook) (PredType t, PredIdx i, const char *name),
1165 TERMTYPE *tp GCC_UNUSED__attribute__((__unused__)),
1166 bool_Bool quiet)
1167/* compare two entries */
1168{
1169 PredIdx i, j;
1170 NCURSES_CONSTconst char *name;
1171
1172 if (!quiet)
1173 fputs(" comparing booleans.\n", stdout(&__sF[1]));
1174 for_each_boolean(j, tp)for(j = 0; j < (tp)->num_Booleans; j++) {
1175 i = BoolIndirect(j)((j >= 44) ? (j) : ((sortmode == 1) ? j : bool_indirect[j]
))
;
1176 name = ExtBoolname(tp, i, bool_names)(i >= 44) ? tp->ext_Names[(i - (tp->num_Booleans - tp
->ext_Booleans))] : bool_names[i]
;
1177
1178 if (isObsolete(outform, name)((outform == 0 || outform == 1) && (!_nc_user_definable
&& (name[0] == 'O' && name[1] == 'T')))
)
1179 continue;
1180
1181 (*hook) (CMP_BOOLEAN0, i, name);
1182 }
1183
1184 if (!quiet)
1185 fputs(" comparing numbers.\n", stdout(&__sF[1]));
1186 for_each_number(j, tp)for(j = 0; j < (tp)->num_Numbers; j++) {
1187 i = NumIndirect(j)((j >= 39) ? (j) : ((sortmode == 1) ? j : num_indirect[j])
)
;
1188 name = ExtNumname(tp, i, num_names)(i >= 39) ? tp->ext_Names[(i - (tp->num_Numbers - tp
->ext_Numbers)) + tp->ext_Booleans] : num_names[i]
;
1189
1190 if (isObsolete(outform, name)((outform == 0 || outform == 1) && (!_nc_user_definable
&& (name[0] == 'O' && name[1] == 'T')))
)
1191 continue;
1192
1193 (*hook) (CMP_NUMBER1, i, name);
1194 }
1195
1196 if (!quiet)
1197 fputs(" comparing strings.\n", stdout(&__sF[1]));
1198 for_each_string(j, tp)for(j = 0; j < (tp)->num_Strings; j++) {
1199 i = StrIndirect(j)((j >= 414) ? (j) : ((sortmode == 1) ? j : str_indirect[j]
))
;
1200 name = ExtStrname(tp, i, str_names)(i >= 414) ? tp->ext_Names[(i - (tp->num_Strings - tp
->ext_Strings)) + (tp->ext_Numbers + tp->ext_Booleans
)] : str_names[i]
;
1201
1202 if (isObsolete(outform, name)((outform == 0 || outform == 1) && (!_nc_user_definable
&& (name[0] == 'O' && name[1] == 'T')))
)
1203 continue;
1204
1205 (*hook) (CMP_STRING2, i, name);
1206 }
1207
1208 /* (void) fputs(" comparing use entries.\n", stdout); */
1209 (*hook) (CMP_USE3, 0, "use");
1210
1211}
1212
1213#define NOTSET(s)((s) == 0) ((s) == 0)
1214
1215/*
1216 * This bit of legerdemain turns all the terminfo variable names into
1217 * references to locations in the arrays Booleans, Numbers, and Strings ---
1218 * precisely what's needed.
1219 */
1220#undef CURtp->
1221#define CURtp-> tp->
1222
1223static void
1224set_obsolete_termcaps(TERMTYPE *tp)
1225{
1226#include "capdefaults.c"
1227}
1228
1229/*
1230 * Convert an alternate-character-set string to canonical form: sorted and
1231 * unique.
1232 */
1233void
1234repair_acsc(TERMTYPE *tp)
1235{
1236 if (VALID_STRING(acs_chars)((tp-> Strings[146]) != (char *)(-1) && (tp-> Strings
[146]) != (char *)0)
) {
1237 size_t n, m;
1238 char mapped[256];
1239 char extra = 0;
1240 unsigned source;
1241 unsigned target;
1242 bool_Bool fix_needed = FALSE0;
1243
1244 for (n = 0, source = 0; acs_charstp-> Strings[146][n] != 0; n++) {
1245 target = UChar(acs_chars[n])((unsigned char)(tp-> Strings[146][n]));
1246 if (source >= target) {
1247 fix_needed = TRUE1;
1248 break;
1249 }
1250 source = target;
1251 if (acs_charstp-> Strings[146][n + 1])
1252 n++;
1253 }
1254 if (fix_needed) {
1255 memset(mapped, 0, sizeof(mapped));
1256 for (n = 0; acs_charstp-> Strings[146][n] != 0; n++) {
1257 source = UChar(acs_chars[n])((unsigned char)(tp-> Strings[146][n]));
1258 if ((target = (unsigned char) acs_charstp-> Strings[146][n + 1]) != 0) {
1259 mapped[source] = (char) target;
1260 n++;
1261 } else {
1262 extra = (char) source;
1263 }
1264 }
1265 for (n = m = 0; n < sizeof(mapped); n++) {
1266 if (mapped[n]) {
1267 acs_charstp-> Strings[146][m++] = (char) n;
1268 acs_charstp-> Strings[146][m++] = mapped[n];
1269 }
1270 }
1271 if (extra)
1272 acs_charstp-> Strings[146][m++] = extra; /* garbage in, garbage out */
1273 acs_charstp-> Strings[146][m] = 0;
1274 }
1275 }
1276}