Annotation of src/usr.bin/tic/dump_entry.c, Revision 1.8
1.8 ! millert 1: /* $OpenBSD: dump_entry.c,v 1.7 1999/03/22 18:43:19 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.8 ! millert 43: MODULE_ID("$From: dump_entry.c,v 1.38 1999/11/27 23:00:21 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.8 ! millert 631: if (pretty
! 632: && (outform == F_TERMINFO
! 633: || outform == F_VARIABLE))
1.1 millert 634: fmt_complex(buffer + strlen(buffer), src, 1);
635: else
636: strcat(buffer, src);
637: len += strlen(tterm->Strings[i]) + 1;
638: }
639:
640: catenate:
641: WRAP_CONCAT;
642: }
643: }
644: len += num_strings * 2;
645:
646: /*
647: * This piece of code should be an effective inverse of the functions
648: * postprocess_terminfo and postprocess_terminfo in parse_entry.c.
649: * Much more work should be done on this to support dumping termcaps.
650: */
651: if (tversion == V_HPUX)
652: {
653: if (memory_lock)
654: {
655: (void) sprintf(buffer, "meml=%s", memory_lock);
656: WRAP_CONCAT;
657: }
658: if (memory_unlock)
659: {
660: (void) sprintf(buffer, "memu=%s", memory_unlock);
661: WRAP_CONCAT;
662: }
663: }
664: else if (tversion == V_AIX)
665: {
666: if (VALID_STRING(acs_chars))
667: {
668: bool box_ok = TRUE;
669: const char *acstrans = "lqkxjmwuvtn";
670: const char *cp;
671: char *tp, *sp, boxchars[11];
672:
673: tp = boxchars;
674: for (cp = acstrans; *cp; cp++)
675: {
676: sp = strchr(acs_chars, *cp);
677: if (sp)
678: *tp++ = sp[1];
679: else
680: {
681: box_ok = FALSE;
682: break;
683: }
684: }
685: tp[0] = '\0';
686:
687: if (box_ok)
688: {
689: (void) strcpy(buffer, "box1=");
1.2 millert 690: (void) strcat(buffer, _nc_tic_expand(boxchars, outform==F_TERMINFO, numbers));
1.1 millert 691: WRAP_CONCAT;
692: }
693: }
694: }
695:
696: /*
697: * kludge: trim off trailer to avoid an extra blank line
698: * in infocmp -u output when there are no string differences
699: */
700: if (outcount)
701: {
702: j = out_used;
703: if (j >= 2
704: && outbuf[j-1] == '\t'
705: && outbuf[j-2] == '\n') {
706: out_used -= 2;
707: } else if (j >= 4
708: && outbuf[j-1] == ':'
709: && outbuf[j-2] == '\t'
710: && outbuf[j-3] == '\n'
711: && outbuf[j-4] == '\\') {
712: out_used -= 4;
713: }
714: outbuf[out_used] = '\0';
715: column = oldcol;
716: }
717:
718: #if 0
719: fprintf(stderr, "num_bools = %d\n", num_bools);
720: fprintf(stderr, "num_values = %d\n", num_values);
721: fprintf(stderr, "num_strings = %d\n", num_strings);
722: fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n",
723: tterm->term_names, len, out_used, outbuf);
724: #endif
725: /*
726: * Here's where we use infodump to trigger a more stringent length check
727: * for termcap-translation purposes.
728: * Return the length of the raw entry, without tc= expansions,
729: * It gives an idea of which entries are deadly to even *scan past*,
730: * as opposed to *use*.
731: */
732: return(infodump ? len : termcap_length(outbuf));
733: }
734:
1.5 millert 735: int dump_entry(TERMTYPE *tterm, bool limited, int numbers, int (*pred)(int type, int idx))
1.1 millert 736: /* dump a single entry */
737: {
738: int len, critlen;
739: const char *legend;
740: bool infodump;
741:
742: if (outform==F_TERMCAP || outform==F_TCONVERR)
743: {
744: critlen = MAX_TERMCAP_LENGTH;
745: legend = "older termcap";
746: infodump = FALSE;
747: set_obsolete_termcaps(tterm);
748: }
749: else
750: {
751: critlen = MAX_TERMINFO_LENGTH;
752: legend = "terminfo";
753: infodump = TRUE;
754: }
755:
1.7 millert 756: if (((len = fmt_entry(tterm, pred, FALSE, infodump, numbers)) > critlen) && limited)
1.1 millert 757: {
758: (void) printf("# (untranslatable capabilities removed to fit entry within %d bytes)\n",
759: critlen);
1.2 millert 760: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 761: {
762: /*
763: * We pick on sgr because it's a nice long string capability that
764: * is really just an optimization hack.
765: */
766: char *oldsgr = set_attributes;
1.3 millert 767: set_attributes = ABSENT_STRING;
1.1 millert 768: (void) printf("# (sgr removed to fit entry within %d bytes)\n",
769: critlen);
1.2 millert 770: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 771: {
772: int oldversion = tversion;
773:
774: tversion = V_BSD;
775: (void) printf("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n",
776: critlen);
777:
1.2 millert 778: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 779: {
780: (void) fprintf(stderr,
781: "warning: %s entry is %d bytes long\n",
782: _nc_first_name(tterm->term_names),
783: len);
784: (void) printf(
785: "# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
786: len, legend);
787: }
788: tversion = oldversion;
789: }
790: set_attributes = oldsgr;
791: }
792: }
793:
794: (void) fputs(outbuf, stdout);
795: return len;
796: }
797:
798: int dump_uses(const char *name, bool infodump)
799: /* dump "use=" clauses in the appropriate format */
800: {
801: char buffer[MAX_TERMINFO_LENGTH];
802:
803: append_output(0);
804: (void)sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name);
805: wrap_concat(buffer);
806: (void) fputs(outbuf, stdout);
807: return out_used;
808: }
809:
1.4 millert 810: void compare_entry(void (*hook)(int t, int i, const char *name), TERMTYPE *tp GCC_UNUSED)
1.1 millert 811: /* compare two entries */
812: {
813: int i, j;
1.6 millert 814: NCURSES_CONST char * name;
1.1 millert 815:
816: (void) fputs(" comparing booleans.\n", stdout);
1.4 millert 817: for_each_boolean(j,tp)
1.1 millert 818: {
1.4 millert 819: i = BoolIndirect(j);
820: name = ExtBoolname(tp,i,bool_names);
1.1 millert 821:
822: if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
1.4 millert 823: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 824: continue;
825:
1.4 millert 826: (*hook)(BOOLEAN, i, name);
1.1 millert 827: }
828:
829: (void) fputs(" comparing numbers.\n", stdout);
1.4 millert 830: for_each_number(j,tp)
1.1 millert 831: {
1.4 millert 832: i = NumIndirect(j);
833: name = ExtNumname(tp,i,num_names);
1.1 millert 834:
835: if ((outform==F_LITERAL || outform==F_TERMINFO || outform==F_VARIABLE)
1.4 millert 836: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 837: continue;
838:
1.4 millert 839: (*hook)(NUMBER, i, name);
1.1 millert 840: }
841:
842: (void) fputs(" comparing strings.\n", stdout);
1.4 millert 843: for_each_string(j,tp)
1.1 millert 844: {
1.4 millert 845: i = StrIndirect(j);
846: name = ExtStrname(tp,i,str_names);
1.1 millert 847:
848: if ((outform==F_LITERAL || outform==F_TERMINFO || outform==F_VARIABLE)
1.4 millert 849: && (OBSOLETE(name) && outform != F_LITERAL))
1.1 millert 850: continue;
851:
1.4 millert 852: (*hook)(STRING, i, name);
1.1 millert 853: }
854: }
855:
856: #define NOTSET(s) ((s) == 0)
857:
858: /*
859: * This bit of legerdemain turns all the terminfo variable names into
860: * references to locations in the arrays Booleans, Numbers, and Strings ---
861: * precisely what's needed.
862: */
863: #undef CUR
864: #define CUR tp->
865:
866: static void set_obsolete_termcaps(TERMTYPE *tp)
867: {
868: #include "capdefaults.c"
869: }
870:
871: /*
872: * Convert an alternate-character-set string to canonical form: sorted and
873: * unique.
874: */
875: static void repair_acsc(TERMTYPE *tp)
876: {
877: if (VALID_STRING(acs_chars)) {
878: size_t n, m;
879: char mapped[256];
880: char extra = 0;
881: unsigned source;
882: unsigned target;
883: bool fix_needed = FALSE;
884:
885: for (n = 0, source = 0; acs_chars[n] != 0; n++) {
886: target = acs_chars[n];
887: if (source >= target) {
888: fix_needed = TRUE;
889: break;
890: }
891: source = target;
892: if (acs_chars[n+1])
893: n++;
894: }
895: if (fix_needed) {
896: memset(mapped, 0, sizeof(mapped));
897: for (n = 0; acs_chars[n] != 0; n++) {
898: source = acs_chars[n];
899: if ((target = (unsigned char)acs_chars[n+1]) != 0) {
900: mapped[source] = target;
901: n++;
902: } else {
903: extra = source;
904: }
905: }
906: for (n = m = 0; n < sizeof(mapped); n++) {
907: if (mapped[n]) {
908: acs_chars[m++] = n;
909: acs_chars[m++] = mapped[n];
910: }
911: }
912: if (extra)
913: acs_chars[m++] = extra; /* garbage in, garbage out */
914: acs_chars[m] = 0;
915: }
916: }
917: }