Annotation of src/usr.bin/tic/dump_entry.c, Revision 1.19
1.18 millert 1: /* $OpenBSD: dump_entry.c,v 1.17 2003/04/06 18:38:42 deraadt Exp $ */
1.2 millert 2:
1.1 millert 3: /****************************************************************************
1.19 ! nicm 4: * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. *
1.1 millert 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> *
1.19 ! nicm 34: * and: Thomas E. Dickey 1996 on *
1.1 millert 35: ****************************************************************************/
36:
37: #define __INTERNAL_CAPS_VISIBLE
38: #include <progs.priv.h>
39:
40: #include "dump_entry.h"
1.19 ! nicm 41: #include "termsort.c" /* this C file is generated */
1.1 millert 42: #include <parametrized.h> /* so is this */
43:
1.19 ! nicm 44: MODULE_ID("$Id: dump_entry.c,v 1.88 2008/08/04 12:36:12 tom Exp $")
1.11 millert 45:
1.1 millert 46: #define INDENT 8
1.2 millert 47: #define DISCARD(string) string = ABSENT_STRING
1.11 millert 48: #define PRINTF (void) printf
1.2 millert 49:
1.19 ! nicm 50: #define OkIndex(index,array) ((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array))
! 51:
1.15 millert 52: typedef struct {
53: char *text;
54: size_t used;
55: size_t size;
56: } DYNBUF;
57:
1.11 millert 58: static int tversion; /* terminfo version */
59: static int outform; /* output format to use */
60: static int sortmode; /* sort mode to use */
61: static int width = 60; /* max line width for listings */
62: static int column; /* current column, limited by 'width' */
63: static int oldcol; /* last value of column before wrap */
64: static bool pretty; /* true if we format if-then-else strings */
65:
1.19 ! nicm 66: static char *save_sgr;
! 67:
1.15 millert 68: static DYNBUF outbuf;
69: static DYNBUF tmpbuf;
1.1 millert 70:
71: /* indirection pointers for implementing sort and display modes */
1.19 ! nicm 72: static const PredIdx *bool_indirect, *num_indirect, *str_indirect;
1.11 millert 73: static NCURSES_CONST char *const *bool_names;
74: static NCURSES_CONST char *const *num_names;
75: static NCURSES_CONST char *const *str_names;
1.1 millert 76:
1.11 millert 77: static const char *separator, *trailer;
1.1 millert 78:
79: /* cover various ports and variants of terminfo */
80: #define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */
81: #define V_SVR1 1 /* SVR1, Ultrix */
82: #define V_HPUX 2 /* HP/UX */
83: #define V_AIX 3 /* AIX */
84: #define V_BSD 4 /* BSD */
85:
1.9 millert 86: #if NCURSES_XNAMES
87: #define OBSOLETE(n) (!_nc_user_definable && (n[0] == 'O' && n[1] == 'T'))
88: #else
1.1 millert 89: #define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T')
1.9 millert 90: #endif
91:
92: #define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n))
1.1 millert 93:
1.4 millert 94: #if NCURSES_XNAMES
95: #define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j]))
96: #define NumIndirect(j) ((j >= NUMCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : num_indirect[j]))
97: #define StrIndirect(j) ((j >= STRCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : str_indirect[j]))
98: #else
99: #define BoolIndirect(j) ((sortmode == S_NOSORT) ? (j) : bool_indirect[j])
100: #define NumIndirect(j) ((sortmode == S_NOSORT) ? (j) : num_indirect[j])
101: #define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j])
102: #endif
103:
1.15 millert 104: static void
105: strncpy_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);
111: }
112: (void) strncpy(dst->text + dst->used, src, need);
113: dst->used += need;
114: dst->text[dst->used] = 0;
115: }
116:
117: static void
118: strcpy_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:
1.1 millert 128: #if NO_LEAKS
1.15 millert 129: static void
130: free_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:
1.11 millert 139: void
140: _nc_leaks_dump_entry(void)
1.1 millert 141: {
1.15 millert 142: free_DYN(&outbuf);
143: free_DYN(&tmpbuf);
1.1 millert 144: }
145: #endif
146:
1.19 ! nicm 147: #define NameTrans(check,result) \
! 148: if (OkIndex(np->nte_index, check) \
! 149: && check[np->nte_index]) \
! 150: return (result[np->nte_index])
! 151:
1.10 millert 152: NCURSES_CONST char *
153: nametrans(const char *name)
1.1 millert 154: /* translate a capability name from termcap to terminfo */
155: {
1.10 millert 156: const struct name_table_entry *np;
1.1 millert 157:
1.3 millert 158: if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0)
1.10 millert 159: switch (np->nte_type) {
1.1 millert 160: case BOOLEAN:
1.19 ! nicm 161: NameTrans(bool_from_termcap, boolcodes);
1.1 millert 162: break;
163:
164: case NUMBER:
1.19 ! nicm 165: NameTrans(num_from_termcap, numcodes);
1.1 millert 166: break;
167:
168: case STRING:
1.19 ! nicm 169: NameTrans(str_from_termcap, strcodes);
1.1 millert 170: break;
171: }
172:
1.10 millert 173: return (0);
1.1 millert 174: }
175:
1.10 millert 176: void
177: dump_init(const char *version, int mode, int sort, int twidth, int traceval,
1.19 ! nicm 178: bool formatted)
1.1 millert 179: /* set up for entry display */
180: {
181: width = twidth;
182: pretty = formatted;
183:
184: /* versions */
185: if (version == 0)
186: tversion = V_ALLCAPS;
187: else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1")
1.19 ! nicm 188: || !strcmp(version, "Ultrix"))
1.1 millert 189: tversion = V_SVR1;
190: else if (!strcmp(version, "HP"))
191: tversion = V_HPUX;
192: else if (!strcmp(version, "AIX"))
193: tversion = V_AIX;
194: else if (!strcmp(version, "BSD"))
195: tversion = V_BSD;
196: else
197: tversion = V_ALLCAPS;
198:
199: /* implement display modes */
1.10 millert 200: switch (outform = mode) {
1.1 millert 201: case F_LITERAL:
202: case F_TERMINFO:
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_VARIABLE:
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_TERMCAP:
219: case F_TCONVERR:
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 */
1.10 millert 229: switch (sortmode = sort) {
1.1 millert 230: case S_NOSORT:
231: if (traceval)
232: (void) fprintf(stderr,
1.19 ! nicm 233: "%s: sorting by term structure order\n", _nc_progname);
1.1 millert 234: break;
235:
236: case S_TERMINFO:
237: if (traceval)
238: (void) fprintf(stderr,
1.19 ! nicm 239: "%s: sorting by terminfo name order\n", _nc_progname);
1.1 millert 240: bool_indirect = bool_terminfo_sort;
241: num_indirect = num_terminfo_sort;
242: str_indirect = str_terminfo_sort;
243: break;
244:
245: case S_VARIABLE:
246: if (traceval)
247: (void) fprintf(stderr,
1.19 ! nicm 248: "%s: sorting by C variable order\n", _nc_progname);
1.1 millert 249: bool_indirect = bool_variable_sort;
250: num_indirect = num_variable_sort;
251: str_indirect = str_variable_sort;
252: break;
253:
254: case S_TERMCAP:
255: if (traceval)
256: (void) fprintf(stderr,
1.19 ! nicm 257: "%s: sorting by termcap name order\n", _nc_progname);
1.1 millert 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,
1.19 ! nicm 266: "%s: width = %d, tversion = %d, outform = %d\n",
! 267: _nc_progname, width, tversion, outform);
1.1 millert 268: }
269:
1.10 millert 270: static TERMTYPE *cur_type;
1.1 millert 271:
1.10 millert 272: static int
1.19 ! nicm 273: dump_predicate(PredType type, PredIdx idx)
1.1 millert 274: /* predicate function to use for ordinary decompilation */
275: {
1.10 millert 276: switch (type) {
277: case BOOLEAN:
278: return (cur_type->Booleans[idx] == FALSE)
279: ? FAIL : cur_type->Booleans[idx];
1.1 millert 280:
1.10 millert 281: case NUMBER:
282: return (cur_type->Numbers[idx] == ABSENT_NUMERIC)
283: ? FAIL : cur_type->Numbers[idx];
1.1 millert 284:
1.10 millert 285: case STRING:
286: return (cur_type->Strings[idx] != ABSENT_STRING)
287: ? (int) TRUE : FAIL;
288: }
1.1 millert 289:
1.10 millert 290: return (FALSE); /* pacify compiler */
1.1 millert 291: }
292:
1.19 ! nicm 293: static void set_obsolete_termcaps(TERMTYPE *tp);
1.1 millert 294:
295: /* is this the index of a function key string? */
296: #define FNKEY(i) (((i)<= 65 && (i)>= 75) || ((i)<= 216 && (i)>= 268))
297:
1.19 ! nicm 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) - &(CUR Booleans[0]))
! 303: #define NUM_IDX(name) (PredType) (&(name) - &(CUR Numbers[0]))
! 304: #define STR_IDX(name) (PredType) (&(name) - &(CUR Strings[0]))
! 305:
1.10 millert 306: static bool
1.19 ! nicm 307: version_filter(PredType type, PredIdx idx)
1.1 millert 308: /* filter out capabilities we may want to suppress */
309: {
1.10 millert 310: switch (tversion) {
311: case V_ALLCAPS: /* SVr4, XSI Curses */
312: return (TRUE);
313:
314: case V_SVR1: /* System V Release 1, Ultrix */
315: switch (type) {
1.1 millert 316: case BOOLEAN:
1.19 ! nicm 317: return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
1.1 millert 318: case NUMBER:
1.19 ! nicm 319: return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE);
1.1 millert 320: case STRING:
1.19 ! nicm 321: return ((idx <= STR_IDX(prtr_non)) ? TRUE : FALSE);
1.1 millert 322: }
323: break;
324:
325: case V_HPUX: /* Hewlett-Packard */
1.10 millert 326: switch (type) {
1.1 millert 327: case BOOLEAN:
1.19 ! nicm 328: return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
1.1 millert 329: case NUMBER:
1.19 ! nicm 330: return ((idx <= NUM_IDX(label_width)) ? TRUE : FALSE);
1.1 millert 331: case STRING:
1.19 ! nicm 332: if (idx <= STR_IDX(prtr_non))
1.10 millert 333: return (TRUE);
1.1 millert 334: else if (FNKEY(idx)) /* function keys */
1.10 millert 335: return (TRUE);
1.19 ! nicm 336: else if (idx == STR_IDX(plab_norm)
! 337: || idx == STR_IDX(label_on)
! 338: || idx == STR_IDX(label_off))
1.10 millert 339: return (TRUE);
1.1 millert 340: else
1.10 millert 341: return (FALSE);
1.1 millert 342: }
343: break;
344:
345: case V_AIX: /* AIX */
1.10 millert 346: switch (type) {
1.1 millert 347: case BOOLEAN:
1.19 ! nicm 348: return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
1.1 millert 349: case NUMBER:
1.19 ! nicm 350: return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE);
1.1 millert 351: case STRING:
1.19 ! nicm 352: if (idx <= STR_IDX(prtr_non))
1.10 millert 353: return (TRUE);
1.1 millert 354: else if (FNKEY(idx)) /* function keys */
1.10 millert 355: return (TRUE);
1.1 millert 356: else
1.10 millert 357: return (FALSE);
1.1 millert 358: }
359: break;
360:
1.19 ! nicm 361: #define is_termcap(type) (OkIndex(idx, type##_from_termcap) && \
! 362: type##_from_termcap[idx])
! 363:
1.1 millert 364: case V_BSD: /* BSD */
1.10 millert 365: switch (type) {
1.1 millert 366: case BOOLEAN:
1.19 ! nicm 367: return is_termcap(bool);
1.1 millert 368: case NUMBER:
1.19 ! nicm 369: return is_termcap(num);
1.1 millert 370: case STRING:
1.19 ! nicm 371: return is_termcap(str);
1.1 millert 372: }
373: break;
374: }
375:
1.10 millert 376: return (FALSE); /* pacify the compiler */
1.1 millert 377: }
378:
1.11 millert 379: static void
1.19 ! nicm 380: trim_trailing(void)
! 381: {
! 382: while (outbuf.used > 0 && outbuf.text[outbuf.used - 1] == ' ')
! 383: outbuf.text[--outbuf.used] = '\0';
! 384: }
! 385:
! 386: static void
1.10 millert 387: force_wrap(void)
1.1 millert 388: {
1.10 millert 389: oldcol = column;
1.19 ! nicm 390: trim_trailing();
1.15 millert 391: strcpy_DYN(&outbuf, trailer);
1.10 millert 392: column = INDENT;
1.1 millert 393: }
394:
1.11 millert 395: static void
1.10 millert 396: wrap_concat(const char *src)
1.1 millert 397: {
1.19 ! nicm 398: unsigned need = strlen(src);
! 399: unsigned want = strlen(separator) + need;
1.1 millert 400:
1.10 millert 401: if (column > INDENT
1.19 ! nicm 402: && column + (int) want > width) {
1.10 millert 403: force_wrap();
404: }
1.15 millert 405: strcpy_DYN(&outbuf, src);
406: strcpy_DYN(&outbuf, separator);
1.19 ! nicm 407: column += (int) need;
1.1 millert 408: }
409:
410: #define IGNORE_SEP_TRAIL(first,last,sep_trail) \
411: if ((size_t)(last - first) > sizeof(sep_trail)-1 \
412: && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \
1.19 ! nicm 413: first += sizeof(sep_trail)-2
1.1 millert 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
1.10 millert 425: static int
426: termcap_length(const char *src)
1.1 millert 427: {
1.10 millert 428: static const char pattern[] = ":\\\n\t:";
1.1 millert 429:
1.10 millert 430: int len = 0;
431: const char *const t = src + strlen(src);
1.1 millert 432:
1.10 millert 433: while (*src != '\0') {
434: IGNORE_SEP_TRAIL(src, t, pattern);
435: src++;
436: len++;
437: }
438: return len;
1.1 millert 439: }
440: #else
441: #define termcap_length(src) strlen(src)
442: #endif
443:
1.19 ! nicm 444: static void
! 445: indent_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:
! 453: static bool
! 454: has_params(const char *src)
! 455: {
! 456: bool result = FALSE;
! 457: int len = (int) strlen(src);
! 458: int n;
! 459: bool ifthen = FALSE;
! 460: bool params = FALSE;
! 461:
! 462: for (n = 0; n < len - 1; ++n) {
! 463: if (!strncmp(src + n, "%p", 2)) {
! 464: params = TRUE;
! 465: } else if (!strncmp(src + n, "%;", 2)) {
! 466: ifthen = TRUE;
! 467: result = params;
! 468: break;
! 469: }
! 470: }
! 471: if (!ifthen) {
! 472: result = ((len > 50) && params);
! 473: }
! 474: return result;
! 475: }
! 476:
1.10 millert 477: static char *
1.15 millert 478: fmt_complex(char *src, int level)
1.1 millert 479: {
1.19 ! nicm 480: bool percent = FALSE;
! 481: bool params = has_params(src);
1.10 millert 482:
483: while (*src != '\0') {
484: switch (*src) {
485: case '\\':
1.19 ! nicm 486: percent = FALSE;
1.15 millert 487: strncpy_DYN(&tmpbuf, src++, 1);
1.10 millert 488: break;
489: case '%':
1.19 ! nicm 490: percent = TRUE;
1.10 millert 491: break;
492: case '?': /* "if" */
493: case 't': /* "then" */
494: case 'e': /* "else" */
495: if (percent) {
1.19 ! nicm 496: percent = FALSE;
1.15 millert 497: tmpbuf.text[tmpbuf.used - 1] = '\n';
1.19 ! nicm 498: /* treat a "%e" as else-if, on the same level */
! 499: if (*src == 'e') {
! 500: indent_DYN(&tmpbuf, level);
1.15 millert 501: strncpy_DYN(&tmpbuf, "%", 1);
1.19 ! nicm 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: }
1.15 millert 509: } else {
1.19 ! nicm 510: indent_DYN(&tmpbuf, level + 1);
1.15 millert 511: strncpy_DYN(&tmpbuf, "%", 1);
512: strncpy_DYN(&tmpbuf, src, 1);
513: if (*src++ == '?') {
514: src = fmt_complex(src, level + 1);
1.19 ! nicm 515: if (*src != '\0' && *src != '%') {
! 516: strncpy_DYN(&tmpbuf, "\n", 1);
! 517: indent_DYN(&tmpbuf, level + 1);
! 518: }
1.15 millert 519: } else if (level == 1) {
520: _nc_warning("%%%c without %%?", *src);
521: }
1.10 millert 522: }
523: continue;
524: }
525: break;
526: case ';': /* "endif" */
527: if (percent) {
1.19 ! nicm 528: percent = FALSE;
1.10 millert 529: if (level > 1) {
1.15 millert 530: tmpbuf.text[tmpbuf.used - 1] = '\n';
1.19 ! nicm 531: indent_DYN(&tmpbuf, level);
1.15 millert 532: strncpy_DYN(&tmpbuf, "%", 1);
533: strncpy_DYN(&tmpbuf, src++, 1);
1.10 millert 534: return src;
1.1 millert 535: }
1.10 millert 536: _nc_warning("%%; without %%?");
537: }
538: break;
539: case 'p':
540: if (percent && params) {
1.15 millert 541: tmpbuf.text[tmpbuf.used - 1] = '\n';
1.19 ! nicm 542: indent_DYN(&tmpbuf, level + 1);
1.15 millert 543: strncpy_DYN(&tmpbuf, "%", 1);
1.10 millert 544: }
1.19 ! nicm 545: params = FALSE;
! 546: percent = FALSE;
1.10 millert 547: break;
1.19 ! nicm 548: case ' ':
! 549: strncpy_DYN(&tmpbuf, "\\s", 2);
! 550: ++src;
! 551: continue;
1.10 millert 552: default:
1.19 ! nicm 553: percent = FALSE;
1.10 millert 554: break;
1.1 millert 555: }
1.15 millert 556: strncpy_DYN(&tmpbuf, src++, 1);
1.10 millert 557: }
558: return src;
1.1 millert 559: }
560:
1.19 ! nicm 561: #define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap)
! 562: #define EXTRA_CAP 20
! 563:
1.10 millert 564: int
1.19 ! nicm 565: fmt_entry(TERMTYPE *tterm,
! 566: PredFunc pred,
! 567: bool content_only,
! 568: bool suppress_untranslatable,
! 569: bool infodump,
! 570: int numbers)
1.10 millert 571: {
1.19 ! nicm 572: PredIdx i, j;
! 573: char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP];
! 574: char *capability;
1.10 millert 575: NCURSES_CONST char *name;
576: int predval, len;
1.19 ! nicm 577: PredIdx num_bools = 0;
! 578: PredIdx num_values = 0;
! 579: PredIdx num_strings = 0;
1.10 millert 580: bool outcount = 0;
1.1 millert 581:
582: #define WRAP_CONCAT \
583: wrap_concat(buffer); \
584: outcount = TRUE
585:
586: len = 12; /* terminfo file-header */
587:
588: if (pred == 0) {
589: cur_type = tterm;
590: pred = dump_predicate;
591: }
592:
1.15 millert 593: strcpy_DYN(&outbuf, 0);
1.19 ! nicm 594: if (content_only) {
! 595: column = INDENT; /* 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: }
1.1 millert 602:
1.10 millert 603: for_each_boolean(j, tterm) {
1.4 millert 604: i = BoolIndirect(j);
1.10 millert 605: name = ExtBoolname(tterm, i, bool_names);
1.19 ! nicm 606: assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
1.1 millert 607:
608: if (!version_filter(BOOLEAN, i))
609: continue;
1.10 millert 610: else if (isObsolete(outform, name))
1.1 millert 611: continue;
612:
613: predval = pred(BOOLEAN, i);
614: if (predval != FAIL) {
1.17 deraadt 615: (void) strlcpy(buffer, name, sizeof buffer);
1.1 millert 616: if (predval <= 0)
1.17 deraadt 617: (void) strlcat(buffer, "@", sizeof buffer);
1.1 millert 618: else if (i + 1 > num_bools)
619: num_bools = i + 1;
620: WRAP_CONCAT;
621: }
622: }
623:
624: if (column != INDENT)
625: force_wrap();
626:
1.10 millert 627: for_each_number(j, tterm) {
1.4 millert 628: i = NumIndirect(j);
1.10 millert 629: name = ExtNumname(tterm, i, num_names);
1.19 ! nicm 630: assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
1.1 millert 631:
632: if (!version_filter(NUMBER, i))
633: continue;
1.10 millert 634: else if (isObsolete(outform, name))
1.1 millert 635: continue;
636:
637: predval = pred(NUMBER, i);
638: if (predval != FAIL) {
639: if (tterm->Numbers[i] < 0) {
1.17 deraadt 640: snprintf(buffer, sizeof buffer, "%s@", name);
1.1 millert 641: } else {
1.17 deraadt 642: snprintf(buffer, sizeof buffer, "%s#%d", name, tterm->Numbers[i]);
1.1 millert 643: if (i + 1 > num_values)
644: num_values = i + 1;
645: }
646: WRAP_CONCAT;
647: }
648: }
649:
650: if (column != INDENT)
651: force_wrap();
652:
1.19 ! nicm 653: len += (int) (num_bools
! 654: + num_values * 2
! 655: + strlen(tterm->term_names) + 1);
1.1 millert 656: if (len & 1)
1.10 millert 657: len++;
1.1 millert 658:
1.15 millert 659: #undef CUR
660: #define CUR tterm->
661: if (outform == F_TERMCAP) {
662: if (termcap_reset != ABSENT_STRING) {
663: if (init_3string != ABSENT_STRING
664: && !strcmp(init_3string, termcap_reset))
665: DISCARD(init_3string);
666:
667: if (reset_2string != ABSENT_STRING
668: && !strcmp(reset_2string, termcap_reset))
669: DISCARD(reset_2string);
670: }
671: }
672:
1.4 millert 673: for_each_string(j, tterm) {
674: i = StrIndirect(j);
1.10 millert 675: name = ExtStrname(tterm, i, str_names);
1.19 ! nicm 676: assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
! 677:
! 678: capability = tterm->Strings[i];
1.1 millert 679:
680: if (!version_filter(STRING, i))
681: continue;
1.10 millert 682: else if (isObsolete(outform, name))
1.1 millert 683: continue;
684:
1.19 ! nicm 685: #if NCURSES_XNAMES
1.1 millert 686: /*
1.19 ! nicm 687: * Extended names can be longer than 2 characters, but termcap programs
! 688: * cannot read those (filter them out).
1.1 millert 689: */
1.19 ! nicm 690: if (outform == F_TERMCAP && (strlen(name) > 2))
! 691: continue;
! 692: #endif
! 693:
1.10 millert 694: if (outform == F_TERMCAP) {
1.19 ! nicm 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) || PRESENT(parm_ich)) {
! 701: if (SAME_CAP(i, enter_insert_mode)
1.10 millert 702: && enter_insert_mode == ABSENT_STRING) {
1.19 ! nicm 703: (void) strlcpy(buffer, "im=", sizeof(buffer));
1.15 millert 704: WRAP_CONCAT;
705: continue;
1.1 millert 706: }
707:
1.19 ! nicm 708: if (SAME_CAP(i, exit_insert_mode)
1.10 millert 709: && exit_insert_mode == ABSENT_STRING) {
1.19 ! nicm 710: (void) strlcpy(buffer, "ei=", sizeof(buffer));
1.15 millert 711: WRAP_CONCAT;
712: continue;
1.1 millert 713: }
714: }
1.19 ! nicm 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)) {
! 720: if (SAME_CAP(i, exit_attribute_mode)) {
! 721: char *trimmed_sgr0;
! 722: char *my_sgr = set_attributes;
! 723:
! 724: set_attributes = save_sgr;
! 725:
! 726: trimmed_sgr0 = _nc_trim_sgr0(tterm);
! 727: if (strcmp(capability, trimmed_sgr0))
! 728: capability = trimmed_sgr0;
! 729:
! 730: set_attributes = my_sgr;
! 731: }
! 732: }
1.2 millert 733: }
734:
1.1 millert 735: predval = pred(STRING, i);
736: buffer[0] = '\0';
1.15 millert 737:
1.1 millert 738: if (predval != FAIL) {
1.19 ! nicm 739: if (capability != ABSENT_STRING
1.10 millert 740: && i + 1 > num_strings)
1.1 millert 741: num_strings = i + 1;
1.15 millert 742:
1.19 ! nicm 743: if (!VALID_STRING(capability)) {
! 744: snprintf(buffer, sizeof(buffer), "%s@", name);
1.15 millert 745: WRAP_CONCAT;
746: } else if (outform == F_TERMCAP || outform == F_TCONVERR) {
1.19 ! nicm 747: int params = ((i < (int) SIZEOF(parametrized))
! 748: ? parametrized[i]
! 749: : 0);
! 750: char *srccap = _nc_tic_expand(capability, TRUE, numbers);
1.16 millert 751: char *cv = _nc_infotocap(name, srccap, params);
1.1 millert 752:
1.10 millert 753: if (cv == 0) {
1.15 millert 754: if (outform == F_TCONVERR) {
1.19 ! nicm 755: snprintf(buffer, sizeof(buffer),
! 756: "%s=!!! %s WILL NOT CONVERT !!!", name, srccap);
1.15 millert 757: } else if (suppress_untranslatable) {
1.1 millert 758: continue;
1.15 millert 759: } else {
1.18 millert 760: char *d, *s = srccap;
1.19 ! nicm 761: snprintf(buffer, sizeof(buffer), "..%s=", name);
1.17 deraadt 762: d = buffer + strlen(buffer);
1.19 ! nicm 763: while ((*d = *s++) != 0) { /* XXX overflow */
1.10 millert 764: if (*d == ':') {
765: *d++ = '\\';
766: *d = ':';
767: } else if (*d == '\\') {
768: *++d = *s++;
769: }
770: d++;
771: }
772: }
1.15 millert 773: } else {
1.17 deraadt 774: snprintf(buffer, sizeof buffer, "%s=%s", name, cv);
1.15 millert 775: }
1.19 ! nicm 776: len += (int) strlen(capability) + 1;
1.15 millert 777: WRAP_CONCAT;
1.10 millert 778: } else {
1.19 ! nicm 779: char *src = _nc_tic_expand(capability,
! 780: outform == F_TERMINFO, numbers);
1.15 millert 781:
782: strcpy_DYN(&tmpbuf, 0);
783: strcpy_DYN(&tmpbuf, name);
784: strcpy_DYN(&tmpbuf, "=");
1.8 millert 785: if (pretty
1.10 millert 786: && (outform == F_TERMINFO
1.15 millert 787: || outform == F_VARIABLE)) {
788: fmt_complex(src, 1);
789: } else {
790: strcpy_DYN(&tmpbuf, src);
791: }
1.19 ! nicm 792: len += (int) strlen(capability) + 1;
1.15 millert 793: wrap_concat(tmpbuf.text);
794: outcount = TRUE;
1.1 millert 795: }
796: }
1.19 ! nicm 797: /* e.g., trimmed_sgr0 */
! 798: if (capability != tterm->Strings[i])
! 799: free(capability);
1.1 millert 800: }
1.19 ! nicm 801: len += (int) (num_strings * 2);
1.1 millert 802:
803: /*
804: * This piece of code should be an effective inverse of the functions
1.19 ! nicm 805: * postprocess_terminfo() and postprocess_terminfo() in parse_entry.c.
1.1 millert 806: * Much more work should be done on this to support dumping termcaps.
807: */
1.10 millert 808: if (tversion == V_HPUX) {
1.19 ! nicm 809: if (VALID_STRING(memory_lock)) {
! 810: (void) snprintf(buffer, sizeof(buffer), "meml=%s", memory_lock);
1.1 millert 811: WRAP_CONCAT;
812: }
1.19 ! nicm 813: if (VALID_STRING(memory_unlock)) {
! 814: (void) snprintf(buffer, sizeof(buffer), "memu=%s", memory_unlock);
1.1 millert 815: WRAP_CONCAT;
816: }
1.10 millert 817: } else if (tversion == V_AIX) {
818: if (VALID_STRING(acs_chars)) {
819: bool box_ok = TRUE;
820: const char *acstrans = "lqkxjmwuvtn";
821: const char *cp;
822: char *tp, *sp, boxchars[11];
1.1 millert 823:
824: tp = boxchars;
1.10 millert 825: for (cp = acstrans; *cp; cp++) {
1.1 millert 826: sp = strchr(acs_chars, *cp);
827: if (sp)
828: *tp++ = sp[1];
1.10 millert 829: else {
1.1 millert 830: box_ok = FALSE;
831: break;
832: }
833: }
834: tp[0] = '\0';
835:
1.10 millert 836: if (box_ok) {
1.19 ! nicm 837: (void) strlcpy(buffer, "box1=", sizeof(buffer));
1.17 deraadt 838: (void) strlcat(buffer, _nc_tic_expand(boxchars,
1.19 ! nicm 839: outform == F_TERMINFO, numbers), sizeof(buffer));
1.1 millert 840: WRAP_CONCAT;
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: */
1.10 millert 849: if (outcount) {
1.15 millert 850: bool trimmed = FALSE;
851: j = outbuf.used;
1.1 millert 852: if (j >= 2
1.15 millert 853: && outbuf.text[j - 1] == '\t'
854: && outbuf.text[j - 2] == '\n') {
855: outbuf.used -= 2;
856: trimmed = TRUE;
1.1 millert 857: } else if (j >= 4
1.19 ! nicm 858: && outbuf.text[j - 1] == ':'
! 859: && outbuf.text[j - 2] == '\t'
! 860: && outbuf.text[j - 3] == '\n'
! 861: && outbuf.text[j - 4] == '\\') {
1.15 millert 862: outbuf.used -= 4;
863: trimmed = TRUE;
864: }
865: if (trimmed) {
866: outbuf.text[outbuf.used] = '\0';
867: column = oldcol;
1.19 ! nicm 868: strcpy_DYN(&outbuf, " ");
1.1 millert 869: }
870: }
871: #if 0
872: fprintf(stderr, "num_bools = %d\n", num_bools);
873: fprintf(stderr, "num_values = %d\n", num_values);
874: fprintf(stderr, "num_strings = %d\n", num_strings);
875: fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n",
1.19 ! nicm 876: tterm->term_names, len, outbuf.used, outbuf.text);
1.1 millert 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: */
1.19 ! nicm 885: return (infodump ? len : (int) termcap_length(outbuf.text));
! 886: }
! 887:
! 888: static bool
! 889: kill_string(TERMTYPE *tterm, char *cap)
! 890: {
! 891: unsigned n;
! 892: for (n = 0; n < NUM_STRINGS(tterm); ++n) {
! 893: if (cap == tterm->Strings[n]) {
! 894: tterm->Strings[n] = ABSENT_STRING;
! 895: return TRUE;
! 896: }
! 897: }
! 898: return FALSE;
1.1 millert 899: }
900:
1.19 ! nicm 901: static char *
! 902: find_string(TERMTYPE *tterm, char *name)
! 903: {
! 904: PredIdx n;
! 905: for (n = 0; n < NUM_STRINGS(tterm); ++n) {
! 906: if (version_filter(STRING, n)
! 907: && !strcmp(name, strnames[n])) {
! 908: char *cap = tterm->Strings[n];
! 909: if (VALID_STRING(cap)) {
! 910: return cap;
! 911: }
! 912: break;
! 913: }
! 914: }
! 915: return ABSENT_STRING;
! 916: }
! 917:
! 918: /*
! 919: * This is used to remove function-key labels from a termcap entry to
! 920: * make it smaller.
! 921: */
! 922: static int
! 923: kill_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
! 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: */
! 947: static int
! 948: kill_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
! 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)
! 973:
! 974: static bool
! 975: one_one_mapping(const char *mapping)
! 976: {
! 977: bool result = TRUE;
! 978:
! 979: if (mapping != ABSENT_STRING) {
! 980: int n = 0;
! 981: while (mapping[n] != '\0') {
! 982: if (isLine(mapping[n]) &&
! 983: mapping[n] != mapping[n + 1]) {
! 984: result = FALSE;
! 985: break;
! 986: }
! 987: n += 2;
! 988: }
! 989: }
! 990: return result;
! 991: }
! 992:
! 993: #define FMT_ENTRY() \
! 994: fmt_entry(tterm, pred, \
! 995: 0, \
! 996: suppress_untranslatable, \
! 997: infodump, numbers)
! 998:
! 999: #define SHOW_WHY PRINTF
! 1000:
! 1001: static bool
! 1002: purged_acs(TERMTYPE *tterm)
! 1003: {
! 1004: bool result = FALSE;
! 1005:
! 1006: if (VALID_STRING(acs_chars)) {
! 1007: if (!one_one_mapping(acs_chars)) {
! 1008: enter_alt_charset_mode = ABSENT_STRING;
! 1009: exit_alt_charset_mode = ABSENT_STRING;
! 1010: SHOW_WHY("# (rmacs/smacs removed for consistency)\n");
! 1011: }
! 1012: result = TRUE;
! 1013: }
! 1014: return result;
! 1015: }
! 1016:
! 1017: /*
! 1018: * Dump a single entry.
! 1019: */
! 1020: void
! 1021: dump_entry(TERMTYPE *tterm,
! 1022: bool suppress_untranslatable,
! 1023: bool limited,
! 1024: int numbers,
! 1025: PredFunc pred)
1.1 millert 1026: {
1.19 ! nicm 1027: TERMTYPE save_tterm;
1.10 millert 1028: int len, critlen;
1029: const char *legend;
1030: bool infodump;
1.1 millert 1031:
1.10 millert 1032: if (outform == F_TERMCAP || outform == F_TCONVERR) {
1.1 millert 1033: critlen = MAX_TERMCAP_LENGTH;
1034: legend = "older termcap";
1035: infodump = FALSE;
1036: set_obsolete_termcaps(tterm);
1.10 millert 1037: } else {
1.1 millert 1038: critlen = MAX_TERMINFO_LENGTH;
1039: legend = "terminfo";
1040: infodump = TRUE;
1041: }
1042:
1.19 ! nicm 1043: save_sgr = set_attributes;
! 1044:
! 1045: if (((len = FMT_ENTRY()) > critlen)
1.10 millert 1046: && limited) {
1.19 ! nicm 1047:
! 1048: save_tterm = *tterm;
! 1049: if (!suppress_untranslatable) {
! 1050: SHOW_WHY("# (untranslatable capabilities removed to fit entry within %d bytes)\n",
! 1051: critlen);
! 1052: suppress_untranslatable = TRUE;
! 1053: }
! 1054: if ((len = FMT_ENTRY()) > critlen) {
1.1 millert 1055: /*
1056: * We pick on sgr because it's a nice long string capability that
1.12 millert 1057: * is really just an optimization hack. Another good candidate is
1058: * acsc since it is both long and unused by BSD termcap.
1.1 millert 1059: */
1.19 ! nicm 1060: bool changed = FALSE;
! 1061:
! 1062: #if NCURSES_XNAMES
! 1063: /*
! 1064: * Extended names are most likely function-key definitions. Drop
! 1065: * those first.
! 1066: */
! 1067: unsigned n;
! 1068: for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) {
! 1069: const char *name = ExtStrname(tterm, n, strnames);
! 1070:
! 1071: if (VALID_STRING(tterm->Strings[n])) {
! 1072: set_attributes = ABSENT_STRING;
! 1073: /* we remove long names anyway - only report the short */
! 1074: if (strlen(name) <= 2) {
! 1075: SHOW_WHY("# (%s removed to fit entry within %d bytes)\n",
! 1076: name,
! 1077: critlen);
! 1078: }
! 1079: changed = TRUE;
! 1080: if ((len = FMT_ENTRY()) <= critlen)
! 1081: break;
! 1082: }
1.12 millert 1083: }
1.19 ! nicm 1084: #endif
! 1085: if (VALID_STRING(set_attributes)) {
! 1086: set_attributes = ABSENT_STRING;
! 1087: SHOW_WHY("# (sgr removed to fit entry within %d bytes)\n",
! 1088: critlen);
! 1089: changed = TRUE;
! 1090: }
! 1091: if (!changed || ((len = FMT_ENTRY()) > critlen)) {
! 1092: if (purged_acs(tterm)) {
! 1093: acs_chars = ABSENT_STRING;
! 1094: SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n",
! 1095: critlen);
! 1096: changed = TRUE;
! 1097: }
! 1098: }
! 1099: if (!changed || ((len = FMT_ENTRY()) > critlen)) {
1.1 millert 1100: int oldversion = tversion;
1101:
1102: tversion = V_BSD;
1.19 ! nicm 1103: SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n",
! 1104: critlen);
1.1 millert 1105:
1.19 ! nicm 1106: len = FMT_ENTRY();
! 1107: if (len > critlen
! 1108: && kill_labels(tterm, len - critlen)) {
! 1109: SHOW_WHY("# (some labels capabilities suppressed to fit entry within %d bytes)\n",
! 1110: critlen);
! 1111: len = FMT_ENTRY();
! 1112: }
! 1113: if (len > critlen
! 1114: && kill_fkeys(tterm, len - critlen)) {
! 1115: SHOW_WHY("# (some function-key capabilities suppressed to fit entry within %d bytes)\n",
! 1116: critlen);
! 1117: len = FMT_ENTRY();
! 1118: }
! 1119: if (len > critlen) {
1.1 millert 1120: (void) fprintf(stderr,
1.19 ! nicm 1121: "warning: %s entry is %d bytes long\n",
! 1122: _nc_first_name(tterm->term_names),
! 1123: len);
! 1124: SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
! 1125: len, legend);
1.1 millert 1126: }
1127: tversion = oldversion;
1128: }
1.19 ! nicm 1129: set_attributes = save_sgr;
! 1130: *tterm = save_tterm;
! 1131: }
! 1132: } else if (!version_filter(STRING, STR_IDX(acs_chars))) {
! 1133: save_tterm = *tterm;
! 1134: if (purged_acs(tterm)) {
! 1135: len = FMT_ENTRY();
1.1 millert 1136: }
1.19 ! nicm 1137: *tterm = save_tterm;
1.1 millert 1138: }
1139: }
1140:
1.19 ! nicm 1141: void
1.10 millert 1142: dump_uses(const char *name, bool infodump)
1.1 millert 1143: /* dump "use=" clauses in the appropriate format */
1144: {
1145: char buffer[MAX_TERMINFO_LENGTH];
1146:
1.19 ! nicm 1147: if (outform == F_TERMCAP || outform == F_TCONVERR)
! 1148: trim_trailing();
! 1149: (void) snprintf(buffer, sizeof(buffer), "%s%s", infodump ? "use=" : "tc=",
! 1150: name);
1.1 millert 1151: wrap_concat(buffer);
1.19 ! nicm 1152: }
! 1153:
! 1154: int
! 1155: show_entry(void)
! 1156: {
! 1157: trim_trailing();
1.15 millert 1158: (void) fputs(outbuf.text, stdout);
1.19 ! nicm 1159: putchar('\n');
! 1160: return (int) outbuf.used;
1.1 millert 1161: }
1162:
1.10 millert 1163: void
1.19 ! nicm 1164: compare_entry(void (*hook) (PredType t, PredIdx i, const char *name),
! 1165: TERMTYPE *tp GCC_UNUSED,
! 1166: bool quiet)
1.1 millert 1167: /* compare two entries */
1168: {
1.19 ! nicm 1169: PredIdx i, j;
1.10 millert 1170: NCURSES_CONST char *name;
1.1 millert 1171:
1.15 millert 1172: if (!quiet)
1173: fputs(" comparing booleans.\n", stdout);
1.10 millert 1174: for_each_boolean(j, tp) {
1.4 millert 1175: i = BoolIndirect(j);
1.10 millert 1176: name = ExtBoolname(tp, i, bool_names);
1.1 millert 1177:
1.10 millert 1178: if (isObsolete(outform, name))
1.1 millert 1179: continue;
1180:
1.14 millert 1181: (*hook) (CMP_BOOLEAN, i, name);
1.1 millert 1182: }
1183:
1.15 millert 1184: if (!quiet)
1185: fputs(" comparing numbers.\n", stdout);
1.10 millert 1186: for_each_number(j, tp) {
1.4 millert 1187: i = NumIndirect(j);
1.10 millert 1188: name = ExtNumname(tp, i, num_names);
1.1 millert 1189:
1.10 millert 1190: if (isObsolete(outform, name))
1.1 millert 1191: continue;
1192:
1.14 millert 1193: (*hook) (CMP_NUMBER, i, name);
1.1 millert 1194: }
1195:
1.15 millert 1196: if (!quiet)
1197: fputs(" comparing strings.\n", stdout);
1.10 millert 1198: for_each_string(j, tp) {
1.4 millert 1199: i = StrIndirect(j);
1.10 millert 1200: name = ExtStrname(tp, i, str_names);
1.1 millert 1201:
1.10 millert 1202: if (isObsolete(outform, name))
1.1 millert 1203: continue;
1204:
1.14 millert 1205: (*hook) (CMP_STRING, i, name);
1.1 millert 1206: }
1.14 millert 1207:
1208: /* (void) fputs(" comparing use entries.\n", stdout); */
1209: (*hook) (CMP_USE, 0, "use");
1210:
1.1 millert 1211: }
1212:
1213: #define NOTSET(s) ((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 CUR
1221: #define CUR tp->
1222:
1.10 millert 1223: static void
1.19 ! nicm 1224: set_obsolete_termcaps(TERMTYPE *tp)
1.1 millert 1225: {
1226: #include "capdefaults.c"
1227: }
1228:
1229: /*
1230: * Convert an alternate-character-set string to canonical form: sorted and
1231: * unique.
1232: */
1.14 millert 1233: void
1.19 ! nicm 1234: repair_acsc(TERMTYPE *tp)
1.1 millert 1235: {
1.10 millert 1236: if (VALID_STRING(acs_chars)) {
1237: size_t n, m;
1238: char mapped[256];
1239: char extra = 0;
1240: unsigned source;
1241: unsigned target;
1242: bool fix_needed = FALSE;
1243:
1244: for (n = 0, source = 0; acs_chars[n] != 0; n++) {
1.19 ! nicm 1245: target = UChar(acs_chars[n]);
1.10 millert 1246: if (source >= target) {
1247: fix_needed = TRUE;
1248: break;
1249: }
1250: source = target;
1251: if (acs_chars[n + 1])
1252: n++;
1253: }
1254: if (fix_needed) {
1255: memset(mapped, 0, sizeof(mapped));
1256: for (n = 0; acs_chars[n] != 0; n++) {
1.19 ! nicm 1257: source = UChar(acs_chars[n]);
1.10 millert 1258: if ((target = (unsigned char) acs_chars[n + 1]) != 0) {
1.19 ! nicm 1259: mapped[source] = (char) target;
1.10 millert 1260: n++;
1261: } else {
1.19 ! nicm 1262: extra = (char) source;
1.1 millert 1263: }
1264: }
1.10 millert 1265: for (n = m = 0; n < sizeof(mapped); n++) {
1266: if (mapped[n]) {
1.19 ! nicm 1267: acs_chars[m++] = (char) n;
1.10 millert 1268: acs_chars[m++] = mapped[n];
1.1 millert 1269: }
1270: }
1.10 millert 1271: if (extra)
1272: acs_chars[m++] = extra; /* garbage in, garbage out */
1273: acs_chars[m] = 0;
1.1 millert 1274: }
1.10 millert 1275: }
1.1 millert 1276: }