Annotation of src/usr.bin/tic/dump_entry.c, Revision 1.7
1.7 ! millert 1: /* $OpenBSD: dump_entry.c,v 1.6 1999/03/15 19:00:18 millert Exp $ */
1.2 millert 2:
1.1 millert 3: /****************************************************************************
1.4 millert 4: * Copyright (c) 1998,1999 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> *
34: ****************************************************************************/
35:
36: #define __INTERNAL_CAPS_VISIBLE
37: #include <progs.priv.h>
38:
39: #include "dump_entry.h"
40: #include <termsort.c> /* this C file is generated */
41: #include <parametrized.h> /* so is this */
42:
1.6 millert 43: MODULE_ID("$From: dump_entry.c,v 1.37 1999/03/14 12:29:30 tom Exp $")
1.1 millert 44:
45: #define INDENT 8
46:
1.2 millert 47: #define DISCARD(string) string = ABSENT_STRING
48:
1.1 millert 49: static int tversion; /* terminfo version */
50: static int outform; /* output format to use */
51: static int sortmode; /* sort mode to use */
52: static int width = 60; /* max line width for listings */
53: static int column; /* current column, limited by 'width' */
54: static int oldcol; /* last value of column before wrap */
55: static int tracelevel; /* level of debug output */
56: static bool pretty; /* true if we format if-then-else strings */
57:
58: static char *outbuf; /* the output-buffer */
59: static size_t out_used; /* ...its current length */
60: static size_t out_size; /* ...and its allocated length */
61:
62: /* indirection pointers for implementing sort and display modes */
63: static const int *bool_indirect, *num_indirect, *str_indirect;
64: static NCURSES_CONST char * const *bool_names;
65: static NCURSES_CONST char * const *num_names;
66: static NCURSES_CONST char * const *str_names;
67:
68: static const char *separator, *trailer;
69:
70: /* cover various ports and variants of terminfo */
71: #define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */
72: #define V_SVR1 1 /* SVR1, Ultrix */
73: #define V_HPUX 2 /* HP/UX */
74: #define V_AIX 3 /* AIX */
75: #define V_BSD 4 /* BSD */
76:
77: #define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T')
78:
1.4 millert 79: #if NCURSES_XNAMES
80: #define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j]))
81: #define NumIndirect(j) ((j >= NUMCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : num_indirect[j]))
82: #define StrIndirect(j) ((j >= STRCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : str_indirect[j]))
83: #else
84: #define BoolIndirect(j) ((sortmode == S_NOSORT) ? (j) : bool_indirect[j])
85: #define NumIndirect(j) ((sortmode == S_NOSORT) ? (j) : num_indirect[j])
86: #define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j])
87: #endif
88:
1.1 millert 89: #if NO_LEAKS
90: void _nc_leaks_dump_entry(void)
91: {
92: if (outbuf != 0) {
93: free(outbuf);
94: outbuf = 0;
95: }
96: }
97: #endif
98:
99: NCURSES_CONST char *nametrans(const char *name)
100: /* translate a capability name from termcap to terminfo */
101: {
102: const struct name_table_entry *np;
103:
1.3 millert 104: if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0)
1.1 millert 105: switch(np->nte_type)
106: {
107: case BOOLEAN:
108: if (bool_from_termcap[np->nte_index])
109: return(boolcodes[np->nte_index]);
110: break;
111:
112: case NUMBER:
113: if (num_from_termcap[np->nte_index])
114: return(numcodes[np->nte_index]);
115: break;
116:
117: case STRING:
118: if (str_from_termcap[np->nte_index])
119: return(strcodes[np->nte_index]);
120: break;
121: }
122:
123: return(0);
124: }
125:
126: void dump_init(const char *version, int mode, int sort, int twidth, int traceval, bool formatted)
127: /* set up for entry display */
128: {
129: width = twidth;
130: pretty = formatted;
131: tracelevel = traceval;
132:
133: /* versions */
134: if (version == 0)
135: tversion = V_ALLCAPS;
136: else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1")
137: || !strcmp(version, "Ultrix"))
138: tversion = V_SVR1;
139: else if (!strcmp(version, "HP"))
140: tversion = V_HPUX;
141: else if (!strcmp(version, "AIX"))
142: tversion = V_AIX;
143: else if (!strcmp(version, "BSD"))
144: tversion = V_BSD;
145: else
146: tversion = V_ALLCAPS;
147:
148: /* implement display modes */
149: switch (outform = mode)
150: {
151: case F_LITERAL:
152: case F_TERMINFO:
153: bool_names = boolnames;
154: num_names = numnames;
155: str_names = strnames;
156: separator = twidth ? ", " : ",";
157: trailer = "\n\t";
158: break;
159:
160: case F_VARIABLE:
161: bool_names = boolfnames;
162: num_names = numfnames;
163: str_names = strfnames;
164: separator = twidth ? ", " : ",";
165: trailer = "\n\t";
166: break;
167:
168: case F_TERMCAP:
169: case F_TCONVERR:
170: bool_names = boolcodes;
171: num_names = numcodes;
172: str_names = strcodes;
173: separator = ":";
174: trailer = "\\\n\t:";
175: break;
176: }
177:
178: /* implement sort modes */
179: switch(sortmode = sort)
1.3 millert 180: {
1.1 millert 181: case S_NOSORT:
182: if (traceval)
183: (void) fprintf(stderr,
184: "%s: sorting by term structure order\n", _nc_progname);
185: break;
186:
187: case S_TERMINFO:
188: if (traceval)
189: (void) fprintf(stderr,
190: "%s: sorting by terminfo name order\n", _nc_progname);
191: bool_indirect = bool_terminfo_sort;
192: num_indirect = num_terminfo_sort;
193: str_indirect = str_terminfo_sort;
194: break;
195:
196: case S_VARIABLE:
197: if (traceval)
198: (void) fprintf(stderr,
199: "%s: sorting by C variable order\n", _nc_progname);
200: bool_indirect = bool_variable_sort;
201: num_indirect = num_variable_sort;
202: str_indirect = str_variable_sort;
203: break;
204:
205: case S_TERMCAP:
206: if (traceval)
207: (void) fprintf(stderr,
208: "%s: sorting by termcap name order\n", _nc_progname);
209: bool_indirect = bool_termcap_sort;
210: num_indirect = num_termcap_sort;
211: str_indirect = str_termcap_sort;
212: break;
213: }
214:
215: if (traceval)
216: (void) fprintf(stderr,
217: "%s: width = %d, tversion = %d, outform = %d\n",
218: _nc_progname, width, tversion, outform);
219: }
220:
221: static TERMTYPE *cur_type;
222:
223: static int dump_predicate(int type, int idx)
224: /* predicate function to use for ordinary decompilation */
225: {
226: switch(type) {
227: case BOOLEAN:
228: return (cur_type->Booleans[idx] == FALSE)
229: ? FAIL : cur_type->Booleans[idx];
230:
231: case NUMBER:
232: return (cur_type->Numbers[idx] == ABSENT_NUMERIC)
233: ? FAIL : cur_type->Numbers[idx];
234:
235: case STRING:
236: return (cur_type->Strings[idx] != ABSENT_STRING)
237: ? (int)TRUE : FAIL;
238: }
239:
240: return(FALSE); /* pacify compiler */
241: }
242:
243: static void set_obsolete_termcaps(TERMTYPE *tp);
244: static void repair_acsc(TERMTYPE *tp);
245:
246: /* is this the index of a function key string? */
247: #define FNKEY(i) (((i)<= 65 && (i)>= 75) || ((i)<= 216 && (i)>= 268))
248:
249: static bool version_filter(int type, int idx)
250: /* filter out capabilities we may want to suppress */
251: {
252: switch (tversion)
253: {
254: case V_ALLCAPS: /* SVr4, XSI Curses */
255: return(TRUE);
256:
257: case V_SVR1: /* System V Release 1, Ultrix */
258: switch (type)
259: {
260: case BOOLEAN:
261: /* below and including xon_xoff */
262: return ((idx <= 20) ? TRUE : FALSE);
263: case NUMBER:
264: /* below and including width_status_line */
265: return ((idx <= 7) ? TRUE : FALSE);
266: case STRING:
267: /* below and including prtr_non */
268: return ((idx <= 144) ? TRUE : FALSE);
269: }
270: break;
271:
272: case V_HPUX: /* Hewlett-Packard */
273: switch (type)
274: {
275: case BOOLEAN:
276: /* below and including xon_xoff */
277: return ((idx <= 20) ? TRUE : FALSE);
278: case NUMBER:
279: /* below and including label_width */
280: return ((idx <= 10) ? TRUE : FALSE);
281: case STRING:
282: if (idx <= 144) /* below and including prtr_non */
283: return(TRUE);
284: else if (FNKEY(idx)) /* function keys */
285: return(TRUE);
286: else if (idx==147||idx==156||idx==157) /* plab_norm,label_on,label_off */
287: return(TRUE);
288: else
289: return(FALSE);
290: }
291: break;
292:
293: case V_AIX: /* AIX */
294: switch (type)
295: {
296: case BOOLEAN:
297: /* below and including xon_xoff */
298: return ((idx <= 20) ? TRUE : FALSE);
299: case NUMBER:
300: /* below and including width_status_line */
301: return ((idx <= 7) ? TRUE : FALSE);
302: case STRING:
303: if (idx <= 144) /* below and including prtr_non */
304: return(TRUE);
305: else if (FNKEY(idx)) /* function keys */
306: return(TRUE);
307: else
308: return(FALSE);
309: }
310: break;
311:
312: case V_BSD: /* BSD */
313: switch (type)
314: {
315: case BOOLEAN:
316: return bool_from_termcap[idx];
317: case NUMBER:
318: return num_from_termcap[idx];
319: case STRING:
320: return str_from_termcap[idx];
321: }
322: break;
323: }
324:
325: return(FALSE); /* pacify the compiler */
326: }
327:
328: static
329: void append_output (const char *src)
330: {
331: if (src == 0) {
332: out_used = 0;
333: append_output("");
334: } else {
335: size_t need = strlen(src);
336: size_t want = need + out_used + 1;
337: if (want > out_size) {
338: out_size += want; /* be generous */
339: if (outbuf == 0)
340: outbuf = malloc(out_size);
341: else
342: outbuf = realloc(outbuf, out_size);
343: }
344: (void)strcpy(outbuf + out_used, src);
345: out_used += need;
346: }
347: }
348:
349: static
350: void force_wrap(void)
351: {
352: oldcol = column;
353: append_output(trailer);
354: column = INDENT;
355: }
356:
357: static
358: void wrap_concat(const char *src)
359: {
360: int need = strlen(src);
361: int want = strlen(separator) + need;
362:
363: if (column > INDENT
364: && column + want > width) {
365: force_wrap();
366: }
367: append_output(src);
368: append_output(separator);
369: column += need;
370: }
371:
372: #define IGNORE_SEP_TRAIL(first,last,sep_trail) \
373: if ((size_t)(last - first) > sizeof(sep_trail)-1 \
374: && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \
375: first += sizeof(sep_trail)-2
376:
377: /* Returns the nominal length of the buffer assuming it is termcap format,
378: * i.e., the continuation sequence is treated as a single character ":".
379: *
380: * There are several implementations of termcap which read the text into a
381: * fixed-size buffer. Generally they strip the newlines from the text, but may
382: * not do it until after the buffer is read. Also, "tc=" resolution may be
383: * expanded in the same buffer. This function is useful for measuring the size
384: * of the best fixed-buffer implementation; the worst case may be much worse.
385: */
386: #ifdef TEST_TERMCAP_LENGTH
387: static int termcap_length(const char *src)
388: {
389: static const char pattern[] = ":\\\n\t:";
390:
391: int len = 0;
392: const char *const t = src + strlen(src);
393:
394: while (*src != '\0') {
395: IGNORE_SEP_TRAIL(src, t, pattern);
396: src++;
397: len++;
398: }
399: return len;
400: }
401: #else
402: #define termcap_length(src) strlen(src)
403: #endif
404:
405: static char * fmt_complex(char *dst, char *src, int level)
406: {
407: int percent = 0;
408: int n;
409:
410: dst += strlen(dst);
411: while (*src != '\0') {
412: switch (*src) {
413: case '\\':
414: percent = 0;
415: *dst++ = *src++;
416: break;
417: case '%':
418: percent = 1;
419: break;
420: case '?': /* "if" */
421: case 't': /* "then" */
422: case 'e': /* "else" */
423: if (percent) {
424: percent = 0;
425: dst[-1] = '\n';
426: for (n = 0; n <= level; n++)
427: *dst++ = '\t';
428: *dst++ = '%';
429: *dst++ = *src;
430: *dst = '\0';
431: if (*src++ == '?') {
432: src = fmt_complex(dst, src, level+1);
433: dst += strlen(dst);
434: } else if (level == 1) {
435: _nc_warning("%%%c without %%?", *src);
436: }
437: continue;
438: }
439: break;
440: case ';': /* "endif" */
441: if (percent) {
442: percent = 0;
443: if (level > 1) {
444: dst[-1] = '\n';
445: for (n = 0; n < level; n++)
446: *dst++ = '\t';
447: *dst++ = '%';
448: *dst++ = *src++;
449: *dst = '\0';
450: return src;
451: }
452: _nc_warning("%%; without %%?");
453: }
454: break;
455: default:
456: percent = 0;
457: break;
458: }
459: *dst++ = *src++;
460: }
461: *dst = '\0';
462: return src;
463: }
464:
465: int fmt_entry(TERMTYPE *tterm,
466: int (*pred)(int type, int idx),
467: bool suppress_untranslatable,
1.2 millert 468: bool infodump,
1.5 millert 469: int numbers)
1.1 millert 470: {
471: int i, j;
472: char buffer[MAX_TERMINFO_LENGTH];
1.6 millert 473: NCURSES_CONST char *name;
1.1 millert 474: int predval, len;
475: int num_bools = 0;
476: int num_values = 0;
477: int num_strings = 0;
478: bool outcount = 0;
479:
480: #define WRAP_CONCAT \
481: wrap_concat(buffer); \
482: outcount = TRUE
483:
484: len = 12; /* terminfo file-header */
485:
486: if (pred == 0) {
487: cur_type = tterm;
488: pred = dump_predicate;
489: }
490:
491: append_output(0);
492: append_output(tterm->term_names);
493: append_output(separator);
494: column = out_used;
495: force_wrap();
496:
1.4 millert 497: for_each_boolean(j,tterm) {
498: i = BoolIndirect(j);
499: name = ExtBoolname(tterm,i,bool_names);
1.1 millert 500:
501: if (!version_filter(BOOLEAN, i))
502: continue;
503: else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
1.4 millert 504: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 505: continue;
506:
507: predval = pred(BOOLEAN, i);
508: if (predval != FAIL) {
1.4 millert 509: (void) strcpy(buffer, name);
1.1 millert 510: if (predval <= 0)
511: (void) strcat(buffer, "@");
512: else if (i + 1 > num_bools)
513: num_bools = i + 1;
514: WRAP_CONCAT;
515: }
516: }
517:
518: if (column != INDENT)
519: force_wrap();
520:
1.4 millert 521: for_each_number(j,tterm) {
522: i = NumIndirect(j);
523: name = ExtNumname(tterm,i,num_names);
1.1 millert 524:
525: if (!version_filter(NUMBER, i))
526: continue;
527: else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
1.4 millert 528: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 529: continue;
530:
531: predval = pred(NUMBER, i);
532: if (predval != FAIL) {
533: if (tterm->Numbers[i] < 0) {
1.4 millert 534: sprintf(buffer, "%s@", name);
1.1 millert 535: } else {
1.4 millert 536: sprintf(buffer, "%s#%d", name, tterm->Numbers[i]);
1.1 millert 537: if (i + 1 > num_values)
538: num_values = i + 1;
539: }
540: WRAP_CONCAT;
541: }
542: }
543:
544: if (column != INDENT)
545: force_wrap();
546:
547: len += num_bools
548: + num_values * 2
549: + strlen(tterm->term_names) + 1;
550: if (len & 1)
551: len++;
552:
553: repair_acsc(tterm);
1.4 millert 554: for_each_string(j, tterm) {
555: i = StrIndirect(j);
556: name = ExtStrname(tterm,i,str_names);
1.1 millert 557:
558: if (!version_filter(STRING, i))
559: continue;
560: else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
1.4 millert 561: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 562: continue;
563:
564: /*
565: * Some older versions of vi want rmir/smir to be defined
566: * for ich/ich1 to work. If they're not defined, force
567: * them to be output as defined and empty.
568: */
569: if (outform==F_TERMCAP)
1.2 millert 570: {
1.1 millert 571: #undef CUR
572: #define CUR tterm->
573: if (insert_character || parm_ich)
574: {
575: if (&tterm->Strings[i] == &enter_insert_mode
576: && enter_insert_mode == ABSENT_STRING)
577: {
578: (void) strcpy(buffer, "im=");
579: goto catenate;
580: }
581:
582: if (&tterm->Strings[i] == &exit_insert_mode
583: && exit_insert_mode == ABSENT_STRING)
584: {
585: (void) strcpy(buffer, "ei=");
586: goto catenate;
587: }
588: }
589:
1.2 millert 590: if (init_3string != 0
591: && termcap_reset != 0
592: && !strcmp(init_3string, termcap_reset))
593: DISCARD(init_3string);
594:
595: if (reset_2string != 0
596: && termcap_reset != 0
597: && !strcmp(reset_2string, termcap_reset))
598: DISCARD(reset_2string);
599: }
600:
1.1 millert 601: predval = pred(STRING, i);
602: buffer[0] = '\0';
603: if (predval != FAIL) {
604: if (tterm->Strings[i] != ABSENT_STRING
605: && i + 1 > num_strings)
606: num_strings = i + 1;
607: if (!VALID_STRING(tterm->Strings[i]))
1.4 millert 608: sprintf(buffer, "%s@", name);
1.1 millert 609: else if (outform == F_TERMCAP || outform == F_TCONVERR)
610: {
1.2 millert 611: char *srccap = _nc_tic_expand(tterm->Strings[i], FALSE, numbers);
1.4 millert 612: char *cv = _nc_infotocap(name, srccap, parametrized[i]);
1.1 millert 613:
614: if (cv == 0)
615: {
616: if (outform == F_TCONVERR)
1.4 millert 617: sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!", name, srccap);
1.1 millert 618: else if (suppress_untranslatable)
619: continue;
620: else
1.4 millert 621: sprintf(buffer, "..%s=%s", name, srccap);
1.1 millert 622: }
623: else
1.4 millert 624: sprintf(buffer, "%s=%s", name, cv);
1.1 millert 625: len += strlen(tterm->Strings[i]) + 1;
626: }
627: else
628: {
1.2 millert 629: char *src = _nc_tic_expand(tterm->Strings[i], outform==F_TERMINFO, numbers);
1.4 millert 630: sprintf(buffer, "%s=", name);
1.1 millert 631: if (pretty && outform==F_TERMINFO)
632: fmt_complex(buffer + strlen(buffer), src, 1);
633: else
634: strcat(buffer, src);
635: len += strlen(tterm->Strings[i]) + 1;
636: }
637:
638: catenate:
639: WRAP_CONCAT;
640: }
641: }
642: len += num_strings * 2;
643:
644: /*
645: * This piece of code should be an effective inverse of the functions
646: * postprocess_terminfo and postprocess_terminfo in parse_entry.c.
647: * Much more work should be done on this to support dumping termcaps.
648: */
649: if (tversion == V_HPUX)
650: {
651: if (memory_lock)
652: {
653: (void) sprintf(buffer, "meml=%s", memory_lock);
654: WRAP_CONCAT;
655: }
656: if (memory_unlock)
657: {
658: (void) sprintf(buffer, "memu=%s", memory_unlock);
659: WRAP_CONCAT;
660: }
661: }
662: else if (tversion == V_AIX)
663: {
664: if (VALID_STRING(acs_chars))
665: {
666: bool box_ok = TRUE;
667: const char *acstrans = "lqkxjmwuvtn";
668: const char *cp;
669: char *tp, *sp, boxchars[11];
670:
671: tp = boxchars;
672: for (cp = acstrans; *cp; cp++)
673: {
674: sp = strchr(acs_chars, *cp);
675: if (sp)
676: *tp++ = sp[1];
677: else
678: {
679: box_ok = FALSE;
680: break;
681: }
682: }
683: tp[0] = '\0';
684:
685: if (box_ok)
686: {
687: (void) strcpy(buffer, "box1=");
1.2 millert 688: (void) strcat(buffer, _nc_tic_expand(boxchars, outform==F_TERMINFO, numbers));
1.1 millert 689: WRAP_CONCAT;
690: }
691: }
692: }
693:
694: /*
695: * kludge: trim off trailer to avoid an extra blank line
696: * in infocmp -u output when there are no string differences
697: */
698: if (outcount)
699: {
700: j = out_used;
701: if (j >= 2
702: && outbuf[j-1] == '\t'
703: && outbuf[j-2] == '\n') {
704: out_used -= 2;
705: } else if (j >= 4
706: && outbuf[j-1] == ':'
707: && outbuf[j-2] == '\t'
708: && outbuf[j-3] == '\n'
709: && outbuf[j-4] == '\\') {
710: out_used -= 4;
711: }
712: outbuf[out_used] = '\0';
713: column = oldcol;
714: }
715:
716: #if 0
717: fprintf(stderr, "num_bools = %d\n", num_bools);
718: fprintf(stderr, "num_values = %d\n", num_values);
719: fprintf(stderr, "num_strings = %d\n", num_strings);
720: fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n",
721: tterm->term_names, len, out_used, outbuf);
722: #endif
723: /*
724: * Here's where we use infodump to trigger a more stringent length check
725: * for termcap-translation purposes.
726: * Return the length of the raw entry, without tc= expansions,
727: * It gives an idea of which entries are deadly to even *scan past*,
728: * as opposed to *use*.
729: */
730: return(infodump ? len : termcap_length(outbuf));
731: }
732:
1.5 millert 733: int dump_entry(TERMTYPE *tterm, bool limited, int numbers, int (*pred)(int type, int idx))
1.1 millert 734: /* dump a single entry */
735: {
736: int len, critlen;
737: const char *legend;
738: bool infodump;
739:
740: if (outform==F_TERMCAP || outform==F_TCONVERR)
741: {
742: critlen = MAX_TERMCAP_LENGTH;
743: legend = "older termcap";
744: infodump = FALSE;
745: set_obsolete_termcaps(tterm);
746: }
747: else
748: {
749: critlen = MAX_TERMINFO_LENGTH;
750: legend = "terminfo";
751: infodump = TRUE;
752: }
753:
1.7 ! millert 754: if (((len = fmt_entry(tterm, pred, FALSE, infodump, numbers)) > critlen) && limited)
1.1 millert 755: {
756: (void) printf("# (untranslatable capabilities removed to fit entry within %d bytes)\n",
757: critlen);
1.2 millert 758: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 759: {
760: /*
761: * We pick on sgr because it's a nice long string capability that
762: * is really just an optimization hack.
763: */
764: char *oldsgr = set_attributes;
1.3 millert 765: set_attributes = ABSENT_STRING;
1.1 millert 766: (void) printf("# (sgr removed to fit entry within %d bytes)\n",
767: critlen);
1.2 millert 768: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 769: {
770: int oldversion = tversion;
771:
772: tversion = V_BSD;
773: (void) printf("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n",
774: critlen);
775:
1.2 millert 776: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 777: {
778: (void) fprintf(stderr,
779: "warning: %s entry is %d bytes long\n",
780: _nc_first_name(tterm->term_names),
781: len);
782: (void) printf(
783: "# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
784: len, legend);
785: }
786: tversion = oldversion;
787: }
788: set_attributes = oldsgr;
789: }
790: }
791:
792: (void) fputs(outbuf, stdout);
793: return len;
794: }
795:
796: int dump_uses(const char *name, bool infodump)
797: /* dump "use=" clauses in the appropriate format */
798: {
799: char buffer[MAX_TERMINFO_LENGTH];
800:
801: append_output(0);
802: (void)sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name);
803: wrap_concat(buffer);
804: (void) fputs(outbuf, stdout);
805: return out_used;
806: }
807:
1.4 millert 808: void compare_entry(void (*hook)(int t, int i, const char *name), TERMTYPE *tp GCC_UNUSED)
1.1 millert 809: /* compare two entries */
810: {
811: int i, j;
1.6 millert 812: NCURSES_CONST char * name;
1.1 millert 813:
814: (void) fputs(" comparing booleans.\n", stdout);
1.4 millert 815: for_each_boolean(j,tp)
1.1 millert 816: {
1.4 millert 817: i = BoolIndirect(j);
818: name = ExtBoolname(tp,i,bool_names);
1.1 millert 819:
820: if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
1.4 millert 821: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 822: continue;
823:
1.4 millert 824: (*hook)(BOOLEAN, i, name);
1.1 millert 825: }
826:
827: (void) fputs(" comparing numbers.\n", stdout);
1.4 millert 828: for_each_number(j,tp)
1.1 millert 829: {
1.4 millert 830: i = NumIndirect(j);
831: name = ExtNumname(tp,i,num_names);
1.1 millert 832:
833: if ((outform==F_LITERAL || outform==F_TERMINFO || outform==F_VARIABLE)
1.4 millert 834: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 835: continue;
836:
1.4 millert 837: (*hook)(NUMBER, i, name);
1.1 millert 838: }
839:
840: (void) fputs(" comparing strings.\n", stdout);
1.4 millert 841: for_each_string(j,tp)
1.1 millert 842: {
1.4 millert 843: i = StrIndirect(j);
844: name = ExtStrname(tp,i,str_names);
1.1 millert 845:
846: if ((outform==F_LITERAL || outform==F_TERMINFO || outform==F_VARIABLE)
1.4 millert 847: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 848: continue;
849:
1.4 millert 850: (*hook)(STRING, i, name);
1.1 millert 851: }
852: }
853:
854: #define NOTSET(s) ((s) == 0)
855:
856: /*
857: * This bit of legerdemain turns all the terminfo variable names into
858: * references to locations in the arrays Booleans, Numbers, and Strings ---
859: * precisely what's needed.
860: */
861: #undef CUR
862: #define CUR tp->
863:
864: static void set_obsolete_termcaps(TERMTYPE *tp)
865: {
866: #include "capdefaults.c"
867: }
868:
869: /*
870: * Convert an alternate-character-set string to canonical form: sorted and
871: * unique.
872: */
873: static void repair_acsc(TERMTYPE *tp)
874: {
875: if (VALID_STRING(acs_chars)) {
876: size_t n, m;
877: char mapped[256];
878: char extra = 0;
879: unsigned source;
880: unsigned target;
881: bool fix_needed = FALSE;
882:
883: for (n = 0, source = 0; acs_chars[n] != 0; n++) {
884: target = acs_chars[n];
885: if (source >= target) {
886: fix_needed = TRUE;
887: break;
888: }
889: source = target;
890: if (acs_chars[n+1])
891: n++;
892: }
893: if (fix_needed) {
894: memset(mapped, 0, sizeof(mapped));
895: for (n = 0; acs_chars[n] != 0; n++) {
896: source = acs_chars[n];
897: if ((target = (unsigned char)acs_chars[n+1]) != 0) {
898: mapped[source] = target;
899: n++;
900: } else {
901: extra = source;
902: }
903: }
904: for (n = m = 0; n < sizeof(mapped); n++) {
905: if (mapped[n]) {
906: acs_chars[m++] = n;
907: acs_chars[m++] = mapped[n];
908: }
909: }
910: if (extra)
911: acs_chars[m++] = extra; /* garbage in, garbage out */
912: acs_chars[m] = 0;
913: }
914: }
915: }