Bug Summary

File:src/usr.bin/infocmp/../tic/dump_entry.c
Warning:line 1091, column 24
Although the value stored to 'len' is used in the enclosing expression, the value is never actually read from 'len'

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/infocmp/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/infocmp/../../lib/libcurses -I /usr/src/usr.bin/infocmp/../tic -I /usr/src/usr.bin/infocmp -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/infocmp/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/infocmp/../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)) {
Although the value stored to 'len' is used in the enclosing expression, the value is never actually read from 'len'
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
)
;
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}